58 Commits

Author SHA1 Message Date
85706518fe Update to SHVDN nightly (#70) 2024-06-30 16:17:35 +08:00
49208371d1 Allow keyboard layout change in chat 2023-12-12 11:52:20 -03:00
761156a574 Avoid vehicle door break and repair loop 2023-11-27 10:24:35 -03:00
8bd6ea15a3 Remove global limits
world limits will be applied to all players instead
Fix explosions when remote and local vehicles exist at same position
Fix "floating corpses" issue when remote NPCs are killed
2023-11-20 11:32:18 -03:00
3c7f16f7a4 Add ped limit menu setting
Fix vehicle limit menu setting
Fix player blip disappearing after switching character
2023-11-12 10:50:37 -03:00
393a401860 Always sync vehicles with synced peds 2023-11-07 20:27:14 -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
9287aba0f9 Update README.md 2023-07-26 15:42:08 -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 3470 additions and 3652 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:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
branches: [ "dev-nightly" ]
jobs:
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
- 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
- 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
with:
files: bin/Release/Client
@ -47,11 +43,6 @@ jobs:
files: bin/Release/Server/linux-x64
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
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # automatically provided by github actions
@ -84,17 +75,3 @@ jobs:
asset_name: RageCoop.Server-linux-x64.zip
asset_content_type: application/zip
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
- ScriptHookV
- ScriptHookVDotNet 3.5.1 or later
- ScriptHookVDotNet 3.6.0 or later
- .NET Framework 4.8 Runtime or SDK
# 📋 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!
6. Weaponized vehicle sync(WIP).
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

View File

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

View File

@ -1,27 +1,17 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
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 Path = System.IO.Path;
using System.Windows.Input;
using MessageBox = System.Windows.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using Path = System.IO.Path;
using RageCoop.Core;
namespace RageCoop.Client.Installer
{
@ -45,7 +35,8 @@ namespace RageCoop.Client.Installer
};
if (od.ShowDialog() ?? false == true)
{
Task.Run(() => {
Task.Run(() =>
{
try
{
Install(Directory.GetParent(od.FileName).FullName);
@ -62,7 +53,8 @@ namespace RageCoop.Client.Installer
Environment.Exit(0);
}
}
void Install(string root)
private void Install(string root)
{
UpdateStatus("Checking requirements");
var shvPath = Path.Combine(root, "ScriptHookV.dll");
@ -86,10 +78,10 @@ namespace RageCoop.Client.Installer
Environment.Exit(1);
}
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!" +
$"\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);
}
if (File.Exists(lemonPath))
@ -201,15 +193,18 @@ namespace RageCoop.Client.Installer
Environment.Exit(0);
}
}
void UpdateStatus(string status)
private void UpdateStatus(string status)
{
Dispatcher.BeginInvoke(new Action(() => Status.Content = status));
}
Version GetVer(string location)
private Version GetVer(string location)
{
return Version.Parse(FileVersionInfo.GetVersionInfo(location).FileVersion);
}
byte[] getLemon()
private byte[] getLemon()
{
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

@ -43,7 +43,7 @@ namespace RageCoop.Client
public static void ShowTimeStamps()
{
GTA.UI.Notification.Hide(_lastNfHandle);
_lastNfHandle=GTA.UI.Notification.Show(Debug.TimeStamps.Dump());
_lastNfHandle = GTA.UI.Notification.PostTicker(TimeStamps.Dump(), false).Handle;
}
}

View File

@ -162,7 +162,7 @@ namespace RageCoop.Client
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
GTA.UI.Notification.Show("Copied to clipboard, please paste it on the GitHub issue page!");
GTA.UI.Notification.PostTicker("Copied to clipboard, please paste it on the GitHub issue page!", false);
}
}

View File

@ -6,12 +6,11 @@ using RageCoop.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace RageCoop.Client
{
@ -39,7 +38,7 @@ namespace RageCoop.Client
internal static ulong Ticked = 0;
internal static Vector3 PlayerPosition;
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;
/// <summary>
@ -47,9 +46,6 @@ namespace RageCoop.Client
/// </summary>
public Main()
{
#if DEBUG_HIGH_PING
Networking.SimulatedLatency=0.3f;
#endif
Worker = new Worker("RageCoop.Client.Main.Worker", Logger);
try
{
@ -57,7 +53,7 @@ namespace RageCoop.Client
}
catch
{
GTA.UI.Notification.Show("Malformed configuration, overwriting with default values...");
GTA.UI.Notification.PostTicker("Malformed configuration, overwriting with default values...", false);
Settings = new Settings();
Util.SaveSettings();
}
@ -83,7 +79,7 @@ namespace RageCoop.Client
}
if (!_gameLoaded)
{
GTA.UI.Notification.Show("~r~Please update your GTA5 to v1.0.1290 or newer!", true);
GTA.UI.Notification.PostTicker("~r~Please update your GTA5 to v1.0.1290 or newer!", true);
_gameLoaded = true;
}
};
@ -100,7 +96,7 @@ namespace RageCoop.Client
KeyDown += OnKeyDown;
KeyDown += (s, e) => { Scripting.API.Events.InvokeKeyDown(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();
Counter.Restart();
@ -111,24 +107,9 @@ namespace RageCoop.Client
private bool _lastDead;
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;
PlayerPosition = P.ReadPosition();
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)
{
return;
@ -136,8 +117,7 @@ namespace RageCoop.Client
else if (!_gameLoaded && (_gameLoaded = true))
{
#if !NON_INTERACTIVE
GTA.UI.Notification.Show(GTA.UI.NotificationIcon.AllPlayersConf, "RAGECOOP", "Welcome!", $"Press ~g~{Main.Settings.MenuKey}~s~ to open the menu.");
WorldThread.Traffic(!Settings.DisableTraffic);
GTA.UI.Notification.PostMessageText($"Press ~g~{Settings.MenuKey}~s~ to open the menu.", new GTA.Graphics.TextureAsset("CHAR_ALL_PLAYERS_CONF", "CHAR_ALL_PLAYERS_CONF"), false, GTA.UI.FeedTextIcon.Message, "RAGECOOP", "Welcome!");
#endif
}
@ -161,7 +141,9 @@ namespace RageCoop.Client
}
catch (Exception ex)
{
#if DEBUG
Main.Logger.Error(ex);
#endif
}
if (Networking.ShowNetworkInfo)
@ -188,7 +170,7 @@ namespace RageCoop.Client
P.Health = 1;
Game.Player.WantedLevel = 0;
Main.Logger.Debug("Player died.");
Scripting.API.Events.InvokePlayerDied();
Scripting.API.Events.InvokePlayerDied(KillMessage());
}
GTA.UI.Screen.StopEffects();
}
@ -199,7 +181,7 @@ namespace RageCoop.Client
}
else if (P.IsDead && !_lastDead)
{
Scripting.API.Events.InvokePlayerDied();
Scripting.API.Events.InvokePlayerDied(KillMessage());
}
_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);
Function.Call(Hash.SET_ENABLE_VEHICLE_SLIPSTREAMING, true);
CoopMenu.ConnectedMenuSetting();
MainChat.Init();
GTA.UI.Notification.PostTicker("~g~Connected!", false);
});
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);
CoopMenu.DisconnectedMenuSetting();
if (reason != "Abort")
GTA.UI.Notification.PostTicker("~r~Disconnected: " + reason, false);
LocalPlayerID = default;
});
Memory.RestorePatches();
DownloadManager.Cleanup();
Voice.ClearAll();
Resources.Unload();
}
private static void DoQueuedActions()
{
@ -334,7 +350,9 @@ namespace RageCoop.Client
}
catch (Exception ex)
{
#if DEBUG
Logger.Error(ex);
#endif
QueuedActions.Remove(action);
}
}
@ -375,5 +393,16 @@ namespace RageCoop.Client
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.Native;
using LemonUI;
using LemonUI.Menus;
using LemonUI.Scaleform;
@ -49,7 +50,7 @@ namespace RageCoop.Client.Menus
{
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;
_passwordItem.Activated += _passwordActivated;
@ -66,17 +67,18 @@ namespace RageCoop.Client.Menus
Menu.AddSubMenu(SettingsMenu.Menu);
Menu.AddSubMenu(DevToolMenu.Menu);
#if DEBUG
Menu.AddSubMenu(DebugMenu.Menu);
Menu.AddSubMenu(UpdateMenu.Menu);
#endif
MenuPool.Add(Menu);
MenuPool.Add(SettingsMenu.Menu);
MenuPool.Add(DevToolMenu.Menu);
#if DEBUG
MenuPool.Add(DebugMenu.Menu);
MenuPool.Add(DebugMenu.DiagnosticMenu);
#endif
MenuPool.Add(ServersMenu.Menu);
MenuPool.Add(UpdateMenu.Menu);
MenuPool.Add(PopUp);
Menu.Add(_aboutItem);
@ -96,6 +98,16 @@ namespace RageCoop.Client.Menus
{
Game.DisableAllControlsThisFrame();
MenuPool.Process();
var scaleform = Scaleform.RequestMovie("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))
{
PopUp.Visible = false;
@ -107,6 +119,8 @@ namespace RageCoop.Client.Menus
return false;
}
Script.Yield();
Game.DisableAllControlsThisFrame();
}
}
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 System.Drawing;
using System;
using System.Drawing;
namespace RageCoop.Client
{
@ -24,7 +25,7 @@ namespace RageCoop.Client
static DebugMenu()
{
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) =>
@ -56,3 +57,4 @@ namespace RageCoop.Client
}
}
#endif

View File

@ -12,9 +12,9 @@ namespace RageCoop.Client
UseMouse = false,
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 secondaryBoneIndexItem = new NativeItem("Secondary bone index");
public static NativeItem clipboardItem = new NativeItem("Copy to clipboard");
@ -22,7 +22,7 @@ namespace RageCoop.Client
static DevToolMenu()
{
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.Checked = false;

View File

@ -1,12 +1,12 @@
using LemonUI.Menus;
using GTA.UI;
using LemonUI.Menus;
using Newtonsoft.Json;
using RageCoop.Core;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Net;
using System.Threading;
using RageCoop.Core;
using GTA.UI;
namespace RageCoop.Client.Menus
{
@ -30,7 +30,7 @@ namespace RageCoop.Client.Menus
static ServersMenu()
{
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) =>
{
@ -76,7 +76,7 @@ namespace RageCoop.Client.Menus
foreach (ServerInfo server in serverList)
{
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) =>
{
try
@ -85,7 +85,7 @@ namespace RageCoop.Client.Menus
if (server.useZT)
{
address = $"{server.ztAddress}:{server.port}";
Notification.Show($"~y~Joining ZeroTier network... {server.ztID}");
Notification.PostTicker($"~y~Joining ZeroTier network... {server.ztID}", false);
if (ZeroTierHelper.Join(server.ztID) == null)
{
throw new Exception("Failed to obtain ZeroTier network IP");
@ -102,10 +102,10 @@ namespace RageCoop.Client.Menus
}
catch (Exception ex)
{
Notification.Show($"~r~{ex.Message}");
Notification.PostTicker($"~r~{ex.Message}", false);
if (server.useZT)
{
Notification.Show($"Make sure ZeroTier is correctly installed, download it from https://www.zerotier.com/");
Notification.PostTicker($"Make sure ZeroTier is correctly installed, download it from https://www.zerotier.com/", false);
}
}
};

View File

@ -17,16 +17,19 @@ 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 _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 _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 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 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 _menuKey = new NativeItem("Menu Key", "The key to open menu", Main.Settings.MenuKey.ToString());
private static readonly NativeItem _passengerKey = new NativeItem("Passenger Key", "The key to enter a vehicle as passenger", Main.Settings.PassengerKey.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());
private static readonly NativeItem _pedSoftLimit = new NativeItem("Ped limit (soft)", "The game won't spawn more NPCs if the limit is exceeded. \n-1 for unlimited (not recommended).", Main.Settings.WorldPedSoftLimit.ToString());
static SettingsMenu()
{
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;
_disablePauseAlt.CheckboxChanged += DisablePauseAltCheckboxChanged;
@ -35,6 +38,17 @@ namespace RageCoop.Client.Menus
_menuKey.Activated += ChaneMenuKey;
_passengerKey.Activated += ChangePassengerKey;
_vehicleSoftLimit.Activated += VehicleSoftLimitActivated;
_pedSoftLimit.Activated += PedSoftLimitActivated;
_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(_disablePauseAlt);
@ -43,6 +57,9 @@ namespace RageCoop.Client.Menus
Menu.Add(_menuKey);
Menu.Add(_passengerKey);
Menu.Add(_vehicleSoftLimit);
Menu.Add(_pedSoftLimit);
Menu.Add(_showBlip);
Menu.Add(_showNametag);
}
private static void DisableVoiceCheckboxChanged(object sender, EventArgs e)
@ -53,7 +70,9 @@ namespace RageCoop.Client.Menus
{
Voice.Init();
}
} else {
}
else
{
Voice.ClearAll();
}
@ -73,7 +92,19 @@ namespace RageCoop.Client.Menus
Main.Settings.WorldVehicleSoftLimit = int.Parse(
Game.GetUserInput(WindowTitle.EnterMessage20,
Main.Settings.WorldVehicleSoftLimit.ToString(), 20));
_menuKey.AltTitle=Main.Settings.WorldVehicleSoftLimit.ToString();
_vehicleSoftLimit.AltTitle = Main.Settings.WorldVehicleSoftLimit.ToString();
Util.SaveSettings();
}
catch { }
}
private static void PedSoftLimitActivated(object sender, EventArgs e)
{
try
{
Main.Settings.WorldPedSoftLimit = int.Parse(
Game.GetUserInput(WindowTitle.EnterMessage20,
Main.Settings.WorldPedSoftLimit.ToString(), 20));
_pedSoftLimit.AltTitle = Main.Settings.WorldPedSoftLimit.ToString();
Util.SaveSettings();
}
catch { }

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; }
public bool Focused
{
get { return CurrentFocused; }
get => CurrentFocused;
set
{
if (value && Hidden)
@ -31,11 +31,12 @@ namespace RageCoop.Client
}
private ulong LastMessageTime { get; set; }
private Keys LastKey { get; set; }
private bool CurrentHidden { get; set; }
private bool Hidden
{
get { return CurrentHidden; }
get => CurrentHidden;
set
{
if (value)
@ -56,7 +57,7 @@ namespace RageCoop.Client
public Chat()
{
MainScaleForm = new Scaleform("multiplayer_chat");
MainScaleForm = Scaleform.RequestMovie("multiplayer_chat");
}
public void Init()
@ -115,6 +116,10 @@ namespace RageCoop.Client
MainScaleForm.CallFunction("PAGE_DOWN");
}
if (key == Keys.Menu && LastKey == Keys.ShiftKey)
ActivateKeyboardLayout(1, 0);
LastKey = key;
string keyChar = GetCharFromKey(key, Game.IsKeyPressed(Keys.ShiftKey), false);
if (keyChar.Length == 0)
@ -174,5 +179,8 @@ namespace RageCoop.Client
ToUnicodeEx((uint)key, 0, keyboardState, buf, 256, 0, InputLanguage.CurrentInputLanguage.Handle);
return buf.ToString();
}
[DllImport("user32.dll")]
public static extern int ActivateKeyboardLayout(int hkl, uint flags);
}
}

View File

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

View File

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

View File

@ -3,9 +3,8 @@ using Lidgren.Network;
using RageCoop.Client.Menus;
using RageCoop.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using GTA.Native;
namespace RageCoop.Client
{
@ -15,7 +14,7 @@ namespace RageCoop.Client
/// <summary>
/// Reduce GC pressure by reusing frequently used packets
/// </summary>
static class ReceivedPackets
private static class ReceivedPackets
{
public static Packets.PedSync PedPacket = new Packets.PedSync();
public static Packets.VehicleSync VehicelPacket = new Packets.VehicleSync();
@ -25,7 +24,7 @@ namespace RageCoop.Client
/// <summary>
/// Used to reslove entity handle in a <see cref="Packets.CustomEvent"/>
/// </summary>
private static readonly Func<byte, BitReader, object> _resolveHandle = (t, reader) =>
private static readonly Func<byte, NetIncomingMessage, object> _resolveHandle = (t, reader) =>
{
switch (t)
{
@ -42,10 +41,11 @@ namespace RageCoop.Client
}
};
private static readonly AutoResetEvent _publicKeyReceived = new AutoResetEvent(false);
private static bool _recycle;
public static void ProcessMessage(NetIncomingMessage message)
{
if (message == null) { return; }
_recycle = true;
switch (message.MessageType)
{
case NetIncomingMessageType.StatusChanged:
@ -62,32 +62,18 @@ namespace RageCoop.Client
case NetConnectionStatus.Connected:
if (message.SenderConnection == ServerConnection)
{
Memory.ApplyPatches();
var response = message.SenderConnection.RemoteHailMessage;
if ((PacketType)response.ReadByte() != PacketType.HandshakeSuccess)
{
throw new Exception("Invalid handshake response!");
}
var p = new Packets.HandshakeSuccess();
p.Deserialize(response.ReadBytes(response.ReadInt32()));
p.Deserialize(response);
foreach (var player in p.Players)
{
PlayerList.SetPlayer(player.ID, player.Username);
}
Main.QueueAction(() =>
{
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 <<");
Main.Connected();
}
else
{
@ -110,19 +96,7 @@ namespace RageCoop.Client
case NetConnectionStatus.Disconnected:
if (message.SenderConnection == ServerConnection)
{
Memory.RestorePatches();
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();
Main.Disconnected(reason);
}
break;
}
@ -142,7 +116,7 @@ namespace RageCoop.Client
int id = message.ReadInt32();
if (PendingResponses.TryGetValue(id, out var callback))
{
callback((PacketType)message.ReadByte(), message.ReadBytes(message.ReadInt32()));
callback((PacketType)message.ReadByte(), message);
PendingResponses.Remove(id);
}
break;
@ -151,57 +125,60 @@ namespace RageCoop.Client
{
int id = message.ReadInt32();
var realType = (PacketType)message.ReadByte();
int len = message.ReadInt32();
if (RequestHandlers.TryGetValue(realType, out var handler))
{
var response = Peer.CreateMessage();
response.Write((byte)PacketType.Response);
response.Write(id);
handler(message.ReadBytes(len)).Pack(response);
handler(message).Pack(response);
Peer.SendMessage(response, ServerConnection, NetDeliveryMethod.ReliableOrdered, message.SequenceChannel);
Peer.FlushSendQueue();
}
else
{
Main.Logger.Debug("Did not find a request handler of type: " + realType);
}
break;
}
default:
{
byte[] data = message.ReadBytes(message.ReadInt32());
HandlePacket(packetType, data,message.SenderConnection);
HandlePacket(packetType, message, message.SenderConnection, ref _recycle);
break;
}
}
}
catch (Exception ex)
{
#if DEBUG
Main.QueueAction(() =>
{
GTA.UI.Notification.Show("~r~~h~Packet Error");
GTA.UI.Notification.Show($"~r~~h~Packet Error {ex.Message}");
return true;
});
Main.Logger.Error($"[{packetType}] {ex.Message}");
Main.Logger.Error(ex);
Peer.Shutdown($"Packet Error [{packetType}]");
#endif
_recycle = false;
}
break;
}
case NetIncomingMessageType.UnconnectedData:
{
var packetType = (PacketType)message.ReadByte();
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
switch (packetType)
{
case PacketType.HolePunch:
{
HolePunch.Punched(data.GetPacket<Packets.HolePunch>(), message.SenderEndPoint);
HolePunch.Punched(message.GetPacket<Packets.HolePunch>(), message.SenderEndPoint);
break;
}
case PacketType.PublicKeyResponse:
{
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);
_publicKeyReceived.Set();
break;
@ -218,41 +195,42 @@ namespace RageCoop.Client
default:
break;
}
if (_recycle)
{
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)
{
case PacketType.HolePunchInit:
HolePunch.Add(data.GetPacket<Packets.HolePunchInit>());
HolePunch.Add(msg.GetPacket<Packets.HolePunchInit>());
break;
case PacketType.PlayerConnect:
PlayerConnect(data.GetPacket<Packets.PlayerConnect>());
PlayerConnect(msg.GetPacket<Packets.PlayerConnect>());
break;
case PacketType.PlayerDisconnect:
PlayerDisconnect(data.GetPacket<Packets.PlayerDisconnect>());
PlayerDisconnect(msg.GetPacket<Packets.PlayerDisconnect>());
break;
case PacketType.PlayerInfoUpdate:
PlayerList.UpdatePlayer(data.GetPacket<Packets.PlayerInfoUpdate>());
PlayerList.UpdatePlayer(msg.GetPacket<Packets.PlayerInfoUpdate>());
break;
case PacketType.VehicleSync:
ReceivedPackets.VehicelPacket.Deserialize(data);
ReceivedPackets.VehicelPacket.Deserialize(msg);
VehicleSync(ReceivedPackets.VehicelPacket);
break;
case PacketType.PedSync:
ReceivedPackets.PedPacket.Deserialize(data);
ReceivedPackets.PedPacket.Deserialize(msg);
PedSync(ReceivedPackets.PedPacket);
break;
case PacketType.ProjectileSync:
ReceivedPackets.ProjectilePacket.Deserialize(data);
ReceivedPackets.ProjectilePacket.Deserialize(msg);
ProjectileSync(ReceivedPackets.ProjectilePacket);
break;
@ -260,7 +238,7 @@ namespace RageCoop.Client
{
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; });
}
@ -271,7 +249,7 @@ namespace RageCoop.Client
if (Main.Settings.Voice)
{
Packets.Voice packet = new Packets.Voice();
packet.Deserialize(data);
packet.Deserialize(msg);
SyncedPed player = EntityPool.GetPedByID(packet.ID);
@ -286,18 +264,20 @@ namespace RageCoop.Client
case PacketType.CustomEvent:
{
Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle);
packet.Deserialize(data);
packet.Deserialize(msg);
Scripting.API.Events.InvokeCustomEventReceived(packet);
}
break;
case PacketType.CustomEventQueued:
{
recycle = false;
Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle);
Main.QueueAction(() =>
{
packet.Deserialize(data);
packet.Deserialize(msg);
Scripting.API.Events.InvokeCustomEventReceived(packet);
Peer.Recycle(msg);
});
}
break;
@ -305,7 +285,7 @@ namespace RageCoop.Client
case PacketType.FileTransferChunk:
{
Packets.FileTransferChunk packet = new Packets.FileTransferChunk();
packet.Deserialize(data);
packet.Deserialize(msg);
DownloadManager.Write(packet.ID, packet.FileChunk);
}
break;
@ -313,8 +293,9 @@ namespace RageCoop.Client
default:
if (packetType.IsSyncEvent())
{
recycle = false;
// Dispatch to script thread
Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, data); return true; });
Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); return true; });
}
break;
}
@ -324,11 +305,16 @@ namespace RageCoop.Client
{
SyncedPed c = EntityPool.GetPedByID(packet.ID);
if (c == null)
{
if (EntityPool.PedsByID.Count(x => x.Value.OwnerID == packet.OwnerID) < Main.Settings.WorldPedSoftLimit / PlayerList.Players.Count ||
/*EntityPool.VehiclesByID.Any(x => x.Value.Position.DistanceTo(packet.Position) < 2) ||*/ // allows players to exceed the peds limit
packet.ID == packet.OwnerID)
{
// Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}");
EntityPool.ThreadSafe.Add(c = new SyncedPed(packet.ID));
}
PedDataFlags flags = packet.Flags;
else return;
}
c.ID = packet.ID;
c.OwnerID = packet.OwnerID;
c.Health = packet.Health;
@ -374,8 +360,14 @@ namespace RageCoop.Client
SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID);
if (v == null)
{
if (EntityPool.VehiclesByID.Count(x => x.Value.OwnerID == packet.OwnerID) < Main.Settings.WorldVehicleSoftLimit / PlayerList.Players.Count ||
EntityPool.PedsByID.Any(x => x.Value.VehicleID == packet.ID || x.Value.Position.DistanceTo(packet.Position) < 2))
{
// Main.Logger.Debug($"Creating vehicle for incoming sync:{packet.ID}");
EntityPool.ThreadSafe.Add(v = new SyncedVehicle(packet.ID));
}
else return;
}
if (v.IsLocal) { return; }
v.ID = packet.ID;
v.OwnerID = packet.OwnerID;
@ -408,7 +400,6 @@ namespace RageCoop.Client
}
private static void ProjectileSync(Packets.ProjectileSync packet)
{
var p = EntityPool.GetProjectileByID(packet.ID);
if (p == null)
{
@ -424,6 +415,7 @@ namespace RageCoop.Client
p.Shooter = packet.Flags.HasProjDataFlag(ProjectileDataFlags.IsShotByVehicle) ?
(SyncedEntity)EntityPool.GetVehicleByID(packet.ShooterID) : EntityPool.GetPedByID(packet.ShooterID);
p.LastSynced = Main.Ticked;
p.LastSyncedStopWatch.Restart();
}
}
}

View File

@ -13,7 +13,7 @@ namespace RageCoop.Client
/// <summary>
/// Reduce GC pressure by reusing frequently used packets
/// </summary>
static class SendPackets
private static class SendPackets
{
public static Packets.PedSync PedPacket = new Packets.PedSync();
public static Packets.VehicleSync VehicelPacket = new Packets.VehicleSync();
@ -126,7 +126,7 @@ namespace RageCoop.Client
packet.Position = veh.ReadPosition();
packet.Velocity = veh.Velocity;
packet.Quaternion = veh.ReadQuaternion();
packet.RotationVelocity=veh.RotationVelocity;
packet.RotationVelocity = veh.LocalRotationVelocity;
packet.ThrottlePower = veh.ThrottlePower;
packet.BrakePower = veh.BrakePower;
v.LastSentStopWatch.Restart();

View File

@ -1,11 +1,11 @@
using GTA;
using GTA.Math;
using GTA.Native;
using Lidgren.Network;
using RageCoop.Core;
using System.Collections.Generic;
using Lidgren.Network;
using System.Net;
using System.Linq;
using System.Net;
namespace RageCoop.Client
{
@ -13,7 +13,7 @@ namespace RageCoop.Client
{
private const float LEFT_POSITION = 0.122f;
private const float RIGHT_POSITION = 0.9f;
private static readonly Scaleform _mainScaleform = new Scaleform("mp_mm_card_freemode");
private static readonly Scaleform _mainScaleform = Scaleform.RequestMovie("mp_mm_card_freemode");
private static ulong _lastUpdate = Util.GetTickCount64();
public static ulong Pressed { get; set; }
@ -63,16 +63,15 @@ namespace RageCoop.Client
public static void SetPlayer(int id, string username, float latency = 0)
{
Main.Logger.Debug($"{id},{username},{latency}");
Player p;
if (Players.TryGetValue(id, out p))
if (Players.TryGetValue(id, out Player p))
{
p.Username = username;
p.PedID=id;
p.ID = id;
p._latencyToServer = latency;
}
else
{
p = new Player { PedID=id, Username=username, _latencyToServer=latency };
p = new Player { ID = id, Username = username, _latencyToServer = latency };
Players.Add(id, p);
}
}
@ -90,7 +89,7 @@ namespace RageCoop.Client
{
p.FakeBlip = World.CreateBlip(p.Position);
}
if (EntityPool.PedExists(p.PedID))
if (EntityPool.PedExists(p.ID))
{
p.FakeBlip.DisplayType = BlipDisplayType.NoDisplay;
}
@ -108,8 +107,7 @@ namespace RageCoop.Client
}
public static Player GetPlayer(int id)
{
Player p;
Players.TryGetValue(id, out p);
Players.TryGetValue(id, out Player p);
return 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 bool IsHost;
public byte HolePunchStatus { get; internal set; } = 1;
public bool IsHost { get; internal set; }
public string Username { get; internal set; }
/// <summary>
/// Universal character ID.
/// Universal ped ID.
/// </summary>
public int PedID
public int ID
{
get; internal set;
}
public IPEndPoint InternalEndPoint { get; set; }
public IPEndPoint ExternalEndPoint { get; set; }
public bool ConnectWhenPunched { get; set; }
public Blip FakeBlip { get; set; }
public Vector3 Position { get; set; }
public SyncedPed Character { get; set; }
public IPEndPoint InternalEndPoint { get; internal set; }
public IPEndPoint ExternalEndPoint { get; internal set; }
internal bool ConnectWhenPunched { get; set; }
public Blip FakeBlip { get; internal set; }
public Vector3 Position { get; internal set; }
public SyncedPed Character { get; internal set; }
/// <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>
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 _latencyToServer = 0;
internal float _latencyToServer = 0;
public bool DisplayNameTag { get; set; } = true;
public NetConnection Connection { get; set; }
public NetConnection Connection { get; internal set; }
public bool HasDirectConnection => Connection?.Status == NetConnectionStatus.Connected;
}
}

View File

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

View File

@ -21,6 +21,7 @@
<OutPutPath>..\bin\Debug\Client</OutPutPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>DEBUG</DefineConstants>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<OutPutPath>..\bin\Release\Client</OutPutPath>
@ -35,7 +36,6 @@
<Compile Include="Menus\Sub\DevToolMenu.cs" />
<Compile Include="Menus\Sub\ServersMenu.cs" />
<Compile Include="Menus\Sub\SettingsMenu.cs" />
<Compile Include="Menus\Sub\UpdateMenu.cs" />
<Compile Include="Networking\Chat.cs" />
<Compile Include="Networking\DownloadManager.cs" />
<Compile Include="Networking\HolePunch.cs" />
@ -55,6 +55,7 @@
<Compile Include="Scripting\Resources.cs" />
<Compile Include="Security.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\SyncedEntity.cs" />
<Compile Include="Sync\Entities\Ped\SyncedPed.cs" />
@ -65,6 +66,7 @@
<Compile Include="Sync\EntityPool.cs" />
<Compile Include="Sync\SyncEvents.cs" />
<Compile Include="Sync\Voice.cs" />
<Compile Include="Util\AddOnDataProvider.cs" />
<Compile Include="Util\Memory.cs" />
<Compile Include="Util\NativeCaller.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">
<HintPath>..\packages\SharpZipLib.1.3.3\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
</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>
<HintPath>..\libs\LemonUI.SHVDN3.dll</HintPath>
</Reference>

View File

@ -1,5 +1,6 @@
#undef DEBUG
using GTA;
using Newtonsoft.Json;
using RageCoop.Core;
using System;
using System.Collections.Generic;
@ -39,7 +40,7 @@ namespace RageCoop.Client.Scripting
/// </summary>
public static string Username
{
get { return Main.Settings.Username; }
get => Main.Settings.Username;
set
{
if (Networking.IsOnServer || string.IsNullOrEmpty(value))
@ -90,7 +91,7 @@ namespace RageCoop.Client.Scripting
/// <summary>
/// The local player is dead
/// </summary>
public static event EmptyEvent OnPlayerDied;
public static event EventHandler<string> OnPlayerDied;
/// <summary>
/// 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 InvokePedSpawned(SyncedPed p) { OnPedSpawned?.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 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());
List<Action<CustomEventReceivedArgs>> handlers;
if (CustomEventHandlers.TryGetValue(p.Hash, out handlers))
if (CustomEventHandlers.TryGetValue(p.Hash, out List<Action<CustomEventReceivedArgs>> handlers))
{
handlers.ForEach((x) => { x.Invoke(args); });
}
@ -160,65 +160,48 @@ namespace RageCoop.Client.Scripting
/// Get the local player's ID
/// </summary>
/// <returns>PlayerID</returns>
public static int LocalPlayerID
{
get { return Main.LocalPlayerID; }
}
public static int LocalPlayerID => Main.LocalPlayerID;
/// <summary>
/// Check if player is connected to a server
/// </summary>
public static bool IsOnServer { get { return Networking.IsOnServer; } }
public static bool IsOnServer => Networking.IsOnServer;
/// <summary>
/// Get an <see cref="System.Net.IPEndPoint"/> that the player is currently connected to, or null if not connected to the server
/// </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>
/// Check if a RAGECOOP menu is visible
/// </summary>
public static bool IsMenuVisible
{
get { return Menus.CoopMenu.MenuPool.AreAnyVisible; }
}
public static bool IsMenuVisible => Menus.CoopMenu.MenuPool.AreAnyVisible;
/// <summary>
/// Check if the RAGECOOP chat is visible
/// </summary>
public static bool IsChatFocused
{
get { return Main.MainChat.Focused; }
}
public static bool IsChatFocused => Main.MainChat.Focused;
/// <summary>
/// Check if the RAGECOOP list of players is visible
/// </summary>
public static bool IsPlayerListVisible
{
get { return Util.GetTickCount64() - PlayerList.Pressed < 5000; }
}
public static bool IsPlayerListVisible => Util.GetTickCount64() - PlayerList.Pressed < 5000;
/// <summary>
/// Get the version of RAGECOOP
/// </summary>
public static Version CurrentVersion
{
get { return Main.Version; }
}
public static Version CurrentVersion => Main.Version;
/// <summary>
/// Get a <see cref="Core.Logger"/> that RAGECOOP is currently using.
/// </summary>
/// <returns></returns>
public static Logger Logger
{
get
{
return Main.Logger;
}
}
public static Logger Logger => Main.Logger;
/// <summary>
/// Get all players indexed by their ID
/// </summary>
public static Dictionary<int, Player> Players => new Dictionary<int, Player>(PlayerList.Players);
#endregion
#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>
/// Send a local chat message to this player
/// </summary>

View File

@ -16,7 +16,7 @@ namespace RageCoop.Client.Scripting
{
API.Events.OnPedDeleted += (s, p) => { API.SendCustomEvent(CustomEvents.OnPedDeleted, 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.SetDisplayNameTag, SetDisplayNameTag);
@ -31,7 +31,7 @@ namespace RageCoop.Client.Scripting
API.RegisterCustomEventHandler(CustomEvents.UpdatePedBlip, UpdatePedBlip);
API.RegisterCustomEventHandler(CustomEvents.IsHost, (e) => { _isHost = (bool)e.Args[0]; });
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.PostTicker((string)e.Args[0], false); });
Task.Run(() =>
{
while (true)
@ -42,12 +42,11 @@ namespace RageCoop.Client.Scripting
{
unsafe
{
var time = World.CurrentTimeOfDay;
int weather1 = default(int);
int weather2 = default(int);
float percent2 = default(float);
Function.Call(Hash._GET_WEATHER_TYPE_TRANSITION, &weather1, &weather2, &percent2);
API.SendCustomEvent(CustomEvents.WeatherTimeSync, time.Hours, time.Minutes, time.Seconds, weather1, weather2, percent2);
Function.Call(Hash.GET_CURR_WEATHER_STATE, &weather1, &weather2, &percent2);
API.SendCustomEvent(CustomEvents.WeatherTimeSync, GTA.Chrono.GameClock.Hour, GTA.Chrono.GameClock.Minute, GTA.Chrono.GameClock.Second, weather1, weather2, percent2);
}
});
}
@ -59,8 +58,10 @@ namespace RageCoop.Client.Scripting
private void WeatherTimeSync(CustomEventReceivedArgs e)
{
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]);
GTA.Chrono.GameClock.Hour = (int)e.Args[0];
GTA.Chrono.GameClock.Minute = (int)e.Args[1];
GTA.Chrono.GameClock.Second = (int)e.Args[2];
Function.Call(Hash.SET_CURR_WEATHER_STATE, (int)e.Args[3], (int)e.Args[4], (float)e.Args[5]);
}
private void SetDisplayNameTag(CustomEventReceivedArgs e)
@ -127,8 +128,7 @@ namespace RageCoop.Client.Scripting
var pos = (Vector3)obj.Args[4];
int rot = (int)obj.Args[5];
var name = (string)obj.Args[6];
Blip blip;
if (!EntityPool.ServerBlips.TryGetValue(id, out blip))
if (!EntityPool.ServerBlips.TryGetValue(id, out Blip blip))
{
EntityPool.ServerBlips.Add(id, blip = World.CreateBlip(pos));
}

View File

@ -30,7 +30,7 @@ namespace RageCoop.Client.Scripting
/// <summary>
/// Eqivalent of <see cref="ClientResource.Logger"/> in <see cref="CurrentResource"/>
/// </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
{
private readonly List<ClientResource> LoadedResources = new List<ClientResource>();
private const string BaseScriptType = "RageCoop.Client.Scripting.ClientScript";
private Logger Logger { get; set; }
public Resources()
{
BaseScriptType = "RageCoop.Client.Scripting.ClientScript";
Logger = Main.Logger;
}
private void StartAll()
@ -106,9 +108,6 @@ namespace RageCoop.Client.Scripting
}
LoadedResources.Clear();
}
private List<ClientResource> LoadedResources = new List<ClientResource>();
private string BaseScriptType;
public Logger Logger { get; set; }
private void LoadResource(ZipFile file, string dataFolderRoot)
{

View File

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

View File

@ -22,7 +22,7 @@ namespace RageCoop.Client
/// <summary>
/// Don't use it!
/// </summary>
public string MasterServer { get; set; } = "https://masterserver.ragecoop.online/";
public string MasterServer { get; set; } = "https://masterserver.ragecoop.com/";
/// <summary>
/// Don't use it!
/// </summary>
@ -51,7 +51,7 @@ namespace RageCoop.Client
/// <summary>
/// Disable world NPC traffic, mission entities won't be affected
/// </summary>
public bool DisableTraffic { get; set; } = true;
public bool DisableTraffic { get; set; } = false;
/// <summary>
/// Bring up pause menu but don't freeze time when FrontEndPauseAlternate(Esc) is pressed.
@ -67,6 +67,7 @@ namespace RageCoop.Client
/// The game won't spawn more NPC traffic if the limit is exceeded. -1 for unlimited (not recommended).
/// </summary>
public int WorldPedSoftLimit { get; set; } = 30;
/// <summary>
/// The directory where log and resources downloaded from server will be placed.
/// </summary>
@ -76,5 +77,15 @@ namespace RageCoop.Client
/// Show the owner name of the entity you're aiming at
/// </summary>
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)-1074790547):
case unchecked((uint)2132975508):
case unchecked(2132975508):
case unchecked((uint)-2084633992):
case unchecked((uint)-952879014):
case unchecked((uint)100416529):
case unchecked(100416529):
case unchecked((uint)WeaponHash.Gusenberg):
case unchecked((uint)WeaponHash.MG):
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>
public partial class SyncedPed : SyncedEntity
{
#region CONSTRUCTORS
/// <summary>
/// Create a local entity (outgoing sync)
@ -29,8 +28,8 @@ namespace RageCoop.Client
MainPed = p;
OwnerID = Main.LocalPlayerID;
Function.Call(Hash._SET_PED_CAN_PLAY_INJURED_ANIMS, false);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true);
//Function.Call(Hash.SET_PED_IS_IGNORED_BY_AUTO_OPEN_DOORS, false);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisableHurt, true);
// MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableMelee, true);
}
@ -43,75 +42,6 @@ namespace RageCoop.Client
ID = id;
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()
{
@ -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 = null;
}
else if (((byte)BlipColor != 255) && PedBlip==null)
else if ((byte)BlipColor != 255 && PedBlip == null)
{
PedBlip = MainPed.AddBlip();
@ -210,6 +141,12 @@ namespace RageCoop.Client
}
}
if (!IsPlayer && Health <= 0 && !MainPed.IsDead)
{
MainPed.Kill();
return;
}
if (Speed >= 4)
{
DisplayInVehicle();
@ -240,7 +177,7 @@ namespace RageCoop.Client
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;
}
@ -274,7 +211,7 @@ namespace RageCoop.Client
MainPed = null;
}
if (PedBlip != null && PedBlip.Exists())
if (PedBlip != null)
{
PedBlip.Delete();
PedBlip = null;
@ -305,19 +242,18 @@ namespace RageCoop.Client
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_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);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DrownsInWater, false);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableExplosionReactions, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_AvoidTearGas, false);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_IgnoreBeingOnFire, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableEvasiveDives, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisablePanicInVehicle, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_BlockNonTemporaryEvents, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableShockingEvents, true);
MainPed.SetConfigFlag((int)PedConfigFlags.CPED_CONFIG_FLAG_DisableHurt, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.DrownsInWater, false);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisableHurt, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisableExplosionReactions, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.AvoidTearGas, false);
MainPed.SetConfigFlag(PedConfigFlagToggles.IgnoreBeingOnFire, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisableEvasiveDives, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisablePanicInVehicle, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.BlockNonTemporaryEvents, true);
MainPed.SetConfigFlag(PedConfigFlagToggles.DisableShockingEvents, true);
SetClothes();
@ -343,9 +279,6 @@ namespace RageCoop.Client
}
#region ONFOOT
private string[] _currentAnimation = new string[2] { "", "" };
private void DisplayOnFoot()
{
@ -492,7 +425,7 @@ namespace RageCoop.Client
}
_lastIsJumping = false;
if (IsRagdoll || Health==0)
if (IsRagdoll || (IsPlayer && Health == 0))
{
if (!MainPed.IsRagdoll)
{
@ -506,8 +439,6 @@ namespace RageCoop.Client
}
return;
}
else
{
if (MainPed.IsRagdoll)
{
if (Speed == 0)
@ -518,10 +449,8 @@ namespace RageCoop.Client
{
MainPed.Task.ClearAllImmediately();
}
return;
}
_lastRagdoll = false;
return;
}
if (IsReloading)
@ -581,12 +510,12 @@ namespace RageCoop.Client
}
}
#region WEAPON
private void CheckCurrentWeapon()
{
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();
_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; }
@ -616,7 +545,7 @@ namespace RageCoop.Client
{
if (Velocity == default)
{
MainPed.Task.AimAt(AimCoords, 1000);
MainPed.Task.AimGunAtPosition(AimCoords, 1000);
}
else
{
@ -627,9 +556,7 @@ namespace RageCoop.Client
}
SmoothTransition();
}
#endregion
private bool LastMoving;
private void WalkTo()
{
MainPed.Task.ClearAll();
@ -676,6 +603,8 @@ namespace RageCoop.Client
MainPed.Task.StandStill(2000);
LastMoving = false;
}
if (MainPed.IsTaskActive(TaskType.CTaskDiveToGround)) MainPed.Task.ClearAll();
break;
}
SmoothTransition();
@ -750,10 +679,6 @@ namespace RageCoop.Client
}
}
#endregion
private void DisplayInVehicle()
{
if (CurrentVehicle?.MainVehicle == null) { return; }
@ -796,7 +721,7 @@ namespace RageCoop.Client
case 5:
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;
case 6:

View File

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

View File

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

View File

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

View File

@ -4,8 +4,7 @@ using GTA.Native;
using RageCoop.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
namespace RageCoop.Client
{
@ -31,7 +30,9 @@ namespace RageCoop.Client
SetUpFixedData();
}
private void SetUpFixedData(){
internal void SetUpFixedData()
{
if (MainVehicle == null) { return; }
IsAircraft = MainVehicle.IsAircraft;
IsMotorcycle = MainVehicle.IsMotorcycle;
@ -141,7 +142,7 @@ namespace RageCoop.Client
if (LightsOn != MainVehicle.AreLightsOn)
{
MainVehicle.AreLightsOn = LightsOn;
MainVehicle.SetScriptedLightSetting(LightsOn ? ScriptedVehicleLightSetting.SetVehicleLightsOn : ScriptedVehicleLightSetting.SetVehicleLightsOff);
}
if (HighBeamsOn != MainVehicle.AreHighBeamsOn)
@ -149,8 +150,6 @@ namespace RageCoop.Client
MainVehicle.AreHighBeamsOn = HighBeamsOn;
}
if (IsAircraft)
{
if (LandingGear != (byte)MainVehicle.LandingGearState)
@ -184,10 +183,12 @@ namespace RageCoop.Client
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));
}
if(HasParachute && Flags.HasFlag(VehicleDataFlags.IsParachuteActive) != MainVehicle.IsParachuteActive()){
if (HasParachute && Flags.HasFlag(VehicleDataFlags.IsParachuteActive) != MainVehicle.IsParachuteActive())
{
MainVehicle.SetParachuteActive(Flags.HasFlag(VehicleDataFlags.IsParachuteActive));
}
if (IsSubmarineCar)
@ -197,13 +198,13 @@ namespace RageCoop.Client
if (!_lastTransformed)
{
_lastTransformed = true;
Function.Call(Hash._TRANSFORM_VEHICLE_TO_SUBMARINE, MainVehicle.Handle, false);
Function.Call(Hash.TRANSFORM_TO_SUBMARINE, MainVehicle.Handle, false);
}
}
else if (_lastTransformed)
{
_lastTransformed = false;
Function.Call(Hash._TRANSFORM_SUBMARINE_TO_VEHICLE, MainVehicle.Handle, false);
Function.Call(Hash.TRANSFORM_TO_CAR, MainVehicle.Handle, false);
}
}
else if (IsDeluxo)
@ -260,7 +261,8 @@ namespace RageCoop.Client
}
LastUpdated = Main.Ticked;
}
void DisplayVehicle()
private void DisplayVehicle()
{
_predictedPosition = Predict(Position);
var current = MainVehicle.ReadPosition();
@ -274,7 +276,7 @@ namespace RageCoop.Client
MainVehicle.Quaternion = Quaternion;
return;
}
else if (dist > 0.03)
if (dist > 0.03)
{
MainVehicle.Velocity = Velocity + cali;
}
@ -283,13 +285,10 @@ namespace RageCoop.Client
if (IsFlipped || (calirot = GetCalibrationRotation()).Length() > 50)
{
MainVehicle.Quaternion = Quaternion.Slerp(MainVehicle.ReadQuaternion(), Quaternion, 0.5f);
MainVehicle.RotationVelocity = RotationVelocity;
MainVehicle.LocalRotationVelocity = RotationVelocity;
return;
}
else
{
MainVehicle.RotationVelocity = RotationVelocity + calirot * 0.2f;
}
MainVehicle.LocalRotationVelocity = RotationVelocity + calirot * 0.2f;
}
private Vector3 GetCalibrationRotation()
{
@ -309,6 +308,16 @@ namespace RageCoop.Client
}
private bool CreateVehicle()
{
var existing = World.GetNearbyVehicles(Position, 2).ToList().FirstOrDefault();
if (existing != null && existing != MainVehicle)
{
if (EntityPool.VehiclesByHandle.ContainsKey(existing.Handle))
{
EntityPool.RemoveVehicle(ID);
return false;
}
existing.Delete();
}
MainVehicle?.Delete();
MainVehicle = Util.CreateVehicle(Model, Position);
if (!Model.IsInCdImage)
@ -316,7 +325,7 @@ namespace RageCoop.Client
// GTA.UI.Notification.Show($"~r~(Vehicle)Model ({CurrentVehicleModelHash}) cannot be loaded!");
return false;
}
else if (MainVehicle==null)
if (MainVehicle == null)
{
Model.Request();
return false;
@ -339,43 +348,5 @@ namespace RageCoop.Client
Model.MarkAsNoLongerNeeded();
return true;
}
#region -- PEDALING --
/*
* Thanks to @oldnapalm.
*/
private string PedalingAnimDict()
{
switch ((VehicleHash)Model)
{
case VehicleHash.Bmx:
return "veh@bicycle@bmx@front@base";
case VehicleHash.Cruiser:
return "veh@bicycle@cruiserfront@base";
case VehicleHash.Scorcher:
return "veh@bicycle@mountainfront@base";
default:
return "veh@bicycle@roadfront@base";
}
}
private string PedalingAnimName(bool fast)
{
return fast ? "fast_pedal_char" : "cruise_pedal_char";
}
private void StartPedalingAnim(bool fast)
{
MainVehicle.Driver?.Task.PlayAnimation(PedalingAnimDict(), PedalingAnimName(fast), 8.0f, -8.0f, -1, AnimationFlags.Loop | AnimationFlags.AllowRotation, 1.0f);
}
private void StopPedalingAnim(bool fast)
{
MainVehicle.Driver.Task.ClearAnimation(PedalingAnimDict(), PedalingAnimName(fast));
}
#endregion
}
}

View File

@ -1,18 +1,17 @@
using GTA;
using GTA.Native;
using Lidgren.Network;
using RageCoop.Client.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using Lidgren.Network;
namespace RageCoop.Client
{
internal class EntityPool
{
public static object PedsLock = new object();
public static int CharactersCount { get { return PedsByID.Count; } }
#if BENCHMARK
private static Stopwatch PerfCounter=new Stopwatch();
private static Stopwatch PerfCounter2=Stopwatch.StartNew();
@ -44,15 +43,15 @@ namespace RageCoop.Client
#endregion
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; }
RemovePed(id);
if ((keepPlayer && (ped.ID == Main.LocalPlayerID)) || (keepMine && (ped.OwnerID == Main.LocalPlayerID))) { continue; }
RemovePed(ped.ID);
}
PedsByID.Clear();
PedsByHandle.Clear();
foreach (int id in new List<int>(VehiclesByID.Keys))
foreach (int id in VehiclesByID.Keys.ToArray())
{
if (keepMine && (VehiclesByID[id].OwnerID == Main.LocalPlayerID)) { continue; }
RemoveVehicle(id);
@ -278,8 +277,8 @@ namespace RageCoop.Client
{
ProjectilesByHandle.Remove(p.Handle);
}
Main.Logger.Debug($"Removing projectile {sp.ID}. Reason:{reason}");
p.Explode();
//Main.Logger.Debug($"Removing projectile {sp.ID}. Reason:{reason}");
if (sp.Exploded) p.Explode();
}
ProjectilesByID.Remove(id);
}
@ -289,11 +288,11 @@ namespace RageCoop.Client
public static bool VehicleExists(int id) => VehiclesByID.ContainsKey(id);
public static bool ProjectileExists(int id) => ProjectilesByID.ContainsKey(id);
#endregion
static int vehStateIndex;
static int pedStateIndex;
static int vehStatesPerFrame;
static int pedStatesPerFrame;
static int i;
private static int vehStateIndex;
private static int pedStateIndex;
private static int vehStatesPerFrame;
private static int pedStatesPerFrame;
private static int i;
public static Ped[] allPeds = new Ped[0];
public static Vehicle[] allVehicles = new Vehicle[0];
public static Projectile[] allProjectiles = new Projectile[0];
@ -310,17 +309,6 @@ namespace RageCoop.Client
allProjectiles = World.GetAllProjectiles();
vehStatesPerFrame = allVehicles.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
Debug.TimeStamps[TimeStamp.GetAllEntities]=PerfCounter.ElapsedTicks;
@ -345,7 +333,7 @@ namespace RageCoop.Client
if (p.MainProjectile.AttachedEntity == null)
{
// 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;
}
@ -370,22 +358,25 @@ namespace RageCoop.Client
lock (PedsLock)
{
EntityPool.AddPlayer();
AddPlayer();
var mainCharacters = new List<PedHash> { PedHash.Michael, PedHash.Franklin, PedHash.Franklin02, PedHash.Trevor };
foreach (Ped p in allPeds)
{
SyncedPed c = EntityPool.GetPedByHandle(p.Handle);
if (c==null && (p!=Game.Player.Character))
if (!PedsByHandle.ContainsKey(p.Handle) && p != Game.Player.Character && !mainCharacters.Contains((PedHash)p.Model.Hash))
{
if (allPeds.Length>Main.Settings.WorldPedSoftLimit && p.PopulationType != EntityPopulationType.RandomAmbient)
if (PedsByID.Count(x => x.Value.IsLocal) > Main.Settings.WorldPedSoftLimit)
{
if (p.PopulationType == EntityPopulationType.RandomAmbient && !p.IsInVehicle())
{
p.Delete();
continue;
}
if (p.PopulationType == EntityPopulationType.RandomScenario) continue;
}
// Main.Logger.Trace($"Creating SyncEntity for ped, handle:{p.Handle}");
c=new SyncedPed(p);
EntityPool.Add(c);
Add(new SyncedPed(p));
}
}
#if BENCHMARK
@ -404,7 +395,7 @@ namespace RageCoop.Client
i++;
if ((c.MainPed != null) && (!c.MainPed.Exists()))
{
EntityPool.RemovePed(c.ID, "non-existent");
RemovePed(c.ID, "non-existent");
continue;
}
@ -441,27 +432,25 @@ namespace RageCoop.Client
Debug.TimeStamps[TimeStamp.PedTotal]=PerfCounter.ElapsedTicks;
#endif
}
var check = Main.Ticked % 100 == 0;
i = -1;
lock (VehiclesLock)
{
foreach (Vehicle veh in allVehicles)
{
if (!VehiclesByHandle.ContainsKey(veh.Handle))
{
if (allVehicles.Length>Main.Settings.WorldVehicleSoftLimit)
if (VehiclesByID.Count(x => x.Value.IsLocal) > Main.Settings.WorldVehicleSoftLimit)
{
var type = veh.PopulationType;
if (type==EntityPopulationType.RandomAmbient || type==EntityPopulationType.RandomParked)
if (veh.PopulationType == EntityPopulationType.RandomAmbient || veh.PopulationType == EntityPopulationType.RandomParked)
{
foreach (var p in veh.Occupants)
{
p.Delete();
var c = EntityPool.GetPedByHandle(p.Handle);
var c = GetPedByHandle(p.Handle);
if (c != null)
{
EntityPool.RemovePed(c.ID, "ThrottleTraffic");
RemovePed(c.ID, "ThrottleTraffic");
}
}
veh.Delete();
@ -488,10 +477,13 @@ namespace RageCoop.Client
i++;
if ((v.MainVehicle != null) && (!v.MainVehicle.Exists()))
{
EntityPool.RemoveVehicle(v.ID, "non-existent");
RemoveVehicle(v.ID, "non-existent");
continue;
}
if (check)
{
v.SetUpFixedData();
}
// Outgoing sync
if (v.IsLocal)
{
@ -516,7 +508,8 @@ namespace RageCoop.Client
}
Networking.Peer.FlushSendQueue();
}
static void UpdateTargets()
private static void UpdateTargets()
{
Networking.Targets = new List<NetConnection>(PlayerList.Players.Count) { Networking.ServerConnection };
foreach (var p in PlayerList.Players.Values.ToArray())
@ -581,21 +574,21 @@ namespace RageCoop.Client
{
public static void Add(SyncedVehicle v)
{
lock (EntityPool.VehiclesLock)
lock (VehiclesLock)
{
EntityPool.Add(v);
}
}
public static void Add(SyncedPed p)
{
lock (EntityPool.PedsLock)
lock (PedsLock)
{
EntityPool.Add(p);
}
}
public static void Add(SyncedProjectile sp)
{
lock (EntityPool.ProjectilesLock)
lock (ProjectilesLock)
{
EntityPool.Add(sp);
}

View File

@ -1,10 +1,8 @@
using GTA;
using GTA.Math;
using Lidgren.Network;
using RageCoop.Core;
using System;
using System.Threading;
using System.Threading.Tasks;
using Lidgren.Network;
namespace RageCoop.Client
{
@ -73,9 +71,8 @@ namespace RageCoop.Client
#region HANDLE
public static ParticleEffectAsset CorePFXAsset = new ParticleEffectAsset("core");
static WeaponAsset _weaponAsset = default;
static uint _lastWeaponHash;
private static WeaponAsset _weaponAsset = default;
private static uint _lastWeaponHash;
private static void HandlePedKilled(Packets.PedKilled p)
{
@ -129,7 +126,7 @@ namespace RageCoop.Client
}
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 (_lastWeaponHash != weaponHash)
{
@ -138,7 +135,7 @@ namespace RageCoop.Client
_lastWeaponHash = weaponHash;
}
if (!_weaponAsset.IsLoaded) { _weaponAsset.Request(); }
World.ShootBullet(start, end, p, _weaponAsset, (int)p.GetWeaponDamage(weaponHash));
World.ShootSingleBullet(start, end, (int)p.GetWeaponDamage(weaponHash), _weaponAsset, p);
Prop w;
if (((w = p.Weapons.CurrentWeaponObject) != null) && (p.VehicleWeapon == VehicleWeaponHash.Invalid))
{
@ -162,44 +159,39 @@ namespace RageCoop.Client
WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash),
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)
{
case PacketType.BulletShot:
{
Packets.BulletShot p = new Packets.BulletShot();
p.Deserialize(data);
p.Deserialize(msg);
HandleBulletShot(p.StartPosition, p.EndPosition, p.WeaponHash, p.OwnerID);
break;
}
case PacketType.VehicleBulletShot:
{
HandleVehicleBulletShot(data.GetPacket<Packets.VehicleBulletShot>());
HandleVehicleBulletShot(msg.GetPacket<Packets.VehicleBulletShot>());
break;
}
case PacketType.OwnerChanged:
{
Packets.OwnerChanged packet = new Packets.OwnerChanged();
packet.Deserialize(data);
HandleOwnerChanged(packet);
HandleOwnerChanged(msg.GetPacket<Packets.OwnerChanged>());
}
break;
case PacketType.PedKilled:
{
var packet = new Packets.PedKilled();
packet.Deserialize(data);
HandlePedKilled(packet);
HandlePedKilled(msg.GetPacket<Packets.PedKilled>());
}
break;
case PacketType.NozzleTransform:
{
var packet = new Packets.NozzleTransform();
packet.Deserialize(data);
HandleNozzleTransform(packet);
HandleNozzleTransform(msg.GetPacket<Packets.NozzleTransform>());
break;
}
}
Networking.Peer.Recycle(msg);
}
#endregion

View File

@ -1,6 +1,5 @@
using System.Threading;
using NAudio.Wave;
using NAudio.Wave;
using System.Threading;
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.Collections.Generic;
using GTA.Math;
using GTA;
using SHVDN;
using RageCoop.Core;
using System.Runtime.InteropServices;
namespace RageCoop.Client
{
internal unsafe class MemPatch{
private byte[] _data;
private byte[] _orginal;
private IntPtr _address;
internal unsafe class MemPatch
{
private readonly byte[] _data;
private readonly byte[] _orginal;
private readonly IntPtr _address;
public MemPatch(byte* address, byte[] data)
{
_data = data;
@ -39,7 +40,7 @@ internal static unsafe class Memory
{
// Weapon/radio wheel slow-mo patch
// Thanks @CamxxCore, https://github.com/CamxxCore/GTAVWeaponWheelMod
var result = NativeMemory.FindPattern("\x38\x51\x64\x74\x19", "xxxxx");
var result = MemScanner.FindPatternBmh("\x38\x51\x64\x74\x19", "xxxxx");
if (result == null) { throw new NotSupportedException("Can't find memory pattern to patch weapon/radio slow-mo"); }
var address = result + 26;
address = address + *(int*)address + 4u;
@ -68,8 +69,8 @@ internal static unsafe class Memory
public const int MatrixOffset = 96;
#endregion
#region OPCODE
const byte XOR_32_64 = 0x31;
const byte RET = 0xC3;
private const byte XOR_32_64 = 0x31;
private const byte RET = 0xC3;
#endregion
public static Vector3 ReadPosition(this Entity e) => ReadVector3(e.MemoryAddress + PositionOffset);
public static Quaternion ReadQuaternion(this Entity e) => Quaternion.RotationMatrix(e.Matrix);
@ -90,7 +91,7 @@ internal static unsafe class Memory
var foundOffsets = new List<int>(100);
for (int i = 0; i <= range; i++)
{
var val = NativeMemory.ReadFloat(start+i);
var val = MemDataMarshal.ReadFloat(start + i);
if (Math.Abs(val - toSearch) < tolerance)
{
foundOffsets.Add(i);

View File

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

View File

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

View File

@ -6,13 +6,10 @@ using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("RageCoop.Client.Installer")]
namespace RageCoop.Client
@ -204,7 +201,7 @@ namespace RageCoop.Client
return v;
}
public static void ApplyForce(this Entity e, int boneIndex, Vector3 direction, Vector3 rotation = default(Vector3), ForceType forceType = ForceType.MaxForceRot2)
public static void ApplyForce(this Entity e, int boneIndex, Vector3 direction, Vector3 rotation = default(Vector3), ForceType forceType = ForceType.ExternalImpulse)
{
Function.Call(Hash.APPLY_FORCE_TO_ENTITY, e.Handle, forceType, direction.X, direction.Y, direction.Z, rotation.X, rotation.Y, rotation.Z, boneIndex, false, true, true, false, true);
}
@ -219,7 +216,7 @@ namespace RageCoop.Client
#region WIN32
const UInt32 WM_KEYDOWN = 0x0100;
private const UInt32 WM_KEYDOWN = 0x0100;
public static void Reload()
{
string reloadKey = "None";
@ -238,6 +235,7 @@ namespace RageCoop.Client
foreach (var l in lines)
{
var ss = l.Split('=');
ss.ForEach(s => s.Replace(" ", ""));
if (ss.Length > 0 && ss[0] == "ReloadKey")
{
reloadKey = ss[1];
@ -246,7 +244,7 @@ namespace RageCoop.Client
}
lineList.Add("ReloadKey=Insert");
File.WriteAllLines("ScriptHookVDotNet.ini", lineList.ToArray());
GTA.UI.Notification.Show("Reload cannot be performed automatically, please type \"Reload()\" manually in the SHVDN console.");
GTA.UI.Notification.PostTicker("Reload cannot be performed automatically, please type \"Reload()\" manually in the SHVDN console.", false);
}
Keys key = (Keys)Enum.Parse(typeof(Keys), reloadKey, true);
@ -261,14 +259,14 @@ namespace RageCoop.Client
}
catch (Exception ex)
{
GTA.UI.Notification.Show(ex.Message);
GTA.UI.Notification.PostTicker(ex.Message, false);
}
PostMessage(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle, WM_KEYDOWN, (int)key, 0);
}
[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")]

View File

@ -50,47 +50,54 @@ namespace RageCoop.Client
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;
}
if (v.IsAircraft)
{
flags |= VehicleDataFlags.IsAircraft;
}
if (v.IsDeluxo && veh.IsDeluxoHovering())
{
flags |= VehicleDataFlags.IsDeluxoHovering;
}
if (v.HasRoof)
{
flags |= VehicleDataFlags.HasRoof;
}
if (v.HasRocketBoost && veh.IsRocketBoostActive())
{
flags |= VehicleDataFlags.IsRocketBoostActive;
}
if(v.HasParachute && veh.IsParachuteActive()){
if (v.HasParachute && veh.IsParachuteActive())
{
flags |= VehicleDataFlags.IsParachuteActive;
}
if (veh.IsOnFire)
{
flags |= VehicleDataFlags.IsOnFire;
}
return flags;
}
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);
}
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)
{
@ -133,7 +140,6 @@ namespace RageCoop.Client
}
}
// Bursted tires
short burstedTires = 0;
foreach (VehicleWheel wheel in veh.Wheels.GetAllWheels())
@ -168,12 +174,12 @@ namespace RageCoop.Client
}
continue;
}
else if (door.IsBroken)
/*else if (door.IsBroken) // causes break/repair loop in some situations
{
// The vehicle can only fix a door if the vehicle was completely fixed
veh.Repair();
return;
}
}*/
if ((model.OpenedDoors & (byte)(1 << i)) != 0)
{
if ((!door.IsOpen) && (!door.IsBroken))
@ -190,10 +196,10 @@ namespace RageCoop.Client
{
veh.Windows[(VehicleWindowIndex)i].Smash();
}
else if (!veh.Windows[(VehicleWindowIndex)i].IsIntact)
/*else if (!veh.Windows[(VehicleWindowIndex)i].IsIntact) // causes smash/repair loop in some situations
{
veh.Windows[(VehicleWindowIndex)i].Repair();
}
}*/
}
foreach (VehicleWheel wheel in veh.Wheels)
@ -228,16 +234,15 @@ namespace RageCoop.Client
{
if (p.IsSittingInVehicle())
{
ps.Add((int)p.SeatIndex, (int)p.GetSyncEntity().ID);
ps.Add((int)p.SeatIndex, p.GetSyncEntity().ID);
}
}
return ps;
}
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)
{
@ -245,7 +250,7 @@ namespace RageCoop.Client
}
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)
{
@ -253,7 +258,7 @@ namespace RageCoop.Client
}
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)
{
@ -283,8 +288,6 @@ namespace RageCoop.Client
{
Function.Call(Hash.SET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane, ratio);
}
#endregion
}
}

View File

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

View File

@ -1,8 +1,6 @@
using GTA;
using GTA.Native;
using System;
using System.Threading.Tasks;
using System.Threading;
namespace RageCoop.Client
{
@ -22,28 +20,11 @@ namespace RageCoop.Client
{
ChangeTraffic(true);
};
Task.Run(() =>
{
while (true)
{
Thread.Sleep(5000);
Main.QueueAction(() => { ChangeTraffic(_trafficEnabled); });
}
});
}
static bool _trafficEnabled;
private static bool _trafficEnabled;
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)
{
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)
{
@ -94,7 +85,7 @@ namespace RageCoop.Client
{
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_RANDOM_TRAINS, 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.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_RANDOM_TRAINS, 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_DISTANT_CARS_ENABLED, false);
Function.Call(Hash.DISABLE_VEHICLE_DISTANTLIGHTS, true);
if (Networking.IsOnServer)
{
foreach (Ped ped in World.GetAllPeds())
{
if (ped == Game.Player.Character) { continue; }
SyncedPed c = EntityPool.GetPedByHandle(ped.Handle);
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");
ped.CurrentVehicle?.Delete();
ped.Kill();
ped.Delete();
}
}
foreach (Vehicle veh in World.GetAllVehicles())
{
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
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 System.Text;
using System.Linq;
using GTA.Math;
using GTA.Math;
using System.IO;
using System.Text;
namespace RageCoop.Core
{

View File

@ -1,17 +1,18 @@
using System;
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 GTA.Math;
using Lidgren.Network;
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.Client")]
@ -33,43 +34,44 @@ namespace RageCoop.Core
{
return ToIgnore.Contains(name);
}
public static (byte, byte[]) GetBytesFromObject(object obj)
public static void GetBytesFromObject(object obj, NetOutgoingMessage m)
{
switch (obj)
{
case byte _:
return (0x01, new byte[] { (byte)obj });
case short _:
return (0x02, BitConverter.GetBytes((short)obj));
case ushort _:
return (0x03, BitConverter.GetBytes((ushort)obj));
case int _:
return (0x04, BitConverter.GetBytes((int)obj));
case uint _:
return (0x05, BitConverter.GetBytes((uint)obj));
case long _:
return (0x06, BitConverter.GetBytes((long)obj));
case ulong _:
return (0x07, BitConverter.GetBytes((ulong)obj));
case float _:
return (0x08, BitConverter.GetBytes((float)obj));
case bool _:
return (0x09, BitConverter.GetBytes((bool)obj));
case string _:
return (0x10, ((string)obj).GetBytesWithLength());
case Vector3 _:
return (0x11,((Vector3)obj).GetBytes());
case Quaternion _:
return (0x12, ((Quaternion)obj).GetBytes());
case GTA.Model _:
return (0x13, BitConverter.GetBytes((GTA.Model)obj));
case Vector2 _:
return (0x14, ((Vector2)obj).GetBytes());
case Tuple<byte, byte[]> _:
var tup = (Tuple<byte, byte[]>)obj;
return (tup.Item1, tup.Item2);
case byte value:
m.Write((byte)0x01); m.Write(value); break;
case short value:
m.Write((byte)0x02); m.Write(value); break;
case ushort value:
m.Write((byte)0x03); m.Write(value); break;
case int value:
m.Write((byte)0x04); m.Write(value); break;
case uint value:
m.Write((byte)0x05); m.Write(value); break;
case long value:
m.Write((byte)0x06); m.Write(value); break;
case ulong value:
m.Write((byte)0x07); m.Write(value); break;
case float value:
m.Write((byte)0x08); m.Write(value); break;
case bool value:
m.Write((byte)0x09); m.Write(value); break;
case string value:
m.Write((byte)0x10); m.Write(value); break;
case Vector3 value:
m.Write((byte)0x11); m.Write(value); break;
case Quaternion value:
m.Write((byte)0x12); m.Write(value); break;
case GTA.Model value:
m.Write((byte)0x13); m.Write(value); break;
case Vector2 value:
m.Write((byte)0x14); m.Write(value); break;
case byte[] value:
m.Write((byte)0x15); m.WriteByteArray(value); break;
case Tuple<byte, byte[]> value:
m.Write(value.Item1); m.Write(value.Item2); break;
default:
return (0x0, null);
throw new Exception("Unsupported object type: " + obj.GetType());
}
}
public static IPEndPoint StringToEndPoint(string endpointstring)
@ -136,9 +138,8 @@ namespace RageCoop.Core
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.MaxPort)
{
@ -190,7 +191,40 @@ namespace RageCoop.Core
foreach (FileInfo file in source.GetFiles())
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
{
@ -202,74 +236,10 @@ namespace RageCoop.Core
}
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)
{
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)
{
return Encoding.UTF8.GetString(data);
@ -296,17 +266,10 @@ namespace RageCoop.Core
// 16 bytes
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, T existingPacket = null) where T : Packet, new()
public static T GetPacket<T>(this NetIncomingMessage msg) where T : Packet, new()
{
msg.ReadByte();
return GetPacket<T>(msg.ReadBytes(msg.ReadInt32()),existingPacket);
}
public static T GetPacket<T>(this byte[] data, T existingPacket=null) where T : Packet, new()
{
var p = existingPacket??new T();
p.Deserialize(data);
var p = new T();
p.Deserialize(msg);
return p;
}
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)
{
return "{"+string.Join(",",objects)+"}";
return $"{{{string.Join(",", objects)}}}";
}
public static void ForEach<T>(this IEnumerable<T> objects, Action<T> action)
{
@ -482,5 +445,6 @@ namespace RageCoop.Core
{
return IPAddress.Parse(ip);
}
}
}

View File

@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
namespace RageCoop.Core
@ -32,9 +31,9 @@ namespace RageCoop.Core
private StreamWriter logWriter;
private string Buffer = "";
private Thread LoggerThread;
private readonly Thread LoggerThread;
private bool Stopping = false;
private bool FlushImmediately;
private readonly bool FlushImmediately;
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
{
internal static class MathExtensions
{
public const float Deg2Rad = (float)(Math.PI * 2) / 360;
@ -82,14 +81,14 @@ namespace RageCoop.Core
vect = vect.ToRadians();
float rollOver2 = vect.Z * 0.5f;
float sinRollOver2 = (float)Math.Sin((double)rollOver2);
float cosRollOver2 = (float)Math.Cos((double)rollOver2);
float sinRollOver2 = (float)Math.Sin(rollOver2);
float cosRollOver2 = (float)Math.Cos(rollOver2);
float pitchOver2 = vect.Y * 0.5f;
float sinPitchOver2 = (float)Math.Sin((double)pitchOver2);
float cosPitchOver2 = (float)Math.Cos((double)pitchOver2);
float sinPitchOver2 = (float)Math.Sin(pitchOver2);
float cosPitchOver2 = (float)Math.Cos(pitchOver2);
float yawOver2 = vect.X * 0.5f; // pitch
float sinYawOver2 = (float)Math.Sin((double)yawOver2);
float cosYawOver2 = (float)Math.Cos((double)yawOver2);
float sinYawOver2 = (float)Math.Sin(yawOver2);
float cosYawOver2 = (float)Math.Cos(yawOver2);
Quaternion result = new Quaternion()
{
X = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2,
@ -146,16 +145,12 @@ namespace RageCoop.Core
}
private static float CopySign(double x, double y)
{
bool isPositive = y>=0;
if (isPositive)
if (y >= 0)
{
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)
{
@ -163,7 +158,6 @@ namespace RageCoop.Core
}
public static float GetCosTheta(this Vector3 v1, Vector3 v2)
{
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.Text;
using Lidgren.Network;
using System.Threading;
namespace RageCoop.Core
@ -57,6 +56,5 @@ namespace RageCoop.Core
p.Pack(outgoingMessage);
SendMessage(outgoingMessage, cons, method, (int)channel);
}
}
}

View File

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

View File

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

View File

@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
namespace RageCoop.Core
namespace RageCoop.Core
{
internal class ServerInfo
/// <summary>
/// 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 port { get; set; }
public string name { get; set; }

View File

@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.IO;
using System.Diagnostics;
using System.Net;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
namespace RageCoop.Core
@ -93,7 +91,8 @@ namespace RageCoop.Core
}
public static Dictionary<string, ZeroTierNetwork> Networks
{
get {
get
{
Dictionary<string, ZeroTierNetwork> networks = new Dictionary<string, ZeroTierNetwork>();
var p = Run("listnetworks");
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 System.Collections.Generic;
using Lidgren.Network;
using Lidgren.Network;
using System;
namespace RageCoop.Core
{
@ -11,8 +10,8 @@ namespace RageCoop.Core
internal class ChatMessage : Packet
{
public override PacketType Type => PacketType.ChatMessage;
private Func<string, byte[]> crypt;
private Func<byte[], byte[]> decrypt;
private readonly Func<string, byte[]> crypt;
private readonly Func<byte[], byte[]> decrypt;
public ChatMessage(Func<string, byte[]> crypter)
{
crypt = crypter;
@ -25,33 +24,31 @@ namespace RageCoop.Core
public string Message { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
List<byte> byteArray = new List<byte>();
// Write Username
byteArray.AddString(Username);
m.Write(Username);
// Write Message
byteArray.AddArray(crypt(Message));
return byteArray.ToArray();
m.WriteByteArray(crypt(Message));
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read username
Username = reader.ReadString();
Username = m.ReadString();
Message = decrypt(reader.ReadByteArray()).GetString();
Message = decrypt(m.ReadByteArray()).GetString();
#endregion
}
}

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
using Lidgren.Network;
using System;
namespace RageCoop.Core
{
internal partial class Packets
@ -10,85 +8,78 @@ namespace RageCoop.Core
internal class CustomEvent : Packet
{
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;
_queued = queued;
}
private bool _queued;
private Func<byte, BitReader, object> _resolve { get; set; }
private readonly bool _queued;
private Func<byte, NetIncomingMessage, object> _resolve { get; set; }
public int Hash { get; set; }
public object[] Args { get; set; }
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
Args = Args ?? new object[] { };
List<byte> result = new List<byte>();
result.AddInt(Hash);
result.AddInt(Args.Length);
(byte, byte[]) tup;
m.Write(Hash);
m.Write(Args.Length);
foreach (var arg in Args)
{
tup=CoreUtils.GetBytesFromObject(arg);
if (tup.Item1==0||tup.Item2==null)
{
throw new ArgumentException($"Object of type {arg.GetType()} is not supported");
CoreUtils.GetBytesFromObject(arg, m);
}
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];
for (int i = 0; i < len; i++)
{
byte type = reader.ReadByte();
byte type = m.ReadByte();
switch (type)
{
case 0x01:
Args[i]=reader.ReadByte(); break;
Args[i] = m.ReadByte(); break;
case 0x02:
Args[i]=reader.ReadInt32(); break;
Args[i] = m.ReadInt32(); break;
case 0x03:
Args[i]=reader.ReadUInt16(); break;
Args[i] = m.ReadUInt16(); break;
case 0x04:
Args[i]=reader.ReadInt32(); break;
Args[i] = m.ReadInt32(); break;
case 0x05:
Args[i]=reader.ReadUInt32(); break;
Args[i] = m.ReadUInt32(); break;
case 0x06:
Args[i]=reader.ReadInt64(); break;
Args[i] = m.ReadInt64(); break;
case 0x07:
Args[i]=reader.ReadUInt64(); break;
Args[i] = m.ReadUInt64(); break;
case 0x08:
Args[i]=reader.ReadSingle(); break;
Args[i] = m.ReadFloat(); break;
case 0x09:
Args[i]=reader.ReadBoolean(); break;
Args[i] = m.ReadBoolean(); break;
case 0x10:
Args[i]=reader.ReadString(); break;
Args[i] = m.ReadString(); break;
case 0x11:
Args[i]=reader.ReadVector3(); break;
Args[i] = m.ReadVector3(); break;
case 0x12:
Args[i]=reader.ReadQuaternion(); break;
Args[i] = m.ReadQuaternion(); break;
case 0x13:
Args[i]=(GTA.Model)reader.ReadInt32(); break;
Args[i] = (GTA.Model)m.ReadInt32(); break;
case 0x14:
Args[i]=reader.ReadVector2(); break;
Args[i] = m.ReadVector2(); break;
case 0x15:
Args[i] = m.ReadByteArray(); break;
default:
if (_resolve == null)
{
throw new InvalidOperationException($"Unexpected type:{type}\r\n{array.Dump()}");
throw new InvalidOperationException($"Unexpected type: {type}");
}
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;
namespace RageCoop.Core
@ -25,34 +22,30 @@ namespace RageCoop.Core
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
byteArray.AddInt(ID);
m.Write(ID);
// The name of the file
byte[] nameBytes = Encoding.UTF8.GetBytes(Name);
byteArray.AddRange(BitConverter.GetBytes(nameBytes.Length));
byteArray.AddRange(nameBytes);
m.Write(Name);
// The length of the file
byteArray.AddRange(BitConverter.GetBytes(FileLength));
return byteArray.ToArray();
m.Write(FileLength);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
BitReader reader = new BitReader(array);
ID = reader.ReadInt32();
Name = reader.ReadString();
FileLength = reader.ReadInt64();
ID = m.ReadInt32();
Name = m.ReadString();
FileLength = m.ReadInt64();
}
}
@ -61,25 +54,21 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.FileTransferResponse;
public int ID { 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
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();
Response = (FileResponse)reader.ReadByte();
ID = m.ReadInt32();
Response = (FileResponse)m.ReadByte();
}
}
@ -90,27 +79,21 @@ namespace RageCoop.Core
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
byteArray.AddInt(ID);
// The chunk of the file
byteArray.AddInt(FileChunk.Length);
byteArray.AddRange(FileChunk);
return byteArray.ToArray();
m.Write(ID);
m.WriteByteArray(FileChunk);
}
public override void Deserialize(byte[] array)
public override void Deserialize(NetIncomingMessage m)
{
BitReader reader = new BitReader(array);
ID = reader.ReadInt32();
FileChunk = reader.ReadByteArray();
ID = m.ReadInt32();
FileChunk = m.ReadByteArray();
}
}
@ -119,22 +102,20 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.FileTransferComplete;
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
byteArray.AddInt(ID);
return byteArray.ToArray();
m.Write(ID);
}
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

View File

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

View File

@ -1,4 +1,4 @@
using System;
using Lidgren.Network;
using System.Collections.Generic;
namespace RageCoop.Core
@ -12,16 +12,15 @@ namespace RageCoop.Core
{
public int TargetID { get; set; }
public override PacketType Type => PacketType.ConnectionRequest;
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
var data = new List<byte>(10);
data.AddInt(TargetID);
return data.ToArray();
m.Write(TargetID);
}
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 override PacketType Type => PacketType.P2PConnect;
public override byte[] Serialize()
protected override void Serialize(NetOutgoingMessage m)
{
var data = new List<byte>(10);
data.AddInt(ID);
return data.ToArray();
m.Write(ID);
}
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 System.Collections.Generic;
using System.Text;
using Lidgren.Network;
using Newtonsoft.Json;
using GTA.Math;
using Lidgren.Network;
using System;
namespace RageCoop.Core
{
@ -55,14 +51,6 @@ namespace RageCoop.Core
Unknown = 255
}
internal static class PacketExtensions
{
internal static bool IsSyncEvent(this PacketType p)
{
return (30<=(byte)p)&&((byte)p<=40);
}
}
internal enum ConnectionChannel
{
Default = 0,
@ -153,25 +141,19 @@ namespace RageCoop.Core
internal interface IPacket
{
PacketType Type { get; }
byte[] Serialize();
void Deserialize(byte[] data);
void Deserialize(NetIncomingMessage m);
}
internal abstract class Packet : IPacket
{
public abstract PacketType Type { get; }
public virtual byte[] Serialize()
public void Pack(NetOutgoingMessage m)
{
return new byte[0];
}
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);
m.Write((byte)Type);
Serialize(m);
}
protected virtual void Serialize(NetOutgoingMessage m) { }
public virtual void Deserialize(NetIncomingMessage m) { }
}
}

View File

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

View File

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

View File

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

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using GTA.Math;
using Lidgren.Network;
namespace RageCoop.Core
@ -19,44 +16,44 @@ namespace RageCoop.Core
public Vector3 StartPosition { 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
byteArray.AddRange(BitConverter.GetBytes(OwnerID));
m.Write(OwnerID);
// Write weapon hash
byteArray.AddRange(BitConverter.GetBytes(WeaponHash));
m.Write(WeaponHash);
// Write StartPosition
byteArray.AddVector3(StartPosition);
m.Write(StartPosition);
// 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
BitReader reader = new BitReader(array);
// Read OwnerID
OwnerID=reader.ReadInt32();
OwnerID = m.ReadInt32();
// Read WeponHash
WeaponHash=reader.ReadUInt32();
WeaponHash = m.ReadUInt32();
// Read StartPosition
StartPosition=reader.ReadVector3();
StartPosition = m.ReadVector3();
// Read EndPosition
EndPosition=reader.ReadVector3();
EndPosition = m.ReadVector3();
#endregion
}
}

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

using Lidgren.Network;
namespace RageCoop.Core
@ -15,24 +12,24 @@ namespace RageCoop.Core
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
BitReader reader = new BitReader(array);
VehicleID=reader.ReadInt32();
Hover=reader.ReadBoolean();
VehicleID = m.ReadInt32();
Hover = m.ReadBoolean();
#endregion
}

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

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

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

using Lidgren.Network;
namespace RageCoop.Core
@ -14,22 +11,22 @@ namespace RageCoop.Core
public override PacketType Type => PacketType.PedKilled;
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
BitReader reader = new BitReader(array);
VictimID=reader.ReadInt32();
VictimID = m.ReadInt32();
#endregion
}

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using GTA.Math;
using GTA.Math;
using Lidgren.Network;
namespace RageCoop.Core
{
@ -18,31 +16,31 @@ namespace RageCoop.Core
public Vector3 StartPosition { 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
BitReader reader = new BitReader(array);
OwnerID=reader.ReadInt32();
Bone=reader.ReadUInt16();
WeaponHash=reader.ReadUInt32();
StartPosition=reader.ReadVector3();
EndPosition=reader.ReadVector3();
OwnerID = m.ReadInt32();
Bone = m.ReadUInt16();
WeaponHash = m.ReadUInt32();
StartPosition = m.ReadVector3();
EndPosition = m.ReadVector3();
#endregion
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
using System;
using System.Threading;
using System.Collections.Concurrent;
using System.Threading;
namespace RageCoop.Core
{
@ -9,8 +9,8 @@ namespace RageCoop.Core
/// </summary>
public class Worker : IDisposable
{
private SemaphoreSlim _semaphoreSlim;
private Thread _workerThread;
private readonly SemaphoreSlim _semaphoreSlim;
private readonly Thread _workerThread;
private bool _stopping = false;
/// <summary>
/// Name of the worker
@ -81,6 +81,6 @@ namespace RageCoop.Core
Stop();
_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 System.Collections.Generic;
using Lidgren.Network;
using RageCoop.Core;
using Lidgren.Network;
using System.Diagnostics;
using RageCoop.Core.Scripting;
using System.Security.Cryptography;
using RageCoop.Server.Scripting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Security.Cryptography;
namespace RageCoop.Server
{
@ -28,7 +28,7 @@ namespace RageCoop.Server
/// <summary>
/// Th client's IP address and port.
/// </summary>
public IPEndPoint EndPoint { get { return Connection?.RemoteEndPoint; } }
public IPEndPoint EndPoint => Connection?.RemoteEndPoint;
/// <summary>
/// Internal(LAN) address of this client, used for NAT hole-punching
@ -62,23 +62,25 @@ namespace RageCoop.Server
/// <summary>
/// Gets or sets whether to enable automatic respawn for this client's main ped.
/// </summary>
public bool EnableAutoRespawn {
get { return _autoRespawn; }
set {
public bool EnableAutoRespawn
{
get => _autoRespawn;
set
{
BaseScript.SetAutoRespawn(this, value);
_autoRespawn = value;
}
}
private bool _displayNameTag = true;
private Stopwatch _latencyWatch = new Stopwatch();
private readonly Stopwatch _latencyWatch = new Stopwatch();
/// <summary>
/// Gets or sets whether to enable automatic respawn for this client's main ped.
/// </summary>
public bool DisplayNameTag
{
get { return _displayNameTag; }
get => _displayNameTag;
set
{
Server.BaseScript.SetNameTag(this, value);

View File

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

View File

@ -1,12 +1,4 @@
using System;
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
namespace RageCoop.Server
{
internal class HolePunch
{

View File

@ -1,25 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;
using Lidgren.Network;
using Newtonsoft.Json;
using RageCoop.Core;
using RageCoop.Server.Scripting;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using Newtonsoft.Json;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using System.Diagnostics;
using System.Text;
using System.Threading;
namespace RageCoop.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()
{
foreach (var c in ClientsByNetHandle.Values.ToArray())
@ -44,6 +42,7 @@ namespace RageCoop.Server
}
}
private IpInfo IpInfo = null;
private bool CanAnnounce = false;
private void Announce()
{
HttpResponseMessage response = null;
@ -54,7 +53,10 @@ namespace RageCoop.Server
{
// TLS only
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; };
try
@ -77,6 +79,19 @@ namespace RageCoop.Server
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
{
Security.GetPublicKey(out var pModulus, out var pExpoenet);
@ -144,7 +159,7 @@ namespace RageCoop.Server
Thread.Sleep(10 * 60 * 1000);
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); }
HttpHelper.DownloadFile(downloadURL, "Update.zip", null);
Logger?.Info("Installing update");
@ -161,23 +176,12 @@ namespace RageCoop.Server
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()
{
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");
API.SendChatMessage($"Asshole {c.Username} was kicked: Spamming");

View File

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

View File

@ -1,11 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using Lidgren.Network;
using RageCoop.Core;
using RageCoop.Core.Scripting;
using RageCoop.Server.Scripting;
namespace RageCoop.Server
@ -14,12 +8,12 @@ namespace RageCoop.Server
{
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;
if (isPlayer)
{
_worker.QueueJob(() => API.Events.InvokePlayerUpdate(client));
QueueJob(() => API.Events.InvokePlayerUpdate(client));
}
if (Settings.UseP2P) { return; }
@ -49,7 +43,7 @@ namespace RageCoop.Server
}
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;
@ -64,7 +58,6 @@ namespace RageCoop.Server
{
continue;
}
}
else if ((Settings.NpcStreamingDistance != -1) && (packet.Position.DistanceTo(c.Player.Position) > Settings.NpcStreamingDistance))
{
@ -72,12 +65,11 @@ namespace RageCoop.Server
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
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)
{
if (Settings.UseP2P) { return; }
Forward(packet, client, ConnectionChannel.ProjectileSync);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using Lidgren.Network;
using RageCoop.Core;
using RageCoop.Core.Scripting;
using System.Reflection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace RageCoop.Server.Scripting
{
@ -118,8 +117,7 @@ namespace RageCoop.Server.Scripting
internal void InvokeCustomEventReceived(Packets.CustomEvent p, Client sender)
{
var args = new CustomEventReceivedArgs() { Hash = p.Hash, Args = p.Args, Client = sender };
List<Action<CustomEventReceivedArgs>> handlers;
if (CustomEventHandlers.TryGetValue(p.Hash, out handlers))
if (CustomEventHandlers.TryGetValue(p.Hash, out List<Action<CustomEventReceivedArgs>> handlers))
{
handlers.ForEach((x) => { x.Invoke(args); });
}
@ -173,7 +171,7 @@ namespace RageCoop.Server.Scripting
/// <summary>
/// All synchronized entities on this server.
/// </summary>
public ServerEntities Entities { get { return Server.Entities; } }
public ServerEntities Entities => Server.Entities;
#region FUNCTIONS
/// <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>
public void RegisterCustomEventHandler(int hash, Action<CustomEventReceivedArgs> handler)
{
List<Action<CustomEventReceivedArgs>> handlers;
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>>());
}
@ -415,7 +412,7 @@ namespace RageCoop.Server.Scripting
/// <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.
/// </summary>
public Logger Logger { get { return Server.Logger; } }
public Logger Logger => Server.Logger;
/// <summary>
@ -423,8 +420,9 @@ namespace RageCoop.Server.Scripting
/// </summary>
public Client Host
{
get { return Server._hostClient; }
set {
get => Server._hostClient;
set
{
if (Server._hostClient != value)
{
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.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core.Scripting;
using RageCoop.Core;
namespace RageCoop.Server.Scripting
{
@ -41,7 +38,7 @@ namespace RageCoop.Server.Scripting
});
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) =>
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);
}
}
void NativeResponse(CustomEventReceivedArgs e)
private void NativeResponse(CustomEventReceivedArgs e)
{
try
{
int id = (int)e.Args[0];
Action<object> callback;
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]);
e.Client.Callbacks.Remove(id);

View File

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

View File

@ -1,14 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core.Scripting;
using ICSharpCode.SharpZipLib.Zip;
using RageCoop.Core;
using System;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using System.Reflection;
using McMaster.NETCore.Plugins;
using System.Threading.Tasks;
namespace RageCoop.Server.Scripting
{
internal class Resources
@ -22,9 +17,8 @@ namespace RageCoop.Server.Scripting
Server = server;
Logger = server.Logger;
}
private Dictionary<string,Func<Stream>> ClientResources=new();
private Dictionary<string,Func<Stream>> ResourceStreams=new();
private List<MemoryStream> MemStreams = new();
private readonly Dictionary<string, Stream> ClientResources = new();
private readonly Dictionary<string, Stream> ResourceStreams = new();
public void LoadAll()
{
// Packages
@ -33,7 +27,7 @@ namespace RageCoop.Server.Scripting
Directory.CreateDirectory(path);
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);
foreach (ZipEntry e in pkgZip)
{
@ -41,15 +35,13 @@ namespace RageCoop.Server.Scripting
if (e.Name.StartsWith("Client") && e.Name.EndsWith(".res"))
{
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));
}
else if (e.Name.StartsWith("Server") && e.Name.EndsWith(".res"))
{
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));
}
}
@ -91,7 +83,7 @@ namespace RageCoop.Server.Scripting
}
zip.CommitUpdate();
zip.Close();
ClientResources.Add(Path.GetFileNameWithoutExtension(zipPath), () => File.OpenRead(zipPath));
ClientResources.Add(Path.GetFileNameWithoutExtension(zipPath), File.OpenRead(zipPath));
}
catch (Exception ex)
{
@ -105,7 +97,7 @@ namespace RageCoop.Server.Scripting
{
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))
{
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...");
continue;
@ -155,7 +147,7 @@ namespace RageCoop.Server.Scripting
continue;
}
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);
}
catch (Exception ex)
@ -215,7 +207,7 @@ namespace RageCoop.Server.Scripting
}
LoadedResources.Clear();
}
foreach(var s in MemStreams)
foreach (var s in ResourceStreams.Values)
{
try
{
@ -224,13 +216,27 @@ namespace RageCoop.Server.Scripting
}
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)
{
Task.Run(() =>
{
try
{
if (ClientResources.Count != 0)
@ -239,7 +245,7 @@ namespace RageCoop.Server.Scripting
foreach (var rs in ClientResources)
{
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}");
@ -253,6 +259,12 @@ namespace RageCoop.Server.Scripting
{
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 System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GTA;
using GTA.Math;
using RageCoop.Core;
using RageCoop.Core.Scripting;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Security.Cryptography;
using GTA.Math;
using GTA;
namespace RageCoop.Server.Scripting
{
@ -33,68 +30,28 @@ namespace RageCoop.Server.Scripting
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ServerPed GetPedByID(int id)
{
if(Peds.TryGetValue(id,out var ped))
{
return ped;
}
else
{
return null;
}
}
public ServerPed GetPedByID(int id) => Peds.TryGetValue(id, out var ped) ? ped : null;
/// <summary>
/// Get a <see cref="ServerVehicle"/> by it's id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ServerVehicle GetVehicleByID(int id)
{
if (Vehicles.TryGetValue(id, out var veh))
{
return veh;
}
else
{
return null;
}
}
public ServerVehicle GetVehicleByID(int id) => Vehicles.TryGetValue(id, out var veh) ? veh : null;
/// <summary>
/// Get a <see cref="ServerProp"/> owned by server from it's ID.
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ServerProp GetPropByID(int id)
{
if (ServerProps.TryGetValue(id, out var obj))
{
return obj;
}
else
{
return null;
}
}
public ServerProp GetPropByID(int id) => ServerProps.TryGetValue(id, out var obj) ? obj : null;
/// <summary>
/// Get a <see cref="ServerBlip"/> by it's id.
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public ServerBlip GetBlipByID(int id)
{
if (Blips.TryGetValue(id, out var obj))
{
return obj;
}
else
{
return null;
}
}
public ServerBlip GetBlipByID(int id) => Blips.TryGetValue(id, out var obj) ? obj : null;
/// <summary>
/// Create a static prop owned by server.
@ -164,45 +121,32 @@ namespace RageCoop.Server.Scripting
/// Get all peds on this server
/// </summary>
/// <returns></returns>
public ServerPed[] GetAllPeds()
{
return Peds.Values.ToArray();
}
public ServerPed[] GetAllPeds() => Peds.Values.ToArray();
/// <summary>
/// Get all vehicles on this server
/// </summary>
/// <returns></returns>
public ServerVehicle[] GetAllVehicles()
{
return Vehicles.Values.ToArray();
}
public ServerVehicle[] GetAllVehicles() => Vehicles.Values.ToArray();
/// <summary>
/// Get all static prop objects owned by server
/// </summary>
/// <returns></returns>
public ServerProp[] GetAllProps()
{
return ServerProps.Values.ToArray();
}
public ServerProp[] GetAllProps() => ServerProps.Values.ToArray();
/// <summary>
/// Get all blips owned by server
/// </summary>
/// <returns></returns>
public ServerBlip[] GetAllBlips()
{
return Blips.Values.ToArray();
}
public ServerBlip[] GetAllBlips() => Blips.Values.ToArray();
/// <summary>
/// Not thread safe
/// </summary>
internal void Update(Packets.PedSync p, Client sender)
{
ServerPed ped;
if(!Peds.TryGetValue(p.ID,out ped))
if (!Peds.TryGetValue(p.ID, out ServerPed ped))
{
Peds.TryAdd(p.ID, ped = new ServerPed(Server));
ped.ID = p.ID;
@ -229,8 +173,7 @@ namespace RageCoop.Server.Scripting
}
internal void Update(Packets.VehicleSync p, Client sender)
{
ServerVehicle veh;
if (!Vehicles.TryGetValue(p.ID, out veh))
if (!Vehicles.TryGetValue(p.ID, out ServerVehicle veh))
{
Vehicles.TryAdd(p.ID, veh = new ServerVehicle(Server));
veh.ID = p.ID;
@ -277,14 +220,8 @@ namespace RageCoop.Server.Scripting
}
}
internal void RemoveProp(int id)
{
ServerProps.TryRemove(id, out _);
}
internal void RemoveServerBlip(int id)
{
Blips.TryRemove(id, out _);
}
internal void RemoveProp(int id) => ServerProps.TryRemove(id, out _);
internal void RemoveServerBlip(int id) => Blips.TryRemove(id, out _);
internal void RemovePed(int id)
{
Peds.TryRemove(id, out var ped);
@ -299,12 +236,11 @@ namespace RageCoop.Server.Scripting
if (Peds.ContainsKey(ped.ID))
{
Peds[ped.ID] = ped;
return;
}
else
{
Peds.TryAdd(ped.ID, ped);
}
}
internal int RequestNetworkID()
{
int ID = 0;

View File

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

View File

@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RageCoop.Core;
using System.Reflection;
using ICSharpCode.SharpZipLib.Zip;
using McMaster.NETCore.Plugins;
using System.IO;
using RageCoop.Core;
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
{
@ -17,8 +18,22 @@ namespace RageCoop.Server.Scripting
{
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")))
{
PreferSharedTypes = true,
@ -66,6 +81,9 @@ namespace RageCoop.Server.Scripting
}
foreach (var a in assemblies)
{
if (a.Key.Name.ToLower() == r.Name.ToLower() + ".dll")
{
try
{
r.LoadScriptsFromAssembly(a.Key, a.Value);
@ -79,13 +97,16 @@ namespace RageCoop.Server.Scripting
}
}
}
}
return r;
}
internal static ServerResource LoadFrom(Stream input, string name, string tmpDir, string dataFolder, Logger logger = null)
{
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);
return LoadFrom(tmpDir, dataFolder, logger, true);
return LoadFrom(tmpDir, dataFolder, logger);
}
/// <summary>
/// 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
{
@ -35,7 +35,7 @@ namespace RageCoop.Server.Scripting
/// <summary>
/// Eqivalent of <see cref="ServerResource.Logger"/> in <see cref="CurrentResource"/>
/// </summary>
public Core.Logger Logger { get { return CurrentResource.Logger; } }
public Core.Logger Logger => CurrentResource.Logger;
}
/// <summary>
/// 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.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using RageCoop.Core;
using System.Runtime.Serialization;
using System.Net;
using System.Security.Cryptography;
namespace RageCoop.Server
{
@ -18,7 +13,7 @@ namespace RageCoop.Server
Logger = logger;
}
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)
{

View File

@ -28,7 +28,7 @@
/// <summary>
/// The website address to be shown on master server
/// </summary>
public string Website { get; set; } = "https://ragecoop.online/";
public string Website { get; set; } = "https://ragecoop.com/";
/// <summary>
/// The description to be shown on master server
@ -58,7 +58,7 @@
/// <summary>
/// Master server address, mostly doesn't need to be changed.
/// </summary>
public string MasterServer { get; set; } = "https://masterserver.ragecoop.online/";
public string MasterServer { get; set; } = "https://masterserver.ragecoop.com/";
/// <summary>
/// See <see cref="Core.Logger.LogLevel"/>.
@ -119,5 +119,10 @@
/// Kick spamming assholes
/// </summary>
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;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Linq;
using System.Collections.Generic;
global using System.Collections.Generic;
using Lidgren.Network;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Xml;
using System.Xml.Serialization;
namespace RageCoop.Server
{
static partial class Util
internal static partial class Util
{
public static string DownloadString(string url)
@ -35,22 +34,6 @@ namespace RageCoop.Server
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)
{
return new(connections.Where(e => e != toExclude));

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