Add files

This commit is contained in:
sausage
2022-05-22 15:55:26 +08:00
parent c84e9ee146
commit a716db1ac6
80 changed files with 6152 additions and 8642 deletions

View File

@ -1,10 +1,10 @@
using System.Collections.Generic;
#undef DEBUG
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using RageCoop.Core;
using CoopClient.Entities.Player;
namespace CoopClient
namespace RageCoop.Client
{
/// <summary>
/// ?
@ -50,32 +50,32 @@ namespace CoopClient
/// </summary>
public static event ModEvent OnModPacketReceived;
internal static void Connected()
public static void Connected()
{
OnConnection?.Invoke(true, GetLocalNetHandle());
OnConnection?.Invoke(true, GetPlayerID());
}
internal static void Disconnected(string reason)
public static void Disconnected(string reason)
{
OnConnection?.Invoke(false, GetLocalNetHandle(), reason);
OnConnection?.Invoke(false, GetPlayerID(), reason);
}
internal static void Connected(long netHandle)
public static void Connected(long netHandle)
{
OnConnection?.Invoke(true, netHandle);
}
internal static void Disconnected(long netHandle)
public static void Disconnected(long netHandle)
{
OnConnection?.Invoke(false, netHandle);
}
internal static void ModPacketReceived(long from, string mod, byte customID, byte[] bytes)
public static void ModPacketReceived(long from, string mod, byte customID, byte[] bytes)
{
OnModPacketReceived?.Invoke(from, mod, customID, bytes);
}
internal static bool ChatMessageReceived(string from, string message)
public static bool ChatMessageReceived(string from, string message)
{
CancelEventArgs args = new CancelEventArgs(false);
OnChatMessage?.Invoke(from, message, args);
@ -119,44 +119,28 @@ namespace CoopClient
}
/// <summary>
/// Get the local net handle from this Lidgren-Network client when connected to a server
/// Get the local player's ID
/// </summary>
/// <returns>NetHandle</returns>
public static long GetLocalNetHandle()
/// <returns>PlayerID</returns>
public static long GetPlayerID()
{
return Main.LocalNetHandle;
return Main.MyPlayerID;
}
/// <summary>
/// Get all connected player's as a Dictionary.
/// Key = Lidgren-Network net handle.
/// Value = Character handle or null.
/// </summary>
public static Dictionary<long, int?> GetAllPlayers()
{
Dictionary<long, int?> result = new Dictionary<long, int?>();
lock (Main.Players)
{
foreach (KeyValuePair<long, EntitiesPlayer> player in Main.Players.Where(x => x.Key != Main.LocalNetHandle))
{
result.Add(player.Key, player.Value.Character?.Handle);
}
}
return result;
}
/*
/// <summary>
/// Get a player using their Lidgren Network net handle
/// </summary>
/// <param name="handle">Lidgren-Network net handle</param>
public static EntitiesPlayer GetPlayer(long handle)
public static CharacterEntity GetPed(int ID)
{
lock (Main.Players)
lock (Main.Characters)
{
return Main.Players.ContainsKey(handle) ? Main.Players[handle] : null;
return Main.Characters.ContainsKey(ID) ? Main.Characters[ID] : null;
}
}
*/
/// <summary>
/// Check if a RAGECOOP menu is visible
/// </summary>
@ -232,7 +216,7 @@ namespace CoopClient
/// </summary>
public static string GetUsername()
{
return Main.MainSettings.Username;
return Main.Settings.Username;
}
/// <summary>
@ -247,19 +231,11 @@ namespace CoopClient
return false;
}
Main.MainSettings.Username = username;
Main.Settings.Username = username;
return true;
}
/// <summary>
/// Enable or disable sharing of NPCs with other players
/// </summary>
/// <param name="share">true to share NPCs</param>
public static void SetShareNPCs(bool share)
{
Main.ShareNPCsWithPlayers = share;
}
/// <summary>
/// Enable or disable the local traffic for this player

View File

@ -2,13 +2,13 @@
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using RageCoop.Core;
using GTA;
using GTA.Native;
namespace CoopClient
namespace RageCoop.Client
{
internal class Chat
public class Chat
{
private readonly Scaleform MainScaleForm;

54
Client/Debug.cs Normal file
View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RageCoop.Client
{
internal enum TimeStamp
{
AddPeds,
SendPed,
SendPedState,
PedTotal,
UpdatePed,
AddVehicles,
SendVehicle,
SendVehicleState,
UpdateVehicle,
CheckPersistent,
VehicleTotal,
CheckProjectiles,
GetAllEntities,
Receive,
}
internal static class Debug
{
public static Dictionary<TimeStamp, long> TimeStamps = new Dictionary<TimeStamp, long>();
private static int _lastNfHandle;
static Debug()
{
foreach(TimeStamp t in Enum.GetValues(typeof(TimeStamp)))
{
TimeStamps.Add(t, 0);
}
}
public static string Dump(this Dictionary<TimeStamp, long> d)
{
string s = "";
foreach(KeyValuePair<TimeStamp, long> kvp in d)
{
s+=kvp.Key+":"+kvp.Value+"\n";
}
return s;
}
public static void ShowTimeStamps()
{
GTA.UI.Notification.Hide(_lastNfHandle);
_lastNfHandle=GTA.UI.Notification.Show(Debug.TimeStamps.Dump());
}
}
}

View File

@ -2,9 +2,9 @@
using System.Linq;
using System.Collections.Generic;
namespace CoopClient
namespace RageCoop.Client
{
internal static class DownloadManager
public static class DownloadManager
{
private static readonly List<DownloadFile> _downloadFiles = new List<DownloadFile>();
private static readonly Dictionary<byte, FileStream> _streams = new Dictionary<byte, FileStream>();
@ -13,7 +13,7 @@ namespace CoopClient
public static void AddFile(byte id, string name, long length)
{
string downloadFolder = $"scripts\\resources\\{Main.MainSettings.LastServerAddress.Replace(":", ".")}";
string downloadFolder = $"scripts\\resources\\{Main.Settings.LastServerAddress.Replace(":", ".")}";
if (!Directory.Exists(downloadFolder))
{
@ -34,7 +34,7 @@ namespace CoopClient
Cancel(id);
GTA.UI.Notification.Show($"The download of a file from the server was blocked! [{name}]", true);
Logger.Write($"The download of a file from the server was blocked! [{name}]", Logger.LogLevel.Server);
Main.Logger.Error($"The download of a file from the server was blocked! [{name}]");
return;
}
@ -107,7 +107,7 @@ namespace CoopClient
FileStream fs = _streams.FirstOrDefault(x => x.Key == id).Value;
if (fs == null)
{
Logger.Write($"Stream for file {id} not found!", Logger.LogLevel.Server);
Main.Logger.Error($"Stream for file {id} not found!");
return;
}
@ -118,7 +118,7 @@ namespace CoopClient
DownloadFile file = _downloadFiles.FirstOrDefault(x => x.FileID == id);
if (file == null)
{
Logger.Write($"File {id} couldn't be found in the list!", Logger.LogLevel.Server);
Main.Logger.Error($"File {id} couldn't be found in the list!");
return;
}
@ -175,7 +175,7 @@ namespace CoopClient
}
}
internal class DownloadFile
public class DownloadFile
{
public byte FileID { get; set; } = 0;
public string FileName { get; set; } = string.Empty;

View File

@ -1,97 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GTA;
namespace CoopClient.Entities
{
/// <summary>
/// Don't use it!
/// </summary>
public class EntitiesThread : Script
{
/// <summary>
/// Don't use it!
/// </summary>
public EntitiesThread()
{
// Required for some synchronization!
if (Game.Version < GameVersion.v1_0_1290_1_Steam)
{
return;
}
Tick += OnTick;
}
private void OnTick(object sender, EventArgs e)
{
if (Game.IsLoading || !Main.MainNetworking.IsOnServer() || !Main.NPCsAllowed)
{
return;
}
Dictionary<long, NPC.EntitiesNPC> localNPCs = null;
lock (Main.NPCs)
{
localNPCs = new Dictionary<long, NPC.EntitiesNPC>(Main.NPCs);
ulong tickCount = Util.GetTickCount64();
foreach (KeyValuePair<long, NPC.EntitiesNPC> npc in new Dictionary<long, NPC.EntitiesNPC>(localNPCs))
{
if ((tickCount - npc.Value.LastUpdateReceived) > 2500)
{
if (npc.Value.Character != null && npc.Value.Character.Exists() && !npc.Value.Character.IsDead)
{
npc.Value.Character.Kill();
npc.Value.Character.MarkAsNoLongerNeeded();
npc.Value.Character.Delete();
}
if (npc.Value.MainVehicle != null && npc.Value.MainVehicle.Exists() && npc.Value.MainVehicle.IsSeatFree(VehicleSeat.Driver) && npc.Value.MainVehicle.PassengerCount == 0)
{
if (npc.Value.PlayerVehicleHandle != 0)
{
lock (Main.NPCsVehicles)
{
if (Main.NPCsVehicles.ContainsKey(npc.Value.PlayerVehicleHandle))
{
Main.NPCsVehicles.Remove(npc.Value.PlayerVehicleHandle);
}
}
}
if (!npc.Value.MainVehicle.IsDead)
{
npc.Value.MainVehicle.MarkAsNoLongerNeeded();
npc.Value.MainVehicle.Delete();
}
}
localNPCs.Remove(npc.Key);
Main.NPCs.Remove(npc.Key);
}
}
}
foreach (NPC.EntitiesNPC npc in localNPCs.Values)
{
npc.Update();
}
// Only if that player wants to share his NPCs with others
if (Main.ShareNPCsWithPlayers)
{
// Send all npcs from the current player
foreach (Ped ped in World.GetNearbyPeds(Game.Player.Character.Position, 200f) // Get all NPCs around 200f
.Where(p => !p.IsDead && p.Handle != Game.Player.Character.Handle && p.RelationshipGroup != Main.RelationshipGroup)
.OrderBy(p => (p.Position - Game.Player.Character.Position).Length()) // Get the nearest NPCs
.Take(35)) // We shouldn't sync more peds than 35 as the network traffic can be too high for many players
{
Main.MainNetworking.SendNpcData(ped);
}
}
}
}
}

View File

@ -1,159 +0,0 @@
using System.Collections.Generic;
using GTA;
using GTA.Native;
using GTA.Math;
namespace CoopClient.Entities.NPC
{
internal partial class EntitiesNPC
{
internal bool LastSyncWasFull { get; set; } = false;
public ulong LastUpdateReceived { get; set; }
internal Ped Character { get; set; }
internal int Health { get; set; }
private int _lastModelHash = 0;
private int _currentModelHash = 0;
internal int ModelHash
{
get => _currentModelHash;
set
{
_lastModelHash = _lastModelHash == 0 ? value : _currentModelHash;
_currentModelHash = value;
}
}
private Dictionary<byte, short> _lastClothes = null;
internal Dictionary<byte, short> Clothes { get; set; }
internal Vector3 Position { get; set; }
internal Vector3 Velocity { get; set; }
internal Vector3 AimCoords { get; set; }
internal void Update()
{
#region NOT_IN_RANGE
if (!Game.Player.Character.IsInRange(Position, 500f))
{
if (Character != null && Character.Exists())
{
Character.Kill();
Character.MarkAsNoLongerNeeded();
Character.Delete();
Character = null;
}
return;
}
#endregion
#region IS_IN_RANGE
bool characterExist = Character != null && Character.Exists();
if (!characterExist)
{
if (!CreateCharacter())
{
return;
}
}
else if (LastSyncWasFull)
{
if (_currentModelHash != _lastModelHash)
{
Character.Kill();
Character.Delete();
if (!CreateCharacter())
{
return;
}
}
else if (!Clothes.Compare(_lastClothes))
{
SetClothes();
}
}
if (Character.IsDead)
{
if (Health <= 0)
{
return;
}
Character.IsInvincible = true;
Character.Resurrect();
}
else if (Character.Health != Health)
{
Character.Health = Health;
if (Health <= 0 && !Character.IsDead)
{
Character.IsInvincible = false;
Character.Kill();
return;
}
}
if (IsInVehicle)
{
DisplayInVehicle();
}
else
{
DisplayOnFoot();
}
#endregion
}
private bool CreateCharacter()
{
Model characterModel = _currentModelHash.ModelRequest();
if (characterModel == null)
{
//GTA.UI.Notification.Show($"~r~(Character)Model ({CurrentModelHash}) cannot be loaded!");
return false;
}
Character = World.CreatePed(characterModel, Position, Rotation.Z);
characterModel.MarkAsNoLongerNeeded();
Character.RelationshipGroup = Main.RelationshipGroup;
Character.Health = Health;
if (IsInVehicle)
{
Character.IsVisible = false;
}
Character.BlockPermanentEvents = true;
Character.CanRagdoll = false;
Character.IsInvincible = true;
Character.CanSufferCriticalHits = false;
Function.Call(Hash.SET_PED_CAN_EVASIVE_DIVE, Character.Handle, false);
Function.Call(Hash.SET_PED_CAN_BE_TARGETTED, Character.Handle, true);
Function.Call(Hash.SET_PED_CAN_BE_TARGETTED_BY_PLAYER, Character.Handle, Game.Player, true);
Function.Call(Hash.SET_PED_GET_OUT_UPSIDE_DOWN_VEHICLE, Character.Handle, false);
Function.Call(Hash.SET_PED_AS_ENEMY, Character.Handle, false);
Function.Call(Hash.SET_CAN_ATTACK_FRIENDLY, Character.Handle, true, true);
SetClothes();
return true;
}
private void SetClothes()
{
foreach (KeyValuePair<byte, short> cloth in Clothes)
{
Function.Call(Hash.SET_PED_COMPONENT_VARIATION, Character.Handle, cloth.Key, cloth.Value, 0, 0);
}
_lastClothes = Clothes;
}
}
}

View File

@ -1,221 +0,0 @@
using System.Collections.Generic;
using GTA;
using GTA.Native;
using GTA.Math;
namespace CoopClient.Entities.NPC
{
internal partial class EntitiesNPC
{
#region -- VARIABLES --
/// <summary>
/// The latest character rotation (may not have been applied yet)
/// </summary>
public Vector3 Rotation { get; internal set; }
internal byte Speed { get; set; }
private bool _lastIsJumping = false;
internal bool IsJumping { get; set; }
internal bool IsRagdoll { get; set; }
internal bool IsOnFire { get; set; }
internal bool IsAiming { get; set; }
internal bool IsShooting { get; set; }
internal bool IsReloading { get; set; }
internal uint CurrentWeaponHash { get; set; }
private Dictionary<uint, bool> _lastWeaponComponents = null;
internal Dictionary<uint, bool> WeaponComponents { get; set; } = null;
private int _lastWeaponObj = 0;
#endregion
private void DisplayOnFoot()
{
if (Character.IsInVehicle())
{
Character.Task.LeaveVehicle();
}
if (MainVehicle != null)
{
MainVehicle = null;
}
if (IsOnFire && !Character.IsOnFire)
{
Character.IsInvincible = false;
Function.Call(Hash.START_ENTITY_FIRE, Character.Handle);
}
else if (!IsOnFire && Character.IsOnFire)
{
Function.Call(Hash.STOP_ENTITY_FIRE, Character.Handle);
Character.IsInvincible = true;
if (Character.IsDead)
{
Character.Resurrect();
}
}
if (IsJumping && !_lastIsJumping)
{
Character.Task.Jump();
}
_lastIsJumping = IsJumping;
if (IsRagdoll)
{
if (!Character.IsRagdoll)
{
// CanRagdoll = true, inside this function
Character.Ragdoll();
}
return;
}
else if (!IsRagdoll && Character.IsRagdoll)
{
Character.CanRagdoll = false;
Character.Task.ClearAllImmediately();
return;
}
if (IsJumping || IsOnFire)
{
return;
}
if (IsReloading && Character.IsInRange(Position, 0.5f))
{
if (!Character.IsReloading)
{
Character.Task.ClearAll();
Character.Task.ReloadWeapon();
}
return;
}
if (Character.Weapons.Current.Hash != (WeaponHash)CurrentWeaponHash || !WeaponComponents.Compare(_lastWeaponComponents))
{
Character.Weapons.RemoveAll();
if (CurrentWeaponHash != (uint)WeaponHash.Unarmed)
{
if (WeaponComponents == null || WeaponComponents.Count == 0)
{
Character.Weapons.Give((WeaponHash)CurrentWeaponHash, -1, true, true);
}
else
{
_lastWeaponObj = Function.Call<int>(Hash.CREATE_WEAPON_OBJECT, CurrentWeaponHash, -1, Position.X, Position.Y, Position.Z, true, 0, 0);
foreach (KeyValuePair<uint, bool> comp in WeaponComponents)
{
if (comp.Value)
{
Function.Call(Hash.GIVE_WEAPON_COMPONENT_TO_WEAPON_OBJECT, _lastWeaponObj, comp.Key);
}
}
Function.Call(Hash.GIVE_WEAPON_OBJECT_TO_PED, _lastWeaponObj, Character.Handle);
}
}
_lastWeaponComponents = WeaponComponents;
}
if (IsShooting)
{
if (!Character.IsInRange(Position, 0.5f))
{
Function.Call(Hash.TASK_GO_TO_COORD_WHILE_AIMING_AT_COORD, Character.Handle, Position.X, Position.Y,
Position.Z, AimCoords.X, AimCoords.Y, AimCoords.Z, 3f, true, 0x3F000000, 0x40800000, false, 0, false,
unchecked((int)FiringPattern.FullAuto));
}
else
{
Function.Call(Hash.TASK_SHOOT_AT_COORD, Character.Handle, AimCoords.X, AimCoords.Y, AimCoords.Z, 1500, unchecked((int)FiringPattern.FullAuto));
}
}
else if (IsAiming)
{
if (!Character.IsInRange(Position, 0.5f))
{
Function.Call(Hash.TASK_GO_TO_COORD_WHILE_AIMING_AT_COORD, Character.Handle, Position.X, Position.Y,
Position.Z, AimCoords.X, AimCoords.Y, AimCoords.Z, 3f, false, 0x3F000000, 0x40800000, false, 512, false,
unchecked((int)FiringPattern.FullAuto));
}
else
{
Character.Task.AimAt(AimCoords, 100);
}
}
else
{
WalkTo();
}
}
private bool LastMoving;
private void WalkTo()
{
if (!Character.IsInRange(Position, 6.0f))
{
Character.PositionNoOffset = Position;
Character.Rotation = Rotation;
}
Vector3 predictPosition = Position + (Position - Character.Position) + Velocity;
float range = predictPosition.DistanceToSquared(Character.Position);
switch (Speed)
{
case 1:
if (!Character.IsWalking || range > 0.25f)
{
float nrange = range * 2;
if (nrange > 1.0f)
{
nrange = 1.0f;
}
Character.Task.GoStraightTo(predictPosition);
Function.Call(Hash.SET_PED_DESIRED_MOVE_BLEND_RATIO, Character.Handle, nrange);
}
LastMoving = true;
break;
case 2:
if (!Character.IsRunning || range > 0.50f)
{
Character.Task.RunTo(predictPosition, true);
Function.Call(Hash.SET_PED_DESIRED_MOVE_BLEND_RATIO, Character.Handle, 1.0f);
}
LastMoving = true;
break;
case 3:
if (!Character.IsSprinting || range > 0.75f)
{
Function.Call(Hash.TASK_GO_STRAIGHT_TO_COORD, Character.Handle, predictPosition.X, predictPosition.Y, predictPosition.Z, 3.0f, -1, 0.0f, 0.0f);
Function.Call(Hash.SET_RUN_SPRINT_MULTIPLIER_FOR_PLAYER, Character.Handle, 1.49f);
Function.Call(Hash.SET_PED_DESIRED_MOVE_BLEND_RATIO, Character.Handle, 1.0f);
}
LastMoving = true;
break;
default:
if (!Character.IsInRange(Position, 0.5f))
{
Character.Task.RunTo(Position, true, 500);
}
else if (LastMoving)
{
Character.Task.StandStill(2000);
LastMoving = false;
}
break;
}
}
}
}

View File

@ -1,323 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GTA;
using GTA.Native;
using GTA.Math;
namespace CoopClient.Entities.NPC
{
internal partial class EntitiesNPC
{
#region -- VARIABLES --
internal long PlayerVehicleHandle = 0;
private ulong _vehicleStopTime { get; set; }
internal bool IsInVehicle { get; set; }
internal int VehicleModelHash { get; set; }
private byte[] _lastVehicleColors = new byte[] { 0, 0 };
internal byte[] VehicleColors { get; set; }
private Dictionary<int, int> _lastVehicleMods = new Dictionary<int, int>();
internal Dictionary<int, int> VehicleMods { get; set; }
internal bool VehicleDead { get; set; }
internal float VehicleEngineHealth { get; set; }
internal short VehicleSeatIndex { get; set; }
internal Vehicle MainVehicle { get; set; }
internal Quaternion VehicleRotation { get; set; }
internal float VehicleSpeed { get; set; }
internal float VehicleSteeringAngle { get; set; }
internal bool VehIsEngineRunning { get; set; }
internal float VehRPM { get; set; }
private bool _lastTransformed = false;
internal bool Transformed { get; set; }
private bool _lastHornActive = false;
internal bool IsHornActive { get; set; }
internal bool VehAreLightsOn { get; set; }
internal bool VehAreBrakeLightsOn = false;
internal bool VehAreHighBeamsOn { get; set; }
internal byte VehLandingGear { get; set; }
internal bool VehRoofOpened { get; set; }
internal bool VehIsSireneActive { get; set; }
internal VehicleDamageModel VehDamageModel { get; set; }
#endregion
private void DisplayInVehicle()
{
if (MainVehicle == null || !MainVehicle.Exists() || MainVehicle.Model.Hash != VehicleModelHash)
{
bool vehFound = false;
lock (Main.NPCsVehicles)
{
if (Main.NPCsVehicles.ContainsKey(PlayerVehicleHandle))
{
Vehicle targetVehicle = World.GetAllVehicles().FirstOrDefault(x => x.Handle == Main.NPCsVehicles[PlayerVehicleHandle]);
if (targetVehicle == null)
{
return;
}
MainVehicle = targetVehicle;
vehFound = true;
}
}
if (!vehFound)
{
Model vehicleModel = VehicleModelHash.ModelRequest();
if (vehicleModel == null)
{
//GTA.UI.Notification.Show($"~r~(Vehicle)Model ({CurrentVehicleModelHash}) cannot be loaded!");
Character.IsVisible = false;
return;
}
Vehicle targetVehicle = World.GetClosestVehicle(Position, 7f, vehicleModel);
if (targetVehicle != null && targetVehicle.IsSeatFree((VehicleSeat)VehicleSeatIndex))
{
MainVehicle = targetVehicle;
lock (Main.NPCsVehicles)
{
Main.NPCsVehicles.Add(PlayerVehicleHandle, MainVehicle.Handle);
}
}
else
{
MainVehicle = World.CreateVehicle(vehicleModel, Position);
lock (Main.NPCsVehicles)
{
Main.NPCsVehicles.Add(PlayerVehicleHandle, MainVehicle.Handle);
}
MainVehicle.Quaternion = VehicleRotation;
if (MainVehicle.HasRoof)
{
bool roofOpened = MainVehicle.RoofState == VehicleRoofState.Opened || MainVehicle.RoofState == VehicleRoofState.Opening;
if (roofOpened != VehRoofOpened)
{
MainVehicle.RoofState = VehRoofOpened ? VehicleRoofState.Opened : VehicleRoofState.Closed;
}
}
}
vehicleModel.MarkAsNoLongerNeeded();
}
}
if (!Character.IsInVehicle() || (int)Character.SeatIndex != VehicleSeatIndex || Character.CurrentVehicle.Handle != MainVehicle.Handle)
{
if (VehicleSeatIndex == -1 &&
Game.Player.Character.IsInVehicle() &&
(int)Game.Player.Character.SeatIndex == -1 &&
Game.Player.Character.CurrentVehicle.Handle == MainVehicle.Handle)
{
Game.Player.Character.Task.WarpOutOfVehicle(MainVehicle);
GTA.UI.Notification.Show("~r~Car jacked!");
}
Character.SetIntoVehicle(MainVehicle, (VehicleSeat)VehicleSeatIndex);
Character.IsVisible = true;
}
#region -- VEHICLE SYNC --
if (MainVehicle.GetResponsiblePedHandle() != Character.Handle)
{
return;
}
if (VehicleColors != null && VehicleColors != _lastVehicleColors)
{
Function.Call(Hash.SET_VEHICLE_COLOURS, MainVehicle, VehicleColors[0], VehicleColors[1]);
_lastVehicleColors = VehicleColors;
}
if (Character.IsOnBike && MainVehicle.ClassType == VehicleClass.Cycles)
{
bool isFastPedaling = Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, Character.Handle, PedalingAnimDict(), "fast_pedal_char", 3);
if (VehicleSpeed < 0.2f)
{
StopPedalingAnim(isFastPedaling);
}
else if (VehicleSpeed < 11f && !Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, Character.Handle, PedalingAnimDict(), "cruise_pedal_char", 3))
{
StartPedalingAnim(false);
}
else if (VehicleSpeed >= 11f && !isFastPedaling)
{
StartPedalingAnim(true);
}
}
else
{
if (VehicleMods != null && !VehicleMods.Compare(_lastVehicleMods))
{
Function.Call(Hash.SET_VEHICLE_MOD_KIT, MainVehicle, 0);
foreach (KeyValuePair<int, int> mod in VehicleMods)
{
MainVehicle.Mods[(VehicleModType)mod.Key].Index = mod.Value;
}
_lastVehicleMods = VehicleMods;
}
MainVehicle.EngineHealth = VehicleEngineHealth;
if (VehicleDead && !MainVehicle.IsDead)
{
MainVehicle.Explode();
}
else if (!VehicleDead && MainVehicle.IsDead)
{
MainVehicle.Repair();
}
if (VehIsEngineRunning != MainVehicle.IsEngineRunning)
{
MainVehicle.IsEngineRunning = VehIsEngineRunning;
}
MainVehicle.CurrentRPM = VehRPM;
if (VehAreLightsOn != MainVehicle.AreLightsOn)
{
MainVehicle.AreLightsOn = VehAreLightsOn;
}
if (VehAreHighBeamsOn != MainVehicle.AreHighBeamsOn)
{
MainVehicle.AreHighBeamsOn = VehAreHighBeamsOn;
}
if (MainVehicle.IsSubmarineCar)
{
if (Transformed)
{
if (!_lastTransformed)
{
_lastTransformed = true;
Function.Call(Hash._TRANSFORM_VEHICLE_TO_SUBMARINE, MainVehicle.Handle, false);
}
}
else if (_lastTransformed)
{
_lastTransformed = false;
Function.Call(Hash._TRANSFORM_SUBMARINE_TO_VEHICLE, MainVehicle.Handle, false);
}
}
if (MainVehicle.IsPlane)
{
if (VehLandingGear != (byte)MainVehicle.LandingGearState)
{
MainVehicle.LandingGearState = (VehicleLandingGearState)VehLandingGear;
}
}
else
{
if (MainVehicle.HasSiren && VehIsSireneActive != MainVehicle.IsSirenActive)
{
MainVehicle.IsSirenActive = VehIsSireneActive;
}
if (IsHornActive)
{
if (!_lastHornActive)
{
_lastHornActive = true;
MainVehicle.SoundHorn(99999);
}
}
else if (_lastHornActive)
{
_lastHornActive = false;
MainVehicle.SoundHorn(1);
}
if (MainVehicle.HasRoof)
{
bool roofOpened = MainVehicle.RoofState == VehicleRoofState.Opened || MainVehicle.RoofState == VehicleRoofState.Opening;
if (roofOpened != VehRoofOpened)
{
MainVehicle.RoofState = VehRoofOpened ? VehicleRoofState.Opening : VehicleRoofState.Closing;
}
}
Function.Call(Hash.SET_VEHICLE_BRAKE_LIGHTS, MainVehicle.Handle, VehAreBrakeLightsOn);
if (LastSyncWasFull)
{
MainVehicle.SetVehicleDamageModel(VehDamageModel);
}
}
}
if (VehicleSteeringAngle != MainVehicle.SteeringAngle)
{
MainVehicle.CustomSteeringAngle((float)(Math.PI / 180) * VehicleSteeringAngle);
}
// Good enough for now, but we need to create a better sync
if (VehicleSpeed > 0.05f && MainVehicle.IsInRange(Position, 7.0f))
{
int forceMultiplier = (Game.Player.Character.IsInVehicle() && MainVehicle.IsTouching(Game.Player.Character.CurrentVehicle)) ? 1 : 3;
MainVehicle.Velocity = Velocity + forceMultiplier * (Position - MainVehicle.Position);
MainVehicle.Quaternion = Quaternion.Slerp(MainVehicle.Quaternion, VehicleRotation, 0.5f);
_vehicleStopTime = Util.GetTickCount64();
}
else if ((Util.GetTickCount64() - _vehicleStopTime) <= 1000)
{
Vector3 posTarget = Util.LinearVectorLerp(MainVehicle.Position, Position + (Position - MainVehicle.Position), Util.GetTickCount64() - _vehicleStopTime, 1000);
MainVehicle.PositionNoOffset = posTarget;
MainVehicle.Quaternion = Quaternion.Slerp(MainVehicle.Quaternion, VehicleRotation, 0.5f);
}
else
{
MainVehicle.PositionNoOffset = Position;
MainVehicle.Quaternion = VehicleRotation;
}
#endregion
}
#region -- PEDALING --
/*
* Thanks to @oldnapalm.
*/
private string PedalingAnimDict()
{
switch ((VehicleHash)VehicleModelHash)
{
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)
{
Character.Task.PlayAnimation(PedalingAnimDict(), PedalingAnimName(fast), 8.0f, -8.0f, -1, AnimationFlags.Loop | AnimationFlags.AllowRotation, 1.0f);
}
private void StopPedalingAnim(bool fast)
{
Character.Task.ClearAnimation(PedalingAnimDict(), PedalingAnimName(fast));
}
#endregion
}
}

View File

@ -1,278 +0,0 @@
using System;
using System.Drawing;
using System.Collections.Generic;
using GTA;
using GTA.Native;
using GTA.Math;
using LemonUI.Elements;
namespace CoopClient.Entities.Player
{
/// <summary>
/// ?
/// </summary>
public partial class EntitiesPlayer
{
/// <summary>
/// ?
/// </summary>
public string Username { get; set; } = "Player";
private bool _allDataAvailable = false;
internal bool LastSyncWasFull { get; set; } = false;
/// <summary>
/// Get the last update = TickCount64()
/// </summary>
public ulong LastUpdateReceived { get; set; } = 0;
/// <summary>
/// Get the player latency
/// </summary>
public float Latency { get; internal set; }
/// <summary>
/// ?
/// </summary>
public Ped Character { get; internal set; }
/// <summary>
/// The latest character health (may not have been applied yet)
/// </summary>
public int Health { get; internal set; }
private int _lastModelHash = 0;
private int _currentModelHash = 0;
/// <summary>
/// The latest character model hash (may not have been applied yet)
/// </summary>
public int ModelHash
{
get => _currentModelHash;
internal set
{
_lastModelHash = _lastModelHash == 0 ? value : _currentModelHash;
_currentModelHash = value;
}
}
private Dictionary<byte, short> _lastClothes = null;
internal Dictionary<byte, short> Clothes { get; set; }
/// <summary>
/// The latest character position (may not have been applied yet)
/// </summary>
public Vector3 Position { get; internal set; }
internal Vector3 Velocity { get; set; }
internal Blip PedBlip = null;
internal Vector3 AimCoords { get; set; }
internal void Update()
{
// Check beforehand whether ped has all the required data
if (!_allDataAvailable)
{
if (!LastSyncWasFull)
{
if (Position != default)
{
if (PedBlip != null && PedBlip.Exists())
{
PedBlip.Position = Position;
}
else
{
PedBlip = World.CreateBlip(Position);
PedBlip.Color = BlipColor.White;
PedBlip.Scale = 0.8f;
PedBlip.Name = Username;
}
}
return;
}
_allDataAvailable = true;
}
#region NOT_IN_RANGE
if (!Game.Player.Character.IsInRange(Position, 500f))
{
if (Character != null && Character.Exists())
{
Character.Kill();
Character.MarkAsNoLongerNeeded();
Character.Delete();
Character = null;
}
if (MainVehicle != null && MainVehicle.Exists() && MainVehicle.IsSeatFree(VehicleSeat.Driver) && MainVehicle.PassengerCount == 0)
{
MainVehicle.MarkAsNoLongerNeeded();
MainVehicle.Delete();
MainVehicle = null;
}
if (PedBlip != null && PedBlip.Exists())
{
PedBlip.Position = Position;
}
else
{
PedBlip = World.CreateBlip(Position);
PedBlip.Color = BlipColor.White;
PedBlip.Scale = 0.8f;
PedBlip.Name = Username;
}
return;
}
#endregion
#region IS_IN_RANGE
bool characterExist = Character != null && Character.Exists();
if (!characterExist)
{
CreateCharacter();
return;
}
if (LastSyncWasFull)
{
if (ModelHash != _lastModelHash)
{
CreateCharacter();
return;
}
if (!Clothes.Compare(_lastClothes))
{
SetClothes();
}
}
RenderNameTag();
if (Character.IsDead)
{
if (Health <= 0)
{
return;
}
Character.IsInvincible = true;
Character.Resurrect();
}
else if (Character.Health != Health)
{
Character.Health = Health;
if (Health <= 0 && !Character.IsDead)
{
Character.IsInvincible = false;
Character.Kill();
return;
}
}
if (IsInVehicle)
{
DisplayInVehicle();
}
else
{
DisplayOnFoot();
}
#endregion
}
private void RenderNameTag()
{
if (!Character.IsVisible || !Character.IsInRange(Game.Player.Character.Position, 20f))
{
return;
}
string renderText = (Util.GetTickCount64() - LastUpdateReceived) > 5000 ? "~r~AFK" : Username;
Vector3 targetPos = Character.Bones[Bone.IKHead].Position + new Vector3(0, 0, 0.35f) + (Character.Velocity / Game.FPS);
Function.Call(Hash.SET_DRAW_ORIGIN, targetPos.X, targetPos.Y, targetPos.Z, 0);
float dist = (GameplayCamera.Position - Character.Position).Length();
var sizeOffset = Math.Max(1f - (dist / 30f), 0.3f);
new ScaledText(new PointF(0, 0), renderText, 0.4f * sizeOffset, GTA.UI.Font.ChaletLondon)
{
Outline = true,
Alignment = GTA.UI.Alignment.Center
}.Draw();
Function.Call(Hash.CLEAR_DRAW_ORIGIN);
}
private void CreateCharacter()
{
if (Character != null)
{
if (Character.Exists())
{
Character.Kill();
Character.MarkAsNoLongerNeeded();
Character.Delete();
}
Character = null;
}
if (PedBlip != null && PedBlip.Exists())
{
PedBlip.Delete();
PedBlip = null;
}
Model characterModel = ModelHash.ModelRequest();
if (characterModel == null)
{
return;
}
Character = World.CreatePed(characterModel, Position);
characterModel.MarkAsNoLongerNeeded();
if (Character == null)
{
return;
}
Character.RelationshipGroup = Main.RelationshipGroup;
Character.Health = Health;
Character.BlockPermanentEvents = true;
Character.CanRagdoll = false;
Character.IsInvincible = true;
Character.CanSufferCriticalHits = false;
Function.Call(Hash.SET_PED_CAN_EVASIVE_DIVE, Character.Handle, false);
Function.Call(Hash.SET_PED_DROPS_WEAPONS_WHEN_DEAD, Character.Handle, false);
Function.Call(Hash.SET_PED_CAN_BE_TARGETTED, Character.Handle, true);
Function.Call(Hash.SET_PED_CAN_BE_TARGETTED_BY_PLAYER, Character.Handle, Game.Player, true);
Function.Call(Hash.SET_PED_GET_OUT_UPSIDE_DOWN_VEHICLE, Character.Handle, false);
Function.Call(Hash.SET_PED_AS_ENEMY, Character.Handle, false);
Function.Call(Hash.SET_CAN_ATTACK_FRIENDLY, Character.Handle, true, true);
SetClothes();
// Add a new blip for the ped
Character.AddBlip();
Character.AttachedBlip.Color = BlipColor.White;
Character.AttachedBlip.Scale = 0.8f;
Character.AttachedBlip.Name = Username;
}
private void SetClothes()
{
foreach (KeyValuePair<byte, short> cloth in Clothes)
{
Function.Call(Hash.SET_PED_COMPONENT_VARIATION, Character.Handle, cloth.Key, cloth.Value, 0, 0);
}
_lastClothes = Clothes;
}
}
}

View File

@ -1,471 +0,0 @@
using System;
using System.Collections.Generic;
using GTA;
using GTA.Native;
using GTA.Math;
namespace CoopClient.Entities.Player
{
public partial class EntitiesPlayer
{
#region -- VARIABLES --
/// <summary>
/// The latest character rotation (may not have been applied yet)
/// </summary>
public Vector3 Rotation { get; internal set; }
internal byte Speed { get; set; }
private bool _lastIsJumping = false;
internal bool IsJumping { get; set; }
internal bool IsOnLadder { get; set; }
internal bool IsVaulting { get; set; }
internal bool IsInParachuteFreeFall { get; set; }
internal bool IsParachuteOpen { get; set; }
internal Prop ParachuteProp { get; set; } = null;
internal bool IsRagdoll { get; set; }
internal bool IsOnFire { get; set; }
internal bool IsAiming { get; set; }
internal bool IsShooting { get; set; }
internal bool IsReloading { get; set; }
internal uint CurrentWeaponHash { get; set; }
private Dictionary<uint, bool> _lastWeaponComponents = null;
internal Dictionary<uint, bool> WeaponComponents { get; set; } = null;
private int _lastWeaponObj = 0;
#endregion
private bool _isPlayingAnimation = false;
private string[] _currentAnimation = new string[2] { "", "" };
private float _animationStopTime = 0;
private void DisplayOnFoot()
{
if (Character.IsInVehicle())
{
if (MainVehicle == null)
{
Character.Task.LeaveVehicle();
}
else
{
MainVehicle.Doors[(VehicleDoorIndex)VehicleSeatIndex + 1]?.Open(true, true);
Character.Task.LeaveVehicle(MainVehicle, false);
MainVehicle = null;
}
Character.PositionNoOffset = Position;
return;
}
if (IsInParachuteFreeFall)
{
Character.PositionNoOffset = Vector3.Lerp(Character.Position, Position + Velocity, 0.5f);
Character.Quaternion = Rotation.ToQuaternion();
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, Character.Handle, "skydive@base", "free_idle", 3))
{
Function.Call(Hash.TASK_PLAY_ANIM, Character.Handle, LoadAnim("skydive@base"), "free_idle", 8f, 10f, -1, 0, -8f, 1, 1, 1);
}
return;
}
if (IsParachuteOpen)
{
if (ParachuteProp == null)
{
Model model = 1740193300.ModelRequest();
if (model != null)
{
ParachuteProp = World.CreateProp(model, Character.Position, Character.Rotation, false, false);
model.MarkAsNoLongerNeeded();
ParachuteProp.IsPositionFrozen = true;
ParachuteProp.IsCollisionEnabled = false;
ParachuteProp.AttachTo(Character.Bones[Bone.SkelSpine2], new Vector3(3.6f, 0f, 0f), new Vector3(0f, 90f, 0f));
}
Character.Task.ClearAllImmediately();
Character.Task.ClearSecondary();
}
Character.PositionNoOffset = Vector3.Lerp(Character.Position, Position + Velocity, 0.5f);
Character.Quaternion = Rotation.ToQuaternion();
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, Character.Handle, "skydive@parachute@first_person", "chute_idle_right", 3))
{
Function.Call(Hash.TASK_PLAY_ANIM, Character, LoadAnim("skydive@parachute@first_person"), "chute_idle_right", 8f, 10f, -1, 0, -8f, 1, 1, 1);
}
return;
}
if (ParachuteProp != null)
{
if (ParachuteProp.Exists())
{
ParachuteProp.Delete();
}
ParachuteProp = null;
}
if (IsOnLadder)
{
if (Velocity.Z < 0)
{
string anim = Velocity.Z < -2f ? "slide_climb_down" : "climb_down";
if (_currentAnimation[1] != anim)
{
Character.Task.ClearAllImmediately();
_currentAnimation[1] = anim;
}
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, Character.Handle, "laddersbase", anim, 3))
{
Character.Task.PlayAnimation("laddersbase", anim, 8f, -1, AnimationFlags.Loop);
}
}
else
{
if (Math.Abs(Velocity.Z) < 0.5)
{
if (_currentAnimation[1] != "base_left_hand_up")
{
Character.Task.ClearAllImmediately();
_currentAnimation[1] = "base_left_hand_up";
}
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, Character.Handle, "laddersbase", "base_left_hand_up", 3))
{
Character.Task.PlayAnimation("laddersbase", "base_left_hand_up", 8f, -1, AnimationFlags.Loop);
}
}
else
{
if (_currentAnimation[1] != "climb_up")
{
Character.Task.ClearAllImmediately();
_currentAnimation[1] = "climb_up";
}
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, Character.Handle, "laddersbase", "climb_up", 3))
{
Character.Task.PlayAnimation("laddersbase", "climb_up", 8f, -1, AnimationFlags.Loop);
}
}
}
UpdateOnFootPosition(true, true, false);
return;
}
if (!IsOnLadder && Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, Character.Handle, ETasks.CLIMB_LADDER))
{
Character.Task.ClearAllImmediately();
_currentAnimation[1] = "";
}
if (IsVaulting)
{
if (!Character.IsVaulting)
{
Character.Task.Climb();
}
UpdateOnFootPosition(true, true, false);
return;
}
if (!IsVaulting && Character.IsVaulting)
{
Character.Task.ClearAllImmediately();
}
if (IsOnFire && !Character.IsOnFire)
{
Character.IsInvincible = false;
Function.Call(Hash.START_ENTITY_FIRE, Character.Handle);
}
else if (!IsOnFire && Character.IsOnFire)
{
Function.Call(Hash.STOP_ENTITY_FIRE, Character.Handle);
Character.IsInvincible = true;
if (Character.IsDead)
{
Character.Resurrect();
}
}
if (IsJumping)
{
if (!_lastIsJumping)
{
_lastIsJumping = true;
Character.Task.Jump();
}
UpdateOnFootPosition();
return;
}
_lastIsJumping = false;
if (IsRagdoll)
{
if (!Character.IsRagdoll)
{
Character.CanRagdoll = true;
Function.Call(Hash.SET_PED_TO_RAGDOLL, Character.Handle, 50000, 60000, 0, 1, 1, 1);
}
UpdateOnFootPosition(false, false, true);
return;
}
else
{
if (Character.IsRagdoll)
{
Character.CanRagdoll = false;
Character.Task.ClearAllImmediately();
_isPlayingAnimation = true;
_currentAnimation = new string[2] { "anim@sports@ballgame@handball@", "ball_get_up" };
_animationStopTime = 0.7f;
Function.Call(Hash.TASK_PLAY_ANIM, Character.Handle, LoadAnim("anim@sports@ballgame@handball@"), "ball_get_up", 12f, 12f, -1, 0, -10f, 1, 1, 1);
return;
}
else if (_currentAnimation[1] == "ball_get_up")
{
UpdateOnFootPosition(true, true, false);
float currentTime = Function.Call<float>(Hash.GET_ENTITY_ANIM_CURRENT_TIME, Character.Handle, "anim@sports@ballgame@handball@", _currentAnimation[1]);
if (currentTime < _animationStopTime)
{
return;
}
Character.Task.ClearAnimation(_currentAnimation[0], _currentAnimation[1]);
Character.Task.ClearAll();
_isPlayingAnimation = false;
_currentAnimation = new string[2] { "", "" };
_animationStopTime = 0;
}
}
CheckCurrentWeapon();
if (IsReloading)
{
if (!_isPlayingAnimation)
{
string[] reloadingAnim = Character.GetReloadingAnimation();
if (reloadingAnim != null)
{
_isPlayingAnimation = true;
_currentAnimation = reloadingAnim;
Character.Task.PlayAnimation(_currentAnimation[0], _currentAnimation[1], 8f, -1, AnimationFlags.AllowRotation | AnimationFlags.UpperBodyOnly);
}
}
}
else if (_currentAnimation[1] == "reload_aim")
{
Character.Task.ClearAnimation(_currentAnimation[0], _currentAnimation[1]);
_isPlayingAnimation = false;
_currentAnimation = new string[2] { "", "" };
}
if (IsShooting)
{
DisplayShooting();
}
else if (IsAiming)
{
DisplayAiming();
}
else
{
WalkTo();
}
}
#region WEAPON
private void CheckCurrentWeapon()
{
if (Character.Weapons.Current.Hash != (WeaponHash)CurrentWeaponHash || !WeaponComponents.Compare(_lastWeaponComponents))
{
Character.Weapons.RemoveAll();
if (CurrentWeaponHash != (uint)WeaponHash.Unarmed)
{
if (WeaponComponents == null || WeaponComponents.Count == 0)
{
Character.Weapons.Give((WeaponHash)CurrentWeaponHash, -1, true, true);
}
else
{
_lastWeaponObj = Function.Call<int>(Hash.CREATE_WEAPON_OBJECT, CurrentWeaponHash, -1, Position.X, Position.Y, Position.Z, true, 0, 0);
foreach (KeyValuePair<uint, bool> comp in WeaponComponents)
{
if (comp.Value)
{
Function.Call(Hash.GIVE_WEAPON_COMPONENT_TO_WEAPON_OBJECT, _lastWeaponObj, comp.Key);
}
}
Function.Call(Hash.GIVE_WEAPON_OBJECT_TO_PED, _lastWeaponObj, Character.Handle);
}
}
_lastWeaponComponents = WeaponComponents;
}
}
private void DisplayShooting()
{
if (!Character.IsInRange(Position, 0.5f))
{
Function.Call(Hash.TASK_GO_TO_COORD_WHILE_AIMING_AT_COORD, Character.Handle, Position.X, Position.Y,
Position.Z, AimCoords.X, AimCoords.Y, AimCoords.Z, 3f, true, 2.0f, 0.5f, false, 0, false,
unchecked((uint)FiringPattern.FullAuto));
UpdateOnFootPosition();
}
else
{
Function.Call(Hash.TASK_SHOOT_AT_COORD, Character.Handle, AimCoords.X, AimCoords.Y, AimCoords.Z, 1500, unchecked((uint)FiringPattern.FullAuto));
}
}
private void DisplayAiming()
{
if (!Character.IsInRange(Position, 0.5f))
{
Function.Call(Hash.TASK_GO_TO_COORD_WHILE_AIMING_AT_COORD, Character.Handle, Position.X, Position.Y,
Position.Z, AimCoords.X, AimCoords.Y, AimCoords.Z, 3f, false, 0x3F000000, 0x40800000, false, 512, false, 0);
UpdateOnFootPosition();
}
else
{
Character.Task.AimAt(AimCoords, 100);
}
}
#endregion
private bool LastMoving;
private void WalkTo()
{
Vector3 predictPosition = Position + (Position - Character.Position) + Velocity;
float range = predictPosition.DistanceToSquared(Character.Position);
switch (Speed)
{
case 1:
if (!Character.IsWalking || range > 0.25f)
{
float nrange = range * 2;
if (nrange > 1.0f)
{
nrange = 1.0f;
}
Character.Task.GoStraightTo(predictPosition);
Function.Call(Hash.SET_PED_DESIRED_MOVE_BLEND_RATIO, Character.Handle, nrange);
}
LastMoving = true;
break;
case 2:
if (!Character.IsRunning || range > 0.50f)
{
Character.Task.RunTo(predictPosition, true);
Function.Call(Hash.SET_PED_DESIRED_MOVE_BLEND_RATIO, Character.Handle, 1.0f);
}
LastMoving = true;
break;
case 3:
if (!Character.IsSprinting || range > 0.75f)
{
Function.Call(Hash.TASK_GO_STRAIGHT_TO_COORD, Character.Handle, predictPosition.X, predictPosition.Y, predictPosition.Z, 3.0f, -1, 0.0f, 0.0f);
Function.Call(Hash.SET_RUN_SPRINT_MULTIPLIER_FOR_PLAYER, Character.Handle, 1.49f);
Function.Call(Hash.SET_PED_DESIRED_MOVE_BLEND_RATIO, Character.Handle, 1.0f);
}
LastMoving = true;
break;
default:
if (LastMoving)
{
Character.Task.StandStill(2000);
LastMoving = false;
}
break;
}
UpdateOnFootPosition();
}
private bool StuckDetection = false;
private ulong LastStuckTime;
private void UpdateOnFootPosition(bool updatePosition = true, bool updateRotation = true, bool updateVelocity = true)
{
ulong time = Util.GetTickCount64();
if (StuckDetection)
{
if (time - LastStuckTime >= 500)
{
StuckDetection = false;
if (Character.Position.DistanceTo(Position) > 5f)
{
Character.PositionNoOffset = Position;
Character.Rotation = Rotation;
}
}
}
else if (time - LastStuckTime >= 500)
{
if (Character.Position.DistanceTo(Position) > 5f)
{
StuckDetection = true;
LastStuckTime = time;
}
}
if (updatePosition)
{
float lerpValue = (int)((Latency * 1000 / 2) + (Main.MainNetworking.Latency * 1000 / 2)) * 2 / 50000f;
Vector2 biDimensionalPos = Vector2.Lerp(new Vector2(Character.Position.X, Character.Position.Y), new Vector2(Position.X + (Velocity.X / 5), Position.Y + (Velocity.Y / 5)), lerpValue);
float zPos = Util.Lerp(Character.Position.Z, Position.Z, 0.1f);
Character.PositionNoOffset = new Vector3(biDimensionalPos.X, biDimensionalPos.Y, zPos);
}
if (updateRotation)
{
// You can find the ToQuaternion() for Rotation inside the VectorExtensions
Character.Quaternion = Quaternion.Lerp(Character.Quaternion, Rotation.ToQuaternion(), 0.10f);
}
if (updateVelocity)
{
Character.Velocity = Velocity;
}
}
private string LoadAnim(string anim)
{
ulong startTime = Util.GetTickCount64();
while (!Function.Call<bool>(Hash.HAS_ANIM_DICT_LOADED, anim))
{
Script.Yield();
Function.Call(Hash.REQUEST_ANIM_DICT, anim);
if (Util.GetTickCount64() - startTime >= 1000)
{
break;
}
}
return anim;
}
}
}

View File

@ -1,352 +0,0 @@
using System;
using System.Linq;
using System.Collections.Generic;
using GTA;
using GTA.Native;
using GTA.Math;
namespace CoopClient.Entities.Player
{
public partial class EntitiesPlayer
{
#region -- VARIABLES --
private ulong _vehicleStopTime { get; set; }
internal bool IsInVehicle { get; set; }
/// <summary>
/// The latest vehicle model hash (may not have been applied yet)
/// </summary>
public int VehicleModelHash { get; internal set; }
private byte[] _lastVehicleColors = new byte[] { 0, 0 };
internal byte[] VehicleColors { get; set; }
private Dictionary<int, int> _lastVehicleMods = new Dictionary<int, int>();
internal Dictionary<int, int> VehicleMods { get; set; }
internal bool VehicleDead { get; set; }
internal float VehicleEngineHealth { get; set; }
internal short VehicleSeatIndex { get; set; }
/// <summary>
/// ?
/// </summary>
public Vehicle MainVehicle { get; internal set; }
/// <summary>
/// The latest vehicle rotation (may not have been applied yet)
/// </summary>
public Quaternion VehicleRotation { get; set; }
internal float VehicleSpeed { get; set; }
internal float VehicleSteeringAngle { get; set; }
private int _lastVehicleAim = 0;
internal bool VehIsEngineRunning { get; set; }
internal float VehRPM { get; set; }
private bool _lastTransformed = false;
internal bool Transformed { get; set; }
private bool _lastHornActive = false;
internal bool IsHornActive { get; set; }
internal bool VehAreLightsOn { get; set; }
internal bool VehAreBrakeLightsOn = false;
internal bool VehAreHighBeamsOn { get; set; }
internal byte VehLandingGear { get; set; }
internal bool VehRoofOpened { get; set; }
internal bool VehIsSireneActive { get; set; }
internal VehicleDamageModel VehDamageModel { get; set; }
#endregion
private ulong _lastVehicleEnter = 0;
private void DisplayInVehicle()
{
if (MainVehicle == null || !MainVehicle.Exists() || MainVehicle.Model.Hash != VehicleModelHash)
{
Model vehicleModel = VehicleModelHash.ModelRequest();
if (vehicleModel == null)
{
return;
}
Vehicle targetVehicle = World.GetClosestVehicle(Position, 7f, vehicleModel);
if (targetVehicle != null && targetVehicle.IsSeatFree((VehicleSeat)VehicleSeatIndex))
{
MainVehicle = targetVehicle;
}
else
{
MainVehicle = World.CreateVehicle(vehicleModel, Position);
if (MainVehicle == null)
{
vehicleModel.MarkAsNoLongerNeeded();
return;
}
MainVehicle.IsInvincible = true;
MainVehicle.Quaternion = VehicleRotation;
if (MainVehicle.HasRoof)
{
bool roofOpened = MainVehicle.RoofState == VehicleRoofState.Opened || MainVehicle.RoofState == VehicleRoofState.Opening;
if (roofOpened != VehRoofOpened)
{
MainVehicle.RoofState = VehRoofOpened ? VehicleRoofState.Opened : VehicleRoofState.Closed;
}
}
}
vehicleModel.MarkAsNoLongerNeeded();
}
if (_lastVehicleEnter != 0)
{
if (VehicleSpeed == 0f && Util.GetTickCount64() - _lastVehicleEnter < 1500)
{
return;
}
_lastVehicleEnter = 0;
Character.Task.ClearAll();
Character.SetIntoVehicle(MainVehicle, (VehicleSeat)VehicleSeatIndex);
}
else if (!Character.IsInVehicle() || Character.CurrentVehicle.Handle != MainVehicle.Handle)
{
if (Game.Player.Character.CurrentVehicle?.Handle == MainVehicle.Handle &&
VehicleSeatIndex == (int)Game.Player.Character.SeatIndex)
{
Game.Player.Character.Task.WarpOutOfVehicle(MainVehicle);
GTA.UI.Notification.Show("~r~Car jacked!");
}
if (VehicleSpeed > 0.2f || !Character.IsInRange(MainVehicle.Position, 4f))
{
Character.SetIntoVehicle(MainVehicle, (VehicleSeat)VehicleSeatIndex);
}
else
{
_lastVehicleEnter = Util.GetTickCount64();
Character.Task.ClearAll();
Character.Task.EnterVehicle(MainVehicle, (VehicleSeat)VehicleSeatIndex, -1, 2f, EnterVehicleFlags.WarpToDoor);
}
return;
}
if ((int)Character.SeatIndex != VehicleSeatIndex)
{
Character.Task.WarpIntoVehicle(MainVehicle, (VehicleSeat)VehicleSeatIndex);
}
if (AimCoords != default)
{
if (MainVehicle.IsTurretSeat(VehicleSeatIndex))
{
int gameTime = Game.GameTime;
if (gameTime - _lastVehicleAim > 30)
{
Function.Call(Hash.TASK_VEHICLE_AIM_AT_COORD, Character.Handle, AimCoords.X, AimCoords.Y, AimCoords.Z);
_lastVehicleAim = gameTime;
}
}
}
if (MainVehicle.GetResponsiblePedHandle() != Character.Handle)
{
return;
}
UpdateVehicleInfo();
UpdateVehiclePosition();
}
private void UpdateVehicleInfo()
{
if (LastSyncWasFull)
{
MainVehicle.SetVehicleDamageModel(VehDamageModel);
}
if (VehicleColors != null && VehicleColors != _lastVehicleColors)
{
Function.Call(Hash.SET_VEHICLE_COLOURS, MainVehicle, VehicleColors[0], VehicleColors[1]);
_lastVehicleColors = VehicleColors;
}
if (Character.IsOnBike && MainVehicle.ClassType == VehicleClass.Cycles)
{
bool isFastPedaling = Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, Character.Handle, PedalingAnimDict(), "fast_pedal_char", 3);
if (VehicleSpeed < 0.2f)
{
StopPedalingAnim(isFastPedaling);
}
else if (VehicleSpeed < 11f && !Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, Character.Handle, PedalingAnimDict(), "cruise_pedal_char", 3))
{
StartPedalingAnim(false);
}
else if (VehicleSpeed >= 11f && !isFastPedaling)
{
StartPedalingAnim(true);
}
}
else
{
if (VehicleMods != null && !VehicleMods.Compare(_lastVehicleMods))
{
Function.Call(Hash.SET_VEHICLE_MOD_KIT, MainVehicle, 0);
foreach (KeyValuePair<int, int> mod in VehicleMods)
{
MainVehicle.Mods[(VehicleModType)mod.Key].Index = mod.Value;
}
_lastVehicleMods = VehicleMods;
}
MainVehicle.EngineHealth = VehicleEngineHealth;
if (VehicleDead && !MainVehicle.IsDead)
{
MainVehicle.IsInvincible = false;
MainVehicle.Explode();
}
else if (!VehicleDead && MainVehicle.IsDead)
{
MainVehicle.IsInvincible = true;
MainVehicle.Repair();
}
if (VehIsEngineRunning != MainVehicle.IsEngineRunning)
{
MainVehicle.IsEngineRunning = VehIsEngineRunning;
}
if (MainVehicle.IsPlane)
{
if (VehLandingGear != (byte)MainVehicle.LandingGearState)
{
MainVehicle.LandingGearState = (VehicleLandingGearState)VehLandingGear;
}
}
else
{
if (MainVehicle.IsSubmarineCar)
{
if (Transformed)
{
if (!_lastTransformed)
{
_lastTransformed = true;
Function.Call(Hash._TRANSFORM_VEHICLE_TO_SUBMARINE, MainVehicle.Handle, false);
}
}
else if (_lastTransformed)
{
_lastTransformed = false;
Function.Call(Hash._TRANSFORM_SUBMARINE_TO_VEHICLE, MainVehicle.Handle, false);
}
}
if (MainVehicle.HasRoof)
{
bool roofOpened = MainVehicle.RoofState == VehicleRoofState.Opened || MainVehicle.RoofState == VehicleRoofState.Opening;
if (roofOpened != VehRoofOpened)
{
MainVehicle.RoofState = VehRoofOpened ? VehicleRoofState.Opening : VehicleRoofState.Closing;
}
}
if (VehAreLightsOn != MainVehicle.AreLightsOn)
{
MainVehicle.AreLightsOn = VehAreLightsOn;
}
if (VehAreHighBeamsOn != MainVehicle.AreHighBeamsOn)
{
MainVehicle.AreHighBeamsOn = VehAreHighBeamsOn;
}
if (MainVehicle.HasSiren && VehIsSireneActive != MainVehicle.IsSirenActive)
{
MainVehicle.IsSirenActive = VehIsSireneActive;
}
MainVehicle.AreBrakeLightsOn = VehAreBrakeLightsOn;
if (IsHornActive)
{
if (!_lastHornActive)
{
_lastHornActive = true;
MainVehicle.SoundHorn(99999);
}
}
else if (_lastHornActive)
{
_lastHornActive = false;
MainVehicle.SoundHorn(1);
}
}
}
MainVehicle.CurrentRPM = VehRPM;
}
private void UpdateVehiclePosition()
{
MainVehicle.CustomSteeringAngle(VehicleSteeringAngle.ToRadians());
if (VehicleSpeed != 0f && MainVehicle.IsInRange(Position, 7.0f))
{
int forceMultiplier = (Game.Player.Character.IsInVehicle() && MainVehicle.IsTouching(Game.Player.Character.CurrentVehicle)) ? 1 : 3;
MainVehicle.Velocity = Velocity + forceMultiplier * (Position - MainVehicle.Position);
MainVehicle.Quaternion = Quaternion.Slerp(MainVehicle.Quaternion, VehicleRotation, 0.5f);
}
else if ((Util.GetTickCount64() - _vehicleStopTime) <= 1000)
{
Vector3 posTarget = Util.LinearVectorLerp(MainVehicle.Position, Position + (Position - MainVehicle.Position), Util.GetTickCount64() - _vehicleStopTime, 1000);
MainVehicle.PositionNoOffset = posTarget;
MainVehicle.Quaternion = Quaternion.Slerp(MainVehicle.Quaternion, VehicleRotation, 0.5f);
}
else
{
MainVehicle.PositionNoOffset = Position;
MainVehicle.Quaternion = VehicleRotation;
}
}
#region -- PEDALING --
/*
* Thanks to @oldnapalm.
*/
private string PedalingAnimDict()
{
switch ((VehicleHash)VehicleModelHash)
{
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)
{
Character.Task.PlayAnimation(PedalingAnimDict(), PedalingAnimName(fast), 8.0f, -8.0f, -1, AnimationFlags.Loop | AnimationFlags.AllowRotation, 1.0f);
}
private void StopPedalingAnim(bool fast)
{
Character.Task.ClearAnimation(PedalingAnimDict(), PedalingAnimName(fast));
}
#endregion
}
}

View File

@ -1,582 +0,0 @@
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using Microsoft.ClearScript.V8;
using GTA;
using GTA.Native;
using GTA.Math;
namespace CoopClient
{
/// <summary>
/// Don't use this!
/// </summary>
public class JavascriptHook : Script
{
private static readonly List<V8ScriptEngine> _scriptEngines = new List<V8ScriptEngine>();
internal static bool JavascriptLoaded { get; private set; } = false;
/// <summary>
/// Don't use this!
/// </summary>
public JavascriptHook()
{
Tick += Ontick;
}
private void Ontick(object sender, EventArgs e)
{
if (!Main.MainNetworking.IsOnServer() || _scriptEngines.Count == 0)
{
return;
}
lock (_scriptEngines)
{
_scriptEngines.ForEach(engine =>
{
try
{
engine.Script.API.InvokeTick();
}
catch (Exception ex)
{
GTA.UI.Notification.Show("~r~~h~Javascript Error");
Logger.Write(ex.Message, Logger.LogLevel.Server);
}
});
}
}
internal static void LoadAll()
{
string serverAddress = Main.MainSettings.LastServerAddress.Replace(":", ".");
if (!Directory.Exists("scripts\\resources\\" + serverAddress))
{
try
{
Directory.CreateDirectory("scripts\\resources\\" + serverAddress);
}
catch (Exception ex)
{
GTA.UI.Notification.Show("~r~~h~Javascript Error");
Logger.Write(ex.Message, Logger.LogLevel.Server);
// Without the directory we can't do the other stuff
return;
}
}
lock (_scriptEngines)
{
foreach (string script in Directory.GetFiles("scripts\\resources\\" + serverAddress, "*.js"))
{
try
{
V8ScriptEngine engine = new V8ScriptEngine()
{
AccessContext = typeof(ScriptContext)
};
engine.AddHostObject("API", new ScriptContext());
engine.AddHostType(typeof(Dictionary<,>));
// SHVDN
engine.AddHostType(typeof(Vector3));
engine.AddHostType(typeof(Quaternion));
engine.Execute(File.ReadAllText(script));
try
{
engine.Script.API.InvokeStart();
}
catch (Exception ex)
{
GTA.UI.Notification.Show("~r~~h~Javascript Error");
Logger.Write(ex.Message, Logger.LogLevel.Server);
}
_scriptEngines.Add(engine);
}
catch (Exception ex)
{
GTA.UI.Notification.Show("~r~~h~Javascript Error");
Logger.Write(ex.Message, Logger.LogLevel.Server);
}
}
}
JavascriptLoaded = true;
}
internal static void StopAll()
{
lock (_scriptEngines)
{
_scriptEngines.ForEach(engine =>
{
try
{
engine.Script.API.InvokeStop();
}
catch (Exception ex)
{
GTA.UI.Notification.Show("~r~~h~Javascript Error");
Logger.Write(ex.Message, Logger.LogLevel.Server);
}
engine.Dispose();
});
_scriptEngines.Clear();
}
JavascriptLoaded = false;
}
internal static void InvokePlayerConnect(string username, long nethandle)
{
lock (_scriptEngines)
{
_scriptEngines.ForEach(engine =>
{
try
{
engine.Script.API.InvokePlayerConnect(username, nethandle);
}
catch (Exception ex)
{
GTA.UI.Notification.Show("~r~~h~Javascript Error");
Logger.Write(ex.Message, Logger.LogLevel.Server);
}
});
}
}
internal static void InvokePlayerDisonnect(string username, long nethandle, string reason = null)
{
lock (_scriptEngines)
{
_scriptEngines.ForEach(engine =>
{
try
{
engine.Script.API.InvokePlayerDisonnect(username, nethandle, reason);
}
catch (Exception ex)
{
GTA.UI.Notification.Show("~r~~h~Javascript Error");
Logger.Write(ex.Message, Logger.LogLevel.Server);
}
});
}
}
internal static void InvokeChatMessage(string from, string message)
{
lock (_scriptEngines)
{
_scriptEngines.ForEach(engine =>
{
try
{
engine.Script.API.InvokeChatMessage(from, message);
}
catch (Exception ex)
{
GTA.UI.Notification.Show("~r~~h~Javascript Error");
Logger.Write(ex.Message, Logger.LogLevel.Server);
}
});
}
}
internal static void InvokeServerEvent(string eventName, object[] args)
{
lock (_scriptEngines)
{
_scriptEngines.ForEach(engine =>
{
try
{
engine.Script.API.InvokeServerEvent(eventName, args);
}
catch (Exception ex)
{
GTA.UI.Notification.Show("~r~~h~Javascript Error");
Logger.Write(ex.Message, Logger.LogLevel.Server);
}
});
}
}
}
internal class ScriptContext
{
#region DELEGATES
public delegate void EmptyEvent();
public delegate void PlayerConnectEvent(string username, long nethandle, string reason);
public delegate void ChatMessageEvent(string from, string message);
#endregion
#region EVENTS
private Dictionary<string, Action<object[]>> _serverEvents = new Dictionary<string, Action<object[]>>();
public event EmptyEvent OnStart, OnStop, OnTick;
public event PlayerConnectEvent OnPlayerConnect, OnPlayerDisconnect;
public event ChatMessageEvent OnChatMessage;
internal void InvokeStart()
{
OnStart?.Invoke();
}
internal void InvokeStop()
{
OnStop?.Invoke();
}
internal void InvokeTick()
{
OnTick?.Invoke();
}
internal void InvokePlayerConnect(string username, long nethandle)
{
OnPlayerConnect?.Invoke(username, nethandle, null);
}
internal void InvokePlayerDisonnect(string username, long nethandle, string reason)
{
OnPlayerDisconnect?.Invoke(username, nethandle, reason);
}
internal void InvokeChatMessage(string from, string message)
{
OnChatMessage?.Invoke(from, message);
}
internal void InvokeServerEvent(string eventName, object[] args)
{
_serverEvents.FirstOrDefault(x => x.Key == eventName).Value?.Invoke(args);
}
#endregion
/* ===== PLAYER STUFF ===== */
public void SendLocalMessage(string message)
{
Main.MainChat.AddMessage("JAVASCRIPT", message);
}
public string GetLocalUsername()
{
return Main.MainSettings.Username;
}
public long GetLocalNetHandle()
{
return Main.LocalNetHandle;
}
// This only applies to server-side created objects
public void CleanUpWorld()
{
Main.CleanUpWorld();
}
// This create an object to delete it with CleanUpWorld() or on disconnect
public void CreateObject(string hash, params object[] args)
{
if (!Hash.TryParse(hash, out Hash ourHash) || !Main.CheckNativeHash.ContainsKey((ulong)ourHash))
{
GTA.UI.Notification.Show("~r~~h~Javascript Error");
Logger.Write($"Hash \"{ourHash}\" has not been found!", Logger.LogLevel.Server);
return;
}
int result = Function.Call<int>(ourHash, args.Select(o => new InputArgument(o)).ToArray());
foreach (KeyValuePair<ulong, byte> checkHash in Main.CheckNativeHash)
{
if (checkHash.Key == (ulong)ourHash)
{
lock (Main.ServerItems)
{
Main.ServerItems.Add(result, checkHash.Value);
}
break;
}
}
}
public void SendNotification(string message)
{
GTA.UI.Notification.Show(message);
}
public void SendNotification(string[] messages)
{
SendNotification(string.Concat(messages));
}
public bool IsPlayerInvincible()
{
return Game.Player.Character?.IsInvincible ?? false;
}
public void SetPlayerInvincible(bool invincible)
{
Game.Player.Character.IsInvincible = invincible;
}
public Vector3? GetPlayerPosition()
{
return Game.Player.Character?.Position;
}
public Vector3? GetPlayerRotation()
{
return Game.Player.Character?.Rotation;
}
public void SetPlayerPosition(Vector3 position)
{
Game.Player.Character.Position = position;
}
public void SetPlayerPositionNoOffset(Vector3 position)
{
Game.Player.Character.PositionNoOffset = position;
}
public void SetPlayerRotation(Vector3 rotation)
{
Game.Player.Character.Rotation = rotation;
}
public bool IsPlayerInAnyVehicle()
{
return Game.Player.Character.IsInVehicle();
}
public int? GetCharachterHandle()
{
return Game.Player.Character?.Handle;
}
public int? CreateVehicle(int hash, Vector3 position, Quaternion? Rotation = null)
{
Model model = hash.ModelRequest();
if (model == null)
{
return null;
}
Vehicle veh = World.CreateVehicle(model, position);
model.MarkAsNoLongerNeeded();
if (veh == null)
{
return null;
}
if (Rotation != null)
{
veh.Quaternion = Rotation.Value;
}
return veh.Handle;
}
public Vector3? GetVehiclePosition()
{
return Game.Player.Character.CurrentVehicle?.Position;
}
public Vector3? GetVehicleRotation()
{
return Game.Player.Character.CurrentVehicle?.Rotation;
}
public void SetVehiclePosition(Vector3 position)
{
if (Game.Player.Character.IsInVehicle())
{
Game.Player.Character.CurrentVehicle.Position = position;
}
}
public void SetVehiclePositionNoOffset(Vector3 position)
{
if (Game.Player.Character.IsInVehicle())
{
Game.Player.Character.CurrentVehicle.PositionNoOffset = position;
}
}
public void SetVehicleRotation(Vector3 rotation)
{
if (Game.Player.Character.IsInVehicle())
{
Game.Player.Character.CurrentVehicle.Rotation = rotation;
}
}
public int? GetVehicleHandle()
{
return Game.Player.Character?.CurrentVehicle?.Handle;
}
public int? GetVehicleSeatIndex()
{
return (int)Game.Player.Character?.SeatIndex;
}
public void SetVehicleEngineStatus(bool turnedOn)
{
if (Game.Player.Character.IsInVehicle())
{
Game.Player.Character.CurrentVehicle.IsEngineRunning = turnedOn;
}
}
public bool GetVehicleEngineStatus()
{
return Game.Player.Character.CurrentVehicle?.IsEngineRunning ?? false;
}
public float? GetVehicleHeightAboveGround()
{
return Game.Player.Character.CurrentVehicle?.HeightAboveGround;
}
public string GetVehicleType()
{
Vehicle veh = Game.Player.Character?.CurrentVehicle;
if (veh == null)
{
return null;
}
return Enum.GetName(typeof(VehicleType), veh.Type);
}
public void RepairVehicle()
{
if (Game.Player.Character.IsInVehicle())
{
Game.Player.Character.CurrentVehicle.Repair();
}
}
public void GivePlayerWeapon(uint hash, int ammoCount, bool equipNow, bool isAmmoLoaded)
{
Game.Player.Character.Weapons.Give((WeaponHash)hash, ammoCount, equipNow, isAmmoLoaded);
}
public void SetPlayerHealth(int health)
{
Game.Player.Character.Health = health;
}
public void SetPlayerHealth(float health)
{
Game.Player.Character.HealthFloat = health;
}
public void SetPlayerArmor(int armor)
{
Game.Player.Character.Armor = armor;
}
public void SetPlayerArmor(float armor)
{
Game.Player.Character.ArmorFloat = armor;
}
/* ===== OTHER PLAYER STUFF ===== */
public Vector3 GetPlayerPosition(long nethandle)
{
lock (Main.Players)
{
return Main.Players.ContainsKey(nethandle) ? Main.Players.First(x => x.Key == nethandle).Value.Position : default;
}
}
public Vector3 GetPlayerRotation(long nethandle)
{
lock (Main.Players)
{
return Main.Players.ContainsKey(nethandle) ? Main.Players.First(x => x.Key == nethandle).Value.Rotation : default;
}
}
// Get nethandle and charachter handle
public Dictionary<long, int> GetAllNearbyPlayers(float distance)
{
Dictionary<long, int> result = new Dictionary<long, int>();
lock (Main.Players)
{
Vector3 localPosition = Game.Player.Character.Position;
foreach (KeyValuePair<long, Entities.Player.EntitiesPlayer> player in Main.Players)
{
if (player.Value.Position.DistanceTo2D(localPosition) < distance)
{
// Character handle = 0 (if no character exists)
result.Add(player.Key, player.Value.Character?.Handle ?? 0);
}
}
}
return result;
}
public long GetNetHandleByUsername(string username)
{
lock (Main.Players)
{
return Main.Players.FirstOrDefault(x => x.Value.Username == username).Key;
}
}
/* ===== OTHER STUFF ===== */
public bool IsControlJustReleased(int control)
{
return Game.IsControlJustReleased((Control)control);
}
public bool IsControlJustPressed(int control)
{
return Game.IsControlJustPressed((Control)control);
}
public bool IsControlPressed(int control)
{
return Game.IsControlPressed((Control)control);
}
public bool AnyMapLoaded()
{
return MapLoader.AnyMapLoaded();
}
public void LoadMap(string name)
{
MapLoader.LoadMap(name);
}
public void UnloadMap()
{
MapLoader.UnloadMap();
}
private void AddServerEvent(string eventName, Action<object[]> action)
{
if (!_serverEvents.ContainsKey(eventName))
{
_serverEvents.Add(eventName, action);
}
}
public void AddServerEvent(string eventName, dynamic action)
{
AddServerEvent(eventName, arg => action(arg));
}
public void SendTriggerEvent(string eventName, params object[] args)
{
Main.MainNetworking.SendTriggerEvent(eventName, args);
}
}
}

View File

@ -1,73 +0,0 @@
using System;
using System.IO;
using System.Linq;
namespace CoopClient
{
internal static class Logger
{
public enum LogLevel
{
Normal,
Server,
Custom
}
private static string GetFilePath(LogLevel level, string filepath)
{
string newFilePath = null;
switch (level)
{
case LogLevel.Normal:
newFilePath = "scripts\\CoopLog.txt";
break;
case LogLevel.Server:
newFilePath = $"scripts\\resources\\{Main.MainSettings.LastServerAddress.Replace(":", ".")}\\CoopLog.txt";
break;
case LogLevel.Custom:
if (string.IsNullOrEmpty(filepath))
{
goto case LogLevel.Normal;
}
newFilePath = filepath;
break;
}
return newFilePath;
}
public static void Write(string message, LogLevel level = LogLevel.Normal, string filepath = null)
{
string newFilePath = GetFilePath(level, filepath);
try
{
if (File.Exists(newFilePath))
{
// Check if the rows are under 30 and delete the first 10 if so to avoid large logs
// Firstly get all lines
string[] oldLines = File.ReadAllLines(newFilePath);
// Check the length of the lines
if (oldLines.Length >= 30)
{
// Now overwrite the file without the first 10 lines
File.WriteAllLines(newFilePath, oldLines.Skip(10).ToArray());
}
}
using (StreamWriter sw = new StreamWriter(newFilePath, true))
{
sw.WriteLine($"[{DateTime.Now.ToLongTimeString()} {DateTime.Now.ToLongDateString()}] : {message}");
sw.Flush();
sw.Close();
}
}
catch
{ }
}
}
}

View File

@ -1,47 +1,58 @@
using System;
#undef DEBUG
using System;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Drawing;
using CoopClient.Entities.Player;
using CoopClient.Entities.NPC;
using CoopClient.Menus;
using System.Threading;
using System.Diagnostics;
using RageCoop.Client.Menus;
using RageCoop.Core;
using GTA;
using GTA.Native;
using GTA.Math;
namespace CoopClient
namespace RageCoop.Client
{
/// <summary>
/// Don't use it!
/// </summary>
public class Main : Script
{
internal static RelationshipGroup RelationshipGroup;
private bool _gameLoaded = false;
internal static readonly string CurrentVersion = "V1_4_1";
internal static bool ShareNPCsWithPlayers = false;
internal static bool DisableTraffic = false;
internal static bool NPCsAllowed = false;
private static bool _isGoingToCar = false;
internal static Settings MainSettings = null;
internal static Networking MainNetworking = null;
public static readonly string CurrentVersion = "V1_4_1";
public static int MyPlayerID=0;
public static bool DisableTraffic = true;
public static bool NPCsAllowed = false;
internal static RelationshipGroup SyncedPedsGroup;
public static Settings Settings = null;
public static Networking MainNetworking = null;
#if !NON_INTERACTIVE
internal static MenusMain MainMenu = null;
public static MenusMain MainMenu = null;
#endif
internal static Chat MainChat = null;
internal static PlayerList MainPlayerList = null;
public static Chat MainChat = null;
public static PlayerList MainPlayerList = new PlayerList();
public static Stopwatch Counter = new Stopwatch();
internal static long LocalNetHandle = 0;
internal static Dictionary<long, EntitiesPlayer> Players = null;
internal static Dictionary<long, EntitiesNPC> NPCs = null;
internal static Dictionary<long, int> NPCsVehicles = null;
public static ulong Ticked = 0;
/*
// <ID,Entity>
public static Dictionary<int, CharacterEntity> Characters = new Dictionary<int, CharacterEntity>();
// Dictionary<int ID, Entuty>
public static Dictionary<int, VehicleEntity> Vehicles = new Dictionary<int, VehicleEntity>();
*/
public static Loggger Logger=new Loggger("Scripts\\RageCoop\\RageCoop.Client.log");
private static List<Func<bool>> QueuedActions = new List<Func<bool>>();
/// <summary>
/// Don't use it!
@ -49,7 +60,7 @@ namespace CoopClient
public Main()
{
// Required for some synchronization!
if (Game.Version < GameVersion.v1_0_1290_1_Steam)
/*if (Game.Version < GameVersion.v1_0_1290_1_Steam)
{
Tick += (object sender, EventArgs e) =>
{
@ -57,7 +68,7 @@ namespace CoopClient
{
return;
}
if (!_gameLoaded)
{
GTA.UI.Notification.Show("~r~Please update your GTA5 to v1.0.1290 or newer!", true);
@ -65,25 +76,25 @@ namespace CoopClient
}
};
return;
}
MainSettings = Util.ReadSettings();
}*/
SyncedPedsGroup=World.AddRelationshipGroup("SYNCPED");
Game.Player.Character.RelationshipGroup.SetRelationshipBetweenGroups(SyncedPedsGroup, Relationship.Neutral, true);
Settings = Util.ReadSettings();
MainNetworking = new Networking();
MainNetworking.Start();
#if !NON_INTERACTIVE
MainMenu = new MenusMain();
#endif
MainChat = new Chat();
Players = new Dictionary<long, EntitiesPlayer>();
NPCs = new Dictionary<long, EntitiesNPC>();
NPCsVehicles = new Dictionary<long, int>();
Logger.LogLevel =0;
Tick += OnTick;
KeyDown += OnKeyDown;
Aborted += (object sender, EventArgs e) => CleanUp();
Util.NativeMemory();
Counter.Restart();
}
#if DEBUG
private ulong _lastDebugData;
private int _debugBytesSend;
@ -97,8 +108,6 @@ namespace CoopClient
}
else if (!_gameLoaded && (_gameLoaded = true))
{
RelationshipGroup = World.AddRelationshipGroup("SYNCPED");
Game.Player.Character.RelationshipGroup.SetRelationshipBetweenGroups(RelationshipGroup, Relationship.Neutral, true);
#if !NON_INTERACTIVE
GTA.UI.Notification.Show(GTA.UI.NotificationIcon.AllPlayersConf, "RAGECOOP", "Welcome!", "Press ~g~F9~s~ to open the menu.");
#endif
@ -107,28 +116,36 @@ namespace CoopClient
#if !NON_INTERACTIVE
MainMenu.MenuPool.Process();
#endif
MainNetworking.ReceiveMessages();
if (_isGoingToCar && Game.Player.Character.IsInVehicle())
{
_isGoingToCar = false;
}
DoQueuedActions();
if (!MainNetworking.IsOnServer())
{
return;
}
if (Game.TimeScale!=1)
{
Game.TimeScale=1;
}
try
{
MainNetworking.Tick();
}
catch (Exception ex)
{
Logger.Error(ex);
}
if (!DownloadManager.DownloadComplete)
{
DownloadManager.RenderProgress();
}
else if (!JavascriptHook.JavascriptLoaded)
{
MapLoader.LoadAll();
JavascriptHook.LoadAll();
}
MapLoader.LoadAll();
#if DEBUG
if (MainNetworking.ShowNetworkInfo)
@ -150,6 +167,8 @@ namespace CoopClient
}
#endif
MainChat.Tick();
MainPlayerList.Tick();
@ -160,16 +179,13 @@ namespace CoopClient
}
#endif
// Display all players
foreach (KeyValuePair<long, EntitiesPlayer> player in Players)
{
player.Value.Update();
}
MainNetworking.SendPlayerData();
Ticked++;
}
#if !NON_INTERACTIVE
bool _lastEnteringVeh=false;
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (MainChat.Focused)
@ -177,7 +193,6 @@ namespace CoopClient
MainChat.OnKeyDown(e.KeyCode);
return;
}
if (Game.IsControlPressed(GTA.Control.FrontendPause))
{
Function.Call(Hash.ACTIVATE_FRONTEND_MENU, Function.Call<int>(Hash.GET_HASH_KEY, "FE_MENU_VERSION_SP_PAUSE"), false, 0);
@ -197,28 +212,10 @@ namespace CoopClient
MainMenu.MainMenu.Visible = true;
}
break;
case Keys.G:
if (_isGoingToCar)
{
Game.Player.Character.Task.ClearAll();
_isGoingToCar = false;
}
else if (!Game.Player.Character.IsInVehicle())
{
Vehicle veh = World.GetNearbyVehicles(Game.Player.Character, 5f).FirstOrDefault();
if (veh != null)
{
for (int i = 0; i < veh.PassengerCapacity; i++)
{
if (veh.IsSeatFree((VehicleSeat)i))
{
Game.Player.Character.Task.EnterVehicle(veh, (VehicleSeat)i);
_isGoingToCar = true;
break;
}
}
}
}
case Keys.J:
Game.Player.Character.CurrentVehicle.ApplyForce(new Vector3(0, 0, 100));
Script.Yield();
GTA.UI.Notification.Show(Game.Player.Character.CurrentVehicle.Speed.ToString());
break;
default:
if (Game.IsControlJustPressed(GTA.Control.MultiplayerInfo))
@ -238,6 +235,46 @@ namespace CoopClient
}
break;
}
if (e.KeyCode==Keys.L)
{
GTA.UI.Notification.Show(DumpCharacters());
}
if (e.KeyCode==Keys.I)
{
GTA.UI.Notification.Show(DumpPlayers());
}
if (e.KeyCode==Keys.U)
{
Debug.ShowTimeStamps();
}
if (e.KeyCode==Keys.G)
{
var P = Game.Player.Character;
if (P.IsInVehicle())
{
_lastEnteringVeh=false;
P.Task.LeaveVehicle();
}
else
{
var V = World.GetClosestVehicle(P.Position, 50);
if (_lastEnteringVeh)
{
P.Task.ClearAllImmediately();
_lastEnteringVeh = false;
}
else if (V!=null)
{
var seat = Util.getNearestSeat(P, V);
P.Task.EnterVehicle(V, seat);
_lastEnteringVeh=true;
}
}
}
}
#else
private void OnKeyDown(object sender, KeyEventArgs e)
@ -266,33 +303,18 @@ namespace CoopClient
}
#endif
internal static void CleanUp()
public static void CleanUp()
{
MainChat.Clear();
EntityPool.Cleanup();
MainPlayerList=new PlayerList();
foreach (KeyValuePair<long, EntitiesPlayer> player in Players)
{
player.Value.Character?.AttachedBlip?.Delete();
player.Value.Character?.CurrentVehicle?.Delete();
player.Value.Character?.Kill();
player.Value.Character?.Delete();
player.Value.PedBlip?.Delete();
player.Value.ParachuteProp?.Delete();
}
Players.Clear();
Main.MyPlayerID=default;
foreach (KeyValuePair<long, EntitiesNPC> npc in NPCs)
{
npc.Value.Character?.CurrentVehicle?.Delete();
npc.Value.Character?.Kill();
npc.Value.Character?.Delete();
}
NPCs.Clear();
NPCsVehicles.Clear();
}
internal static readonly Dictionary<ulong, byte> CheckNativeHash = new Dictionary<ulong, byte>()
public static readonly Dictionary<ulong, byte> CheckNativeHash = new Dictionary<ulong, byte>()
{
{ 0xD49F9B0955C367DE, 1 }, // Entities
{ 0xEF29A16337FACADB, 1 }, //
@ -309,8 +331,8 @@ namespace CoopClient
{ 0x5A039BB0BCA604B6, 4 }, //
{ 0x0134F0835AB6BFCB, 5 } // Checkpoints
};
internal static Dictionary<int, byte> ServerItems = new Dictionary<int, byte>();
internal static void CleanUpWorld()
public static Dictionary<int, byte> ServerItems = new Dictionary<int, byte>();
public static void CleanUpWorld()
{
if (ServerItems.Count == 0)
{
@ -353,7 +375,7 @@ namespace CoopClient
catch
{
GTA.UI.Notification.Show("~r~~h~CleanUpWorld() Error");
Logger.Write($"CleanUpWorld(): ~r~Item {item.Value} cannot be deleted!", Logger.LogLevel.Server);
Logger.Error($"CleanUpWorld(): ~r~Item {item.Value} cannot be deleted!");
}
}
@ -361,11 +383,86 @@ namespace CoopClient
}
}
private static void DoQueuedActions()
{
lock (QueuedActions)
{
foreach (var action in QueuedActions.ToArray())
{
try
{
if (action())
{
QueuedActions.Remove(action);
}
}
catch(Exception ex)
{
GTA.UI.Screen.ShowSubtitle(ex.ToString());
QueuedActions.Remove(action);
}
}
}
}
/// <summary>
/// Queue an action to be executed on next tick, allowing you to call scripting API from another thread.
/// </summary>
/// <param name="a"> The action to be executed, must return a bool indicating whether the action cane be removed after execution.</param>
public static void QueueAction(Func<bool> a)
{
lock (QueuedActions)
{
QueuedActions.Add(a);
}
}
public static void QueueAction(Action a)
{
lock (QueuedActions)
{
QueuedActions.Add(() => { a(); return true; }) ;
}
}
/// <summary>
/// Clears all queued actions
/// </summary>
public static void ClearQueuedActions()
{
lock (QueuedActions) { QueuedActions.Clear(); }
}
public static string DumpCharacters()
{
string s = "Characters:";
lock (EntityPool.PedsLock)
{
foreach (int id in EntityPool.GetPedIDs())
{
var c = EntityPool.GetPedByID(id);
s+=$"\r\nID:{c.ID} Owner:{c.OwnerID} LastUpdated:{c.LastUpdated} LastSynced:{c.LastSynced} LastStateSynced:{c.LastStateSynced}";
// s+=$"\r\n{c.IsAiming} {c.IsJumping} {c.IsOnFire} {c.IsOnLadder} {c.IsRagdoll} {c.IsReloading} {c.IsShooting} {c.Speed}";
}
}
Logger.Trace(s);
return s;
}
public static string DumpPlayers()
{
string s = "Players:";
foreach (PlayerData p in MainPlayerList.Players)
{
s+=$"\r\nID:{p.PedID} Username:{p.Username}";
}
Logger.Trace(s);
return s;
}
#if DEBUG
private ulong _artificialLagCounter;
internal static EntitiesPlayer DebugSyncPed;
internal static ulong LastFullDebugSync = 0;
internal static bool UseDebug = false;
public static EntitiesPlayer DebugSyncPed;
public static ulong LastFullDebugSync = 0;
public static bool UseDebug = false;
private void Debug()
{

View File

@ -3,12 +3,12 @@ using System.IO;
using System.Linq;
using System.Xml.Serialization;
using System.Collections.Generic;
using RageCoop.Core;
using GTA;
using GTA.Math;
using GTA.Native;
namespace CoopClient
namespace RageCoop.Client
{
/// <summary>
///
@ -51,7 +51,7 @@ namespace CoopClient
public int Texture { get; set; }
}
internal static class MapLoader
public static class MapLoader
{
// string = file name
private static readonly Dictionary<string, CoopMap> _maps = new Dictionary<string, CoopMap>();
@ -59,7 +59,7 @@ namespace CoopClient
public static void LoadAll()
{
string downloadFolder = $"scripts\\resources\\{Main.MainSettings.LastServerAddress.Replace(":", ".")}";
string downloadFolder = $"scripts\\resources\\{Main.Settings.LastServerAddress.Replace(":", ".")}";
if (!Directory.Exists(downloadFolder))
{
@ -69,7 +69,7 @@ namespace CoopClient
}
catch (Exception ex)
{
Logger.Write(ex.Message, Logger.LogLevel.Server);
Main.Logger.Error(ex.Message);
// Without the directory we can't do the other stuff
return;
@ -95,8 +95,8 @@ namespace CoopClient
}
catch (Exception ex)
{
Logger.Write($"The map with the name \"{fileName}\" couldn't be added!", Logger.LogLevel.Server);
Logger.Write($"{ex.Message}", Logger.LogLevel.Server);
Main.Logger.Error($"The map with the name \"{fileName}\" couldn't be added!");
Main.Logger.Error($"{ex.Message}");
continue;
}
}
@ -113,7 +113,7 @@ namespace CoopClient
if (!_maps.ContainsKey(name) || _createdObjects.Count != 0)
{
GTA.UI.Notification.Show($"The map with the name \"{name}\" couldn't be loaded!");
Logger.Write($"The map with the name \"{name}\" couldn't be loaded!", Logger.LogLevel.Server);
Main.Logger.Error($"The map with the name \"{name}\" couldn't be loaded!");
return;
}
@ -124,7 +124,7 @@ namespace CoopClient
Model model = prop.Hash.ModelRequest();
if (model == null)
{
Logger.Write($"Model for object \"{model.Hash}\" couldn't be loaded!", Logger.LogLevel.Server);
Main.Logger.Error($"Model for object \"{model.Hash}\" couldn't be loaded!");
continue;
}
@ -132,7 +132,7 @@ namespace CoopClient
model.MarkAsNoLongerNeeded();
if (handle == 0)
{
Logger.Write($"Object \"{prop.Hash}\" couldn't be created!", Logger.LogLevel.Server);
Main.Logger.Error($"Object \"{prop.Hash}\" couldn't be created!");
continue;
}

View File

@ -5,33 +5,35 @@ using System.Drawing;
using LemonUI;
using LemonUI.Menus;
namespace CoopClient.Menus
namespace RageCoop.Client.Menus
{
/// <summary>
/// Don't use it!
/// </summary>
public class MenusMain
{
internal ObjectPool MenuPool = new ObjectPool();
public ObjectPool MenuPool = new ObjectPool();
internal NativeMenu MainMenu = new NativeMenu("RAGECOOP", "MAIN")
public NativeMenu MainMenu = new NativeMenu("RAGECOOP", "MAIN")
{
UseMouse = false,
Alignment = Main.MainSettings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
};
#region SUB
internal Sub.Settings SubSettings = new Sub.Settings();
internal Sub.Servers ServerList = new Sub.Servers();
public Sub.Settings SubSettings = new Sub.Settings();
public Sub.Servers ServerList = new Sub.Servers();
#endregion
#region ITEMS
private readonly NativeItem _usernameItem = new NativeItem("Username") { AltTitle = Main.MainSettings.Username };
internal readonly NativeItem ServerIpItem = new NativeItem("Server IP") { AltTitle = Main.MainSettings.LastServerAddress };
private readonly NativeItem _usernameItem = new NativeItem("Username") { AltTitle = Main.Settings.Username };
public readonly NativeItem ServerIpItem = new NativeItem("Server IP") { AltTitle = Main.Settings.LastServerAddress };
private readonly NativeItem _serverConnectItem = new NativeItem("Connect");
private readonly NativeItem _aboutItem = new NativeItem("About", "~y~SOURCE~s~~n~" +
"https://github.com/RAGECOOP~n~" +
"~y~VERSION~s~~n~" +
Main.CurrentVersion.Replace("_", ".")) { LeftBadge = new LemonUI.Elements.ScaledTexture("commonmenu", "shop_new_star") };
#endregion
/// <summary>
@ -44,7 +46,7 @@ namespace CoopClient.Menus
_usernameItem.Activated += UsernameActivated;
ServerIpItem.Activated += ServerIpActivated;
_serverConnectItem.Activated += (sender, item) => { Main.MainNetworking.DisConnectFromServer(Main.MainSettings.LastServerAddress); };
_serverConnectItem.Activated += (sender, item) => { Main.MainNetworking.DisConnectFromServer(Main.Settings.LastServerAddress); };
MainMenu.AddSubMenu(ServerList.MainMenu);
@ -53,39 +55,40 @@ namespace CoopClient.Menus
MainMenu.Add(_serverConnectItem);
MainMenu.AddSubMenu(SubSettings.MainMenu);
MainMenu.AddSubMenu(DebugMenu.Menu);
MainMenu.Add(_aboutItem);
MenuPool.Add(ServerList.MainMenu);
MenuPool.Add(MainMenu);
MenuPool.Add(SubSettings.MainMenu);
MenuPool.Add(DebugMenu.Menu);
}
internal void UsernameActivated(object a, System.EventArgs b)
public void UsernameActivated(object a, System.EventArgs b)
{
string newUsername = Game.GetUserInput(WindowTitle.EnterMessage20, _usernameItem.AltTitle, 20);
if (!string.IsNullOrWhiteSpace(newUsername))
{
Main.MainSettings.Username = newUsername;
Main.Settings.Username = newUsername;
Util.SaveSettings();
_usernameItem.AltTitle = newUsername;
}
}
internal void ServerIpActivated(object a, System.EventArgs b)
public void ServerIpActivated(object a, System.EventArgs b)
{
string newServerIp = Game.GetUserInput(WindowTitle.EnterMessage60, ServerIpItem.AltTitle, 60);
if (!string.IsNullOrWhiteSpace(newServerIp) && newServerIp.Contains(":"))
{
Main.MainSettings.LastServerAddress = newServerIp;
Main.Settings.LastServerAddress = newServerIp;
Util.SaveSettings();
ServerIpItem.AltTitle = newServerIp;
}
}
internal void InitiateConnectionMenuSetting()
public void InitiateConnectionMenuSetting()
{
MainMenu.Items[0].Enabled = false;
MainMenu.Items[1].Enabled = false;
@ -93,7 +96,7 @@ namespace CoopClient.Menus
MainMenu.Items[3].Enabled = false;
}
internal void ConnectedMenuSetting()
public void ConnectedMenuSetting()
{
MainMenu.Items[3].Enabled = true;
MainMenu.Items[3].Title = "Disconnect";
@ -103,7 +106,7 @@ namespace CoopClient.Menus
ServerList.MainMenu.Visible = false;
}
internal void DisconnectedMenuSetting()
public void DisconnectedMenuSetting()
{
MainMenu.Items[0].Enabled = true;
MainMenu.Items[1].Enabled = true;

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LemonUI;
using LemonUI.Menus;
using GTA;
namespace RageCoop.Client
{
internal static class DebugMenu
{
public static NativeMenu Menu = new NativeMenu("RAGECOOP", "Debug", "Debug settings") {
UseMouse = false,
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
};
private static NativeItem d1=new NativeItem("PositionPrediction");
static DebugMenu()
{
d1.Activated+=(sender,e) =>
{
try{ SyncParameters.PositioinPrediction =float.Parse(Game.GetUserInput(WindowTitle.EnterMessage20, SyncParameters.PositioinPrediction.ToString(), 20));}
catch { }
Update();
};
Menu.Add(d1);
Menu.Opening+=(sender, e) =>Update();
Update();
}
private static void Update()
{
d1.AltTitle = SyncParameters.PositioinPrediction.ToString();
}
}
}

View File

@ -7,9 +7,9 @@ using Newtonsoft.Json;
using LemonUI.Menus;
namespace CoopClient.Menus.Sub
namespace RageCoop.Client.Menus.Sub
{
internal class ServerListClass
public class ServerListClass
{
[JsonProperty("address")]
public string Address { get; set; }
@ -36,14 +36,14 @@ namespace CoopClient.Menus.Sub
/// <summary>
/// Don't use it!
/// </summary>
internal class Servers
public class Servers
{
internal NativeMenu MainMenu = new NativeMenu("RAGECOOP", "Servers", "Go to the server list")
public NativeMenu MainMenu = new NativeMenu("RAGECOOP", "Servers", "Go to the server list")
{
UseMouse = false,
Alignment = Main.MainSettings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
};
internal NativeItem ResultItem = null;
public NativeItem ResultItem = null;
/// <summary>
/// Don't use it!
@ -81,7 +81,7 @@ namespace CoopClient.Menus.Sub
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
WebClient client = new WebClient();
string data = client.DownloadString(Main.MainSettings.MasterServer);
string data = client.DownloadString(Main.Settings.MasterServer);
serverList = JsonConvert.DeserializeObject<List<ServerListClass>>(data);
}
catch (Exception ex)
@ -120,7 +120,7 @@ namespace CoopClient.Menus.Sub
Main.MainMenu.MainMenu.Visible = true;
#endif
Main.MainSettings.LastServerAddress = address;
Main.Settings.LastServerAddress = address;
Util.SaveSettings();
}
catch (Exception ex)

View File

@ -1,23 +1,23 @@
using System.Drawing;
#undef DEBUG
using System.Drawing;
using LemonUI.Menus;
namespace CoopClient.Menus.Sub
namespace RageCoop.Client.Menus.Sub
{
/// <summary>
/// Don't use it!
/// </summary>
public class Settings
{
internal NativeMenu MainMenu = new NativeMenu("RAGECOOP", "Settings", "Go to the settings")
public NativeMenu MainMenu = new NativeMenu("RAGECOOP", "Settings", "Go to the settings")
{
UseMouse = false,
Alignment = Main.MainSettings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
};
private readonly NativeCheckboxItem _disableTrafficItem = new NativeCheckboxItem("Disable Traffic (NPCs/Vehicles)", "Local traffic only", Main.DisableTraffic);
private readonly NativeCheckboxItem _shareNPCsItem = new NativeCheckboxItem("Share NPCs", "~y~WARNING:~s~ High network traffic!", Main.ShareNPCsWithPlayers) { Enabled = false };
private readonly NativeCheckboxItem _flipMenuItem = new NativeCheckboxItem("Flip menu", Main.MainSettings.FlipMenu);
private readonly NativeCheckboxItem _flipMenuItem = new NativeCheckboxItem("Flip menu", Main.Settings.FlipMenu);
#if DEBUG
private readonly NativeCheckboxItem _useDebugItem = new NativeCheckboxItem("Debug", Main.UseDebug);
private readonly NativeCheckboxItem _showNetworkInfoItem = new NativeCheckboxItem("Show Network Info", Main.MainNetworking.ShowNetworkInfo);
@ -32,7 +32,6 @@ namespace CoopClient.Menus.Sub
MainMenu.Title.Color = Color.FromArgb(255, 165, 0);
_disableTrafficItem.CheckboxChanged += DisableTrafficCheckboxChanged;
_shareNPCsItem.CheckboxChanged += (item, check) => { Main.ShareNPCsWithPlayers = _shareNPCsItem.Checked; };
_flipMenuItem.CheckboxChanged += FlipMenuCheckboxChanged;
#if DEBUG
_useDebugItem.CheckboxChanged += UseDebugCheckboxChanged;
@ -40,7 +39,6 @@ namespace CoopClient.Menus.Sub
#endif
MainMenu.Add(_disableTrafficItem);
MainMenu.Add(_shareNPCsItem);
MainMenu.Add(_flipMenuItem);
#if DEBUG
MainMenu.Add(_useDebugItem);
@ -48,26 +46,12 @@ namespace CoopClient.Menus.Sub
#endif
}
internal void DisableTrafficCheckboxChanged(object a, System.EventArgs b)
public void DisableTrafficCheckboxChanged(object a, System.EventArgs b)
{
Main.DisableTraffic = _disableTrafficItem.Checked;
if (_disableTrafficItem.Checked)
{
if (_shareNPCsItem.Checked)
{
_shareNPCsItem.Checked = false;
}
_shareNPCsItem.Enabled = false;
}
else if (Main.NPCsAllowed && !_shareNPCsItem.Enabled)
{
_shareNPCsItem.Enabled = true;
}
}
internal void FlipMenuCheckboxChanged(object a, System.EventArgs b)
public void FlipMenuCheckboxChanged(object a, System.EventArgs b)
{
#if !NON_INTERACTIVE
Main.MainMenu.MainMenu.Alignment = _flipMenuItem.Checked ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left;
@ -75,12 +59,12 @@ namespace CoopClient.Menus.Sub
MainMenu.Alignment = _flipMenuItem.Checked ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left;
Main.MainMenu.ServerList.MainMenu.Alignment = _flipMenuItem.Checked ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left;
Main.MainSettings.FlipMenu = _flipMenuItem.Checked;
Main.Settings.FlipMenu = _flipMenuItem.Checked;
Util.SaveSettings();
}
#if DEBUG
internal void UseDebugCheckboxChanged(object a, System.EventArgs b)
public void UseDebugCheckboxChanged(object a, System.EventArgs b)
{
Main.UseDebug = _useDebugItem.Checked;
@ -98,7 +82,7 @@ namespace CoopClient.Menus.Sub
}
}
internal void ShowNetworkInfoCheckboxChanged(object a, System.EventArgs b)
public void ShowNetworkInfoCheckboxChanged(object a, System.EventArgs b)
{
Main.MainNetworking.ShowNetworkInfo = _showNetworkInfoItem.Checked;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,230 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using Lidgren.Network;
using RageCoop.Core;
using System.Threading.Tasks;
using System.Threading;
using GTA;
using GTA.Native;
namespace RageCoop.Client
{
public partial class Networking
{
public NetClient Client;
public float Latency = 0;
public bool ShowNetworkInfo = false;
public int BytesReceived = 0;
public int BytesSend = 0;
private Thread ReceiveThread;
public void DisConnectFromServer(string address)
{
if (IsOnServer())
{
Client.Disconnect("Bye!");
}
else
{
// 623c92c287cc392406e7aaaac1c0f3b0 = RAGECOOP
NetPeerConfiguration config = new NetPeerConfiguration("623c92c287cc392406e7aaaac1c0f3b0")
{
AutoFlushSendQueue = true
};
config.EnableMessageType(NetIncomingMessageType.ConnectionLatencyUpdated);
Client = new NetClient(config);
Client.Start();
string[] ip = new string[2];
int idx = address.LastIndexOf(':');
if (idx != -1)
{
ip[0] = address.Substring(0, idx);
ip[1] = address.Substring(idx + 1);
}
if (ip.Length != 2)
{
throw new Exception("Malformed URL");
}
// Send HandshakePacket
EntityPool.AddPlayer();
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
new Packets.Handshake()
{
PedID = Main.MyPlayerID,
Username = Main.Settings.Username,
ModVersion = Main.CurrentVersion,
NPCsAllowed = false
}.Pack(outgoingMessage);
Client.Connect(ip[0], short.Parse(ip[1]), outgoingMessage);
}
}
public bool IsOnServer()
{
return Client?.ConnectionStatus == NetConnectionStatus.Connected;
}
public void Start()
{
ReceiveThread=new Thread(() =>
{
while (true)
{
try
{
ReceiveMessages();
}
catch (Exception ex)
{
Main.Logger.Error(ex);
}
Thread.Sleep(5);
}
});
ReceiveThread.Start();
}
#region -- GET --
#region -- PLAYER --
private void PlayerConnect(Packets.PlayerConnect packet)
{
var p = new PlayerData
{
PedID = packet.PedID,
Username= packet.Username,
};
GTA.UI.Notification.Show($"{p.Username} connected.");
Main.MainPlayerList.SetPlayer(packet.PedID, packet.Username);
Main.Logger.Debug($"player connected:{p.Username}");
Main.DumpCharacters();
COOPAPI.Connected(packet.PedID);
}
private void PlayerDisconnect(Packets.PlayerDisconnect packet)
{
var name=Main.MainPlayerList.GetPlayer(packet.PedID).Username;
GTA.UI.Notification.Show($"{name} left.");
COOPAPI.Disconnected(packet.PedID);
Main.MainPlayerList.RemovePlayer(packet.PedID);
EntityPool.RemoveAllFromPlayer(packet.PedID);
}
private object DecodeNativeCall(ulong hash, List<object> args, bool returnValue, byte? returnType = null)
{
List<InputArgument> arguments = new List<InputArgument>();
if (args == null || args.Count == 0)
{
return null;
}
for (ushort i = 0; i < args.Count; i++)
{
object x = args.ElementAt(i);
switch (x)
{
case int _:
arguments.Add((int)x);
break;
case bool _:
arguments.Add((bool)x);
break;
case float _:
arguments.Add((float)x);
break;
case string _:
arguments.Add((string)x);
break;
case LVector3 _:
LVector3 vector = (LVector3)x;
arguments.Add((float)vector.X);
arguments.Add((float)vector.Y);
arguments.Add((float)vector.Z);
break;
default:
GTA.UI.Notification.Show("[DecodeNativeCall][" + hash + "]: Type of argument not found!");
return null;
}
}
if (!returnValue)
{
Function.Call((Hash)hash, arguments.ToArray());
return null;
}
switch (returnType.Value)
{
case 0x00: // int
return Function.Call<int>((Hash)hash, arguments.ToArray());
case 0x01: // bool
return Function.Call<bool>((Hash)hash, arguments.ToArray());
case 0x02: // float
return Function.Call<float>((Hash)hash, arguments.ToArray());
case 0x03: // string
return Function.Call<string>((Hash)hash, arguments.ToArray());
case 0x04: // vector3
return Function.Call<GTA.Math.Vector3>((Hash)hash, arguments.ToArray()).ToLVector();
default:
GTA.UI.Notification.Show("[DecodeNativeCall][" + hash + "]: Type of return not found!");
return null;
}
}
private void DecodeNativeResponse(Packets.NativeResponse packet)
{
object result = DecodeNativeCall(packet.Hash, packet.Args, true, packet.ResultType);
if (Main.CheckNativeHash.ContainsKey(packet.Hash))
{
foreach (KeyValuePair<ulong, byte> hash in Main.CheckNativeHash)
{
if (hash.Key == packet.Hash)
{
lock (Main.ServerItems)
{
Main.ServerItems.Add((int)result, hash.Value);
}
break;
}
}
}
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
new Packets.NativeResponse()
{
Hash = 0,
Args = new List<object>() { result },
ID = packet.ID
}.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Native);
Client.FlushSendQueue();
}
#endregion // -- PLAYER --
#endregion
public void Tick()
{
// Sync
EntityPool.DoSync();
}
}
}

View File

@ -0,0 +1,414 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using Lidgren.Network;
using RageCoop.Core;
using GTA;
using GTA.Math;
using GTA.Native;
namespace RageCoop.Client
{
public partial class Networking
{
public void ReceiveMessages()
{
if (Client == null)
{
return;
}
NetIncomingMessage message;
while ((message = Client.ReadMessage()) != null)
{
BytesReceived += message.LengthBytes;
switch (message.MessageType)
{
case NetIncomingMessageType.StatusChanged:
NetConnectionStatus status = (NetConnectionStatus)message.ReadByte();
string reason = message.ReadString();
switch (status)
{
case NetConnectionStatus.InitiatedConnect:
#if !NON_INTERACTIVE
Main.MainMenu.InitiateConnectionMenuSetting();
#endif
Main.QueueAction(() => { GTA.UI.Notification.Show("~y~Trying to connect..."); return true; });
break;
case NetConnectionStatus.Connected:
if (message.SenderConnection.RemoteHailMessage.ReadByte() != (byte)PacketTypes.Handshake)
{
Client.Disconnect("Wrong packet!");
}
else
{
int len = message.SenderConnection.RemoteHailMessage.ReadInt32();
byte[] data = message.SenderConnection.RemoteHailMessage.ReadBytes(len);
Packets.Handshake handshakePacket = new Packets.Handshake();
handshakePacket.Unpack(data);
// Main.LocalNetHandle = handshakePacket.NetHandle;
Main.NPCsAllowed = handshakePacket.NPCsAllowed;
#if !NON_INTERACTIVE
#endif
COOPAPI.Connected();
Main.QueueAction(() => {
Main.MainMenu.ConnectedMenuSetting();
Main.MainChat.Init();
Main.MainPlayerList = new PlayerList();
GTA.UI.Notification.Show("~g~Connected!");
});
Main.Logger.Info(">> Connected <<");
}
break;
case NetConnectionStatus.Disconnected:
DownloadManager.Cleanup(true);
// Reset all values
Latency = 0;
Main.QueueAction(() => { Main.CleanUpWorld();});
Main.NPCsAllowed = false;
if (Main.MainChat.Focused)
{
Main.MainChat.Focused = false;
}
Main.MainPlayerList = null;
Main.QueueAction(() => Main.CleanUp());
#if !NON_INTERACTIVE
Main.MainMenu.DisconnectedMenuSetting();
#endif
COOPAPI.Disconnected(reason);
Main.QueueAction(() =>
GTA.UI.Notification.Show("~r~Disconnected: " + reason));
MapLoader.DeleteAll();
Main.Logger.Info($">> Disconnected << reason: {reason}");
break;
}
break;
case NetIncomingMessageType.Data:
if (message.LengthBytes==0) { continue; }
var packetType = (PacketTypes)message.ReadByte();
try
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
switch (packetType)
{
case PacketTypes.CleanUpWorld:
{
Main.QueueAction(() => { Main.CleanUpWorld(); return true; });
}
break;
case PacketTypes.PlayerConnect:
{
Packets.PlayerConnect packet = new Packets.PlayerConnect();
packet.Unpack(data);
Main.QueueAction(() =>PlayerConnect(packet));
}
break;
case PacketTypes.PlayerDisconnect:
{
Packets.PlayerDisconnect packet = new Packets.PlayerDisconnect();
packet.Unpack(data);
Main.QueueAction(() =>PlayerDisconnect(packet));
}
break;
#region ENTITY SYNC
case PacketTypes.VehicleSync:
{
Packets.VehicleSync packet = new Packets.VehicleSync();
packet.Unpack(data);
VehicleSync(packet);
}
break;
case PacketTypes.CharacterSync:
{
Packets.PedSync packet = new Packets.PedSync();
packet.Unpack(data);
PedSync(packet);
}
break;
case PacketTypes.VehicleStateSync:
{
Packets.VehicleStateSync packet = new Packets.VehicleStateSync();
packet.Unpack(data);
VehicleStateSync(packet);
}
break;
case PacketTypes.CharacterStateSync:
{
Packets.PedStateSync packet = new Packets.PedStateSync();
packet.Unpack(data);
PedStateSync(packet);
}
break;
#endregion
case PacketTypes.ChatMessage:
{
Packets.ChatMessage packet = new Packets.ChatMessage();
packet.Unpack(data);
if (!COOPAPI.ChatMessageReceived(packet.Username, packet.Message))
{
Main.QueueAction(() => { Main.MainChat.AddMessage(packet.Username, packet.Message);return true; });
}
}
break;
case PacketTypes.NativeCall:
{
Packets.NativeCall packet = new Packets.NativeCall();
packet.Unpack(data);
DecodeNativeCall(packet.Hash, packet.Args, false);
}
break;
case PacketTypes.NativeResponse:
{
Packets.NativeResponse packet = new Packets.NativeResponse();
packet.Unpack(data);
DecodeNativeResponse(packet);
}
break;
case PacketTypes.Mod:
{
Packets.Mod packet = new Packets.Mod();
packet.Unpack(data);
COOPAPI.ModPacketReceived(packet.NetHandle, packet.Name, packet.CustomPacketID, packet.Bytes);
}
break;
case PacketTypes.FileTransferTick:
{
Packets.FileTransferTick packet = new Packets.FileTransferTick();
packet.Unpack(data);
DownloadManager.Write(packet.ID, packet.FileChunk);
}
break;
case PacketTypes.FileTransferRequest:
{
Packets.FileTransferRequest packet = new Packets.FileTransferRequest();
packet.Unpack(data);
DownloadManager.AddFile(packet.ID, packet.FileName, packet.FileLength);
}
break;
case PacketTypes.FileTransferComplete:
{
Packets.FileTransferComplete packet = new Packets.FileTransferComplete();
packet.Unpack(data);
DownloadManager.Cleanup(false);
DownloadManager.DownloadComplete = true;
}
break;
case PacketTypes.ServerClientEvent:
{
Packets.ServerClientEvent packet = new Packets.ServerClientEvent();
packet.Unpack(data);
}
break;
default:
if (packetType.IsSyncEvent())
{
// Dispatch to main thread
Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, data); return true; });
}
break;
}
}
catch (Exception ex)
{
Main.QueueAction(() => {
GTA.UI.Notification.Show("~r~~h~Packet Error");
return true;
});
Main.Logger.Error($"[{packetType}] {ex.Message}");
Main.Logger.Error(ex);
Client.Disconnect($"Packet Error [{packetType}]");
}
break;
case NetIncomingMessageType.ConnectionLatencyUpdated:
Latency = message.ReadFloat();
break;
case NetIncomingMessageType.DebugMessage:
case NetIncomingMessageType.ErrorMessage:
case NetIncomingMessageType.WarningMessage:
case NetIncomingMessageType.VerboseDebugMessage:
#if DEBUG
// TODO?
#endif
break;
default:
break;
}
Client.Recycle(message);
}
}
private void PedSync(Packets.PedSync packet)
{
lock (EntityPool.PedsLock)
{
if (!EntityPool.Exists(packet.ID))
{
Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}");
EntityPool.Add(new SyncedPed(packet.ID));
}
PedDataFlags flags=packet.Flag;
SyncedPed c = EntityPool.GetPedByID(packet.ID);
c.ID=packet.ID;
//c.OwnerID=packet.OwnerID;
c.Health = packet.Health;
c.Position = packet.Position.ToVector();
c.Rotation = packet.Rotation.ToVector();
c.Velocity = packet.Velocity.ToVector();
c.Speed = packet.Speed;
c.CurrentWeaponHash = packet.CurrentWeaponHash;
c.IsAiming = flags.HasFlag(PedDataFlags.IsAiming);
c.IsReloading = flags.HasFlag(PedDataFlags.IsReloading);
c.IsJumping = flags.HasFlag(PedDataFlags.IsJumping) ;
c.IsRagdoll = flags.HasFlag(PedDataFlags.IsRagdoll);
c.IsOnFire = flags.HasFlag(PedDataFlags.IsOnFire) ;
c.IsInParachuteFreeFall = flags.HasFlag(PedDataFlags.IsInParachuteFreeFall);
c.IsParachuteOpen = flags.HasFlag(PedDataFlags.IsParachuteOpen);
c.IsOnLadder = flags.HasFlag(PedDataFlags.IsOnLadder);
c.IsVaulting = flags.HasFlag(PedDataFlags.IsVaulting);
c.IsInCover = flags.HasFlag(PedDataFlags.IsInCover);
c.Heading=packet.Heading;
c.LastSynced = Main.Ticked;
if (c.IsAiming)
{
c.AimCoords = packet.AimCoords.ToVector();
}
if (c.IsRagdoll)
{
c.RotationVelocity=packet.RotationVelocity.ToVector();
}
}
}
private void PedStateSync(Packets.PedStateSync packet)
{
lock (EntityPool.PedsLock)
{
if (!EntityPool.Exists(packet.ID))
{
Main.Logger.Debug($"Creating character for incoming sync:{packet.ID}");
EntityPool.Add(new SyncedPed(packet.ID));
}
SyncedPed c = EntityPool.GetPedByID(packet.ID);
c.ID=packet.ID;
c.OwnerID=packet.OwnerID;
c.Clothes=packet.Clothes;
c.WeaponComponents=packet.WeaponComponents;
c.ModelHash=packet.ModelHash;
c.LastSynced=c.LastStateSynced = Main.Ticked;
}
}
private void VehicleSync(Packets.VehicleSync packet)
{
lock (EntityPool.VehiclesLock)
{
if (!EntityPool.Exists(packet.ID))
{
EntityPool.Add(new SyncedVehicle(packet.ID));
}
SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID);
v.ID= packet.ID;
v.Position=packet.Position.ToVector();
v.Rotation=packet.Rotation.ToVector();
v.SteeringAngle=packet.SteeringAngle;
v.ThrottlePower=packet.ThrottlePower;
v.BrakePower=packet.BrakePower;
v.Velocity=packet.Velocity.ToVector();
v.RotationVelocity=packet.RotationVelocity.ToVector();
v.LastSynced=Main.Ticked;
}
}
private void VehicleStateSync(Packets.VehicleStateSync packet)
{
lock (EntityPool.VehiclesLock)
{
if (!EntityPool.Exists(packet.ID))
{
EntityPool.Add( new SyncedVehicle(packet.ID));
}
SyncedVehicle v = EntityPool.GetVehicleByID(packet.ID);
v.ID= packet.ID;
v.OwnerID= packet.OwnerID;
v.DamageModel=packet.DamageModel;
v.EngineHealth=packet.EngineHealth;
v.OwnerID=packet.OwnerID;
v.Mods=packet.Mods;
v.ModelHash=packet.ModelHash;
v.Colors=packet.Colors;
v.LandingGear=packet.LandingGear;
v.EngineRunning = packet.Flag.HasFlag(VehicleDataFlags.IsEngineRunning);
v.LightsOn = packet.Flag.HasFlag(VehicleDataFlags.AreLightsOn);
v.BrakeLightsOn = packet.Flag.HasFlag(VehicleDataFlags.AreBrakeLightsOn);
v.HighBeamsOn = packet.Flag.HasFlag(VehicleDataFlags.AreHighBeamsOn);
v.SireneActive = packet.Flag.HasFlag(VehicleDataFlags.IsSirenActive) ;
v.IsDead = packet.Flag.HasFlag(VehicleDataFlags.IsDead) ;
v.HornActive = packet.Flag.HasFlag(VehicleDataFlags.IsHornActive);
v.Transformed = packet.Flag.HasFlag(VehicleDataFlags.IsTransformed);
v.Passengers=new Dictionary<VehicleSeat, SyncedPed>();
v.LockStatus=packet.LockStatus;
foreach (KeyValuePair<int, int> pair in packet.Passengers)
{
if (EntityPool.Exists(pair.Value))
{
v.Passengers.Add((VehicleSeat)pair.Key, EntityPool.GetPedByID(pair.Value));
}
}
v.LastStateSynced=v.LastSynced= Main.Ticked;
}
}
}
}

265
Client/Networking/Send.cs Normal file
View File

@ -0,0 +1,265 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using Lidgren.Network;
using RageCoop.Core;
using GTA;
using GTA.Native;
using GTA.Math;
namespace RageCoop.Client
{
public partial class Networking
{
/*
public static void MakePlayer()
{
// Create entity for local player
Ped p = Game.Player.Character;
Main.Logger.Debug($"Creating SyncEntity for player, handle:{p.Handle}");
CharacterEntity c = new CharacterEntity(p);
Main.Characters.Add(c.ID, c);
Main.MyPlayerID=c.OwnerID=c.ID;
Main.Logger.Debug($"My player ID is:{c.ID}");
Main.MainPlayerList.SetPlayer(new PlayerData { PedID=c.ID, Username=Main.MainSettings.Username });
}
*/
#region -- SEND --
public void SendPed(SyncedPed c)
{
Ped p = c.MainPed;
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
NetDeliveryMethod messageType = NetDeliveryMethod.UnreliableSequenced;
int connectionChannel = (byte)ConnectionChannel.CharacterSync;
var packet=new Packets.PedSync()
{
ID =c.ID,
Health = p.Health,
Position = p.Position.ToLVector(),
Rotation = p.Rotation.ToLVector(),
Velocity = p.Velocity.ToLVector(),
Speed = p.GetPedSpeed(),
CurrentWeaponHash = (uint)p.Weapons.Current.Hash,
Flag = p.GetPedFlags(),
Heading=p.Heading,
};
if (packet.Flag.HasFlag(PedDataFlags.IsAiming))
{
packet.AimCoords = p.GetAimCoord().ToLVector();
}
if (packet.Flag.HasFlag(PedDataFlags.IsRagdoll))
{
packet.RotationVelocity=p.RotationVelocity.ToLVector();
}
packet.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, messageType, connectionChannel);
}
public void SendPedState(SyncedPed c)
{
Ped p = c.MainPed;
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
NetDeliveryMethod messageType = NetDeliveryMethod.UnreliableSequenced;
int connectionChannel = (byte)ConnectionChannel.CharacterSync;
new Packets.PedStateSync()
{
ID = c.ID,
OwnerID=c.OwnerID,
Clothes=p.GetPedClothes(),
ModelHash=p.Model.Hash,
WeaponComponents=p.Weapons.Current.GetWeaponComponents(),
}.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, messageType, connectionChannel);
}
public void SendVehicle(SyncedVehicle v)
{
Vehicle veh = v.MainVehicle;
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
NetDeliveryMethod messageType = NetDeliveryMethod.UnreliableSequenced;
int connectionChannel = (byte)ConnectionChannel.VehicleSync;
new Packets.VehicleSync()
{
ID =v.ID,
SteeringAngle = veh.SteeringAngle,
Position = veh.Position.ToLVector(),
Rotation = veh.Rotation.ToLVector(),
Velocity = veh.Velocity.ToLVector(),
RotationVelocity=veh.RotationVelocity.ToLVector(),
ThrottlePower = veh.ThrottlePower,
BrakePower = veh.BrakePower,
}.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, messageType, connectionChannel);
}
public void SendVehicleState(SyncedVehicle v)
{
Vehicle veh = v.MainVehicle;
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
NetDeliveryMethod messageType = NetDeliveryMethod.UnreliableSequenced;
int connectionChannel = (byte)ConnectionChannel.VehicleSync;
byte primaryColor = 0;
byte secondaryColor = 0;
unsafe
{
Function.Call<byte>(Hash.GET_VEHICLE_COLOURS, veh, &primaryColor, &secondaryColor);
}
new Packets.VehicleStateSync()
{
ID =v.ID,
OwnerID = v.OwnerID,
Flag = veh.GetVehicleFlags(),
Colors=new byte[] { primaryColor, secondaryColor },
DamageModel=veh.GetVehicleDamageModel(),
LandingGear = veh.IsAircraft ? (byte)veh.LandingGearState : (byte)0,
Mods = veh.Mods.GetVehicleMods(),
ModelHash=veh.Model.Hash,
EngineHealth=veh.EngineHealth,
Passengers=veh.GetPassengers(),
LockStatus=veh.LockStatus,
}.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, messageType, connectionChannel);
}
#region SYNC EVENTS
public void Send(Packet p,ConnectionChannel channel=ConnectionChannel.Default)
{
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
NetDeliveryMethod messageType = NetDeliveryMethod.UnreliableSequenced;
p.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, messageType, (int)channel);
}
public void SendBulletShot(Vector3 start,Vector3 end,uint weapon,int ownerID)
{
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
NetDeliveryMethod messageType = NetDeliveryMethod.UnreliableSequenced;
int connectionChannel = (byte)ConnectionChannel.SyncEvents;
new Packets.BulletShot()
{
StartPosition = start.ToLVector(),
EndPosition = end.ToLVector(),
OwnerID = ownerID,
WeaponHash=weapon,
}.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, messageType, connectionChannel);
}
public void SendOwnerChanged(int id,int newOwnerId)
{
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
NetDeliveryMethod messageType = NetDeliveryMethod.UnreliableSequenced;
int connectionChannel = (byte)ConnectionChannel.SyncEvents;
new Packets.OwnerChanged()
{
ID= id,
NewOwnerID= newOwnerId,
}.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, messageType, connectionChannel);
}
public void SendEnteringVehicle(int pedId,int vehId,short seat)
{
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
NetDeliveryMethod messageType = NetDeliveryMethod.UnreliableSequenced;
int connectionChannel = (byte)ConnectionChannel.SyncEvents;
new Packets.EnteringVehicle()
{
PedID=pedId,
VehicleID= vehId,
VehicleSeat=seat,
}.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, messageType, connectionChannel);
}
public void SendLeaveVehicle(int id)
{
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
NetDeliveryMethod messageType = NetDeliveryMethod.UnreliableSequenced;
int connectionChannel = (byte)ConnectionChannel.SyncEvents;
new Packets.LeaveVehicle()
{
ID=id
}.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, messageType, connectionChannel);
}
#endregion
public void SendChatMessage(string message)
{
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
new Packets.ChatMessage() { Username = Main.Settings.Username, Message = message }.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Chat);
Client.FlushSendQueue();
#if DEBUG
if (ShowNetworkInfo)
{
BytesSend += outgoingMessage.LengthBytes;
}
#endif
}
public void SendModData(long target, string modName, byte customID, byte[] bytes)
{
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
new Packets.Mod()
{
// NetHandle = Main.LocalNetHandle,
Target = target,
Name = modName,
CustomPacketID = customID,
Bytes = bytes
}.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Mod);
Client.FlushSendQueue();
#if DEBUG
if (ShowNetworkInfo)
{
BytesSend += outgoingMessage.LengthBytes;
}
#endif
}
public void SendDownloadFinish(byte id)
{
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
new Packets.FileTransferComplete() { ID = id }.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableUnordered, (byte)ConnectionChannel.File);
Client.FlushSendQueue();
#if DEBUG
if (ShowNetworkInfo)
{
BytesSend += outgoingMessage.LengthBytes;
}
#endif
}
public void SendTriggerEvent(string eventName, params object[] args)
{
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
new Packets.ServerClientEvent()
{
EventName = eventName,
Args = new List<object>(args)
}.Pack(outgoingMessage);
Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableUnordered, (byte)ConnectionChannel.Event);
Client.FlushSendQueue();
}
#endregion
}
}

View File

@ -1,451 +0,0 @@
using System;
using System.Collections.Generic;
using Lidgren.Network;
namespace CoopClient
{
internal partial class Packets
{
public class FullSyncNpc : Packet
{
public long NetHandle { get; set; }
public int ModelHash { get; set; }
public Dictionary<byte, short> Clothes { get; set; }
public int Health { get; set; }
public LVector3 Position { get; set; }
public LVector3 Rotation { get; set; }
public LVector3 Velocity { get; set; }
public byte Speed { get; set; }
public LVector3 AimCoords { get; set; }
public uint CurrentWeaponHash { get; set; }
public ushort? Flag { get; set; } = 0;
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.FullSyncNpc);
List<byte> byteArray = new List<byte>();
// Write player + ped handle
byteArray.AddRange(BitConverter.GetBytes(NetHandle));
// Write npc flags
byteArray.AddRange(BitConverter.GetBytes(Flag.Value));
// Write npc model hash
byteArray.AddRange(BitConverter.GetBytes(ModelHash));
// Write npc position
byteArray.AddRange(BitConverter.GetBytes(Position.X));
byteArray.AddRange(BitConverter.GetBytes(Position.Y));
byteArray.AddRange(BitConverter.GetBytes(Position.Z));
// Write npc rotation
byteArray.AddRange(BitConverter.GetBytes(Rotation.X));
byteArray.AddRange(BitConverter.GetBytes(Rotation.Y));
byteArray.AddRange(BitConverter.GetBytes(Rotation.Z));
// Write npc clothes
// Write the count of clothes
byteArray.AddRange(BitConverter.GetBytes((ushort)Clothes.Count));
// Loop the dictionary and add the values
foreach (KeyValuePair<byte, short> cloth in Clothes)
{
byteArray.Add(cloth.Key);
byteArray.AddRange(BitConverter.GetBytes(cloth.Value));
}
// Write npc health
byteArray.AddRange(BitConverter.GetBytes(Health));
// Write npc velocity
byteArray.AddRange(BitConverter.GetBytes(Velocity.X));
byteArray.AddRange(BitConverter.GetBytes(Velocity.Y));
byteArray.AddRange(BitConverter.GetBytes(Velocity.Z));
// Write npc speed
byteArray.Add(Speed);
if (Flag.HasValue)
{
if ((Flag.Value & (byte)PedDataFlags.IsAiming) != 0 || (Flag.Value & (byte)PedDataFlags.IsShooting) != 0)
{
// Write player aim coords
byteArray.AddRange(BitConverter.GetBytes(Rotation.X));
byteArray.AddRange(BitConverter.GetBytes(Rotation.Y));
byteArray.AddRange(BitConverter.GetBytes(Rotation.Z));
}
}
// Write npc weapon hash
byteArray.AddRange(BitConverter.GetBytes(CurrentWeaponHash));
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player + ped handle
NetHandle = reader.ReadLong();
// Read npc flag
Flag = reader.ReadUShort();
// Read npc model hash
ModelHash = reader.ReadInt();
// Read npc position
Position = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read npc rotation
Rotation = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read npc clothes
// Create new Dictionary
Clothes = new Dictionary<byte, short>();
// Read the count of clothes
ushort clothCount = reader.ReadUShort();
// For clothCount
for (ushort i = 0; i < clothCount; i++)
{
// Read cloth value
Clothes.Add(reader.ReadByte(), reader.ReadShort());
}
// Read npc health
Health = reader.ReadByte();
// Read npc velocity
Velocity = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read npc speed
Speed = reader.ReadByte();
// Read npc flag values
if (Flag.HasValue)
{
if ((Flag.Value & (byte)PedDataFlags.IsAiming) != 0 || (Flag.Value & (byte)PedDataFlags.IsShooting) != 0)
{
AimCoords = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
}
}
// Read npc weapon hash
CurrentWeaponHash = reader.ReadUInt();
#endregion
}
}
public class FullSyncNpcVeh : Packet
{
public long NetHandle { get; set; }
public long VehHandle { get; set; }
public int ModelHash { get; set; }
public Dictionary<byte, short> Clothes { get; set; }
public int Health { get; set; }
public LVector3 Position { get; set; }
public int VehModelHash { get; set; }
public short VehSeatIndex { get; set; }
public LQuaternion VehRotation { get; set; }
public float VehEngineHealth { get; set; }
public float VehRPM { get; set; }
public LVector3 VehVelocity { get; set; }
public float VehSpeed { get; set; }
public float VehSteeringAngle { get; set; }
public byte[] VehColors { get; set; }
public Dictionary<int, int> VehMods { get; set; }
public VehicleDamageModel VehDamageModel { get; set; }
public byte VehLandingGear { get; set; }
public ushort? Flag { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.FullSyncNpcVeh);
List<byte> byteArray = new List<byte>();
// Write player + npc netHandle
byteArray.AddRange(BitConverter.GetBytes(NetHandle));
// Write player + vehicle handle
byteArray.AddRange(BitConverter.GetBytes(VehHandle));
// Write vehicles flags
byteArray.AddRange(BitConverter.GetBytes(Flag.Value));
// Write npc health
byteArray.AddRange(BitConverter.GetBytes(Health));
// Write npc model hash
byteArray.AddRange(BitConverter.GetBytes(ModelHash));
// Write npc clothes
// Write the count of clothes
byteArray.AddRange(BitConverter.GetBytes((ushort)Clothes.Count));
// Loop the dictionary and add the values
foreach (KeyValuePair<byte, short> cloth in Clothes)
{
byteArray.Add(cloth.Key);
byteArray.AddRange(BitConverter.GetBytes(cloth.Value));
}
// Write vehicle model hash
byteArray.AddRange(BitConverter.GetBytes(VehModelHash));
// Write player seat index
byteArray.AddRange(BitConverter.GetBytes(VehSeatIndex));
// Write vehicle position
byteArray.AddRange(BitConverter.GetBytes(Position.X));
byteArray.AddRange(BitConverter.GetBytes(Position.Y));
byteArray.AddRange(BitConverter.GetBytes(Position.Z));
// Write vehicle rotation
byteArray.AddRange(BitConverter.GetBytes(VehRotation.X));
byteArray.AddRange(BitConverter.GetBytes(VehRotation.Y));
byteArray.AddRange(BitConverter.GetBytes(VehRotation.Z));
byteArray.AddRange(BitConverter.GetBytes(VehRotation.W));
// Write vehicle engine health
byteArray.AddRange(BitConverter.GetBytes(VehEngineHealth));
// Write vehicle rpm
byteArray.AddRange(BitConverter.GetBytes(VehRPM));
// Write vehicle velocity
byteArray.AddRange(BitConverter.GetBytes(VehVelocity.X));
byteArray.AddRange(BitConverter.GetBytes(VehVelocity.Y));
byteArray.AddRange(BitConverter.GetBytes(VehVelocity.Z));
// Write vehicle speed
byteArray.AddRange(BitConverter.GetBytes(VehSpeed));
// Write vehicle steering angle
byteArray.AddRange(BitConverter.GetBytes(VehSteeringAngle));
// Check
if (Flag.HasValue)
{
if ((Flag.Value & (ushort)VehicleDataFlags.IsPlane) != 0)
{
// Write the vehicle landing gear
byteArray.AddRange(BitConverter.GetBytes(VehLandingGear));
}
}
// Write vehicle colors
byteArray.Add(VehColors[0]);
byteArray.Add(VehColors[1]);
// Write vehicle mods
// Write the count of mods
byteArray.AddRange(BitConverter.GetBytes((short)VehMods.Count));
// Loop the dictionary and add the values
foreach (KeyValuePair<int, int> mod in VehMods)
{
// Write the mod value
byteArray.AddRange(BitConverter.GetBytes(mod.Key));
byteArray.AddRange(BitConverter.GetBytes(mod.Value));
}
if (!VehDamageModel.Equals(default(VehicleDamageModel)))
{
// Write boolean = true
byteArray.Add(0x01);
// Write vehicle damage model
byteArray.Add(VehDamageModel.BrokenDoors);
byteArray.Add(VehDamageModel.BrokenWindows);
byteArray.AddRange(BitConverter.GetBytes(VehDamageModel.BurstedTires));
byteArray.Add(VehDamageModel.LeftHeadLightBroken);
byteArray.Add(VehDamageModel.RightHeadLightBroken);
}
else
{
// Write boolean = false
byteArray.Add(0x00);
}
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player + npc netHandle
NetHandle = reader.ReadLong();
// Reader player + vehicle handle
VehHandle = reader.ReadLong();
// Read vehicle flags
Flag = reader.ReadUShort();
// Read npc health
Health = reader.ReadInt();
// Read npc model hash
ModelHash = reader.ReadInt();
// Read npc clothes
// Create new Dictionary
Clothes = new Dictionary<byte, short>();
// Read the count of clothes
ushort clothCount = reader.ReadUShort();
// For clothCount
for (int i = 0; i < clothCount; i++)
{
// Read cloth value
Clothes.Add(reader.ReadByte(), reader.ReadShort());
}
// Read vehicle model hash
VehModelHash = reader.ReadInt();
// Read npc seat index
VehSeatIndex = reader.ReadShort();
// Read vehicle position
Position = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read vehicle rotation
VehRotation = new LQuaternion()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat(),
W = reader.ReadFloat()
};
// Read vehicle engine health
VehEngineHealth = reader.ReadFloat();
// Read vehicle rpm
VehRPM = reader.ReadFloat();
// Read vehicle velocity
VehVelocity = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read vehicle speed
VehSpeed = reader.ReadFloat();
// Read vehicle steering angle
VehSteeringAngle = reader.ReadFloat();
// Check
if (Flag.HasValue)
{
if ((Flag.Value & (int)VehicleDataFlags.IsPlane) != 0)
{
// Read vehicle landing gear
VehLandingGear = (byte)reader.ReadShort();
}
}
// Read vehicle colors
byte vehColor1 = reader.ReadByte();
byte vehColor2 = reader.ReadByte();
VehColors = new byte[] { vehColor1, vehColor2 };
// Read vehicle mods
// Create new Dictionary
VehMods = new Dictionary<int, int>();
// Read count of mods
short vehModCount = reader.ReadShort();
// Loop
for (int i = 0; i < vehModCount; i++)
{
// Read the mod value
VehMods.Add(reader.ReadInt(), reader.ReadInt());
}
if (reader.ReadBool())
{
// Read vehicle damage model
VehDamageModel = new VehicleDamageModel()
{
BrokenDoors = reader.ReadByte(),
BrokenWindows = reader.ReadByte(),
BurstedTires = reader.ReadShort(),
LeftHeadLightBroken = reader.ReadByte(),
RightHeadLightBroken = reader.ReadByte()
};
}
#endregion
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,21 @@
using System.Collections.Generic;
using CoopClient.Entities.Player;
using System.Linq;
using RageCoop.Core;
using GTA;
using GTA.Native;
namespace CoopClient
namespace RageCoop.Client
{
internal class PlayerList
public class PlayerList
{
private const float LEFT_POSITION = 0.122f;
private const float RIGHT_POSITION = 0.9f;
private readonly Scaleform _mainScaleform = new Scaleform("mp_mm_card_freemode");
private ulong _lastUpdate = Util.GetTickCount64();
internal ulong Pressed { get; set; }
internal bool LeftAlign = true;
public ulong Pressed { get; set; }
public bool LeftAlign = true;
public List<PlayerData> Players=new List<PlayerData> { };
public void Tick()
{
if (!Main.MainNetworking.IsOnServer())
@ -26,7 +25,7 @@ namespace CoopClient
if ((Util.GetTickCount64() - _lastUpdate) >= 1000)
{
Update(Main.Players, Main.MainSettings.Username);
Update( Main.Settings.Username);
}
if ((Util.GetTickCount64() - Pressed) < 5000 && !Main.MainChat.Focused
@ -42,7 +41,7 @@ namespace CoopClient
}
}
private void Update(Dictionary<long, EntitiesPlayer> players, string localUsername)
private void Update( string localUsername)
{
_lastUpdate = Util.GetTickCount64();
@ -51,13 +50,42 @@ namespace CoopClient
int i = 1;
foreach (KeyValuePair<long, EntitiesPlayer> player in players)
foreach (var player in Players)
{
_mainScaleform.CallFunction("SET_DATA_SLOT", i++, $"{player.Value.Latency * 1000:N0}ms", player.Value.Username, 116, 0, i - 1, "", "", 2, "", "", ' ');
_mainScaleform.CallFunction("SET_DATA_SLOT", i++, $"{player.Latency * 1000:N0}ms", player.Username, 116, 0, i - 1, "", "", 2, "", "", ' ');
}
_mainScaleform.CallFunction("SET_TITLE", "Player list", (players.Count + 1) + " players");
_mainScaleform.CallFunction("SET_TITLE", "Player list", (Players.Count) + " players");
_mainScaleform.CallFunction("DISPLAY_VIEW");
}
public void SetPlayer(int id, string username)
{
var toset = Players.Where(x => x.PedID==id);
if (toset.Any())
{
var p=toset.First();
p.Username=username;
p.PedID=id;
}
else
{
PlayerData p = new PlayerData { PedID=id, Username=username };
Players.Add(p);
}
}
public PlayerData GetPlayer(int id)
{
return Players.Find(x => x.PedID==id);
}
public void RemovePlayer(int id)
{
var p = Players.Where(x => x.PedID==id);
if (p.Any())
{
Players.Remove(p.First());
}
}
}
}

View File

@ -7,8 +7,8 @@
<ProjectGuid>{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CoopClient</RootNamespace>
<AssemblyName>CoopClient</AssemblyName>
<RootNamespace>RageCoop.Client</RootNamespace>
<AssemblyName>RageCoop.Client</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
@ -20,7 +20,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<OutputPath>D:\Games\Grand Theft Auto V\Scripts\RageCoop\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@ -38,7 +38,7 @@
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<DocumentationFile>bin\Release\CoopClient.xml</DocumentationFile>
<DocumentationFile>bin\Release\RageCoop.Client.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="ClearScript.Core, Version=7.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@ -57,6 +57,21 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libs\Release\scripts\Lidgren.Network.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.6.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.6.0.0\lib\net461\Microsoft.Extensions.DependencyInjection.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.6.0.0\lib\net461\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Options.6.0.0\lib\net461\Microsoft.Extensions.Options.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Primitives.6.0.0\lib\net461\Microsoft.Extensions.Primitives.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libs\Release\scripts\Newtonsoft.Json.dll</HintPath>
@ -66,12 +81,35 @@
<HintPath>..\Libs\Release\ScriptHookVDotNet3.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.6.0.0\lib\net461\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@ -81,34 +119,38 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BitReader.cs" />
<Compile Include="Chat.cs" />
<Compile Include="COOPAPI.cs" />
<Compile Include="Debug.cs" />
<Compile Include="DownloadManager.cs" />
<Compile Include="Entities\NPC\EntitiesNPC.cs" />
<Compile Include="Entities\NPC\Sync\OnFootSync.cs" />
<Compile Include="Entities\NPC\Sync\VehicleSync.cs" />
<Compile Include="Entities\Player\EntitiesPlayer.cs" />
<Compile Include="Entities\EntitiesThread.cs" />
<Compile Include="Entities\Player\Sync\OnFootSync.cs" />
<Compile Include="Entities\Player\Sync\VehicleSync.cs" />
<Compile Include="JavascriptHook.cs" />
<Compile Include="Logger.cs" />
<Compile Include="Menus\Sub\DebugMenu.cs" />
<Compile Include="Networking\Receive.cs" />
<Compile Include="Networking\Send.cs" />
<Compile Include="Sync\Entities\SyncedPed.cs" />
<None Include="app.config" />
<None Include="packages.config" />
<Compile Include="Sync\EntityPool.cs" />
<Compile Include="Sync\SyncEvents.cs" />
<Compile Include="Sync\Entities\SyncedEntity.cs" />
<Compile Include="Sync\Entities\SyncedVehicle.cs" />
<Compile Include="Main.cs" />
<Compile Include="MapLoader.cs" />
<Compile Include="Menus\MenusMain.cs" />
<Compile Include="Menus\Sub\Servers.cs" />
<Compile Include="Menus\Sub\Settings.cs" />
<Compile Include="Networking.cs" />
<Compile Include="Packets\DownloadPackets.cs" />
<Compile Include="Packets\NPCPackets.cs" />
<Compile Include="Packets\Packets.cs" />
<Compile Include="Packets\PlayerPackets.cs" />
<Compile Include="Networking\Networking.cs" />
<Compile Include="PlayerList.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sync\SyncParameters.cs" />
<Compile Include="Util.cs" />
<Compile Include="WorldThread.cs" />
<Compile Include="Settings.cs" />
<Compile Include="Util.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\RageCoop.Core.csproj">
<Project>{cc2e8102-e568-4524-aa1f-f8e0f1cfe58a}</Project>
<Name>RageCoop.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,4 +1,5 @@
namespace CoopClient
#undef DEBUG
namespace RageCoop.Client
{
/// <summary>
/// Don't use it!
@ -21,5 +22,7 @@
/// Don't use it!
/// </summary>
public bool FlipMenu { get; set; } = false;
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GTA;
namespace RageCoop.Client
{
public class SyncedEntity
{
/// <summary>
/// Indicates whether the current player is responsible for syncing this entity.
/// </summary>
public bool IsMine
{
get
{
return OwnerID==Main.MyPlayerID;
}
}
public int ID { get; set; }
public int OwnerID { get;set; }
public bool IsOutOfSync
{
get
{
return Main.Ticked-LastSynced>200;
}
}
#region LAST STATE
/// <summary>
/// Last time a new sync message arrived.
/// </summary>
public ulong LastSynced { get; set; } = 0;
/// <summary>
/// Last time a new sync message arrived.
/// </summary>
public ulong LastStateSynced { get; internal set; } = 0;
/// <summary>
/// Last time the local entity has been updated,
/// </summary>
public ulong LastUpdated { get; set; } = 0;
#endregion
}
}

View File

@ -0,0 +1,837 @@
using System;
using System.Linq;
using System.Drawing;
using System.Collections.Generic;
using RageCoop.Core;
using GTA;
using GTA.Native;
using GTA.Math;
using LemonUI.Elements;
using System.Security.Cryptography;
namespace RageCoop.Client
{
/// <summary>
/// ?
/// </summary>
public partial class SyncedPed:SyncedEntity
{
#region CONSTRUCTORS
/// <summary>
/// Create a local entity (outgoing sync)
/// </summary>
/// <param name="p"></param>
public SyncedPed(Ped p)
{
while((ID==0) || (EntityPool.GetPedByID(ID)!=null))
{
byte[] rngBytes = new byte[4];
RandomNumberGenerator.Create().GetBytes(rngBytes);
// Convert the bytes into an integer
ID = BitConverter.ToInt32(rngBytes,0);
}
p.CanWrithe=false;
p.IsOnlyDamagedByPlayer=false;
MainPed=p;
OwnerID=Main.MyPlayerID;
}
/// <summary>
/// Create an empty character with ID
/// </summary>
public SyncedPed(int id)
{
ID=id;
LastSynced=Main.Ticked;
}
#endregion
#region PLAYER -- ONLY
public string Username = "N/A";
public Blip PedBlip = null;
#endregion
/// <summary>
/// Indicates whether this ped is a player
/// </summary>
public bool IsPlayer { get { return (OwnerID==ID)&&(ID!=0); } }
/// <summary>
/// real entity
/// </summary>
public Ped MainPed { get; internal set; }
/// <summary>
/// The latest character health (may not have been applied yet)
/// </summary>
public int Health { get; internal set; }
public bool _lastEnteringVehicle=false;
public bool _lastSittingInVehicle=false;
private bool _lastRagdoll=false;
private ulong _lastRagdollTime=0;
private bool _lastInCover = false;
private bool _isEnteringVehicle = false;
/// <summary>
/// The latest character model hash (may not have been applied yet)
/// </summary>
public int ModelHash
{
get;set;
}
private Dictionary<byte, short> _lastClothes = null;
public Dictionary<byte, short> Clothes { get; set; }
public float Heading { get; set; }
/// <summary>
/// The latest character position (may not have been applied yet)
/// </summary>
public Vector3 Position { get; internal set; }
public Vector3 Velocity { get; set; }
public Vector3 RotationVelocity { get; set; }
public Vector3 AimCoords { get; set; }
public bool Update()
{
if (IsMine) {
// Main.Logger.Trace($"Skipping update for ped {ID}. Reason:WrongWay");
return false;
}
if (IsPlayer && (MainPed!=null))
{
if (Username=="N/A")
{
var p = Main.MainPlayerList.GetPlayer(ID);
if (p!=null)
{
Username=p.Username;
PedBlip.Name=Username;
Main.Logger.Debug($"Username updated:{Username}");
}
}
RenderNameTag();
}
// Check if all data avalible
if ( LastSynced== 0) {
// Main.Logger.Trace($"Skipping update for ped {ID}. Reason:NotReady");
return false;
}
if(LastStateSynced==0) {
// Main.Logger.Trace($"Skipping update for ped {ID}. Reason:StateNotReady");
return false;
}
// Skip update if no new sync message has arrived.
if (LastUpdated>=LastSynced) {
// Main.Logger.Trace($"Skipping update for ped {ID}. Reason:NoNewMessage");
return false;
}
bool characterExist = MainPed != null && MainPed.Exists();
if (!characterExist)
{
CreateCharacter();
return false;
}
// Need to update state
if (LastStateSynced>=LastUpdated)
{
if (MainPed!=null&& (ModelHash != MainPed.Model.Hash))
{
CreateCharacter();
return false;
}
if (!Clothes.Compare(_lastClothes))
{
SetClothes();
}
}
if (MainPed.IsDead)
{
if (Health>0)
{
if (IsPlayer)
{
MainPed.Resurrect();
}
else
{
SyncEvents.TriggerPedKilled(this);
}
}
}
else if (IsPlayer&&(MainPed.Health != Health))
{
MainPed.Health = Health;
if (Health <= 0 && !MainPed.IsDead)
{
MainPed.IsInvincible = false;
Main.Logger.Debug($"Killing ped {ID}. Reason:PedDied");
MainPed.Kill();
return false;
}
}
if (MainPed.IsInVehicle()||MainPed.IsGettingIntoVehicle)
{
DisplayInVehicle();
}
else
{
DisplayOnFoot();
}
LastUpdated=Main.Ticked;
// Main.Logger.Trace($"Character updated:{ID} LastUpdated:{LastUpdated}");
return true;
}
private void RenderNameTag()
{
if (!IsPlayer || !MainPed.IsVisible || !MainPed.IsInRange(Game.Player.Character.Position, 20f))
{
return;
}
string renderText = IsOutOfSync ? "~r~AFK" : Username;
Vector3 targetPos = MainPed.Bones[Bone.IKHead].Position + new Vector3(0, 0, 0.35f);
Function.Call(Hash.SET_DRAW_ORIGIN, targetPos.X, targetPos.Y, targetPos.Z, 0);
float dist = (GameplayCamera.Position - MainPed.Position).Length();
var sizeOffset = Math.Max(1f - (dist / 30f), 0.3f);
new ScaledText(new PointF(0, 0), renderText, 0.4f * sizeOffset, GTA.UI.Font.ChaletLondon)
{
Outline = true,
Alignment = GTA.UI.Alignment.Center
}.Draw();
Function.Call(Hash.CLEAR_DRAW_ORIGIN);
}
private void CreateCharacter()
{
if (MainPed != null)
{
if (MainPed.Exists())
{
Main.Logger.Debug($"Removing ped {ID}. Reason:CreateCharacter");
MainPed.Kill();
MainPed.MarkAsNoLongerNeeded();
MainPed.Delete();
}
MainPed = null;
}
if (PedBlip != null && PedBlip.Exists())
{
PedBlip.Delete();
PedBlip = null;
}
Model characterModel = ModelHash.ModelRequest();
if (characterModel == null)
{
return;
}
MainPed = World.CreatePed(characterModel, Position);
characterModel.MarkAsNoLongerNeeded();
if (MainPed == null)
{
return;
}
Function.Call(Hash.SET_PED_CAN_EVASIVE_DIVE, MainPed.Handle, false);
Function.Call(Hash.SET_PED_DROPS_WEAPONS_WHEN_DEAD, MainPed.Handle, false);
Function.Call(Hash.SET_PED_CAN_BE_TARGETTED, MainPed.Handle, true);
Function.Call(Hash.SET_PED_CAN_BE_TARGETTED_BY_PLAYER, MainPed.Handle, Game.Player, true);
Function.Call(Hash.SET_PED_GET_OUT_UPSIDE_DOWN_VEHICLE, MainPed.Handle, false);
Function.Call(Hash.SET_CAN_ATTACK_FRIENDLY, MainPed.Handle, true, true);
MainPed.BlockPermanentEvents = true;
MainPed.CanWrithe=false;
MainPed.CanBeDraggedOutOfVehicle = true;
MainPed.IsOnlyDamagedByPlayer = false;
MainPed.RelationshipGroup=Main.SyncedPedsGroup;
if (IsPlayer)
{
MainPed.IsInvincible=true;
}
SetClothes();
if (IsPlayer)
{
// Add a new blip for the ped
PedBlip=MainPed.AddBlip();
MainPed.AttachedBlip.Color = BlipColor.White;
MainPed.AttachedBlip.Scale = 0.8f;
MainPed.AttachedBlip.Name =Username;
}
// Add to EntityPool so this Character can be accessed by handle.
EntityPool.Add(this);
}
private void SetClothes()
{
foreach (KeyValuePair<byte, short> cloth in Clothes)
{
Function.Call(Hash.SET_PED_COMPONENT_VARIATION, MainPed.Handle, cloth.Key, cloth.Value, 0, 0);
}
_lastClothes = Clothes;
}
#region Onfoot
#region -- VARIABLES --
/// <summary>
/// The latest character rotation (may not have been applied yet)
/// </summary>
public Vector3 Rotation { get; internal set; }
public byte Speed { get; set; }
private bool _lastIsJumping = false;
public bool IsJumping { get; set; }
public bool IsOnLadder { get; set; }
public bool IsVaulting { get; set; }
public bool IsInParachuteFreeFall { get; set; }
public bool IsParachuteOpen { get; set; }
public Prop ParachuteProp { get; set; } = null;
public bool IsRagdoll { get; set; }
public bool IsOnFire { get; set; }
public bool IsAiming { get; set; }
public bool IsReloading { get; set; }
public bool IsInCover { get; set; }
public uint CurrentWeaponHash { get; set; }
private Dictionary<uint, bool> _lastWeaponComponents = null;
public Dictionary<uint, bool> WeaponComponents { get; set; } = null;
private int _lastWeaponObj = 0;
#endregion
private bool _isPlayingAnimation = false;
private string[] _currentAnimation = new string[2] { "", "" };
private float _animationStopTime = 0;
private void DisplayOnFoot()
{
if (IsInParachuteFreeFall)
{
MainPed.PositionNoOffset = Vector3.Lerp(MainPed.Position, Position + Velocity, 0.5f);
MainPed.Quaternion = Rotation.ToQuaternion();
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, MainPed.Handle, "skydive@base", "free_idle", 3))
{
Function.Call(Hash.TASK_PLAY_ANIM, MainPed.Handle, LoadAnim("skydive@base"), "free_idle", 8f, 10f, -1, 0, -8f, 1, 1, 1);
}
return;
}
if (IsParachuteOpen)
{
if (ParachuteProp == null)
{
Model model = 1740193300.ModelRequest();
if (model != null)
{
ParachuteProp = World.CreateProp(model, MainPed.Position, MainPed.Rotation, false, false);
model.MarkAsNoLongerNeeded();
ParachuteProp.IsPositionFrozen = true;
ParachuteProp.IsCollisionEnabled = false;
ParachuteProp.AttachTo(MainPed.Bones[Bone.SkelSpine2], new Vector3(3.6f, 0f, 0f), new Vector3(0f, 90f, 0f));
}
MainPed.Task.ClearAllImmediately();
MainPed.Task.ClearSecondary();
}
MainPed.PositionNoOffset = Vector3.Lerp(MainPed.Position, Position + Velocity, 0.5f);
MainPed.Quaternion = Rotation.ToQuaternion();
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, MainPed.Handle, "skydive@parachute@first_person", "chute_idle_right", 3))
{
Function.Call(Hash.TASK_PLAY_ANIM, MainPed, LoadAnim("skydive@parachute@first_person"), "chute_idle_right", 8f, 10f, -1, 0, -8f, 1, 1, 1);
}
return;
}
if (ParachuteProp != null)
{
if (ParachuteProp.Exists())
{
ParachuteProp.Delete();
}
ParachuteProp = null;
}
if (IsOnLadder)
{
if (Velocity.Z < 0)
{
string anim = Velocity.Z < -2f ? "slide_climb_down" : "climb_down";
if (_currentAnimation[1] != anim)
{
MainPed.Task.ClearAllImmediately();
_currentAnimation[1] = anim;
}
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, MainPed.Handle, "laddersbase", anim, 3))
{
MainPed.Task.PlayAnimation("laddersbase", anim, 8f, -1, AnimationFlags.Loop);
}
}
else
{
if (Math.Abs(Velocity.Z) < 0.5)
{
if (_currentAnimation[1] != "base_left_hand_up")
{
MainPed.Task.ClearAllImmediately();
_currentAnimation[1] = "base_left_hand_up";
}
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, MainPed.Handle, "laddersbase", "base_left_hand_up", 3))
{
MainPed.Task.PlayAnimation("laddersbase", "base_left_hand_up", 8f, -1, AnimationFlags.Loop);
}
}
else
{
if (_currentAnimation[1] != "climb_up")
{
MainPed.Task.ClearAllImmediately();
_currentAnimation[1] = "climb_up";
}
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, MainPed.Handle, "laddersbase", "climb_up", 3))
{
MainPed.Task.PlayAnimation("laddersbase", "climb_up", 8f, -1, AnimationFlags.Loop);
}
}
}
SmoothTransition();
return;
}
if (!IsOnLadder && Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, MainPed.Handle, ETasks.CLIMB_LADDER))
{
MainPed.Task.ClearAllImmediately();
_currentAnimation[1] = "";
}
if (IsVaulting)
{
if (!MainPed.IsVaulting)
{
MainPed.Task.Climb();
}
UpdateOnFootPosition(true, true, false);
return;
}
if (!IsVaulting && MainPed.IsVaulting)
{
MainPed.Task.ClearAllImmediately();
}
if (IsOnFire && !MainPed.IsOnFire)
{
MainPed.SetOnFire(true);
}
else if (!IsOnFire && MainPed.IsOnFire)
{
MainPed.SetOnFire(false);
}
if (IsJumping)
{
if (!_lastIsJumping)
{
_lastIsJumping = true;
MainPed.Task.Jump();
}
SmoothTransition();
return;
}
_lastIsJumping = false;
if (IsRagdoll || Health==0)
{
if (!MainPed.IsRagdoll)
{
MainPed.Ragdoll();
}
SmoothTransition();
if (!_lastRagdoll)
{
_lastRagdoll = true;
_lastRagdollTime=Main.Ticked;
}
/*
if((Main.Ticked-_lastRagdollTime>30)&&((Position.DistanceTo(MainPed.Position)>2)||MainPed.Velocity.Length()<3f))
{
MainPed.ApplyForce((Position-MainPed.Position)*0.2f, (RotationVelocity-MainPed.RotationVelocity)*0.1f);
}*/
return;
}
else
{
if (MainPed.IsRagdoll)
{
if (Speed==0)
{
MainPed.CancelRagdoll();
}
else
{
MainPed.Task.ClearAllImmediately();
}
return;
}
else
{
_lastRagdoll = false;
}
}
CheckCurrentWeapon();
if (IsReloading)
{
if (!_isPlayingAnimation)
{
string[] reloadingAnim = MainPed.GetReloadingAnimation();
if (reloadingAnim != null)
{
_isPlayingAnimation = true;
_currentAnimation = reloadingAnim;
MainPed.Task.PlayAnimation(_currentAnimation[0], _currentAnimation[1], 8f, -1, AnimationFlags.AllowRotation | AnimationFlags.UpperBodyOnly);
}
}
UpdateOnFootPosition();
}
else if (_currentAnimation[1] == "reload_aim")
{
MainPed.Task.ClearAnimation(_currentAnimation[0], _currentAnimation[1]);
_isPlayingAnimation = false;
_currentAnimation = new string[2] { "", "" };
}
else if (IsInCover)
{
if (!_lastInCover)
{
Function.Call(Hash.TASK_STAY_IN_COVER, MainPed.Handle);
}
_lastInCover=true;
if (IsAiming)
{
DisplayAiming();
_lastInCover=false;
}
else if (MainPed.IsInCover)
{
SmoothTransition();
}
return;
}
else if (_lastInCover)
{
MainPed.Task.ClearAllImmediately();
_lastInCover=false;
}
else if (IsAiming)
{
DisplayAiming();
}
else if (MainPed.IsShooting)
{
MainPed.Task.ClearAllImmediately();
}
else
{
WalkTo();
}
}
private void DisplayInVehicle()
{
if (MainPed.IsOnTurretSeat())
{
Function.Call(Hash.SET_VEHICLE_TURRET_SPEED_THIS_FRAME, MainPed.CurrentVehicle, 100);
Function.Call(Hash.TASK_VEHICLE_AIM_AT_COORD, MainPed.Handle, AimCoords.X, AimCoords.Y, AimCoords.Z);
}
}
#region WEAPON
private void CheckCurrentWeapon()
{
if (MainPed.Weapons.Current.Hash != (WeaponHash)CurrentWeaponHash || !WeaponComponents.Compare(_lastWeaponComponents))
{
MainPed.Weapons.RemoveAll();
if (CurrentWeaponHash != (uint)WeaponHash.Unarmed)
{
if (WeaponComponents == null || WeaponComponents.Count == 0)
{
MainPed.Weapons.Give((WeaponHash)CurrentWeaponHash, 0, true, true);
}
else
{
_lastWeaponObj = Function.Call<int>(Hash.CREATE_WEAPON_OBJECT, CurrentWeaponHash, -1, Position.X, Position.Y, Position.Z, true, 0, 0);
foreach (KeyValuePair<uint, bool> comp in WeaponComponents)
{
if (comp.Value)
{
Function.Call(Hash.GIVE_WEAPON_COMPONENT_TO_WEAPON_OBJECT, _lastWeaponObj, comp.Key);
}
}
Function.Call(Hash.GIVE_WEAPON_OBJECT_TO_PED, _lastWeaponObj, MainPed.Handle);
}
}
_lastWeaponComponents = WeaponComponents;
}
}
private void DisplayAiming()
{
if (Velocity==default)
{
MainPed.Task.AimAt(AimCoords,1000);
}
else
{
Function.Call(Hash.TASK_GO_TO_COORD_WHILE_AIMING_AT_COORD, MainPed.Handle,
Position.X+Velocity.X, Position.Y+Velocity.Y, Position.Z+Velocity.Z,
AimCoords.X, AimCoords.Y, AimCoords.Z, 3f, false, 0x3F000000, 0x40800000, false, 512, false, 0);
}
SmoothTransition();
}
#endregion
private bool LastMoving;
private void WalkTo()
{
Vector3 predictPosition = Position + (Position - MainPed.Position) + Velocity * 0.5f;
float range = predictPosition.DistanceToSquared(MainPed.Position);
switch (Speed)
{
case 1:
if (!MainPed.IsWalking || range > 0.25f)
{
float nrange = range * 2;
if (nrange > 1.0f)
{
nrange = 1.0f;
}
MainPed.Task.GoStraightTo(predictPosition);
Function.Call(Hash.SET_PED_DESIRED_MOVE_BLEND_RATIO, MainPed.Handle, nrange);
}
LastMoving = true;
break;
case 2:
if (!MainPed.IsRunning || range > 0.50f)
{
MainPed.Task.RunTo(predictPosition, true);
Function.Call(Hash.SET_PED_DESIRED_MOVE_BLEND_RATIO, MainPed.Handle, 1.0f);
}
LastMoving = true;
break;
case 3:
if (!MainPed.IsSprinting || range > 0.75f)
{
Function.Call(Hash.TASK_GO_STRAIGHT_TO_COORD, MainPed.Handle, predictPosition.X, predictPosition.Y, predictPosition.Z, 3.0f, -1, 0.0f, 0.0f);
Function.Call(Hash.SET_RUN_SPRINT_MULTIPLIER_FOR_PLAYER, MainPed.Handle, 1.49f);
Function.Call(Hash.SET_PED_DESIRED_MOVE_BLEND_RATIO, MainPed.Handle, 1.0f);
}
LastMoving = true;
break;
default:
if (LastMoving)
{
MainPed.Task.StandStill(2000);
LastMoving = false;
}
break;
}
SmoothTransition();
}
private bool StuckDetection = false;
private ulong LastStuckTime;
private void UpdateOnFootPosition(bool updatePosition = true, bool updateRotation = true, bool updateVelocity = true)
{
/*
ulong time = Util.GetTickCount64();
if (StuckDetection)
{
if (time - LastStuckTime >= 500)
{
StuckDetection = false;
if (Character.Position.DistanceTo(Position) > 5f)
{
Character.PositionNoOffset = Position;
Character.Rotation = Rotation;
}
}
}
else if (time - LastStuckTime >= 500)
{
if (Character.Position.DistanceTo(Position) > 5f)
{
StuckDetection = true;
LastStuckTime = time;
}
}
*/
if (updatePosition)
{
MainPed.PositionNoOffset = Position;
/*
float lerpValue = (int)((Latency * 1000 / 2) + (Main.MainNetworking.Latency * 1000 / 2)) * 2 / 50000f;
Vector2 biDimensionalPos = Vector2.Lerp(new Vector2(Character.Position.X, Character.Position.Y), new Vector2(Position.X + (Velocity.X / 5), Position.Y + (Velocity.Y / 5)), lerpValue);
float zPos = Util.Lerp(Character.Position.Z, Position.Z, 0.1f);
Character.PositionNoOffset = new Vector3(biDimensionalPos.X, biDimensionalPos.Y, zPos);
*/
}
if (updateRotation)
{
// You can find the ToQuaternion() for Rotation inside the VectorExtensions
MainPed.Quaternion = Rotation.ToQuaternion();
}
if (updateVelocity)
{
MainPed.Velocity = Velocity;
}
}
private void SmoothTransition()
{
var localRagdoll = MainPed.IsRagdoll;
var dist = Position.DistanceTo(MainPed.Position);
if (dist>3)
{
MainPed.PositionNoOffset=Position;
return;
}
var f = dist*(Position+SyncParameters.PositioinPrediction*Velocity-MainPed.Position)+(Velocity-MainPed.Velocity)*0.2f;
if (!localRagdoll) { f*=5; }
if (!(localRagdoll|| MainPed.IsDead))
{
MainPed.Rotation=Rotation;
if (MainPed.Speed<0.05) { f*=10; MainPed.Heading=Heading; }
}
else if (Main.Ticked-_lastRagdollTime<10)
{
return;
}
MainPed.ApplyForce(f);
}
private Vector3 GetCalibrationRotation()
{
var r = Rotation-MainPed.Rotation;
if (r.X>180) { r.X=(180-r.X); }
else if (r.X<-180) { r.X=360+r.X; }
if (r.Y>180||r.Y<-180) { r.Y=(180-r.Y); }
else if (r.Y<-180) { r.Y=360+r.Y; }
if (r.Z>180||r.Z<-180) { r.Z=(180-r.Z); }
else if (r.Z<-180) { r.Z=360+r.Z; }
return r;
}
private string LoadAnim(string anim)
{
ulong startTime = Util.GetTickCount64();
while (!Function.Call<bool>(Hash.HAS_ANIM_DICT_LOADED, anim))
{
Script.Yield();
Function.Call(Hash.REQUEST_ANIM_DICT, anim);
if (Util.GetTickCount64() - startTime >= 1000)
{
break;
}
}
return anim;
}
#endregion
#region QUEUED ACTIONS
#region ENTER-VEHICLE
/// <summary>
/// Tell this character to enter a vehicle and do callback when the task is finished.
/// </summary>
/// <param name="veh"></param>
/// <param name="seat"></param>
/// <param name="callback"> callback function to be invoked when done, accepting first argument that indicates whether the operation is successful.</param>
public void EnterVehicle(SyncedVehicle veh,VehicleSeat seat, Action<bool> callback)
{
Main.QueueAction(new Func<bool>(() =>
{
MainPed.Task.EnterVehicle(veh.MainVehicle, seat,-1,2,EnterVehicleFlags.AllowJacking|EnterVehicleFlags.WarpToDoor);
return true;
}));
int i = 0;
float maxwait = Game.FPS*5;
Main.QueueAction(new Func<bool>(() =>
{
i++;
if ((_lastEnteringVehicle && !MainPed.IsGettingIntoVehicle)||i>maxwait)
{
callback(MainPed.IsInVehicle());
_isEnteringVehicle=false;
return true;
}
_lastEnteringVehicle = MainPed.IsGettingIntoVehicle;
return false;
}));
}
#endregion
#endregion
}
}

View File

@ -0,0 +1,430 @@
using System;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GTA;
using GTA.Native;
using GTA.Math;
using RageCoop.Core;
namespace RageCoop.Client
{
public class SyncedVehicle : SyncedEntity
{
#region -- CONSTRUCTORS --
/// <summary>
/// Create a local entity (outgoing sync)
/// </summary>
/// <param name="p"></param>
public SyncedVehicle(Vehicle v)
{
while ((ID==0) || EntityPool.Exists(ID))
{
byte[] rngBytes = new byte[4];
RandomNumberGenerator.Create().GetBytes(rngBytes);
// Convert the bytes into an integer
ID = BitConverter.ToInt32(rngBytes, 0);
}
MainVehicle=v;
MainVehicle.CanPretendOccupants=false;
OwnerID=Main.MyPlayerID;
}
/// <summary>
/// Create an empty VehicleEntity
/// </summary>
public SyncedVehicle()
{
}
public SyncedVehicle(int id)
{
ID=id;
LastSynced=Main.Ticked;
}
#endregion
/// <summary>
/// VehicleSeat,ID
/// </summary>
public Vehicle MainVehicle { get; set; }
#region LAST STATE STORE
private ulong _vehicleStopTime { get; set; }
private byte[] _lastVehicleColors = new byte[] { 0, 0 };
private Dictionary<int, int> _lastVehicleMods = new Dictionary<int, int>();
#endregion
#region -- CRITICAL STUFF --
public Vector3 Position { get; set; }
public Vector3 Velocity { get; set; }
public Vector3 RotationVelocity { get; set; }
public Vector3 Rotation { get; set; }
public float SteeringAngle { get; set; }
public float ThrottlePower { get; set; }
public float BrakePower { get; set; }
#endregion
#region -- VEHICLE STATE --
public bool EngineRunning { get; set; }
private bool _lastTransformed = false;
public bool Transformed { get; set; }
private bool _lastHornActive = false;
public bool HornActive { get; set; }
public bool LightsOn { get; set; }
public bool BrakeLightsOn { get; set; } = false;
public bool HighBeamsOn { get; set; }
public byte LandingGear { get; set; }
public bool RoofOpened { get; set; }
public bool SireneActive { get; set; }
public VehicleDamageModel DamageModel { get; set; }
public int ModelHash { get; set; }
public byte[] Colors { get; set; }
public Dictionary<int, int> Mods { get; set; }
public bool IsDead { get; set; }
public float EngineHealth { get; set; }
public VehicleLockStatus LockStatus{get;set;}
/// <summary>
/// VehicleSeat,PedID
/// </summary>
public Dictionary<VehicleSeat, SyncedPed> Passengers { get; set; }
private long _lastPositionCalibrated { get; set; }
#endregion
public void Update()
{
#region -- INITIAL CHECK --
if (IsMine) { return; }
// Check if all data avalible
if (LastStateSynced == 0) { return; }
if (LastSynced==0) { return; }
// Skip update if no new sync message has arrived.
if (LastUpdated>=LastSynced) { return; }
#endregion
#region -- CHECK EXISTENCE --
if ((MainVehicle == null) || (!MainVehicle.Exists()) || (MainVehicle.Model.Hash != ModelHash))
{
CreateVehicle();
return;
}
#endregion
#region -- SYNC CRITICAL --
if (SteeringAngle != MainVehicle.SteeringAngle)
{
MainVehicle.CustomSteeringAngle((float)(Math.PI / 180) * SteeringAngle);
}
if (MainVehicle.ThrottlePower!=ThrottlePower)
{
MainVehicle.ThrottlePower=ThrottlePower;
}
if (MainVehicle.BrakePower!=BrakePower)
{
MainVehicle.BrakePower=BrakePower;
}
if (MainVehicle.Position.DistanceTo(Position)<5)
{
MainVehicle.Velocity = Velocity+5*(Position+Velocity*SyncParameters.PositioinPrediction - MainVehicle.Position);
_lastPositionCalibrated=Main.Counter.ElapsedMilliseconds;
}
else
{
MainVehicle.Position=Position;
MainVehicle.Velocity=Velocity;
}
#region OBSOLETE
// Good enough for now, but we need to create a better sync
/*
float dist = Position.DistanceTo(MainVehicle.Position);
Vector3 f = 5*dist * (Position+Velocity*0.06f - (MainVehicle.Position+MainVehicle.Velocity*delay));
if (dist < 5f)
{
// Precised calibration
if (Velocity.Length()<0.05) { f*=10f; }
else if (dist<1)
{
// Avoid vibration
f+=(Velocity-MainVehicle.Velocity);
}
MainVehicle.ApplyForce(f);
}
else
{
MainVehicle.PositionNoOffset = Position;
}
*/
#endregion
Vector3 r = GetCalibrationRotation();
if (r.Length() < 20f)
{
MainVehicle.RotationVelocity = r * 0.15f + RotationVelocity;
}
else
{
MainVehicle.Rotation = Rotation;
MainVehicle.RotationVelocity = RotationVelocity;
}
_vehicleStopTime = Util.GetTickCount64();
#endregion
if (LastStateSynced>LastUpdated)
{
#region -- SYNC STATE --
#region -- PASSENGER SYNC --
// check passengers (and driver).
var currentPassengers = MainVehicle.GetPassengers();
lock (Passengers)
{
for (int i = -1; i<MainVehicle.PassengerCapacity; i++)
{
VehicleSeat seat = (VehicleSeat)i;
if (Passengers.ContainsKey(seat))
{
SyncedPed c = Passengers[seat];
if ((c!=null)&&c.MainPed!=null&&(!currentPassengers.ContainsKey(i))) {
Passengers[seat].MainPed.SetIntoVehicle(MainVehicle, seat);
}
}
else if (!MainVehicle.IsSeatFree(seat))
{
if (seat==VehicleSeat.Driver &&MainVehicle.Driver.IsSittingInVehicle())
{
MainVehicle.Driver.Task.WarpOutOfVehicle(MainVehicle);
}
else
{
var p = MainVehicle.Passengers.Where(x => x.SeatIndex==seat).FirstOrDefault();
if ((p!=null)&&p.IsSittingInVehicle())
{
p.Task.WarpOutOfVehicle(MainVehicle);
}
}
}
}
}
#endregion
if (Colors != null && Colors != _lastVehicleColors)
{
Function.Call(Hash.SET_VEHICLE_COLOURS, MainVehicle, Colors[0], Colors[1]);
_lastVehicleColors = Colors;
}
MainVehicle.EngineHealth=EngineHealth;
if (Mods != null && !Mods.Compare(_lastVehicleMods))
{
Function.Call(Hash.SET_VEHICLE_MOD_KIT, MainVehicle, 0);
foreach (KeyValuePair<int, int> mod in Mods)
{
MainVehicle.Mods[(VehicleModType)mod.Key].Index = mod.Value;
}
_lastVehicleMods = Mods;
}
if (IsDead)
{
if (MainVehicle.IsDead)
{
return;
}
else
{
MainVehicle.Explode();
}
}
else
{
if (MainVehicle.IsDead)
{
MainVehicle.Repair();
}
}
if (EngineRunning != MainVehicle.IsEngineRunning)
{
MainVehicle.IsEngineRunning = EngineRunning;
}
if (LightsOn != MainVehicle.AreLightsOn)
{
MainVehicle.AreLightsOn = LightsOn;
}
if (HighBeamsOn != MainVehicle.AreHighBeamsOn)
{
MainVehicle.AreHighBeamsOn = HighBeamsOn;
}
if (MainVehicle.IsSubmarineCar)
{
if (Transformed)
{
if (!_lastTransformed)
{
_lastTransformed = true;
Function.Call(Hash._TRANSFORM_VEHICLE_TO_SUBMARINE, MainVehicle.Handle, false);
}
}
else if (_lastTransformed)
{
_lastTransformed = false;
Function.Call(Hash._TRANSFORM_SUBMARINE_TO_VEHICLE, MainVehicle.Handle, false);
}
}
if (MainVehicle.IsAircraft)
{
if (LandingGear != (byte)MainVehicle.LandingGearState)
{
MainVehicle.LandingGearState = (VehicleLandingGearState)LandingGear;
}
}
else
{
if (MainVehicle.HasSiren && SireneActive != MainVehicle.IsSirenActive)
{
MainVehicle.IsSirenActive = SireneActive;
}
if (HornActive)
{
if (!_lastHornActive)
{
_lastHornActive = true;
MainVehicle.SoundHorn(99999);
}
}
else if (_lastHornActive)
{
_lastHornActive = false;
MainVehicle.SoundHorn(1);
}
if (MainVehicle.HasRoof)
{
bool roofOpened = MainVehicle.RoofState == VehicleRoofState.Opened || MainVehicle.RoofState == VehicleRoofState.Opening;
if (roofOpened != RoofOpened)
{
MainVehicle.RoofState = RoofOpened ? VehicleRoofState.Opening : VehicleRoofState.Closing;
}
}
Function.Call(Hash.SET_VEHICLE_BRAKE_LIGHTS, MainVehicle.Handle, BrakeLightsOn);
MainVehicle.SetVehicleDamageModel(DamageModel);
}
MainVehicle.LockStatus=LockStatus;
#endregion
}
LastUpdated=Main.Ticked;
}
private Vector3 GetCalibrationRotation()
{
var r = Rotation-MainVehicle.Rotation;
if (r.X>180) { r.X=r.X-360; }
else if(r.X<-180) { r.X=360+r.X; }
if (r.Y>180) { r.Y=r.Y-360; }
else if (r.Y<-180) { r.Y=360+r.Y; }
if (r.Z>180) { r.Z=r.Z-360; }
else if (r.Z<-180) { r.Z=360+r.Z; }
return r;
}
private void CreateVehicle()
{
MainVehicle?.Delete();
Model vehicleModel = ModelHash.ModelRequest();
if (vehicleModel == null)
{
//GTA.UI.Notification.Show($"~r~(Vehicle)Model ({CurrentVehicleModelHash}) cannot be loaded!");
return;
}
MainVehicle = World.CreateVehicle(vehicleModel, Position);
lock (EntityPool.VehiclesLock)
{
EntityPool.Add( this);
}
MainVehicle.Rotation = Rotation;
if (MainVehicle.HasRoof)
{
bool roofOpened = MainVehicle.RoofState == VehicleRoofState.Opened || MainVehicle.RoofState == VehicleRoofState.Opening;
if (roofOpened != RoofOpened)
{
MainVehicle.RoofState = RoofOpened ? VehicleRoofState.Opened : VehicleRoofState.Closed;
}
}
vehicleModel.MarkAsNoLongerNeeded();
}
#region -- PEDALING --
/*
* Thanks to @oldnapalm.
*/
private string PedalingAnimDict()
{
switch ((VehicleHash)ModelHash)
{
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
}
}

359
Client/Sync/EntityPool.cs Normal file
View File

@ -0,0 +1,359 @@
using System;
using GTA;
using GTA.Native;
using RageCoop.Core;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;
namespace RageCoop.Client
{
internal class EntityPool
{
public static object PedsLock = new object();
private static Dictionary<int, SyncedPed> ID_Peds = new Dictionary<int, SyncedPed>();
public static int CharactersCount { get { return ID_Peds.Count; } }
private static Stopwatch PerfCounter=new Stopwatch();
/// <summary>
/// Faster access to Character with Handle, but values may not equal to <see cref="ID_Peds"/> since Ped might not have been created.
/// </summary>
private static Dictionary<int, SyncedPed> Handle_Peds = new Dictionary<int, SyncedPed>();
public static object VehiclesLock = new object();
private static Dictionary<int, SyncedVehicle> ID_Vehicles = new Dictionary<int, SyncedVehicle>();
private static Dictionary<int, SyncedVehicle> Handle_Vehicles = new Dictionary<int, SyncedVehicle>();
public static void Cleanup(bool keepPlayer=true,bool keepMine=true)
{
foreach(int id in new List<int>(ID_Peds.Keys))
{
if (keepPlayer&&(id==Main.MyPlayerID)) { continue; }
if (keepMine&&(ID_Peds[id].OwnerID==Main.MyPlayerID)) { continue; }
RemovePed(id);
}
ID_Peds.Clear();
Handle_Peds.Clear();
foreach (int id in new List<int>(ID_Vehicles.Keys))
{
if (keepMine&&(ID_Vehicles[id].OwnerID==Main.MyPlayerID)) { continue; }
RemoveVehicle(id);
}
ID_Vehicles.Clear();
Handle_Vehicles.Clear();
}
public static SyncedPed GetPedByID(int id)
{
return ID_Peds.ContainsKey(id) ? ID_Peds[id] : null;
}
public static SyncedPed GetPedByHandle(int handle)
{
return Handle_Peds.ContainsKey(handle) ? Handle_Peds[handle] : null;
}
public static List<int> GetPedIDs()
{
return new List<int>(ID_Peds.Keys);
}
public static bool AddPlayer()
{
Ped p = Game.Player.Character;
SyncedPed player = GetPedByID(Main.MyPlayerID);
if (player!=null)
{
if (player.MainPed!=p)
{
// Player model changed
player.MainPed = p;
// Remove it from Handle_Characters
var pairs=Handle_Peds.Where(x=>x.Value==player);
if (pairs.Any())
{
var pair=pairs.First();
// Re-add
Handle_Peds.Remove(pair.Key);
if (Handle_Peds.ContainsKey(p.Handle))
{
RemovePed(Handle_Peds[p.Handle].ID);
}
Handle_Peds.Add(p.Handle, player);
}
}
}
else
{
Main.Logger.Debug($"Creating SyncEntity for player, handle:{p.Handle}");
SyncedPed c = new SyncedPed(p);
Main.MyPlayerID=c.OwnerID=c.ID;
Add(c);
Main.Logger.Debug($"My player ID is:{c.ID}");
Main.MainPlayerList.SetPlayer(c.ID, Main.Settings.Username );
return true;
}
return false;
}
public static void Add(SyncedPed c)
{
if (ID_Peds.ContainsKey(c.ID))
{
ID_Peds[c.ID]=c;
}
else
{
ID_Peds.Add(c.ID, c);
}
if (c.MainPed==null) { return; }
if (Handle_Peds.ContainsKey(c.MainPed.Handle))
{
Handle_Peds[c.MainPed.Handle]=c;
}
else
{
Handle_Peds.Add(c.MainPed.Handle, c);
}
}
public static void RemovePed(int id,string reason="Cleanup")
{
if (ID_Peds.ContainsKey(id))
{
SyncedPed c = ID_Peds[id];
var p = c.MainPed;
if (p!=null)
{
if (Handle_Peds.ContainsKey(p.Handle))
{
Handle_Peds.Remove(p.Handle);
}
Main.Logger.Debug($"Removing ped {c.ID}. Reason:{reason}");
p.AttachedBlip?.Delete();
p.Kill();
p.Delete();
}
c.PedBlip?.Delete();
c.ParachuteProp?.Delete();
ID_Peds.Remove(id);
}
}
public static SyncedVehicle GetVehicleByID(int id)
{
return ID_Vehicles.ContainsKey(id) ? ID_Vehicles[id] : null;
}
public static SyncedVehicle GetVehicleByHandle(int handle)
{
return Handle_Vehicles.ContainsKey(handle) ? Handle_Vehicles[handle] : null;
}
public static List<int> GetVehicleIDs()
{
return new List<int>(ID_Vehicles.Keys);
}
public static void Add(SyncedVehicle v)
{
if (ID_Vehicles.ContainsKey(v.ID))
{
ID_Vehicles[v.ID]=v;
}
else
{
ID_Vehicles.Add(v.ID, v);
}
if (v.MainVehicle==null) { return; }
if (Handle_Vehicles.ContainsKey(v.MainVehicle.Handle))
{
Handle_Vehicles[v.MainVehicle.Handle]=v;
}
else
{
Handle_Vehicles.Add(v.MainVehicle.Handle, v);
}
}
public static void RemoveVehicle(int id,string reason = "Cleanup")
{
if (ID_Vehicles.ContainsKey(id))
{
SyncedVehicle v = ID_Vehicles[id];
var veh = v.MainVehicle;
if (veh!=null)
{
if (Handle_Vehicles.ContainsKey(veh.Handle))
{
Handle_Vehicles.Remove(veh.Handle);
}
Main.Logger.Debug($"Removing vehicle {v.ID}. Reason:{reason}");
veh.AttachedBlip?.Delete();
veh.Delete();
}
ID_Vehicles.Remove(id);
}
}
public static bool Exists(int id)
{
return ID_Peds.ContainsKey(id) || ID_Vehicles.ContainsKey(id);
}
public static void DoSync()
{
PerfCounter.Restart();
SyncEvents.CheckProjectiles();
Debug.TimeStamps[TimeStamp.CheckProjectiles]=PerfCounter.ElapsedTicks;
var allPeds = World.GetAllPeds();
var allVehicles=World.GetAllVehicles();
if (Main.Ticked%100==0) { if (allVehicles.Length>50) { SetBudget(0); } else { SetBudget(1); } }
Debug.TimeStamps[TimeStamp.GetAllEntities]=PerfCounter.ElapsedTicks;
lock (EntityPool.PedsLock)
{
EntityPool.AddPlayer();
foreach (Ped p in allPeds)
{
SyncedPed c = EntityPool.GetPedByHandle(p.Handle);
if (c==null && (p!=Game.Player.Character))
{
Main.Logger.Trace($"Creating SyncEntity for ped, handle:{p.Handle}");
c=new SyncedPed(p);
EntityPool.Add(c);
}
}
Debug.TimeStamps[TimeStamp.AddPeds]=PerfCounter.ElapsedTicks;
foreach (SyncedPed c in ID_Peds.Values.ToArray())
{
if ((c.MainPed!=null)&&(!c.MainPed.Exists()))
{
EntityPool.RemovePed(c.ID, "non-existent");
continue;
}
// Outgoing sync
if (c.IsMine)
{
// event check
SyncEvents.Check(c);
if (Main.Ticked%20==0)
{
Main.MainNetworking.SendPedState(c);
}
else
{
Main.MainNetworking.SendPed(c);
}
}
else // Incoming sync
{
c.Update();
if (c.IsOutOfSync)
{
try
{
EntityPool.RemovePed(c.ID,"OutOfSync");
}
catch { }
}
}
}
Debug.TimeStamps[TimeStamp.PedTotal]=PerfCounter.ElapsedTicks;
}
lock (EntityPool.VehiclesLock)
{
foreach (Vehicle veh in allVehicles)
{
SyncedVehicle v = EntityPool.GetVehicleByHandle(veh.Handle);
if (v==null)
{
Main.Logger.Debug($"Creating SyncEntity for vehicle, handle:{veh.Handle}");
EntityPool.Add(new SyncedVehicle(veh));
}
}
Debug.TimeStamps[TimeStamp.AddVehicles]=PerfCounter.ElapsedTicks;
foreach (SyncedVehicle v in ID_Vehicles.Values.ToArray())
{
if ((v.MainVehicle!=null)&&(!v.MainVehicle.Exists()))
{
EntityPool.RemoveVehicle(v.ID,"non-existent");
continue;
}
// Outgoing sync
if (v.IsMine)
{
if (Main.Ticked%20==0)
{
Main.MainNetworking.SendVehicleState(v);
}
else
{
Main.MainNetworking.SendVehicle(v);
}
}
else // Incoming sync
{
v.Update();
if (v.IsOutOfSync)
{
try
{
EntityPool.RemoveVehicle(v.ID, "OutOfSync");
}
catch { }
}
}
}
Debug.TimeStamps[TimeStamp.VehicleTotal]=PerfCounter.ElapsedTicks;
}
}
public static void RemoveAllFromPlayer(int playerPedId)
{
foreach(SyncedPed p in ID_Peds.Values.ToArray())
{
if (p.OwnerID==playerPedId)
{
RemovePed(p.ID);
}
}
foreach (SyncedVehicle v in ID_Vehicles.Values.ToArray())
{
if (v.OwnerID==playerPedId)
{
RemoveVehicle(v.ID);
}
}
}
private static void SetBudget(int b)
{
Function.Call(Hash.SET_PED_POPULATION_BUDGET, b); // 0 - 3
Function.Call(Hash.SET_VEHICLE_POPULATION_BUDGET, b); // 0 - 3
}
}
}

359
Client/Sync/SyncEvents.cs Normal file
View File

@ -0,0 +1,359 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GTA;
using GTA.Math;
using RageCoop.Core;
using GTA.Native;
using System.Threading;
namespace RageCoop.Client {
internal static class SyncEvents
{
#region TRIGGER
/// <summary>
/// Informs other players that this ped has been killed.
/// </summary>
/// <param name="c"></param>
public static void TriggerPedKilled(SyncedPed victim)
{
Main.MainNetworking.Send(new Packets.PedKilled() { VictimID=victim.ID},ConnectionChannel.SyncEvents);
}
public static void TriggerEnteringVehicle(SyncedPed c,SyncedVehicle veh, VehicleSeat seat)
{
Main.MainNetworking.SendEnteringVehicle(c.ID,veh.ID,(short)seat);
}
public static void TriggerEnteredVehicle(SyncedPed c, SyncedVehicle veh, VehicleSeat seat)
{
Main.MainNetworking.Send(new Packets.EnteredVehicle()
{
VehicleSeat=(short)seat,
PedID=c.ID,
VehicleID=veh.ID
},ConnectionChannel.SyncEvents);
if (seat==VehicleSeat.Driver)
{
TriggerChangeOwner(veh, c.ID);
veh.OwnerID=Main.MyPlayerID;
veh.LastSynced=Main.Ticked;
}
}
public static void TriggerChangeOwner(SyncedVehicle c, int newOwnerID)
{
Main.MainNetworking.SendOwnerChanged(c.ID,newOwnerID);
}
public static void TriggerBulletShot(uint hash,SyncedPed owner,Vector3 impactPosition)
{
// Minigun, not working for some reason
if (hash==(uint)WeaponHash.Minigun)
{
hash=(uint)WeaponHash.HeavyRifle;
}
// Valkyire, not working for some reason
if (hash==2756787765) { hash=(uint)WeaponHash.HeavyRifle; }
var start = owner.MainPed.GetMuzzlePosition();
if (owner.MainPed.IsOnTurretSeat()) { start=owner.MainPed.Bones[Bone.SkelHead].Position; }
if (start.DistanceTo(impactPosition)>10)
{
// Reduce latency
start=impactPosition-(impactPosition-start).Normalized*10;
}
Main.MainNetworking.SendBulletShot(start, impactPosition, hash, owner.ID);
}
public static void TriggerLeaveVehicle(int id)
{
Main.MainNetworking.SendLeaveVehicle(id);
}
public static void TriggerVehBulletShot(uint hash, Vehicle veh)
{
}
public static void TriggerProjectileShot(Projectile p)
{
var pp = p.Owner;
if (pp.IsShooting)
{
var start = p.Position;
var end = start+p.Velocity;
Main.MainNetworking.SendBulletShot(start, end, (uint)p.WeaponHash, pp.GetSyncEntity().ID);
}
}
#endregion
#region HANDLE
public static void HandleLeaveVehicle(Packets.LeaveVehicle p)
{
var ped = EntityPool.GetPedByID(p.ID)?.MainPed;
var flag = LeaveVehicleFlags.None;
// Bail out
if (ped?.CurrentVehicle==null) { return; }
if (ped.CurrentVehicle.Speed>5) { flag|=LeaveVehicleFlags.BailOut;}
ped.Task.LeaveVehicle(flag) ;
}
public static void HandlePedKilled(Packets.PedKilled p)
{
EntityPool.GetPedByID(p.VictimID)?.MainPed?.Kill();
}
public static void HandleEnteringVehicle(SyncedPed c, SyncedVehicle veh, VehicleSeat seat)
{
c.MainPed?.Task.EnterVehicle(veh.MainVehicle, seat,-1,2,EnterVehicleFlags.WarpToDoor|EnterVehicleFlags.AllowJacking);
}
public static void HandleEnteredVehicle(int pedId, int vehId, VehicleSeat seat)
{
var v = EntityPool.GetVehicleByID(vehId);
if (v==null) { return; }
EntityPool.GetPedByID(pedId)?.MainPed?.SetIntoVehicle(v.MainVehicle, seat);
}
public static void HandleOwnerChanged(Packets.OwnerChanged p)
{
var v = EntityPool.GetVehicleByID(p.ID);
if (v==null) { return; }
v.OwnerID=p.NewOwnerID;
}
private static ParticleEffectAsset CorePFXAsset = default;
static WeaponAsset _weaponAsset = default;
static uint _lastWeaponHash;
public static void HandleBulletShot(Vector3 start, Vector3 end, uint weaponHash, int ownerID)
{
if (CorePFXAsset==default) {
CorePFXAsset= new ParticleEffectAsset("core");
}
if (!CorePFXAsset.IsLoaded) { CorePFXAsset.Request(); }
var p = EntityPool.GetPedByID(ownerID)?.MainPed;
if (p == null) { p=Game.Player.Character; Main.Logger.Warning("Failed to find owner for bullet"); }
if (_lastWeaponHash!=weaponHash)
{
_weaponAsset=new WeaponAsset(weaponHash);
_lastWeaponHash=weaponHash;
}
if (!_weaponAsset.IsLoaded) { _weaponAsset.Request(); }
World.ShootBullet(start, end, p, _weaponAsset, p.GetWeaponDamage());
var w = p.Weapons.CurrentWeaponObject;
if(w != null)
{
if (p.Weapons.Current.Components.GetSuppressorComponent().Active)
{
World.CreateParticleEffectNonLooped(CorePFXAsset, "muz_pistol_silencer", p.GetMuzzlePosition(), w.Rotation, 1);
}
else
{
World.CreateParticleEffectNonLooped(CorePFXAsset, "muz_assault_rifle", p.GetMuzzlePosition(), w.Rotation, 1);
}
}
}
public static void HandleEvent(PacketTypes type,byte[] data)
{
switch (type)
{
case PacketTypes.BulletShot:
{
Packets.BulletShot p = new Packets.BulletShot();
p.Unpack(data);
HandleBulletShot(p.StartPosition.ToVector(), p.EndPosition.ToVector(), p.WeaponHash, p.OwnerID);
break;
}
case PacketTypes.EnteringVehicle:
{
Packets.EnteringVehicle p = new Packets.EnteringVehicle();
p.Unpack(data);
HandleEnteringVehicle(EntityPool.GetPedByID(p.PedID), EntityPool.GetVehicleByID(p.VehicleID), (VehicleSeat)p.VehicleSeat);
}
break;
case PacketTypes.LeaveVehicle:
{
Packets.LeaveVehicle packet = new Packets.LeaveVehicle();
packet.Unpack(data);
HandleLeaveVehicle(packet);
}
break;
case PacketTypes.OwnerChanged:
{
Packets.OwnerChanged packet = new Packets.OwnerChanged();
packet.Unpack(data);
HandleOwnerChanged(packet);
}
break;
case PacketTypes.PedKilled:
{
var packet = new Packets.PedKilled();
packet.Unpack(data);
HandlePedKilled(packet);
}
break;
case PacketTypes.EnteredVehicle:
{
var packet = new Packets.EnteredVehicle();
packet.Unpack(data);
HandleEnteredVehicle(packet.PedID,packet.VehicleID,(VehicleSeat)packet.VehicleSeat);
break;
}
}
}
public static int GetWeaponDamage(this Ped p)
{
if (p.VehicleWeapon!=VehicleWeaponHash.Invalid)
{
return 30;
}
switch (p.Weapons.Current.Group)
{
case WeaponGroup.Pistol: return 30;
case WeaponGroup.AssaultRifle: return 30;
case WeaponGroup.SMG: return 20;
case WeaponGroup.MG: return 40;
case WeaponGroup.Shotgun: return 30;
case WeaponGroup.Sniper: return 200;
case WeaponGroup.Heavy: return 30;
}
return 0;
}
#endregion
/*
public static List<WeaponHash> ProjectileWeapons = new List<WeaponHash>
{
WeaponHash.RPG,
WeaponHash.Grenade,
WeaponHash.GrenadeLauncher,
WeaponHash.Ball,
WeaponHash.Bottle,
WeaponHash.BZGas,
WeaponHash.Firework,
};
*/
#region CHECK EVENTS
static bool _projectileShot = false;
static Projectile[] lastProjectiles=new Projectile[0];
public static void CheckProjectiles()
{
Projectile[] projectiles = World.GetAllProjectiles();
_projectileShot=false;
foreach (Projectile p in projectiles)
{
var owner = p.Owner.GetSyncEntity();
if ((!lastProjectiles.Contains(p)) && (owner!=null) && owner.IsMine)
{
TriggerProjectileShot(p);
_projectileShot=true;
}
}
lastProjectiles=projectiles;
}
public static void Check(SyncedPed c)
{
Ped subject = c.MainPed;
if (subject.IsShooting && !_projectileShot)
{
int i = 0;
Func<bool> getBulletImpact = (() =>
{
Vector3 endPos = subject.LastWeaponImpactPosition;
if (endPos==default )
{
if (i>5)
{
endPos=subject.GetAimCoord();
if (subject.IsInVehicle() && subject.VehicleWeapon!=VehicleWeaponHash.Invalid)
{
if (subject.IsOnTurretSeat())
{
TriggerBulletShot((uint)subject.VehicleWeapon,subject.GetSyncEntity(), endPos);
}
else
{
TriggerVehBulletShot((uint)subject.VehicleWeapon, subject.CurrentVehicle);
}
}
else
{
TriggerBulletShot((uint)subject.Weapons.Current.Hash, subject.GetSyncEntity(), endPos);
}
return true;
}
i++;
return false;
}
else
{
if (subject.IsInVehicle() && subject.VehicleWeapon!=VehicleWeaponHash.Invalid)
{
if (subject.IsOnTurretSeat())
{
TriggerBulletShot((uint)subject.VehicleWeapon, subject.GetSyncEntity(), endPos);
}
else
{
TriggerVehBulletShot((uint)subject.VehicleWeapon, subject.CurrentVehicle);
}
}
else
{
TriggerBulletShot((uint)subject.Weapons.Current.Hash, subject.GetSyncEntity(), endPos);
}
return true;
}
});
if (!getBulletImpact())
{
Main.QueueAction(getBulletImpact);
}
}
// Vehicles
var g = subject.IsGettingIntoVehicle;
if ( g && (!c._lastEnteringVehicle))
{
var v = subject.VehicleTryingToEnter.GetSyncEntity();
TriggerEnteringVehicle(c, v, subject.GetSeatTryingToEnter());
}
var currentSitting= subject.IsSittingInVehicle();
if (c._lastSittingInVehicle)
{
if (!currentSitting)
{
var veh = subject.CurrentVehicle;
if (veh!=null)
{
var v = veh.GetSyncEntity();
TriggerLeaveVehicle(c.ID);
}
}
}
else if (currentSitting)
{
TriggerEnteredVehicle(c, subject.CurrentVehicle.GetSyncEntity(), subject.SeatIndex);
}
c._lastSittingInVehicle=currentSitting;
c._lastEnteringVehicle=g;
}
#endregion
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RageCoop.Client
{
internal class SyncParameters
{
public static float PositioinPrediction = 0.06f;
}
}

View File

@ -3,19 +3,21 @@ using System.IO;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using RageCoop.Core;
using GTA;
using GTA.Native;
using GTA.Math;
using System.Linq;
using System.Diagnostics;
namespace CoopClient
namespace RageCoop.Client
{
enum ETasks
public enum ETasks
{
CLIMB_LADDER = 47
}
static class Util
internal static partial class Util
{
#region -- POINTER --
private static int _steeringAngleOffset { get; set; }
@ -30,6 +32,8 @@ namespace CoopClient
_steeringAngleOffset = *(int*)(address + 6) + 8;
}
// breaks some stuff.
/*
address = Game.FindPattern("\x32\xc0\xf3\x0f\x11\x09", "xxxxxx"); // Weapon / Radio slowdown
if (address != IntPtr.Zero)
{
@ -38,6 +42,7 @@ namespace CoopClient
*(byte*)(address + i).ToPointer() = 0x90;
}
}
*/
}
public static unsafe void CustomSteeringAngle(this Vehicle veh, float value)
@ -52,33 +57,54 @@ namespace CoopClient
}
#endregion
public static (byte, byte[]) GetBytesFromObject(object obj)
public static Settings ReadSettings()
{
switch (obj)
XmlSerializer ser = new XmlSerializer(typeof(Settings));
string path = Directory.GetCurrentDirectory() + "\\scripts\\CoopSettings.xml";
Settings settings = null;
if (File.Exists(path))
{
case byte _:
return (0x01, BitConverter.GetBytes((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));
default:
return (0x0, null);
using (FileStream stream = File.OpenRead(path))
{
settings = (RageCoop.Client.Settings)ser.Deserialize(stream);
}
using (FileStream stream = new FileStream(path, FileMode.Truncate, FileAccess.ReadWrite))
{
ser.Serialize(stream, settings);
}
}
else
{
using (FileStream stream = File.OpenWrite(path))
{
ser.Serialize(stream, settings = new Settings());
}
}
return settings;
}
public static void SaveSettings()
{
try
{
string path = Directory.GetCurrentDirectory() + "\\scripts\\CoopSettings.xml";
using (FileStream stream = new FileStream(path, File.Exists(path) ? FileMode.Truncate : FileMode.Create, FileAccess.ReadWrite))
{
XmlSerializer ser = new XmlSerializer(typeof(Settings));
ser.Serialize(stream, Main.Settings);
}
}
catch (Exception ex)
{
GTA.UI.Notification.Show("Error saving player settings: " + ex.Message);
}
}
public static string[] GetReloadingAnimation(this Ped ped)
{
switch (ped.Weapons.Current.Hash)
@ -232,29 +258,6 @@ namespace CoopClient
return (from * (1.0f - fAlpha)) + (to * fAlpha); //from + (to - from) * fAlpha
}
public static int GetResponsiblePedHandle(this Vehicle veh)
{
if (veh == null || veh.Handle == 0 || !veh.Exists())
{
return 0;
}
if (!veh.IsSeatFree(VehicleSeat.Driver))
{
return veh.GetPedOnSeat(VehicleSeat.Driver).Handle;
}
for (int i = 0; i < veh.PassengerCapacity; i++)
{
if (!veh.IsSeatFree((VehicleSeat)i))
{
return veh.GetPedOnSeat((VehicleSeat)i).Handle;
}
}
return 0;
}
public static byte GetPedSpeed(this Ped ped)
{
if (ped.IsSprinting)
@ -273,138 +276,132 @@ namespace CoopClient
return 0;
}
public static Vector3 GetPedAimCoords(this Ped ped, bool isNpc)
{
bool aimOrShoot = ped.IsAiming || ped.IsShooting && ped.Weapons.Current?.AmmoInClip != 0;
return aimOrShoot ? (isNpc ? GetLastWeaponImpact(ped) : RaycastEverything(new Vector2(0, 0))) : new Vector3();
}
/// <summary>
/// Only works for players NOT NPCs
/// </summary>
/// <returns>Vector3</returns>
public static Vector3 GetVehicleAimCoords()
public static VehicleDataFlags GetVehicleFlags(this Vehicle veh)
{
return RaycastEverything(new Vector2(0, 0));
}
public static ushort? GetVehicleFlags(this Ped ped, Vehicle veh)
{
ushort? flags = 0;
VehicleDataFlags flags = 0;
if (veh.IsEngineRunning)
{
flags |= (ushort)VehicleDataFlags.IsEngineRunning;
flags |= VehicleDataFlags.IsEngineRunning;
}
if (veh.AreLightsOn)
{
flags |= (ushort)VehicleDataFlags.AreLightsOn;
flags |= VehicleDataFlags.AreLightsOn;
}
if (veh.BrakePower >= 0.01f)
{
flags |= (ushort)VehicleDataFlags.AreBrakeLightsOn;
flags |= VehicleDataFlags.AreBrakeLightsOn;
}
if (veh.AreHighBeamsOn)
{
flags |= (ushort)VehicleDataFlags.AreHighBeamsOn;
flags |= VehicleDataFlags.AreHighBeamsOn;
}
if (veh.IsSirenActive)
{
flags |= (ushort)VehicleDataFlags.IsSirenActive;
flags |= VehicleDataFlags.IsSirenActive;
}
if (veh.IsDead)
{
flags |= (ushort)VehicleDataFlags.IsDead;
flags |= VehicleDataFlags.IsDead;
}
if (Function.Call<bool>(Hash.IS_HORN_ACTIVE, veh.Handle))
{
flags |= (ushort)VehicleDataFlags.IsHornActive;
flags |= VehicleDataFlags.IsHornActive;
}
if (veh.IsSubmarineCar && Function.Call<bool>(Hash._GET_IS_SUBMARINE_VEHICLE_TRANSFORMED, veh.Handle))
{
flags |= (ushort)VehicleDataFlags.IsTransformed;
flags |= VehicleDataFlags.IsTransformed;
}
if (veh.HasRoof && (veh.RoofState == VehicleRoofState.Opened || veh.RoofState == VehicleRoofState.Opening))
{
flags |= (ushort)VehicleDataFlags.RoofOpened;
flags |= VehicleDataFlags.RoofOpened;
}
if (veh.IsTurretSeat((int)ped.SeatIndex))
if (veh.IsAircraft)
{
flags |= (ushort)VehicleDataFlags.OnTurretSeat;
flags |= VehicleDataFlags.IsAircraft;
}
if (veh.IsPlane)
return flags;
}
public static PedDataFlags GetPedFlags(this Ped ped)
{
PedDataFlags flags = PedDataFlags.None;
if (ped.IsAiming || ped.IsOnTurretSeat())
{
flags |= (ushort)VehicleDataFlags.IsPlane;
flags |= PedDataFlags.IsAiming;
}
if (ped.IsReloading)
{
flags |= PedDataFlags.IsReloading;
}
if (ped.IsJumping)
{
flags |= PedDataFlags.IsJumping;
}
if (ped.IsRagdoll)
{
flags |= PedDataFlags.IsRagdoll;
}
if (ped.IsOnFire)
{
flags |= PedDataFlags.IsOnFire;
}
if (ped.IsInParachuteFreeFall)
{
flags |= PedDataFlags.IsInParachuteFreeFall;
}
if (ped.ParachuteState == ParachuteState.Gliding)
{
flags |= PedDataFlags.IsParachuteOpen;
}
if (Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, ped.Handle, ETasks.CLIMB_LADDER)) // USING_LADDER
{
flags |= PedDataFlags.IsOnLadder;
}
if (ped.IsVaulting && !Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, ped.Handle, ETasks.CLIMB_LADDER))
{
flags |= PedDataFlags.IsVaulting;
}
if (ped.IsInCover || ped.IsGoingIntoCover)
{
flags |=PedDataFlags.IsInCover;
}
return flags;
}
public static ushort? GetPedFlags(this Ped ped, bool isPlayer = false)
public static bool HasFlag(this PedDataFlags flagToCheck,PedDataFlags flag)
{
ushort? flags = 0;
return (flagToCheck & flag)!=0;
}
if (ped.IsAiming)
{
flags |= (ushort)PedDataFlags.IsAiming;
}
if ((ped.IsShooting || isPlayer && Game.IsControlPressed(Control.Attack)) && ped.Weapons.Current?.AmmoInClip != 0)
{
flags |= (ushort)PedDataFlags.IsShooting;
}
if (ped.IsReloading)
{
flags |= (ushort)PedDataFlags.IsReloading;
}
if (ped.IsJumping)
{
flags |= (ushort)PedDataFlags.IsJumping;
}
if (ped.IsRagdoll)
{
flags |= (ushort)PedDataFlags.IsRagdoll;
}
if (ped.IsOnFire)
{
flags |= (ushort)PedDataFlags.IsOnFire;
}
if (ped.IsInParachuteFreeFall)
{
flags |= (ushort)PedDataFlags.IsInParachuteFreeFall;
}
if (ped.ParachuteState == ParachuteState.Gliding)
{
flags |= (ushort)PedDataFlags.IsParachuteOpen;
}
if (Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, ped.Handle, ETasks.CLIMB_LADDER)) // USING_LADDER
{
flags |= (ushort)PedDataFlags.IsOnLadder;
}
if (ped.IsVaulting && !Function.Call<bool>(Hash.GET_IS_TASK_ACTIVE, ped.Handle, ETasks.CLIMB_LADDER))
{
flags |= (ushort)PedDataFlags.IsVaulting;
}
return flags;
public static bool HasFlag(this VehicleDataFlags flagToCheck, VehicleDataFlags flag)
{
return (flagToCheck & flag)!=0;
}
public static Dictionary<byte, short> GetPedClothes(this Ped ped)
@ -459,14 +456,20 @@ namespace CoopClient
// Broken doors
byte brokenDoors = 0;
byte openedDoors = 0;
foreach (VehicleDoor door in veh.Doors)
{
if (door.IsBroken)
{
brokenDoors |= (byte)(1 << (byte)door.Index);
}
else if (door.IsOpen)
{
openedDoors |= (byte)(1 << (byte)door.Index);
}
}
// Bursted tires
short burstedTires = 0;
foreach (VehicleWheel wheel in veh.Wheels.GetAllWheels())
@ -480,6 +483,7 @@ namespace CoopClient
return new VehicleDamageModel()
{
BrokenDoors = brokenDoors,
OpenedDoors = openedDoors,
BrokenWindows = brokenWindows,
BurstedTires = burstedTires,
LeftHeadLightBroken = (byte)(veh.IsLeftHeadLightBroken ? 1 : 0),
@ -487,20 +491,74 @@ namespace CoopClient
};
}
public static Dictionary<int,int> GetPassengers(this Vehicle veh)
{
Dictionary<int,int> ps=new Dictionary<int, int>();
var d = veh.Driver;
if (d!=null&&d.IsSittingInVehicle())
{
ps.Add(-1, d.GetSyncEntity().ID);
}
foreach(Ped p in veh.Passengers)
{
if (p.IsSittingInVehicle())
{
ps.Add((int)p.SeatIndex, (int)p.GetSyncEntity().ID);
}
}
return ps;
}
public static void SetOnFire(this Entity e,bool toggle)
{
if (toggle)
{
Function.Call(Hash.START_ENTITY_FIRE, e.Handle);
}
else
{
Function.Call(Hash.STOP_ENTITY_FIRE, e.Handle);
}
}
public static SyncedPed GetSyncEntity(this Ped p)
{
if(p == null) { return null; }
var c = EntityPool.GetPedByHandle(p.Handle);
if(c==null) { EntityPool.Add(c=new SyncedPed(p)); }
return c;
}
public static SyncedVehicle GetSyncEntity(this Vehicle veh)
{
if(veh == null) { return null; }
var v=EntityPool.GetVehicleByHandle(veh.Handle);
if (v==null) { EntityPool.Add(v=new SyncedVehicle(veh)); }
return v;
}
public static void SetVehicleDamageModel(this Vehicle veh, VehicleDamageModel model, bool leavedoors = true)
{
for (int i = 0; i < 8; i++)
{
var door = veh.Doors[(VehicleDoorIndex)i];
if ((model.BrokenDoors & (byte)(1 << i)) != 0)
{
veh.Doors[(VehicleDoorIndex)i].Break(leavedoors);
door.Break(leavedoors);
}
else if (veh.Doors[(VehicleDoorIndex)i].IsBroken)
else if (door.IsBroken)
{
// 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))
{
door.Open();
}
}
else if (door.IsOpen)
{
if (!door.IsBroken) { door.Close(); }
}
if ((model.BrokenWindows & (byte)(1 << i)) != 0)
{
@ -532,65 +590,132 @@ namespace CoopClient
veh.IsRightHeadLightBroken = model.RightHeadLightBroken > 0;
}
public static Settings ReadSettings()
public static double DegToRad(double deg)
{
XmlSerializer ser = new XmlSerializer(typeof(Settings));
return deg * Math.PI / 180.0;
}
string path = Directory.GetCurrentDirectory() + "\\scripts\\CoopSettings.xml";
Settings settings = null;
public static Vector3 RotationToDirection(Vector3 rotation)
{
double z = DegToRad(rotation.Z);
double x = DegToRad(rotation.X);
double num = Math.Abs(Math.Cos(x));
if (File.Exists(path))
return new Vector3
{
using (FileStream stream = File.OpenRead(path))
{
settings = (Settings)ser.Deserialize(stream);
}
X = (float)(-Math.Sin(z) * num),
Y = (float)(Math.Cos(z) * num),
Z = (float)Math.Sin(x)
};
}
using (FileStream stream = new FileStream(path, FileMode.Truncate, FileAccess.ReadWrite))
public static VehicleSeat getNearestSeat(Ped ped, Vehicle veh, float distanceToignoreDoors=50f)
{
float num = 99f;
int result = -2;
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary.Add("door_dside_f", -1);
dictionary.Add("door_pside_f", 0);
dictionary.Add("door_dside_r", 1);
dictionary.Add("door_pside_r", 2);
foreach (string text in dictionary.Keys)
{
bool flag = veh.Bones[text].Position != Vector3.Zero;
if (flag)
{
ser.Serialize(stream, settings);
float num2 = ped.Position.DistanceTo(Function.Call<Vector3>(Hash.GET_WORLD_POSITION_OF_ENTITY_BONE, new InputArgument[]
{
veh,
veh.Bones[text].Index
}));
bool flag2 = (num2 < distanceToignoreDoors) && (num2 < num )&& IsSeatUsableByPed(ped, veh, dictionary[text]);
if (flag2)
{
num = num2;
result = dictionary[text];
}
}
}
return (VehicleSeat)result;
}
public static bool IsSeatUsableByPed(Ped ped, Vehicle veh, int _seat, bool allowJacking=false)
{
/*
*/
if (!allowJacking)
{
return veh.IsSeatFree((VehicleSeat)_seat);
}
else
{
using (FileStream stream = File.OpenWrite(path))
VehicleSeat seat = (VehicleSeat)_seat;
bool result = false;
bool flag = veh.IsSeatFree(seat);
if (flag)
{
ser.Serialize(stream, settings = new Settings());
result = true;
}
else
{
bool isDead = veh.GetPedOnSeat(seat).IsDead;
if (isDead)
{
result = true;
}
else
{
int num = Function.Call<int>(Hash.GET_RELATIONSHIP_BETWEEN_PEDS, new InputArgument[]
{
ped,
veh.GetPedOnSeat(seat)
});
bool flag2 = num > 2;
if (flag2)
{
result = true;
}
}
}
return result;
}
}
public static Vector3 GetAimCoord(this Ped p)
{
var weapon = p.Weapons.CurrentWeaponObject;
if (p.IsOnTurretSeat()) { return p.GetLookingCoord(); }
if (weapon!=null)
{
Vector3 dir = weapon.RightVector;
return weapon.Position+dir*20;
RaycastResult result = World.Raycast(weapon.Position+dir, weapon.Position+dir*10000, IntersectFlags.Everything, p.IsInVehicle() ? (Entity)p : p.CurrentVehicle);
if (result.DidHit)
{
return result.HitPosition;
}
else
{
return weapon.Position+dir*20;
}
}
return settings;
return GetLookingCoord(p);
}
public static void SaveSettings()
public static Vector3 GetLookingCoord(this Ped p)
{
try
{
string path = Directory.GetCurrentDirectory() + "\\scripts\\CoopSettings.xml";
using (FileStream stream = new FileStream(path, File.Exists(path) ? FileMode.Truncate : FileMode.Create, FileAccess.ReadWrite))
{
XmlSerializer ser = new XmlSerializer(typeof(Settings));
ser.Serialize(stream, Main.MainSettings);
}
}
catch (Exception ex)
{
GTA.UI.Notification.Show("Error saving player settings: " + ex.Message);
}
EntityBone b = p.Bones[Bone.FacialForehead];
Vector3 v = b.UpVector.Normalized;
return b.Position+200*v;
}
public static Vector3 GetLastWeaponImpact(Ped ped)
public static bool IsWeapon(this Entity e)
{
OutputArgument coord = new OutputArgument();
if (!Function.Call<bool>(Hash.GET_PED_LAST_WEAPON_IMPACT_COORD, ped.Handle, coord))
{
return new Vector3();
}
return coord.GetResult<Vector3>();
return WeaponModels.Contains(e.Model);
}
public static bool IsTurretSeat(this Vehicle veh, int seat)
{
if (!Function.Call<bool>(Hash.DOES_VEHICLE_HAVE_WEAPONS, veh.Handle))
@ -631,116 +756,124 @@ namespace CoopClient
return false;
}
public static double DegToRad(double deg)
public static bool IsOnTurretSeat(this Ped P)
{
return deg * Math.PI / 180.0;
if (P.CurrentVehicle == null) { return false; }
return IsTurretSeat(P.CurrentVehicle, (int)P.SeatIndex);
}
public static void StayInCover(this Ped p)
{
Function.Call(Hash.TASK_STAY_IN_COVER, p);
}
public static VehicleSeat GetSeatTryingToEnter(this Ped p)
{
return (VehicleSeat)Function.Call<int>(Hash.GET_SEAT_PED_IS_TRYING_TO_ENTER, p);
}
public static Vector3 RotationToDirection(Vector3 rotation)
{
double z = DegToRad(rotation.Z);
double x = DegToRad(rotation.X);
double num = Math.Abs(Math.Cos(x));
return new Vector3
{
X = (float)(-Math.Sin(z) * num),
Y = (float)(Math.Cos(z) * num),
Z = (float)Math.Sin(x)
};
}
public static bool WorldToScreenRel(Vector3 worldCoords, out Vector2 screenCoords)
{
OutputArgument num1 = new OutputArgument();
OutputArgument num2 = new OutputArgument();
if (!Function.Call<bool>(Hash.GET_SCREEN_COORD_FROM_WORLD_COORD, worldCoords.X, worldCoords.Y, worldCoords.Z, num1, num2))
{
screenCoords = new Vector2();
return false;
}
screenCoords = new Vector2((num1.GetResult<float>() - 0.5f) * 2, (num2.GetResult<float>() - 0.5f) * 2);
return true;
}
public static Vector3 ScreenRelToWorld(Vector3 camPos, Vector3 camRot, Vector2 coord)
{
Vector3 camForward = RotationToDirection(camRot);
Vector3 rotUp = camRot + new Vector3(10, 0, 0);
Vector3 rotDown = camRot + new Vector3(-10, 0, 0);
Vector3 rotLeft = camRot + new Vector3(0, 0, -10);
Vector3 rotRight = camRot + new Vector3(0, 0, 10);
Vector3 camRight = RotationToDirection(rotRight) - RotationToDirection(rotLeft);
Vector3 camUp = RotationToDirection(rotUp) - RotationToDirection(rotDown);
double rollRad = -DegToRad(camRot.Y);
Vector3 camRightRoll = camRight * (float)Math.Cos(rollRad) - camUp * (float)Math.Sin(rollRad);
Vector3 camUpRoll = camRight * (float)Math.Sin(rollRad) + camUp * (float)Math.Cos(rollRad);
Vector3 point3D = camPos + camForward * 10.0f + camRightRoll + camUpRoll;
if (!WorldToScreenRel(point3D, out Vector2 point2D))
{
return camPos + camForward * 10.0f;
}
Vector3 point3DZero = camPos + camForward * 10.0f;
if (!WorldToScreenRel(point3DZero, out Vector2 point2DZero))
{
return camPos + camForward * 10.0f;
}
const double eps = 0.001;
if (Math.Abs(point2D.X - point2DZero.X) < eps || Math.Abs(point2D.Y - point2DZero.Y) < eps)
{
return camPos + camForward * 10.0f;
}
float scaleX = (coord.X - point2DZero.X) / (point2D.X - point2DZero.X);
float scaleY = (coord.Y - point2DZero.Y) / (point2D.Y - point2DZero.Y);
return camPos + camForward * 10.0f + camRightRoll * scaleX + camUpRoll * scaleY;
}
public static Vector3 RaycastEverything(Vector2 screenCoord)
{
Vector3 camPos = GameplayCamera.Position;
Vector3 camRot = GameplayCamera.Rotation;
const float raycastToDist = 100.0f;
const float raycastFromDist = 1f;
Vector3 target3D = ScreenRelToWorld(camPos, camRot, screenCoord);
Vector3 source3D = camPos;
Entity ignoreEntity = Game.Player.Character;
if (Game.Player.Character.IsInVehicle())
{
ignoreEntity = Game.Player.Character.CurrentVehicle;
}
Vector3 dir = target3D - source3D;
dir.Normalize();
RaycastResult raycastResults = World.Raycast(source3D + dir * raycastFromDist,
source3D + dir * raycastToDist,
IntersectFlags.Everything,
ignoreEntity);
if (raycastResults.DidHit)
{
return raycastResults.HitPosition;
}
return camPos + dir * raycastToDist;
}
public static readonly Model[] WeaponModels = Weapon.GetAllModels();
[DllImport("kernel32.dll")]
public static extern ulong GetTickCount64();
}
public static int GetDamage(this Weapon w)
{
int damage=0;
switch (w.Group)
{
case WeaponGroup.AssaultRifle: damage=30;break;
case WeaponGroup.Heavy: damage=30;break;
case WeaponGroup.MG: damage=30;break;
case WeaponGroup.PetrolCan: damage=0;break;
case WeaponGroup.Pistol: damage=30;break;
case WeaponGroup.Shotgun: damage=30; break;
case WeaponGroup.SMG: damage=20; break;
case WeaponGroup.Sniper: damage=100; break;
case WeaponGroup.Thrown: damage=0; break;
case WeaponGroup.Unarmed: damage=0; break;
}
return damage;
}
public static Vector3 GetMuzzlePosition(this Ped p)
{
var w = p.Weapons.CurrentWeaponObject;
if (w!=null)
{
var hash = p.Weapons.Current.Hash;
if (MuzzleBoneIndexes.ContainsKey(hash)) { return w.Bones[MuzzleBoneIndexes[hash]].Position; }
return w.Position;
}
return p.Bones[Bone.SkelRightHand].Position;
}
public static readonly Dictionary<WeaponHash, int> MuzzleBoneIndexes = new Dictionary<WeaponHash, int>
{
{WeaponHash.HeavySniper,6},
{WeaponHash.MarksmanRifle,9},
{WeaponHash.SniperRifle,9},
{WeaponHash.AdvancedRifle,5},
{WeaponHash.SpecialCarbine,9},
{WeaponHash.BullpupRifle,7},
{WeaponHash.AssaultRifle,9},
{WeaponHash.CarbineRifle,6},
{WeaponHash.MachinePistol,5},
{WeaponHash.SMG,5},
{WeaponHash.AssaultSMG,6},
{WeaponHash.CombatPDW,5},
{WeaponHash.MG,6},
{WeaponHash.CombatMG,7},
{WeaponHash.Gusenberg,7},
{WeaponHash.MicroSMG,10},
{WeaponHash.APPistol,8},
{WeaponHash.StunGun,4},
{WeaponHash.Pistol,8},
{WeaponHash.CombatPistol,8},
{WeaponHash.Pistol50,7},
{WeaponHash.SNSPistol,8},
{WeaponHash.HeavyPistol,8},
{WeaponHash.VintagePistol,8},
{WeaponHash.Railgun,9},
{WeaponHash.Minigun,5},
{WeaponHash.Musket,3},
{WeaponHash.HeavyShotgun,10},
{WeaponHash.PumpShotgun,11},
{WeaponHash.SawnOffShotgun,8},
{WeaponHash.BullpupShotgun,8},
{WeaponHash.AssaultShotgun,9},
{WeaponHash.HeavySniperMk2,11},
{WeaponHash.MarksmanRifleMk2,9},
{WeaponHash.CarbineRifleMk2,13},
{WeaponHash.SpecialCarbineMk2,16},
{WeaponHash.BullpupRifleMk2,8},
{WeaponHash.CompactRifle,7},
{WeaponHash.MilitaryRifle,11},
{WeaponHash.AssaultrifleMk2,17},
{WeaponHash.MiniSMG,5},
{WeaponHash.SMGMk2,6},
{WeaponHash.CombatMGMk2,16},
{WeaponHash.UnholyHellbringer,4},
{WeaponHash.PistolMk2,12},
{WeaponHash.SNSPistolMk2,15},
{WeaponHash.CeramicPistol,10},
{WeaponHash.MarksmanPistol,4},
{WeaponHash.Revolver,7},
{WeaponHash.RevolverMk2,7},
{WeaponHash.DoubleActionRevolver,7},
{WeaponHash.NavyRevolver,7},
{WeaponHash.PericoPistol,4},
{WeaponHash.FlareGun,4},
{WeaponHash.UpNAtomizer,4},
{WeaponHash.HomingLauncher,5},
{WeaponHash.CompactGrenadeLauncher,8},
{WeaponHash.Widowmaker,6},
{WeaponHash.GrenadeLauncher,3},
{WeaponHash.RPG,9},
{WeaponHash.DoubleBarrelShotgun,8},
{WeaponHash.SweeperShotgun,7},
{WeaponHash.CombatShotgun,7},
{WeaponHash.PumpShotgunMk2,7},
};
}
/// <summary>
///
/// </summary>
@ -773,17 +906,17 @@ namespace CoopClient
};
}
internal static float Denormalize(this float h)
public static float Denormalize(this float h)
{
return h < 0f ? h + 360f : h;
}
internal static float ToRadians(this float val)
public static float ToRadians(this float val)
{
return (float)(Math.PI / 180) * val;
}
internal static Vector3 ToRadians(this Vector3 i)
public static Vector3 ToRadians(this Vector3 i)
{
return new Vector3()
{
@ -793,7 +926,7 @@ namespace CoopClient
};
}
internal static Quaternion ToQuaternion(this Vector3 vect)
public static Quaternion ToQuaternion(this Vector3 vect)
{
vect = new Vector3()
{
@ -850,4 +983,5 @@ namespace CoopClient
};
}
}
}

View File

@ -1,10 +1,10 @@
using System;
using System.Linq;
using RageCoop.Core;
using GTA;
using GTA.Native;
namespace CoopClient
namespace RageCoop.Client
{
/// <summary>
/// Don't use it!
@ -75,8 +75,8 @@ namespace CoopClient
Function.Call(Hash.SET_RANDOM_TRAINS, true);
Function.Call(Hash.SET_RANDOM_BOATS, true);
Function.Call(Hash.SET_GARBAGE_TRUCKS, true);
Function.Call(Hash.SET_PED_POPULATION_BUDGET, 3); // 0 - 3
Function.Call(Hash.SET_VEHICLE_POPULATION_BUDGET, 3); // 0 - 3
Function.Call(Hash.SET_PED_POPULATION_BUDGET, 1); // 0 - 3
Function.Call(Hash.SET_VEHICLE_POPULATION_BUDGET, 1); // 0 - 3
Function.Call(Hash.SET_ALL_VEHICLE_GENERATORS_ACTIVE);
Function.Call(Hash.SET_ALL_LOW_PRIORITY_VEHICLE_GENERATORS_ACTIVE, true);
Function.Call(Hash.SET_NUMBER_OF_PARKED_VEHICLES, -1);
@ -99,16 +99,31 @@ namespace CoopClient
Function.Call(Hash.SET_DISTANT_CARS_ENABLED, false);
Function.Call(Hash.DISABLE_VEHICLE_DISTANTLIGHTS, true);
foreach (Ped ped in World.GetAllPeds().Where(p => p.RelationshipGroup != "SYNCPED" && p.Handle != Game.Player.Character?.Handle))
{
ped.CurrentVehicle?.Delete();
ped.Kill();
ped.Delete();
}
foreach (Vehicle veh in World.GetAllVehicles().Where(v => v.IsSeatFree(VehicleSeat.Driver) && v.PassengerCount == 0))
foreach (Ped ped in World.GetAllPeds())
{
veh.Delete();
SyncedPed c = EntityPool.GetPedByHandle(ped.Handle);
if ((c==null) || (c.IsMine && (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== null) || (v.IsMine&&veh.PopulationType!=EntityPopulationType.Mission))
{
Main.Logger.Debug($"Removing Vehicle {veh.Handle}. Reason:ClearTraffic");
veh.Delete();
}
}
}
}

11
Client/app.config Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

15
Client/packages.config Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl.AsyncInterfaces" version="6.0.0" targetFramework="net48" />
<package id="Microsoft.Extensions.DependencyInjection" version="6.0.0" targetFramework="net48" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="6.0.0" targetFramework="net48" />
<package id="Microsoft.Extensions.Options" version="6.0.0" targetFramework="net48" />
<package id="Microsoft.Extensions.Primitives" version="6.0.0" targetFramework="net48" />
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
<package id="System.Diagnostics.DiagnosticSource" version="6.0.0" targetFramework="net48" />
<package id="System.Memory" version="4.5.4" targetFramework="net48" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net48" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net48" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
</packages>

View File

@ -2,9 +2,9 @@
using System.Text;
using System.Linq;
namespace CoopClient
namespace RageCoop.Core
{
internal class BitReader
public class BitReader
{
public int CurrentIndex { get; set; }
@ -102,5 +102,25 @@ namespace CoopClient
CurrentIndex += index;
return value;
}
public LVector3 ReadLVector3()
{
return new LVector3()
{
X = ReadFloat(),
Y = ReadFloat(),
Z = ReadFloat()
};
}
public LQuaternion ReadLQuaternion()
{
return new LQuaternion()
{
X = ReadFloat(),
Y = ReadFloat(),
Z = ReadFloat(),
W = ReadFloat()
};
}
}
}

107
Core/CoreUtils.cs Normal file
View File

@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RageCoop.Core
{
public class CoreUtils
{
public static (byte, byte[]) GetBytesFromObject(object obj)
{
switch (obj)
{
case byte _:
return (0x01, BitConverter.GetBytes((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));
default:
return (0x0, null);
}
}
}
public static class Extensions
{
public static void AddLVector3(this List<byte> bytes, LVector3 vec3)
{
bytes.AddRange(BitConverter.GetBytes(vec3.X));
bytes.AddRange(BitConverter.GetBytes(vec3.Y));
bytes.AddRange(BitConverter.GetBytes(vec3.Z));
}
public static void AddLQuaternion(this List<byte> bytes, LQuaternion 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 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 byte ToByte(this bool[] source)
{
byte result = 0;
// This assumes the array never contains more than 8 elements!
int index = 8 - source.Length;
// Loop through the array
foreach (bool b in source)
{
// if the element is 'true' set the bit at that position
if (b)
result |= (byte)(1 << (7 - index));
index++;
}
return result;
}
public static bool[] ToBoolArray(this byte b)
{
bool[] result = new bool[8];
// check each bit in the byte. if 1 set to true, if 0 set to false
for (int i = 0; i < 8; i++)
result[i] = (b & (1 << i)) != 0;
// reverse the array
Array.Reverse(result);
return result;
}
}
}

137
Core/Loggger.cs Normal file
View File

@ -0,0 +1,137 @@
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
namespace RageCoop.Core
{
public class Loggger
{
public string LogPath;
private StreamWriter logWriter;
private bool UseConsole=false;
public int LogLevel = 0;
private string Buffer="";
public Loggger(string path)
{
LogPath=path;
Task.Run(() =>
{
while (true)
{
Flush();
Thread.Sleep(1000);
}
});
}
public Loggger()
{
UseConsole=true;
Task.Run(() =>
{
while (true)
{
Flush();
Thread.Sleep(1000);
}
});
}
public void Info(string message)
{
if (LogLevel>2) { return; }
lock (Buffer)
{
string msg = string.Format("[{0}][{2}] [INF] {1}", Date(), message, Process.GetCurrentProcess().Id);
Buffer+=msg+"\r\n";
}
}
public void Warning(string message)
{
if (LogLevel>3) { return; }
lock (Buffer)
{
string msg = string.Format("[{0}][{2}] [WRN] {1}", Date(), message, Process.GetCurrentProcess().Id);
Buffer+=msg+"\r\n";
}
}
public void Error(string message)
{
if (LogLevel>4) { return; }
lock (Buffer)
{
string msg = string.Format("[{0}][{2}] [ERR] {1}", Date(), message, Process.GetCurrentProcess().Id);
Buffer+=msg+"\r\n";
}
}
public void Error(Exception ex)
{
if (LogLevel>4) { return; }
lock (Buffer)
{
string msg = string.Format("[{0}][{2}] [ERR] {1}", Date(),string.Join("\r\n",ex.Message,ex.StackTrace,ex.ToString()), Process.GetCurrentProcess().Id);
Buffer+=msg+"\r\n";
}
}
public void Debug(string message)
{
if (LogLevel>1) { return; }
lock (Buffer)
{
string msg = string.Format("[{0}][{2}] [DBG] {1}", Date(), message,Process.GetCurrentProcess().Id);
Buffer+=msg+"\r\n";
}
}
public void Trace(string message)
{
if (LogLevel>1) { return; }
lock (Buffer)
{
string msg = string.Format("[{0}][{2}] [TRC] {1}", Date(), message, Process.GetCurrentProcess().Id);
Buffer+=msg+"\r\n";
}
}
private string Date()
{
return DateTime.Now.ToString();
}
public void Flush()
{
lock (Buffer)
{
if (Buffer!="")
{
try
{
logWriter=new StreamWriter(LogPath ,true,Encoding.UTF8);
logWriter.Write(Buffer);
logWriter.Close();
Buffer="";
}
catch { }
}
}
}
}
}

View File

@ -4,9 +4,9 @@ using System.Text;
using Lidgren.Network;
namespace CoopClient
namespace RageCoop.Core
{
internal partial class Packets
public partial class Packets
{
public class FileTransferRequest : Packet
{
@ -16,7 +16,7 @@ namespace CoopClient
public long FileLength { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.FileTransferRequest);
@ -41,7 +41,7 @@ namespace CoopClient
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
@ -60,7 +60,7 @@ namespace CoopClient
public byte[] FileChunk { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.FileTransferTick);
@ -81,7 +81,7 @@ namespace CoopClient
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
@ -97,7 +97,7 @@ namespace CoopClient
{
public byte ID { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.FileTransferComplete);
@ -114,7 +114,7 @@ namespace CoopClient
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);

View File

@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
using Newtonsoft.Json;
using GTA.Math;
namespace CoopClient
namespace RageCoop.Core
{
/// <summary>
///
@ -23,7 +21,24 @@ namespace CoopClient
return new Vector3(X, Y, Z);
}
#endregion
#region SERVER-ONLY
public float Length() => (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z));
public static LVector3 Subtract(LVector3 pos1, LVector3 pos2) { return new LVector3(pos1.X - pos2.X, pos1.Y - pos2.Y, pos1.Z - pos2.Z); }
public static bool Equals(LVector3 value1, LVector3 value2) => value1.X == value2.X && value1.Y == value2.Y && value1.Z == value2.Z;
public static LVector3 operator /(LVector3 value1, float value2)
{
float num = 1f / value2;
return new LVector3(value1.X * num, value1.Y * num, value1.Z * num);
}
public static LVector3 operator -(LVector3 left, LVector3 right)
{
return new LVector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
}
public static LVector3 operator -(LVector3 value)
{
return default(LVector3) - value;
}
#endregion
/// <summary>
///
/// </summary>
@ -97,47 +112,90 @@ namespace CoopClient
public float W { get; set; }
}
internal enum PacketTypes
public enum PacketTypes:byte
{
Handshake,
PlayerConnect,
PlayerDisconnect,
FullSyncPlayer,
FullSyncPlayerVeh,
LightSyncPlayer,
LightSyncPlayerVeh,
SuperLightSync,
FullSyncNpc,
FullSyncNpcVeh,
ChatMessage,
NativeCall,
NativeResponse,
Mod,
CleanUpWorld,
FileTransferTick,
FileTransferRequest,
FileTransferComplete,
ServerClientEvent
Handshake=0,
PlayerConnect=1,
PlayerDisconnect=2,
ChatMessage=10,
NativeCall=11,
NativeResponse=12,
Mod=13,
CleanUpWorld=14,
FileTransferTick=15,
FileTransferRequest=16,
FileTransferComplete=17,
ServerClientEvent=18,
#region Sync
#region INTERVAL
VehicleSync = 20,
VehicleStateSync = 21,
CharacterSync = 22,
CharacterStateSync = 23,
#endregion
#region EVENT
PedKilled=30,
BulletShot=31,
ProjectileShot=32,
ProjectileExploded=33,
EnteringVehicle=34,
LeaveVehicle = 35,
EnteredVehicle=36,
OwnerChanged=37,
VehicleBulletShot = 38,
#endregion
/// obsolete sync method
/*
FullSyncPlayer = 3,
FullSyncPlayerVeh = 4,
LightSyncPlayer = 5,
LightSyncPlayerVeh = 6,
SuperLightSync = 7,
FullSyncNpc = 8,
FullSyncNpcVeh = 9,
*/
#endregion
}
public static class PacketExtensions
{
public static bool IsSyncEvent(this PacketTypes p)
{
return (30<=(byte)p)&&((byte)p<=40);
}
}
internal enum ConnectionChannel
public enum ConnectionChannel
{
Default = 0,
PlayerLight = 1,
PlayerFull = 2,
PlayerSuperLight = 3,
NPCFull = 4,
Chat = 5,
Native = 6,
Mod = 7,
File = 8,
Event = 9
Event = 9,
VehicleSync=20,
CharacterSync=21,
SyncEvents=30,
///obsolete
/*
PlayerLight = 1,
PlayerFull = 2,
PlayerSuperLight = 3,
NPCFull = 4,
*/
}
internal enum PedDataFlags
[Flags]
public enum PedDataFlags:ushort
{
None=0,
IsAiming = 1 << 0,
IsShooting = 1 << 1,
IsReloading = 1 << 2,
IsJumping = 1 << 3,
IsRagdoll = 1 << 4,
@ -145,11 +203,12 @@ namespace CoopClient
IsInParachuteFreeFall = 1 << 6,
IsParachuteOpen = 1 << 7,
IsOnLadder = 1 << 8,
IsVaulting = 1 << 9
IsVaulting = 1 << 9,
IsInCover=1<< 10,
}
#region ===== VEHICLE DATA =====
internal enum VehicleDataFlags
public enum VehicleDataFlags:ushort
{
IsEngineRunning = 1 << 0,
AreLightsOn = 1 << 1,
@ -161,13 +220,16 @@ namespace CoopClient
IsTransformed = 1 << 7,
RoofOpened = 1 << 8,
OnTurretSeat = 1 << 9,
IsPlane = 1 << 10
IsAircraft = 1 << 10,
IsHandBrakeOn=1<<11,
}
internal struct VehicleDamageModel
public struct VehicleDamageModel
{
public byte BrokenWindows { get; set; }
public byte BrokenDoors { get; set; }
public byte OpenedDoors { get; set; }
public byte BrokenWindows { get; set; }
public short BurstedTires { get; set; }
public byte LeftHeadLightBroken { get; set; }
public byte RightHeadLightBroken { get; set; }
@ -176,17 +238,17 @@ namespace CoopClient
interface IPacket
{
void PacketToNetOutGoingMessage(NetOutgoingMessage message);
void NetIncomingMessageToPacket(byte[] array);
void Pack(NetOutgoingMessage message);
void Unpack(byte[] array);
}
abstract class Packet : IPacket
public abstract class Packet : IPacket
{
public abstract void PacketToNetOutGoingMessage(NetOutgoingMessage message);
public abstract void NetIncomingMessageToPacket(byte[] array);
public abstract void Pack(NetOutgoingMessage message);
public abstract void Unpack(byte[] array);
}
internal partial class Packets
public partial class Packets
{
public class Mod : Packet
{
@ -200,7 +262,7 @@ namespace CoopClient
public byte[] Bytes { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.Mod);
@ -232,7 +294,7 @@ namespace CoopClient
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
@ -263,7 +325,7 @@ namespace CoopClient
public string Message { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.ChatMessage);
@ -292,7 +354,7 @@ namespace CoopClient
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
@ -314,7 +376,7 @@ namespace CoopClient
public List<object> Args { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.ServerClientEvent);
@ -331,10 +393,10 @@ namespace CoopClient
byteArray.AddRange(BitConverter.GetBytes(Args.Count));
foreach (object arg in Args)
{
var test = Util.GetBytesFromObject(arg);
var test = CoreUtils.GetBytesFromObject(arg);
if (test.Item1 == 0x0)
{
Logger.Write("Can't get type of an object!", Logger.LogLevel.Server);
// Logger.Write("Can't get type of an object!", Logger.LogLevel.Server);
byteArray.Add(0x0);
}
else
@ -351,7 +413,7 @@ namespace CoopClient
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
@ -408,7 +470,7 @@ namespace CoopClient
public List<object> Args { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.NativeCall);
@ -463,7 +525,7 @@ namespace CoopClient
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
@ -516,7 +578,7 @@ namespace CoopClient
public long ID { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.NativeResponse);
@ -581,7 +643,7 @@ namespace CoopClient
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);

276
Core/Packets/PedPackets.cs Normal file
View File

@ -0,0 +1,276 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core
{
public partial class Packets
{
/// <summary>
/// For non-critical properties, synced every 20 frames.
/// </summary>
public class PedStateSync : Packet
{
public int ID { get; set; }
public int ModelHash { get; set; }
public Dictionary<byte, short> Clothes { get; set; }
public int OwnerID { get; set; }
public Dictionary<uint, bool> WeaponComponents { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.CharacterStateSync);
List<byte> byteArray = new List<byte>();
// Write player netHandle
byteArray.AddRange(BitConverter.GetBytes(ID));
// Write player model hash
byteArray.AddRange(BitConverter.GetBytes(ModelHash));
// Write player clothes
// Write the count of clothes
byteArray.AddRange(BitConverter.GetBytes((ushort)Clothes.Count));
// Loop the dictionary and add the values
foreach (KeyValuePair<byte, short> cloth in Clothes)
{
byteArray.Add(cloth.Key);
byteArray.AddRange(BitConverter.GetBytes(cloth.Value));
}
//Write OwnerID for this ped
byteArray.AddRange(BitConverter.GetBytes(OwnerID));
// Write player weapon components
if (WeaponComponents != null)
{
byteArray.Add(0x01);
byteArray.AddRange(BitConverter.GetBytes((ushort)WeaponComponents.Count));
foreach (KeyValuePair<uint, bool> component in WeaponComponents)
{
byteArray.AddRange(BitConverter.GetBytes(component.Key));
byteArray.AddRange(BitConverter.GetBytes(component.Value));
}
}
else
{
// Player weapon doesn't have any components
byteArray.Add(0x00);
}
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player netHandle
ID = reader.ReadInt();
// Read player model hash
ModelHash = reader.ReadInt();
// Read player clothes
// Create new Dictionary
Clothes = new Dictionary<byte, short>();
// Read the count of clothes
ushort clothCount = reader.ReadUShort();
// For clothCount
for (ushort i = 0; i < clothCount; i++)
{
// Read cloth value
Clothes.Add(reader.ReadByte(), reader.ReadShort());
}
// Read ped OwnerID
OwnerID= reader.ReadInt();
// Read player weapon components
if (reader.ReadBool())
{
WeaponComponents = new Dictionary<uint, bool>();
ushort comCount = reader.ReadUShort();
for (ushort i = 0; i < comCount; i++)
{
WeaponComponents.Add(reader.ReadUInt(), reader.ReadBool());
}
}
#endregion
}
}
public class PedSync : Packet
{
public int ID { get; set; }
public PedDataFlags Flag { get; set; }
public int Health { get; set; }
public LVector3 Position { get; set; }
public LVector3 Rotation { get; set; }
public LVector3 Velocity { get; set; }
public LVector3 RotationVelocity { get; set; }
public byte Speed { get; set; }
public LVector3 AimCoords { get; set; }
public uint CurrentWeaponHash { get; set; }
public float Heading { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.CharacterSync);
List<byte> byteArray = new List<byte>();
// Write ped ID
byteArray.AddRange(BitConverter.GetBytes(ID));
// Write ped flags
byteArray.AddRange(BitConverter.GetBytes((ushort)Flag));
// Write ped health
byteArray.AddRange(BitConverter.GetBytes(Health));
// Write ped position
byteArray.AddRange(BitConverter.GetBytes(Position.X));
byteArray.AddRange(BitConverter.GetBytes(Position.Y));
byteArray.AddRange(BitConverter.GetBytes(Position.Z));
// Write ped rotation
byteArray.AddRange(BitConverter.GetBytes(Rotation.X));
byteArray.AddRange(BitConverter.GetBytes(Rotation.Y));
byteArray.AddRange(BitConverter.GetBytes(Rotation.Z));
// Write ped velocity
byteArray.AddRange(BitConverter.GetBytes(Velocity.X));
byteArray.AddRange(BitConverter.GetBytes(Velocity.Y));
byteArray.AddRange(BitConverter.GetBytes(Velocity.Z));
if (Flag.HasFlag(PedDataFlags.IsRagdoll))
{
byteArray.AddLVector3(RotationVelocity);
}
// Write ped speed
byteArray.Add(Speed);
// Write ped weapon hash
byteArray.AddRange(BitConverter.GetBytes(CurrentWeaponHash));
if (Flag.HasFlag(PedDataFlags.IsAiming))
{
// Write ped aim coords
byteArray.AddRange(BitConverter.GetBytes(AimCoords.X));
byteArray.AddRange(BitConverter.GetBytes(AimCoords.Y));
byteArray.AddRange(BitConverter.GetBytes(AimCoords.Z));
}
byteArray.AddFloat(Heading);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player netHandle
ID = reader.ReadInt();
// Read player flags
Flag = (PedDataFlags)reader.ReadUShort();
// Read player health
Health = reader.ReadInt();
// Read player position
Position = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read player rotation
Rotation = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read player velocity
Velocity = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read rotation velocity if in ragdoll
if (Flag.HasFlag(PedDataFlags.IsRagdoll))
{
RotationVelocity=reader.ReadLVector3();
}
// Read player speed
Speed = reader.ReadByte();
// Read player weapon hash
CurrentWeaponHash = reader.ReadUInt();
// Try to read aim coords
if (Flag.HasFlag(PedDataFlags.IsAiming))
{
// Read player aim coords
AimCoords = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
}
Heading=reader.ReadFloat();
#endregion
}
}
}
}

View File

@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core
{
public partial class Packets
{
public class Handshake : Packet
{
public int PedID { get; set; }
public string Username { get; set; }
public string ModVersion { get; set; }
public bool NPCsAllowed { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.Handshake);
List<byte> byteArray = new List<byte>();
// Write Player Ped ID
byteArray.AddRange(BitConverter.GetBytes(PedID));
// Write Username
byte[] usernameBytes = Encoding.UTF8.GetBytes(Username);
byteArray.AddRange(BitConverter.GetBytes(usernameBytes.Length));
byteArray.AddRange(usernameBytes);
// Write ModVersion
byte[] modVersionBytes = Encoding.UTF8.GetBytes(ModVersion);
byteArray.AddRange(BitConverter.GetBytes(modVersionBytes.Length));
byteArray.AddRange(modVersionBytes);
// Write NpcsAllowed
byteArray.Add(NPCsAllowed ? (byte)0x01 : (byte)0x00);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player netHandle
PedID = reader.ReadInt();
// Read Username
int usernameLength = reader.ReadInt();
Username = reader.ReadString(usernameLength);
// Read ModVersion
int modVersionLength = reader.ReadInt();
ModVersion = reader.ReadString(modVersionLength);
// Read NPCsAllowed
NPCsAllowed = reader.ReadBool();
#endregion
}
}
public class PlayerConnect : Packet
{
public int PedID { get; set; }
public string Username { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.PlayerConnect);
List<byte> byteArray = new List<byte>();
// Write NetHandle
byteArray.AddRange(BitConverter.GetBytes(PedID));
// Get Username bytes
byte[] usernameBytes = Encoding.UTF8.GetBytes(Username);
// Write UsernameLength
byteArray.AddRange(BitConverter.GetBytes(usernameBytes.Length));
// Write Username
byteArray.AddRange(usernameBytes);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player netHandle
PedID = reader.ReadInt();
// Read Username
int usernameLength = reader.ReadInt();
Username = reader.ReadString(usernameLength);
#endregion
}
}
public class PlayerDisconnect : Packet
{
public int PedID { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.PlayerDisconnect);
List<byte> byteArray = new List<byte>();
byteArray.AddRange(BitConverter.GetBytes(PedID));
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
PedID = reader.ReadInt();
#endregion
}
}
public class PlayerPedID : Packet
{
/// <summary>
/// Ped ID for this Player
/// </summary>
public int PedID { get; set; }
public string Username { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.PlayerConnect);
List<byte> byteArray = new List<byte>();
// Write ID
byteArray.AddRange(BitConverter.GetBytes(PedID));
// Get Username bytes
byte[] usernameBytes = Encoding.UTF8.GetBytes(Username);
// Write UsernameLength
byteArray.AddRange(BitConverter.GetBytes(usernameBytes.Length));
// Write Username
byteArray.AddRange(usernameBytes);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
BitReader reader = new BitReader(array);
// Read player ID
PedID = reader.ReadInt();
// Read Username
int usernameLength = reader.ReadInt();
Username = reader.ReadString(usernameLength);
}
}
}
}

View File

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core
{
public partial class Packets
{
public class BulletShot : Packet
{
public int OwnerID { get; set; }
public uint WeaponHash { get; set; }
public LVector3 StartPosition { get; set; }
public LVector3 EndPosition { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.BulletShot);
List<byte> byteArray = new List<byte>();
// Write OwnerID
byteArray.AddRange(BitConverter.GetBytes(OwnerID));
// Write weapon hash
byteArray.AddRange(BitConverter.GetBytes(WeaponHash));
// Write StartPosition
byteArray.AddLVector3(StartPosition);
// Write EndPosition
byteArray.AddLVector3(EndPosition);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read OwnerID
OwnerID=reader.ReadInt();
// Read WeponHash
WeaponHash=reader.ReadUInt();
// Read StartPosition
StartPosition=reader.ReadLVector3();
// Read EndPosition
EndPosition=reader.ReadLVector3();
#endregion
}
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core
{
public partial class Packets
{
public class EnteredVehicle : Packet
{
public int PedID { get; set; }
public int VehicleID { get; set; }
public short VehicleSeat { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.EnteredVehicle);
List<byte> byteArray = new List<byte>();
byteArray.AddInt(PedID);
byteArray.AddInt(VehicleID);
byteArray.AddInt(VehicleSeat);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
PedID=reader.ReadInt();
VehicleID=reader.ReadInt();
VehicleSeat=reader.ReadShort();
#endregion
}
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core
{
public partial class Packets
{
public class EnteringVehicle : Packet
{
public int PedID { get; set; }
public int VehicleID { get; set; }
public short VehicleSeat { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.EnteringVehicle);
List<byte> byteArray = new List<byte>();
byteArray.AddInt(PedID);
byteArray.AddInt(VehicleID);
byteArray.AddInt(VehicleSeat);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
PedID=reader.ReadInt();
VehicleID=reader.ReadInt();
VehicleSeat=reader.ReadShort();
#endregion
}
}
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core
{
public partial class Packets
{
public class LeaveVehicle : Packet
{
public int ID { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.LeaveVehicle);
List<byte> byteArray = new List<byte>();
byteArray.AddInt(ID);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
ID=reader.ReadInt();
#endregion
}
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core
{
public partial class Packets
{
public class OwnerChanged : Packet
{
public int ID { get; set; }
public int NewOwnerID { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.OwnerChanged);
List<byte> byteArray = new List<byte>();
byteArray.AddInt(ID);
byteArray.AddInt(NewOwnerID);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
ID=reader.ReadInt();
NewOwnerID=reader.ReadInt();
#endregion
}
}
}
}

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core
{
public partial class Packets
{
public class PedKilled : Packet
{
public int VictimID { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.PedKilled);
List<byte> byteArray = new List<byte>();
byteArray.AddInt(VictimID);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
VictimID=reader.ReadInt();
#endregion
}
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
namespace RageCoop.Core
{
public partial class Packets
{
/// <summary>
/// Non-critical stuff, such as damage model, landing gear, health, etc..
/// </summary>
public class UpdateOwner : Packet
{
public int ID { get; set; }
public int OwnerID { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.PlayerConnect);
List<byte> byteArray = new List<byte>();
// Write ID
byteArray.AddRange(BitConverter.GetBytes(ID));
// Write OwnerID
byteArray.AddRange(BitConverter.GetBytes(OwnerID));
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
BitReader reader = new BitReader(array);
// Read player ID
ID = reader.ReadInt();
// Read Username
OwnerID = reader.ReadInt();
}
}
}
}

View File

@ -0,0 +1,295 @@
using System;
using System.Collections.Generic;
using System.Text;
using GTA;
using Lidgren.Network;
namespace RageCoop.Core
{
public partial class Packets
{
/// <summary>
/// Non-critical stuff, such as damage model, landing gear, health, etc..
/// </summary>
public class VehicleStateSync : Packet
{
public int ID { get; set; }
// ID of player responsible for syncing this vehicle
public int OwnerID { get; set; }
public int ModelHash { get; set; }
public float EngineHealth { get; set; }
public byte[] Colors { get; set; }
public Dictionary<int, int> Mods { get; set; }
public VehicleDamageModel DamageModel { get; set; }
public byte LandingGear { get; set; }
public VehicleDataFlags Flag { get; set; }
public VehicleLockStatus LockStatus { get; set; }
/// <summary>
/// VehicleSeat,PedID
/// </summary>
public Dictionary<int, int> Passengers { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.VehicleStateSync);
List<byte> byteArray = new List<byte>();
// Write player netHandle
byteArray.AddRange(BitConverter.GetBytes(ID));
//Write vehicle flag
byteArray.AddRange(BitConverter.GetBytes((ushort)Flag));
// Write vehicle model hash
byteArray.AddRange(BitConverter.GetBytes(ModelHash));
// Write vehicle engine health
byteArray.AddRange(BitConverter.GetBytes(EngineHealth));
// Check
if (Flag.HasFlag(VehicleDataFlags.IsAircraft))
{
// Write the vehicle landing gear
byteArray.AddRange(BitConverter.GetBytes(LandingGear));
}
// Write vehicle colors
byteArray.Add(Colors[0]);
byteArray.Add(Colors[1]);
// Write vehicle mods
// Write the count of mods
byteArray.AddRange(BitConverter.GetBytes((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));
}
if (!DamageModel.Equals(default(VehicleDamageModel)))
{
// Write boolean = true
byteArray.Add(0x01);
// 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);
}
else
{
// Write boolean = false
byteArray.Add(0x00);
}
// Write OwnerID
byteArray.AddRange(BitConverter.GetBytes(OwnerID));
// Write passengers
byteArray.AddRange(BitConverter.GetBytes(Passengers.Count));
foreach (KeyValuePair<int, int> p in Passengers)
{
byteArray.AddRange(BitConverter.GetBytes(p.Key));
byteArray.AddRange(BitConverter.GetBytes(p.Value));
}
// Write LockStatus
byteArray.Add((byte)LockStatus);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read vehicle id
ID = reader.ReadInt();
// Read vehicle flags
Flag = (VehicleDataFlags)reader.ReadUShort();
// Read vehicle model hash
ModelHash = reader.ReadInt();
// Read vehicle engine health
EngineHealth = reader.ReadFloat();
// Check
if (Flag.HasFlag(VehicleDataFlags.IsAircraft))
{
// Read vehicle landing gear
LandingGear = (byte)reader.ReadShort();
}
// Read vehicle colors
byte vehColor1 = reader.ReadByte();
byte vehColor2 = reader.ReadByte();
Colors = new byte[] { vehColor1, vehColor2 };
// Read vehicle mods
// Create new Dictionary
Mods = new Dictionary<int, int>();
// Read count of mods
short vehModCount = reader.ReadShort();
// Loop
for (int i = 0; i < vehModCount; i++)
{
// Read the mod value
Mods.Add(reader.ReadInt(), reader.ReadInt());
}
if (reader.ReadBool())
{
// Read vehicle damage model
DamageModel = new VehicleDamageModel()
{
BrokenDoors = reader.ReadByte(),
OpenedDoors=reader.ReadByte(),
BrokenWindows = reader.ReadByte(),
BurstedTires = reader.ReadShort(),
LeftHeadLightBroken = reader.ReadByte(),
RightHeadLightBroken = reader.ReadByte()
};
}
// Read OwnerID
OwnerID= reader.ReadInt();
// Read Passengers
Passengers=new Dictionary<int, int>();
int count = reader.ReadInt();
for (int i = 0; i<count; i++)
{
int seat, id;
seat = reader.ReadInt();
id = reader.ReadInt();
Passengers.Add(seat, id);
}
// Read LockStatus
LockStatus=(VehicleLockStatus)reader.ReadByte();
#endregion
}
}
public class VehicleSync : Packet
{
public int ID { get; set; }
public LVector3 Position { get; set; }
public LVector3 Rotation { get; set; }
public LVector3 Velocity { get; set; }
public LVector3 RotationVelocity { get; set; }
public float ThrottlePower { get; set; }
public float BrakePower { get; set; }
public float SteeringAngle { get; set; }
public override void Pack(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.VehicleSync);
List<byte> byteArray = new List<byte>();
// Write vehicle id
byteArray.AddRange(BitConverter.GetBytes(ID));
// Write position
byteArray.AddLVector3(Position);
// Write rotation
byteArray.AddLVector3(Rotation);
// Write velocity
byteArray.AddLVector3(Velocity);
// Write rotation velocity
byteArray.AddLVector3(RotationVelocity);
byteArray.AddFloat(ThrottlePower);
byteArray.AddFloat(BrakePower);
// Write vehicle steering angle
byteArray.AddFloat(SteeringAngle);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void Unpack(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read vehicle id
ID = reader.ReadInt();
// Read position
Position = reader.ReadLVector3();
// Read rotation
Rotation = reader.ReadLVector3();
// Read velocity
Velocity =reader.ReadLVector3();
// Read rotation velocity
RotationVelocity=reader.ReadLVector3();
// Read throttle power
ThrottlePower=reader.ReadFloat();
// Read brake power
BrakePower=reader.ReadFloat();
// Read steering angle
SteeringAngle = reader.ReadFloat();
#endregion
}
}
}
}

30
Core/PlayerData.cs Normal file
View File

@ -0,0 +1,30 @@
using System.Linq;
namespace RageCoop.Core
{
public class PlayerData
{
public string Username { get; set; }
/// <summary>
/// Universal character ID.
/// </summary>
public int PedID
{
get; set;
}
/// <summary>
/// Universal vehicle ID.
/// </summary>
public int VehicleID { get; set; }
public bool IsInVehicle { get; internal set; }
public LVector3 Position { get; set; }
public int Latency { get; set; }
public int Health { get; set; }
public bool IsInRangeOf(LVector3 position, float distance)
{
return LVector3.Subtract(Position, position).Length() < distance;
}
}
}

28
Core/RageCoop.Core.csproj Normal file
View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0|AnyCPU'">
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0|AnyCPU'">
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Lidgren.Network">
<HintPath>..\Libs\Release\scripts\Lidgren.Network.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\Libs\Release\scripts\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="ScriptHookVDotNet3">
<HintPath>..\Libs\Release\ScriptHookVDotNet3.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

248
Output-Build.txt Normal file
View File

@ -0,0 +1,248 @@
Build started...
1>------ Build started: Project: CoopClient, Configuration: Debug Any CPU ------
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(88,17,88,23): warning CS0162: Unreachable code detected
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\Events\SyncEvents.cs(19,34,19,45): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\Events\SyncEvents.cs(24,34,24,53): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\Events\SyncEvents.cs(29,34,29,52): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\Events\SyncEvents.cs(34,34,34,51): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\Events\SyncEvents.cs(39,34,39,54): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\Events\SyncEvents.cs(44,34,44,55): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\Events\SyncEvents.cs(112,13,112,17): warning CS0164: This label has not been referenced
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(679,23,679,36): warning CS0169: The field 'CharacterEntity.LastStuckTime' is never used
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(678,22,678,36): warning CS0414: The field 'CharacterEntity.StuckDetection' is assigned but its value is never used
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(343,23,343,41): warning CS0414: The field 'CharacterEntity._animationStopTime' is assigned but its value is never used
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(11,18,11,22): warning CS1591: Missing XML comment for publicly visible type or member 'Chat'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(15,23,15,35): warning CS1591: Missing XML comment for publicly visible type or member 'Chat.CurrentInput'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(18,21,18,28): warning CS1591: Missing XML comment for publicly visible type or member 'Chat.Focused'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(58,16,58,20): warning CS1591: Missing XML comment for publicly visible type or member 'Chat.Chat()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(63,21,63,25): warning CS1591: Missing XML comment for publicly visible type or member 'Chat.Init()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(69,21,69,26): warning CS1591: Missing XML comment for publicly visible type or member 'Chat.Clear()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(74,21,74,25): warning CS1591: Missing XML comment for publicly visible type or member 'Chat.Tick()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(94,21,94,31): warning CS1591: Missing XML comment for publicly visible type or member 'Chat.AddMessage(string, string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(101,21,101,30): warning CS1591: Missing XML comment for publicly visible type or member 'Chat.OnKeyDown(Keys)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(154,34,154,45): warning CS1591: Missing XML comment for publicly visible type or member 'Chat.ToUnicodeEx(uint, uint, byte[], StringBuilder, int, uint, IntPtr)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Chat.cs(159,30,159,44): warning CS1591: Missing XML comment for publicly visible type or member 'Chat.GetCharFromKey(Keys, bool, bool)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\COOPAPI.cs(53,28,53,37): warning CS1591: Missing XML comment for publicly visible type or member 'COOPAPI.Connected()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\COOPAPI.cs(58,28,58,40): warning CS1591: Missing XML comment for publicly visible type or member 'COOPAPI.Disconnected(string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\COOPAPI.cs(63,28,63,37): warning CS1591: Missing XML comment for publicly visible type or member 'COOPAPI.Connected(long)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\COOPAPI.cs(68,28,68,40): warning CS1591: Missing XML comment for publicly visible type or member 'COOPAPI.Disconnected(long)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\COOPAPI.cs(73,28,73,45): warning CS1591: Missing XML comment for publicly visible type or member 'COOPAPI.ModPacketReceived(long, string, byte, byte[])'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\COOPAPI.cs(78,28,78,47): warning CS1591: Missing XML comment for publicly visible type or member 'COOPAPI.ChatMessageReceived(string, string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(7,25,7,40): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadManager'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(12,28,12,44): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadManager.DownloadComplete'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(14,28,14,35): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadManager.AddFile(byte, string, long)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(82,28,82,42): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadManager.RenderProgress()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(95,28,95,33): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadManager.Write(byte, byte[])'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(135,28,135,34): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadManager.Cancel(byte)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(157,28,157,35): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadManager.Cleanup(bool)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(178,18,178,30): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadFile'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(180,21,180,27): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadFile.FileID'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(181,23,181,31): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadFile.FileName'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(182,21,182,31): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadFile.FileLength'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\DownloadManager.cs(183,21,183,32): warning CS1591: Missing XML comment for publicly visible type or member 'DownloadFile.FileWritten'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Receive.cs(12,26,12,36): warning CS1591: Missing XML comment for publicly visible type or member 'Networking'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Receive.cs(14,21,14,36): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.ReceiveMessages()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(30,21,30,29): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.sendTime'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(31,21,31,28): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.getTime'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(32,21,32,34): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.serializeTime'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(34,21,34,34): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.SendCharacter(CharacterEntity)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(63,21,63,39): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.SendCharacterState(CharacterEntity)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(81,21,81,32): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.SendVehicle(VehicleEntity)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(100,21,100,37): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.SendVehicleState(VehicleEntity)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(323,21,323,36): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.SendChatMessage(string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(340,21,340,32): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.SendModData(long, string, byte, byte[])'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(362,21,362,39): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.SendDownloadFinish(byte)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Send.cs(379,21,379,37): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.SendTriggerEvent(string, params object[])'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Networking.cs(14,26,14,32): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.Client'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Networking.cs(15,22,15,29): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.Latency'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Networking.cs(17,21,17,36): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.ShowNetworkInfo'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Networking.cs(19,20,19,33): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.BytesReceived'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Networking.cs(20,20,20,29): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.BytesSend'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Networking.cs(22,21,22,41): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.DisConnectFromServer(string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Networking.cs(71,21,71,31): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.IsOnServer()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Networking.cs(340,21,340,32): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.pedsChecked'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Networking.cs(341,21,341,38): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.charactersChecked'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Networking\Networking.cs(344,21,344,25): warning CS1591: Missing XML comment for publicly visible type or member 'Networking.Tick()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(50,23,50,31): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.Username'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(51,21,51,28): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.PedBlip'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(66,21,66,41): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity._lastEnteringVehicle'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(75,40,75,47): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.Clothes'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(80,24,80,32): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.Velocity'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(81,24,81,33): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.AimCoords'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(83,21,83,32): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsOutOfSync'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(93,21,93,27): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.Update()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(322,21,322,26): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.Speed'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(324,21,324,30): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsJumping'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(325,21,325,31): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsOnLadder'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(326,21,326,31): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsVaulting'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(327,21,327,42): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsInParachuteFreeFall'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(328,21,328,36): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsParachuteOpen'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(329,21,329,34): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.ParachuteProp'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(330,21,330,30): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsRagdoll'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(331,21,331,29): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsOnFire'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(332,21,332,29): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsAiming'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(333,21,333,31): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsShooting'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(334,21,334,32): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.IsReloading'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(335,21,335,38): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.CurrentWeaponHash'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\CharacterEntity.cs(337,39,337,55): warning CS1591: Missing XML comment for publicly visible type or member 'CharacterEntity.WeaponComponents'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\SyncEntity.cs(10,18,10,28): warning CS1591: Missing XML comment for publicly visible type or member 'SyncEntity'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\SyncEntity.cs(24,20,24,22): warning CS1591: Missing XML comment for publicly visible type or member 'SyncEntity.ID'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\SyncEntity.cs(25,20,25,27): warning CS1591: Missing XML comment for publicly visible type or member 'SyncEntity.OwnerID'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(14,18,14,31): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(22,26,22,27): warning CS1572: XML comment has a param tag for 'p', but there is no parameter by that name
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(23,38,23,39): warning CS1573: Parameter 'v' has no matching param tag in the XML comment for 'VehicleEntity.VehicleEntity(Vehicle)' (but other parameters do)
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(46,16,46,29): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.VehicleEntity(int)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(56,21,56,36): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.IsChangingOwner'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(69,24,69,32): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.Position'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(70,24,70,32): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.Velocity'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(71,27,71,35): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.Rotation'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(72,22,72,27): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.Speed'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(73,22,73,35): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.SteeringAngle'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(77,21,77,34): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.EngineRunning'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(78,22,78,25): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.RPM'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(80,21,80,32): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.Transformed'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(82,21,82,31): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.HornActive'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(83,21,83,29): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.LightsOn'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(84,21,84,34): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.BrakeLightsOn'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(85,21,85,32): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.HighBeamsOn'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(86,21,86,32): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.LandingGear'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(87,21,87,31): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.RoofOpened'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(88,21,88,33): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.SireneActive'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(89,35,89,46): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.DamageModel'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(90,20,90,29): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.ModelHash'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(91,23,91,29): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.Colors'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(92,37,92,41): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.Mods'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(93,21,93,27): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.IsDead'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\SyncEntities\VehicleEntity.cs(94,22,94,34): warning CS1591: Missing XML comment for publicly visible type or member 'VehicleEntity.EngineHealth'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(20,28,20,44): warning CS1591: Missing XML comment for publicly visible type or member 'JavascriptHook.JavascriptLoaded'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(54,28,54,35): warning CS1591: Missing XML comment for publicly visible type or member 'JavascriptHook.LoadAll()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(118,28,118,35): warning CS1591: Missing XML comment for publicly visible type or member 'JavascriptHook.StopAll()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(142,28,142,47): warning CS1591: Missing XML comment for publicly visible type or member 'JavascriptHook.InvokePlayerConnect(string, long)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(161,28,161,49): warning CS1591: Missing XML comment for publicly visible type or member 'JavascriptHook.InvokePlayerDisonnect(string, long, string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(180,28,180,45): warning CS1591: Missing XML comment for publicly visible type or member 'JavascriptHook.InvokeChatMessage(string, string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(199,28,199,45): warning CS1591: Missing XML comment for publicly visible type or member 'JavascriptHook.InvokeServerEvent(string, object[])'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(219,18,219,31): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(222,30,222,40): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.EmptyEvent'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(223,30,223,48): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.PlayerConnectEvent'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(224,30,224,46): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.ChatMessageEvent'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(229,33,229,40): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.OnStart'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(229,42,229,48): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.OnStop'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(229,50,229,56): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.OnTick'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(230,41,230,56): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.OnPlayerConnect'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(230,58,230,76): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.OnPlayerDisconnect'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(231,39,231,52): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.OnChatMessage'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(233,21,233,32): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.InvokeStart()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(238,21,238,31): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.InvokeStop()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(243,21,243,31): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.InvokeTick()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(248,21,248,40): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.InvokePlayerConnect(string, long)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(253,21,253,42): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.InvokePlayerDisonnect(string, long, string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(258,21,258,38): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.InvokeChatMessage(string, string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(263,21,263,38): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.InvokeServerEvent(string, object[])'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(270,21,270,37): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SendLocalMessage(string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(275,23,275,39): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetLocalUsername()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(280,21,280,32): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetPlayerID()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(286,21,286,33): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.CleanUpWorld()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(292,21,292,33): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.CreateObject(string, params object[])'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(316,21,316,37): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SendNotification(string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(320,21,320,37): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SendNotification(string[])'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(325,21,325,39): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.IsPlayerInvincible()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(329,21,329,40): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetPlayerInvincible(bool)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(334,25,334,42): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetPlayerPosition()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(338,25,338,42): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetPlayerRotation()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(343,21,343,38): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetPlayerPosition(Vector3)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(347,21,347,46): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetPlayerPositionNoOffset(Vector3)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(351,21,351,38): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetPlayerRotation(Vector3)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(356,21,356,41): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.IsPlayerInAnyVehicle()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(361,21,361,40): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetCharachterHandle()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(366,21,366,34): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.CreateVehicle(int, Vector3, Quaternion?)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(389,25,389,43): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetVehiclePosition()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(393,25,393,43): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetVehicleRotation()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(398,21,398,39): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetVehiclePosition(Vector3)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(405,21,405,47): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetVehiclePositionNoOffset(Vector3)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(412,21,412,39): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetVehicleRotation(Vector3)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(420,21,420,37): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetVehicleHandle()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(425,21,425,40): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetVehicleSeatIndex()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(430,21,430,43): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetVehicleEngineStatus(bool)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(437,21,437,43): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetVehicleEngineStatus()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(442,23,442,50): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetVehicleHeightAboveGround()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(447,23,447,37): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GetVehicleType()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(458,21,458,34): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.RepairVehicle()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(466,21,466,37): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.GivePlayerWeapon(uint, int, bool, bool)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(471,21,471,36): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetPlayerHealth(int)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(475,21,475,36): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetPlayerHealth(float)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(480,21,480,35): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetPlayerArmor(int)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(484,21,484,35): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SetPlayerArmor(float)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(530,21,530,42): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.IsControlJustReleased(int)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(535,21,535,41): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.IsControlJustPressed(int)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(540,21,540,37): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.IsControlPressed(int)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(545,21,545,33): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.AnyMapLoaded()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(550,21,550,28): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.LoadMap(string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(555,21,555,30): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.UnloadMap()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(567,21,567,35): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.AddServerEvent(string, dynamic)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\JavascriptHook.cs(572,21,572,37): warning CS1591: Missing XML comment for publicly visible type or member 'ScriptContext.SendTriggerEvent(string, params object[])'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(27,39,27,53): warning CS1591: Missing XML comment for publicly visible type or member 'Main.CurrentVersion'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(29,27,29,37): warning CS1591: Missing XML comment for publicly visible type or member 'Main.MyPlayerID'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(30,28,30,48): warning CS1591: Missing XML comment for publicly visible type or member 'Main.ShareNPCsWithPlayers'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(31,28,31,42): warning CS1591: Missing XML comment for publicly visible type or member 'Main.DisableTraffic'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(32,28,32,39): warning CS1591: Missing XML comment for publicly visible type or member 'Main.NPCsAllowed'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(34,32,34,44): warning CS1591: Missing XML comment for publicly visible type or member 'Main.MainSettings'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(35,34,35,48): warning CS1591: Missing XML comment for publicly visible type or member 'Main.MainNetworking'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(38,33,38,41): warning CS1591: Missing XML comment for publicly visible type or member 'Main.MainMenu'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(40,28,40,36): warning CS1591: Missing XML comment for publicly visible type or member 'Main.MainChat'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(41,34,41,48): warning CS1591: Missing XML comment for publicly visible type or member 'Main.MainPlayerList'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(43,29,43,35): warning CS1591: Missing XML comment for publicly visible type or member 'Main.Ticked'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(52,31,52,37): warning CS1591: Missing XML comment for publicly visible type or member 'Main.Logger'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(284,28,284,35): warning CS1591: Missing XML comment for publicly visible type or member 'Main.CleanUp()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(293,56,293,71): warning CS1591: Missing XML comment for publicly visible type or member 'Main.CheckNativeHash'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(310,45,310,56): warning CS1591: Missing XML comment for publicly visible type or member 'Main.ServerItems'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(311,28,311,40): warning CS1591: Missing XML comment for publicly visible type or member 'Main.CleanUpWorld()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(403,30,403,44): warning CS1591: Missing XML comment for publicly visible type or member 'Main.DumpCharacters()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Main.cs(418,30,418,41): warning CS1591: Missing XML comment for publicly visible type or member 'Main.DumpPlayers()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\MapLoader.cs(54,25,54,34): warning CS1591: Missing XML comment for publicly visible type or member 'MapLoader'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\MapLoader.cs(60,28,60,35): warning CS1591: Missing XML comment for publicly visible type or member 'MapLoader.LoadAll()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\MapLoader.cs(109,28,109,35): warning CS1591: Missing XML comment for publicly visible type or member 'MapLoader.LoadMap(string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\MapLoader.cs(149,28,149,40): warning CS1591: Missing XML comment for publicly visible type or member 'MapLoader.AnyMapLoaded()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\MapLoader.cs(154,28,154,37): warning CS1591: Missing XML comment for publicly visible type or member 'MapLoader.UnloadMap()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\MapLoader.cs(171,28,171,37): warning CS1591: Missing XML comment for publicly visible type or member 'MapLoader.DeleteAll()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\MenusMain.cs(15,27,15,35): warning CS1591: Missing XML comment for publicly visible type or member 'MenusMain.MenuPool'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\MenusMain.cs(17,27,17,35): warning CS1591: Missing XML comment for publicly visible type or member 'MenusMain.MainMenu'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\MenusMain.cs(23,29,23,40): warning CS1591: Missing XML comment for publicly visible type or member 'MenusMain.SubSettings'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\MenusMain.cs(24,28,24,38): warning CS1591: Missing XML comment for publicly visible type or member 'MenusMain.ServerList'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\MenusMain.cs(29,36,29,48): warning CS1591: Missing XML comment for publicly visible type or member 'MenusMain.ServerIpItem'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\MenusMain.cs(64,21,64,38): warning CS1591: Missing XML comment for publicly visible type or member 'MenusMain.UsernameActivated(object, EventArgs)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\MenusMain.cs(76,21,76,38): warning CS1591: Missing XML comment for publicly visible type or member 'MenusMain.ServerIpActivated(object, EventArgs)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\MenusMain.cs(88,21,88,50): warning CS1591: Missing XML comment for publicly visible type or member 'MenusMain.InitiateConnectionMenuSetting()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\MenusMain.cs(96,21,96,41): warning CS1591: Missing XML comment for publicly visible type or member 'MenusMain.ConnectedMenuSetting()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\MenusMain.cs(106,21,106,44): warning CS1591: Missing XML comment for publicly visible type or member 'MenusMain.DisconnectedMenuSetting()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(12,18,12,33): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(15,23,15,30): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass.Address'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(17,23,17,27): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass.Port'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(19,23,19,27): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass.Name'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(21,23,21,30): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass.Version'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(23,20,23,27): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass.Players'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(25,20,25,30): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass.MaxPlayers'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(27,21,27,30): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass.AllowList'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(29,21,29,25): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass.Mods'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(31,21,31,25): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass.NPCs'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(33,23,33,30): warning CS1591: Missing XML comment for publicly visible type or member 'ServerListClass.Country'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(41,27,41,35): warning CS1591: Missing XML comment for publicly visible type or member 'Servers.MainMenu'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Servers.cs(46,27,46,37): warning CS1591: Missing XML comment for publicly visible type or member 'Servers.ResultItem'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Settings.cs(13,27,13,35): warning CS1591: Missing XML comment for publicly visible type or member 'Settings.MainMenu'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Settings.cs(52,21,52,50): warning CS1591: Missing XML comment for publicly visible type or member 'Settings.DisableTrafficCheckboxChanged(object, EventArgs)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Menus\Sub\Settings.cs(71,21,71,44): warning CS1591: Missing XML comment for publicly visible type or member 'Settings.FlipMenuCheckboxChanged(object, EventArgs)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\PlayerList.cs(9,18,9,28): warning CS1591: Missing XML comment for publicly visible type or member 'PlayerList'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\PlayerList.cs(15,22,15,29): warning CS1591: Missing XML comment for publicly visible type or member 'PlayerList.Pressed'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\PlayerList.cs(17,21,17,30): warning CS1591: Missing XML comment for publicly visible type or member 'PlayerList.LeftAlign'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\PlayerList.cs(18,33,18,40): warning CS1591: Missing XML comment for publicly visible type or member 'PlayerList.Players'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\PlayerList.cs(19,21,19,25): warning CS1591: Missing XML comment for publicly visible type or member 'PlayerList.Tick()'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\PlayerList.cs(61,21,61,30): warning CS1591: Missing XML comment for publicly visible type or member 'PlayerList.SetPlayer(int, string)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\PlayerList.cs(77,27,77,36): warning CS1591: Missing XML comment for publicly visible type or member 'PlayerList.GetPlayer(int)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\PlayerList.cs(81,21,81,33): warning CS1591: Missing XML comment for publicly visible type or member 'PlayerList.RemovePlayer(int)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Util.cs(15,17,15,23): warning CS1591: Missing XML comment for publicly visible type or member 'ETasks'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Util.cs(17,9,17,21): warning CS1591: Missing XML comment for publicly visible type or member 'ETasks.CLIMB_LADDER'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Util.cs(792,29,792,40): warning CS1591: Missing XML comment for publicly visible type or member 'VectorExtensions.Denormalize(float)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Util.cs(797,29,797,38): warning CS1591: Missing XML comment for publicly visible type or member 'VectorExtensions.ToRadians(float)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Util.cs(802,31,802,40): warning CS1591: Missing XML comment for publicly visible type or member 'VectorExtensions.ToRadians(Vector3)'
1>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Client\Util.cs(812,34,812,46): warning CS1591: Missing XML comment for publicly visible type or member 'VectorExtensions.ToQuaternion(Vector3)'
1> CoopClient -> D:\Games\Grand Theft Auto V\Scripts\RageCoop\CoopClient.dll
========== Build: 1 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========

View File

@ -3,9 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31919.166
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoopServer", "Server\CoopServer.csproj", "{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RageCoop.Server", "Server\RageCoop.Server.csproj", "{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoopClient", "Client\CoopClient.csproj", "{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RageCoop.Client", "Client\RageCoop.Client.csproj", "{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RageCoop.Core", "Core\RageCoop.Core.csproj", "{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -31,6 +33,14 @@ Global
{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}.Release|Any CPU.Build.0 = Release|Any CPU
{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}.Release|x64.ActiveCfg = Release|Any CPU
{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}.Release|x64.Build.0 = Release|Any CPU
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Debug|x64.ActiveCfg = Debug|Any CPU
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Debug|x64.Build.0 = Debug|Any CPU
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Release|Any CPU.Build.0 = Release|Any CPU
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Release|x64.ActiveCfg = Release|Any CPU
{CC2E8102-E568-4524-AA1F-F8E0F1CFE58A}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace CoopServer
namespace RageCoop.Server
{
public class Allowlist
{

View File

@ -1,100 +0,0 @@
using System;
using System.Linq;
using System.Text;
namespace CoopServer
{
internal class BitReader
{
private int _currentIndex { get; set; } = 0;
private byte[] _resultArray = null;
public BitReader(byte[] array)
{
_resultArray = array;
}
public bool CanRead(int bytes)
{
return _resultArray.Length >= _currentIndex + bytes;
}
public bool ReadBool()
{
bool value = BitConverter.ToBoolean(_resultArray, _currentIndex);
_currentIndex += 1;
return value;
}
public float ReadFloat()
{
float value = BitConverter.ToSingle(_resultArray, _currentIndex);
_currentIndex += 4;
return value;
}
public byte ReadByte()
{
byte value = _resultArray[_currentIndex];
_currentIndex += 1;
return value;
}
public byte[] ReadByteArray(int length)
{
byte[] value = _resultArray.Skip(_currentIndex).Take(length).ToArray();
_currentIndex += length;
return value;
}
public short ReadShort()
{
short value = BitConverter.ToInt16(_resultArray, _currentIndex);
_currentIndex += 2;
return value;
}
public ushort ReadUShort()
{
ushort value = BitConverter.ToUInt16(_resultArray, _currentIndex);
_currentIndex += 2;
return value;
}
public int ReadInt()
{
int value = BitConverter.ToInt32(_resultArray, _currentIndex);
_currentIndex += 4;
return value;
}
public uint ReadUInt()
{
uint value = BitConverter.ToUInt32(_resultArray, _currentIndex);
_currentIndex += 4;
return value;
}
public long ReadLong()
{
long value = BitConverter.ToInt64(_resultArray, _currentIndex);
_currentIndex += 8;
return value;
}
public ulong ReadULong()
{
ulong value = BitConverter.ToUInt64(_resultArray, _currentIndex);
_currentIndex += 8;
return value;
}
public string ReadString(int index)
{
string value = Encoding.UTF8.GetString(_resultArray.Skip(_currentIndex).Take(index).ToArray());
_currentIndex += index;
return value;
}
}
}

View File

@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace CoopServer
namespace RageCoop.Server
{
public class Blocklist
{

View File

@ -1,33 +1,33 @@
using System;
using System.Collections.Generic;
using RageCoop.Core;
using Lidgren.Network;
namespace CoopServer
namespace RageCoop.Server
{
public class Client
{
public long NetHandle = 0;
public long ClientID = 0;
private float _currentLatency = 0f;
public float Latency
{
get => _currentLatency;
internal set
set
{
_currentLatency = value;
if ((value * 1000f) > Server.MainSettings.MaxLatency)
{
Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetHandle)?.Disconnect($"Too high latency [{value * 1000f}/{(float)Server.MainSettings.MaxLatency}]");
Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID)?.Disconnect($"Too high latency [{value * 1000f}/{(float)Server.MainSettings.MaxLatency}]");
}
}
}
public PlayerData Player;
private readonly Dictionary<string, object> _customData = new();
private long _callbacksCount = 0;
internal readonly Dictionary<long, Action<object>> Callbacks = new();
public bool FilesReceived { get; internal set; } = false;
internal bool FilesSent = false;
public readonly Dictionary<long, Action<object>> Callbacks = new();
public bool FilesReceived { get; set; } = false;
public bool FilesSent = false;
#region CUSTOMDATA FUNCTIONS
public void SetData<T>(string name, T data)
@ -64,7 +64,7 @@ namespace CoopServer
#region FUNCTIONS
public void Kick(string reason)
{
Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetHandle)?.Disconnect(reason);
Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID)?.Disconnect(reason);
}
public void Kick(string[] reason)
{
@ -75,7 +75,7 @@ namespace CoopServer
{
try
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetHandle);
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID);
if (userConnection == null)
{
return;
@ -93,10 +93,10 @@ namespace CoopServer
{
try
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetHandle);
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID);
if (userConnection == null)
{
Logging.Error($"[Client->SendNativeCall(ulong hash, params object[] args)]: Connection \"{NetHandle}\" not found!");
Logging.Error($"[Client->SendNativeCall(ulong hash, params object[] args)]: Connection \"{ClientID}\" not found!");
return;
}
@ -113,7 +113,7 @@ namespace CoopServer
};
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
packet.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Native);
}
catch (Exception e)
@ -126,10 +126,10 @@ namespace CoopServer
{
try
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetHandle);
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID);
if (userConnection == null)
{
Logging.Error($"[Client->SendNativeResponse(Action<object> callback, ulong hash, Type type, params object[] args)]: Connection \"{NetHandle}\" not found!");
Logging.Error($"[Client->SendNativeResponse(Action<object> callback, ulong hash, Type type, params object[] args)]: Connection \"{ClientID}\" not found!");
return;
}
@ -176,7 +176,7 @@ namespace CoopServer
Args = new List<object>(args) ?? new List<object>(),
ResultType = returnTypeValue,
ID = id
}.PacketToNetOutGoingMessage(outgoingMessage);
}.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Native);
}
catch (Exception e)
@ -187,10 +187,10 @@ namespace CoopServer
public void SendCleanUpWorld()
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetHandle);
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID);
if (userConnection == null)
{
Logging.Error($"[Client->SendCleanUpWorld()]: Connection \"{NetHandle}\" not found!");
Logging.Error($"[Client->SendCleanUpWorld()]: Connection \"{ClientID}\" not found!");
return;
}
@ -203,7 +203,7 @@ namespace CoopServer
{
try
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetHandle);
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID);
if (userConnection == null)
{
return;
@ -217,7 +217,7 @@ namespace CoopServer
Name = modName,
CustomPacketID = customID,
Bytes = bytes
}.PacketToNetOutGoingMessage(outgoingMessage);
}.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Mod);
Server.MainNetServer.FlushSendQueue();
}
@ -237,7 +237,7 @@ namespace CoopServer
try
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetHandle);
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID);
if (userConnection == null)
{
return;
@ -248,7 +248,7 @@ namespace CoopServer
{
EventName = eventName,
Args = new List<object>(args)
}.PacketToNetOutGoingMessage(outgoingMessage);
}.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Event);
Server.MainNetServer.FlushSendQueue();
}

View File

@ -1,12 +1,12 @@
using System.IO;
using System.Linq;
using System.Collections.Generic;
using RageCoop.Core;
using Lidgren.Network;
namespace CoopServer
namespace RageCoop.Server
{
internal static class DownloadManager
public static class DownloadManager
{
private static readonly List<long> _clientsToDelete = new();
private static readonly List<DownloadClient> _clients = new();
@ -105,7 +105,7 @@ namespace CoopServer
{
lock (Server.Clients)
{
Client x = Server.Clients.FirstOrDefault(x => x.NetHandle == client.NetHandle);
Client x = Server.Clients.FirstOrDefault(x => x.ClientID == client.NetHandle);
if (x != null)
{
x.FilesReceived = true;
@ -170,7 +170,7 @@ namespace CoopServer
}
}
internal class DownloadClient
public class DownloadClient
{
public long NetHandle = 0;
private readonly List<DownloadFile> _files = null;
@ -198,7 +198,7 @@ namespace CoopServer
ID = file.FileID,
FileName = file.FileName,
FileLength = file.FileLength
}.PacketToNetOutGoingMessage(outgoingMessage);
}.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, conn, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.File);
});
@ -217,7 +217,7 @@ namespace CoopServer
new Packets.FileTransferComplete()
{
ID = 0x0
}.PacketToNetOutGoingMessage(outgoingMessage);
}.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, conn, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.File);
}
@ -252,7 +252,7 @@ namespace CoopServer
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new Packets.FileTransferTick() { ID = file.FileID, FileChunk = file.FileChunks[FileDataPosition++] }.PacketToNetOutGoingMessage(outgoingMessage);
new Packets.FileTransferTick() { ID = file.FileID, FileChunk = file.FileChunks[FileDataPosition++] }.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, conn, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.File);
}
@ -268,7 +268,7 @@ namespace CoopServer
}
}
internal class DownloadFile
public class DownloadFile
{
public byte FileID { get; set; } = 0;
public string FileName { get; set; } = string.Empty;

26
Server/Entities.cs Normal file
View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core;
namespace RageCoop.Server
{
internal static class EntitiesBlah
{
public static Dictionary<long,SyncedCharacter> Peds=new Dictionary<long,SyncedCharacter>();
public static Dictionary<long, SyncedVehicle> Vehicles = new Dictionary<long, SyncedVehicle>();
}
internal class SyncedVehicle
{
public long Owner { get; set; }
// <index, (enum)VehicleSeat>
// public Dictionary<int, int> Seats=new Dictionary<int, int>();
}
internal class SyncedCharacter
{
public long Owner { get; set; }
}
}

View File

@ -1,7 +1,7 @@
using System;
using System.IO;
namespace CoopServer
namespace RageCoop.Server
{
public class Logging
{

View File

@ -1,127 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
namespace CoopServer
{
internal partial class Packets
{
public class FileTransferRequest : Packet
{
public byte ID { get; set; }
public string FileName { get; set; }
public long FileLength { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.FileTransferRequest);
List<byte> byteArray = new List<byte>();
// The ID from the download
byteArray.Add(ID);
// The name of the file
byte[] nameBytes = Encoding.UTF8.GetBytes(FileName);
byteArray.AddRange(BitConverter.GetBytes(nameBytes.Length));
byteArray.AddRange(nameBytes);
// The length of the file
byteArray.AddRange(BitConverter.GetBytes(FileLength));
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
ID = reader.ReadByte();
int nameArrayLength = reader.ReadInt();
FileName = reader.ReadString(nameArrayLength);
FileLength = reader.ReadLong();
#endregion
}
}
public class FileTransferTick : Packet
{
public byte ID { get; set; }
public byte[] FileChunk { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.FileTransferTick);
List<byte> byteArray = new List<byte>();
// The ID from the download
byteArray.Add(ID);
// The chunk of the file
byteArray.AddRange(BitConverter.GetBytes(FileChunk.Length));
byteArray.AddRange(FileChunk);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
ID = reader.ReadByte();
int chunkLength = reader.ReadInt();
FileChunk = reader.ReadByteArray(chunkLength);
#endregion
}
}
public class FileTransferComplete : Packet
{
public byte ID { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.FileTransferComplete);
List<byte> byteArray = new List<byte>();
// The ID from the download
byteArray.Add(ID);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
ID = reader.ReadByte();
#endregion
}
}
}
}

View File

@ -1,451 +0,0 @@
using System;
using System.Collections.Generic;
using Lidgren.Network;
namespace CoopServer
{
internal partial class Packets
{
public class FullSyncNpc : Packet
{
public long NetHandle { get; set; }
public int ModelHash { get; set; }
public Dictionary<byte, short> Clothes { get; set; }
public int Health { get; set; }
public LVector3 Position { get; set; }
public LVector3 Rotation { get; set; }
public LVector3 Velocity { get; set; }
public byte Speed { get; set; }
public LVector3 AimCoords { get; set; }
public uint CurrentWeaponHash { get; set; }
public ushort? Flag { get; set; } = 0;
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.FullSyncNpc);
List<byte> byteArray = new List<byte>();
// Write player + ped handle
byteArray.AddRange(BitConverter.GetBytes(NetHandle));
// Write npc flags
byteArray.AddRange(BitConverter.GetBytes(Flag.Value));
// Write npc model hash
byteArray.AddRange(BitConverter.GetBytes(ModelHash));
// Write npc position
byteArray.AddRange(BitConverter.GetBytes(Position.X));
byteArray.AddRange(BitConverter.GetBytes(Position.Y));
byteArray.AddRange(BitConverter.GetBytes(Position.Z));
// Write npc rotation
byteArray.AddRange(BitConverter.GetBytes(Rotation.X));
byteArray.AddRange(BitConverter.GetBytes(Rotation.Y));
byteArray.AddRange(BitConverter.GetBytes(Rotation.Z));
// Write npc clothes
// Write the count of clothes
byteArray.AddRange(BitConverter.GetBytes((ushort)Clothes.Count));
// Loop the dictionary and add the values
foreach (KeyValuePair<byte, short> cloth in Clothes)
{
byteArray.Add(cloth.Key);
byteArray.AddRange(BitConverter.GetBytes(cloth.Value));
}
// Write npc health
byteArray.AddRange(BitConverter.GetBytes(Health));
// Write npc velocity
byteArray.AddRange(BitConverter.GetBytes(Velocity.X));
byteArray.AddRange(BitConverter.GetBytes(Velocity.Y));
byteArray.AddRange(BitConverter.GetBytes(Velocity.Z));
// Write npc speed
byteArray.Add(Speed);
if (Flag.HasValue)
{
if ((Flag.Value & (byte)PedDataFlags.IsAiming) != 0 || (Flag.Value & (byte)PedDataFlags.IsShooting) != 0)
{
// Write player aim coords
byteArray.AddRange(BitConverter.GetBytes(Rotation.X));
byteArray.AddRange(BitConverter.GetBytes(Rotation.Y));
byteArray.AddRange(BitConverter.GetBytes(Rotation.Z));
}
}
// Write npc weapon hash
byteArray.AddRange(BitConverter.GetBytes(CurrentWeaponHash));
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player + ped handle
NetHandle = reader.ReadLong();
// Read npc flag
Flag = reader.ReadUShort();
// Read npc model hash
ModelHash = reader.ReadInt();
// Read npc position
Position = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read npc rotation
Rotation = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read npc clothes
// Create new Dictionary
Clothes = new Dictionary<byte, short>();
// Read the count of clothes
ushort clothCount = reader.ReadUShort();
// For clothCount
for (ushort i = 0; i < clothCount; i++)
{
// Read cloth value
Clothes.Add(reader.ReadByte(), reader.ReadShort());
}
// Read npc health
Health = reader.ReadByte();
// Read npc velocity
Velocity = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read npc speed
Speed = reader.ReadByte();
// Read npc flag values
if (Flag.HasValue)
{
if ((Flag.Value & (byte)PedDataFlags.IsAiming) != 0 || (Flag.Value & (byte)PedDataFlags.IsShooting) != 0)
{
AimCoords = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
}
}
// Read npc weapon hash
CurrentWeaponHash = reader.ReadUInt();
#endregion
}
}
public class FullSyncNpcVeh : Packet
{
public long NetHandle { get; set; }
public long VehHandle { get; set; }
public int ModelHash { get; set; }
public Dictionary<byte, short> Clothes { get; set; }
public int Health { get; set; }
public LVector3 Position { get; set; }
public int VehModelHash { get; set; }
public short VehSeatIndex { get; set; }
public LQuaternion VehRotation { get; set; }
public float VehEngineHealth { get; set; }
public float VehRPM { get; set; }
public LVector3 VehVelocity { get; set; }
public float VehSpeed { get; set; }
public float VehSteeringAngle { get; set; }
public byte[] VehColors { get; set; }
public Dictionary<int, int> VehMods { get; set; }
public VehicleDamageModel VehDamageModel { get; set; }
public byte VehLandingGear { get; set; }
public ushort? Flag { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.FullSyncNpcVeh);
List<byte> byteArray = new List<byte>();
// Write player + npc netHandle
byteArray.AddRange(BitConverter.GetBytes(NetHandle));
// Write player + vehicle handle
byteArray.AddRange(BitConverter.GetBytes(VehHandle));
// Write vehicles flags
byteArray.AddRange(BitConverter.GetBytes(Flag.Value));
// Write npc health
byteArray.AddRange(BitConverter.GetBytes(Health));
// Write npc model hash
byteArray.AddRange(BitConverter.GetBytes(ModelHash));
// Write npc clothes
// Write the count of clothes
byteArray.AddRange(BitConverter.GetBytes((ushort)Clothes.Count));
// Loop the dictionary and add the values
foreach (KeyValuePair<byte, short> cloth in Clothes)
{
byteArray.Add(cloth.Key);
byteArray.AddRange(BitConverter.GetBytes(cloth.Value));
}
// Write vehicle model hash
byteArray.AddRange(BitConverter.GetBytes(VehModelHash));
// Write player seat index
byteArray.AddRange(BitConverter.GetBytes(VehSeatIndex));
// Write vehicle position
byteArray.AddRange(BitConverter.GetBytes(Position.X));
byteArray.AddRange(BitConverter.GetBytes(Position.Y));
byteArray.AddRange(BitConverter.GetBytes(Position.Z));
// Write vehicle rotation
byteArray.AddRange(BitConverter.GetBytes(VehRotation.X));
byteArray.AddRange(BitConverter.GetBytes(VehRotation.Y));
byteArray.AddRange(BitConverter.GetBytes(VehRotation.Z));
byteArray.AddRange(BitConverter.GetBytes(VehRotation.W));
// Write vehicle engine health
byteArray.AddRange(BitConverter.GetBytes(VehEngineHealth));
// Write vehicle rpm
byteArray.AddRange(BitConverter.GetBytes(VehRPM));
// Write vehicle velocity
byteArray.AddRange(BitConverter.GetBytes(VehVelocity.X));
byteArray.AddRange(BitConverter.GetBytes(VehVelocity.Y));
byteArray.AddRange(BitConverter.GetBytes(VehVelocity.Z));
// Write vehicle speed
byteArray.AddRange(BitConverter.GetBytes(VehSpeed));
// Write vehicle steering angle
byteArray.AddRange(BitConverter.GetBytes(VehSteeringAngle));
// Check
if (Flag.HasValue)
{
if ((Flag.Value & (ushort)VehicleDataFlags.IsPlane) != 0)
{
// Write the vehicle landing gear
byteArray.AddRange(BitConverter.GetBytes(VehLandingGear));
}
}
// Write vehicle colors
byteArray.Add(VehColors[0]);
byteArray.Add(VehColors[1]);
// Write vehicle mods
// Write the count of mods
byteArray.AddRange(BitConverter.GetBytes((short)VehMods.Count));
// Loop the dictionary and add the values
foreach (KeyValuePair<int, int> mod in VehMods)
{
// Write the mod value
byteArray.AddRange(BitConverter.GetBytes(mod.Key));
byteArray.AddRange(BitConverter.GetBytes(mod.Value));
}
if (!VehDamageModel.Equals(default(VehicleDamageModel)))
{
// Write boolean = true
byteArray.Add(0x01);
// Write vehicle damage model
byteArray.Add(VehDamageModel.BrokenDoors);
byteArray.Add(VehDamageModel.BrokenWindows);
byteArray.AddRange(BitConverter.GetBytes(VehDamageModel.BurstedTires));
byteArray.Add(VehDamageModel.LeftHeadLightBroken);
byteArray.Add(VehDamageModel.RightHeadLightBroken);
}
else
{
// Write boolean = false
byteArray.Add(0x00);
}
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read player + npc netHandle
NetHandle = reader.ReadLong();
// Reader player + vehicle handle
VehHandle = reader.ReadLong();
// Read vehicle flags
Flag = reader.ReadUShort();
// Read npc health
Health = reader.ReadInt();
// Read npc model hash
ModelHash = reader.ReadInt();
// Read npc clothes
// Create new Dictionary
Clothes = new Dictionary<byte, short>();
// Read the count of clothes
ushort clothCount = reader.ReadUShort();
// For clothCount
for (int i = 0; i < clothCount; i++)
{
// Read cloth value
Clothes.Add(reader.ReadByte(), reader.ReadShort());
}
// Read vehicle model hash
VehModelHash = reader.ReadInt();
// Read npc seat index
VehSeatIndex = reader.ReadShort();
// Read vehicle position
Position = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read vehicle rotation
VehRotation = new LQuaternion()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat(),
W = reader.ReadFloat()
};
// Read vehicle engine health
VehEngineHealth = reader.ReadFloat();
// Read vehicle rpm
VehRPM = reader.ReadFloat();
// Read vehicle velocity
VehVelocity = new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
};
// Read vehicle speed
VehSpeed = reader.ReadFloat();
// Read vehicle steering angle
VehSteeringAngle = reader.ReadFloat();
// Check
if (Flag.HasValue)
{
if ((Flag.Value & (int)VehicleDataFlags.IsPlane) != 0)
{
// Read vehicle landing gear
VehLandingGear = (byte)reader.ReadShort();
}
}
// Read vehicle colors
byte vehColor1 = reader.ReadByte();
byte vehColor2 = reader.ReadByte();
VehColors = new byte[] { vehColor1, vehColor2 };
// Read vehicle mods
// Create new Dictionary
VehMods = new Dictionary<int, int>();
// Read count of mods
short vehModCount = reader.ReadShort();
// Loop
for (int i = 0; i < vehModCount; i++)
{
// Read the mod value
VehMods.Add(reader.ReadInt(), reader.ReadInt());
}
if (reader.ReadBool())
{
// Read vehicle damage model
VehDamageModel = new VehicleDamageModel()
{
BrokenDoors = reader.ReadByte(),
BrokenWindows = reader.ReadByte(),
BurstedTires = reader.ReadShort(),
LeftHeadLightBroken = reader.ReadByte(),
RightHeadLightBroken = reader.ReadByte()
};
}
#endregion
}
}
}
}

View File

@ -1,649 +0,0 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Lidgren.Network;
using Newtonsoft.Json;
namespace CoopServer
{
public static class VectorExtensions
{
public static LVector3 Normalize(this LVector3 value)
{
float value2 = value.Length();
return value / value2;
}
public static float Distance(this LVector3 value1, LVector3 value2)
{
LVector3 vector = value1 - value2;
float num = Dot(vector, vector);
return (float)Math.Sqrt(num);
}
public static float Dot(this LVector3 vector1, LVector3 vector2)
{
return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
}
}
public struct LVector3
{
public LVector3(float X, float Y, float Z)
{
this.X = X;
this.Y = Y;
this.Z = Z;
}
public float X { get; set; }
public float Y { get; set; }
public float Z { get; set; }
#region SERVER-ONLY
public float Length() => (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z));
public static LVector3 Subtract(LVector3 pos1, LVector3 pos2) => new(pos1.X - pos2.X, pos1.Y - pos2.Y, pos1.Z - pos2.Z);
public static bool Equals(LVector3 value1, LVector3 value2) => value1.X == value2.X && value1.Y == value2.Y && value1.Z == value2.Z;
public static LVector3 operator /(LVector3 value1, float value2)
{
float num = 1f / value2;
return new LVector3(value1.X * num, value1.Y * num, value1.Z * num);
}
public static LVector3 operator -(LVector3 left, LVector3 right)
{
return new LVector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
}
public static LVector3 operator -(LVector3 value)
{
return default(LVector3) - value;
}
#endregion
}
public struct LQuaternion
{
public LQuaternion(float X, float Y, float Z, float W)
{
this.X = X;
this.Y = Y;
this.Z = Z;
this.W = W;
}
public float X { get; set; }
public float Y { get; set; }
public float Z { get; set; }
public float W { get; set; }
}
internal enum PacketTypes
{
Handshake,
PlayerConnect,
PlayerDisconnect,
FullSyncPlayer,
FullSyncPlayerVeh,
LightSyncPlayer,
LightSyncPlayerVeh,
SuperLightSync,
FullSyncNpc,
FullSyncNpcVeh,
ChatMessage,
NativeCall,
NativeResponse,
Mod,
CleanUpWorld,
FileTransferTick,
FileTransferRequest,
FileTransferComplete,
ServerClientEvent
}
internal enum ConnectionChannel
{
Default = 0,
PlayerLight = 1,
PlayerFull = 2,
PlayerSuperLight = 3,
NPCFull = 4,
Chat = 5,
Native = 6,
Mod = 7,
File = 8,
Event = 9
}
[Flags]
internal enum PedDataFlags
{
IsAiming = 1 << 0,
IsShooting = 1 << 1,
IsReloading = 1 << 2,
IsJumping = 1 << 3,
IsRagdoll = 1 << 4,
IsOnFire = 1 << 5,
IsInParachuteFreeFall = 1 << 6,
IsParachuteOpen = 1 << 7,
IsOnLadder = 1 << 8,
IsVaulting = 1 << 9
}
#region ===== VEHICLE DATA =====
[Flags]
internal enum VehicleDataFlags
{
IsEngineRunning = 1 << 0,
AreLightsOn = 1 << 1,
AreBrakeLightsOn = 1 << 2,
AreHighBeamsOn = 1 << 3,
IsSirenActive = 1 << 4,
IsDead = 1 << 5,
IsHornActive = 1 << 6,
IsTransformed = 1 << 7,
RoofOpened = 1 << 8,
OnTurretSeat = 1 << 9,
IsPlane = 1 << 10
}
internal struct VehicleDamageModel
{
public byte BrokenWindows { get; set; }
public byte BrokenDoors { get; set; }
public short BurstedTires { get; set; }
public byte LeftHeadLightBroken { get; set; }
public byte RightHeadLightBroken { get; set; }
}
#endregion
interface IPacket
{
void PacketToNetOutGoingMessage(NetOutgoingMessage message);
void NetIncomingMessageToPacket(byte[] array);
}
abstract class Packet : IPacket
{
public abstract void PacketToNetOutGoingMessage(NetOutgoingMessage message);
public abstract void NetIncomingMessageToPacket(byte[] array);
}
internal partial class Packets
{
public class Mod : Packet
{
public long NetHandle { get; set; }
public long Target { get; set; }
public string Name { get; set; }
public byte CustomPacketID { get; set; }
public byte[] Bytes { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.Mod);
List<byte> byteArray = new List<byte>();
// Write NetHandle
byteArray.AddRange(BitConverter.GetBytes(NetHandle));
// Write Target
byteArray.AddRange(BitConverter.GetBytes(Target));
// Write Name
byte[] nameBytes = Encoding.UTF8.GetBytes(Name);
byteArray.AddRange(BitConverter.GetBytes(nameBytes.Length));
byteArray.AddRange(nameBytes);
// Write CustomPacketID
byteArray.Add(CustomPacketID);
// Write Bytes
byteArray.AddRange(BitConverter.GetBytes(Bytes.Length));
byteArray.AddRange(Bytes);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read NetHandle
NetHandle = reader.ReadLong();
// Read Target
Target = reader.ReadLong();
// Read Name
int nameLength = reader.ReadInt();
Name = reader.ReadString(nameLength);
// Read CustomPacketID
CustomPacketID = reader.ReadByte();
// Read Bytes
int bytesLength = reader.ReadInt();
Bytes = reader.ReadByteArray(bytesLength);
#endregion
}
}
public class ChatMessage : Packet
{
public string Username { get; set; }
public string Message { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.ChatMessage);
List<byte> byteArray = new List<byte>();
byte[] usernameBytes = Encoding.UTF8.GetBytes(Username);
byte[] messageBytes = Encoding.UTF8.GetBytes(Message);
// Write UsernameLength
byteArray.AddRange(BitConverter.GetBytes(usernameBytes.Length));
// Write Username
byteArray.AddRange(usernameBytes);
// Write MessageLength
byteArray.AddRange(BitConverter.GetBytes(messageBytes.Length));
// Write Message
byteArray.AddRange(messageBytes);
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read username
int usernameLength = reader.ReadInt();
Username = reader.ReadString(usernameLength);
// Read message
int messageLength = reader.ReadInt();
Message = reader.ReadString(messageLength);
#endregion
}
}
public class ServerClientEvent : Packet
{
public string EventName { get; set; }
public List<object> Args { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.ServerClientEvent);
List<byte> byteArray = new List<byte>();
byte[] eventNameBytes = Encoding.UTF8.GetBytes(EventName);
// Write event name
byteArray.AddRange(BitConverter.GetBytes(eventNameBytes.Length));
byteArray.AddRange(eventNameBytes);
// Write args
byteArray.AddRange(BitConverter.GetBytes(Args.Count));
foreach (object arg in Args)
{
var test = Util.GetBytesFromObject(arg);
if (test.Item1 == 0x0)
{
Logging.Warning("Can't get type of an object!");
byteArray.Add(0x0);
}
else
{
byteArray.Add(test.Item1);
byteArray.AddRange(test.Item2);
}
}
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read event name
int eventNameBytes = reader.ReadInt();
EventName = reader.ReadString(eventNameBytes);
// Read args
Args = new List<object>();
int argsCount = reader.ReadInt();
for (int i = 0; i < argsCount; i++)
{
byte argType = reader.ReadByte();
switch (argType)
{
case 0x01:
Args.Add(reader.ReadByte());
break;
case 0x02:
Args.Add(reader.ReadShort());
break;
case 0x03:
Args.Add(reader.ReadUShort());
break;
case 0x04:
Args.Add(reader.ReadInt());
break;
case 0x05:
Args.Add(reader.ReadUInt());
break;
case 0x06:
Args.Add(reader.ReadLong());
break;
case 0x07:
Args.Add(reader.ReadULong());
break;
case 0x08:
Args.Add(reader.ReadFloat());
break;
case 0x09:
Args.Add(reader.ReadBool());
break;
}
}
#endregion
}
}
#region ===== NATIVECALL =====
public class NativeCall : Packet
{
public ulong Hash { get; set; }
public List<object> Args { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.NativeCall);
List<byte> byteArray = new List<byte>();
// Write Hash
byteArray.AddRange(BitConverter.GetBytes(Hash));
// Write Args
byteArray.AddRange(BitConverter.GetBytes(Args.Count));
Args.ForEach(x =>
{
Type type = x.GetType();
if (type == typeof(int))
{
byteArray.Add(0x00);
byteArray.AddRange(BitConverter.GetBytes((int)x));
}
else if (type == typeof(bool))
{
byteArray.Add(0x01);
byteArray.AddRange(BitConverter.GetBytes((bool)x));
}
else if (type == typeof(float))
{
byteArray.Add(0x02);
byteArray.AddRange(BitConverter.GetBytes((float)x));
}
else if (type == typeof(string))
{
byteArray.Add(0x03);
byte[] stringBytes = Encoding.UTF8.GetBytes((string)x);
byteArray.AddRange(BitConverter.GetBytes(stringBytes.Length));
byteArray.AddRange(stringBytes);
}
else if (type == typeof(LVector3))
{
byteArray.Add(0x04);
LVector3 vector = (LVector3)x;
byteArray.AddRange(BitConverter.GetBytes(vector.X));
byteArray.AddRange(BitConverter.GetBytes(vector.Y));
byteArray.AddRange(BitConverter.GetBytes(vector.Z));
}
});
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read Hash
Hash = reader.ReadULong();
// Read Args
Args = new List<object>();
int argsLength = reader.ReadInt();
for (int i = 0; i < argsLength; i++)
{
byte argType = reader.ReadByte();
switch (argType)
{
case 0x00:
Args.Add(reader.ReadInt());
break;
case 0x01:
Args.Add(reader.ReadBool());
break;
case 0x02:
Args.Add(reader.ReadFloat());
break;
case 0x03:
int stringLength = reader.ReadInt();
Args.Add(reader.ReadString(stringLength));
break;
case 0x04:
Args.Add(new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
});
break;
}
}
#endregion
}
}
public class NativeResponse : Packet
{
public ulong Hash { get; set; }
public List<object> Args { get; set; }
public byte? ResultType { get; set; }
public long ID { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
#region PacketToNetOutGoingMessage
message.Write((byte)PacketTypes.NativeResponse);
List<byte> byteArray = new List<byte>();
// Write Hash
byteArray.AddRange(BitConverter.GetBytes(Hash));
Type type;
// Write Args
byteArray.AddRange(BitConverter.GetBytes(Args.Count));
Args.ForEach(x =>
{
type = x.GetType();
if (type == typeof(int))
{
byteArray.Add(0x00);
byteArray.AddRange(BitConverter.GetBytes((int)x));
}
else if (type == typeof(bool))
{
byteArray.Add(0x01);
byteArray.AddRange(BitConverter.GetBytes((bool)x));
}
else if (type == typeof(float))
{
byteArray.Add(0x02);
byteArray.AddRange(BitConverter.GetBytes((float)x));
}
else if (type == typeof(string))
{
byteArray.Add(0x03);
byte[] stringBytes = Encoding.UTF8.GetBytes((string)x);
byteArray.AddRange(BitConverter.GetBytes(stringBytes.Length));
byteArray.AddRange(stringBytes);
}
else if (type == typeof(LVector3))
{
byteArray.Add(0x04);
LVector3 vector = (LVector3)x;
byteArray.AddRange(BitConverter.GetBytes(vector.X));
byteArray.AddRange(BitConverter.GetBytes(vector.Y));
byteArray.AddRange(BitConverter.GetBytes(vector.Z));
}
});
byteArray.AddRange(BitConverter.GetBytes(ID));
// Write type of result
if (ResultType.HasValue)
{
byteArray.Add(ResultType.Value);
}
byte[] result = byteArray.ToArray();
message.Write(result.Length);
message.Write(result);
#endregion
}
public override void NetIncomingMessageToPacket(byte[] array)
{
#region NetIncomingMessageToPacket
BitReader reader = new BitReader(array);
// Read Hash
Hash = reader.ReadULong();
// Read Args
Args = new List<object>();
int argsLength = reader.ReadInt();
for (int i = 0; i < argsLength; i++)
{
byte argType = reader.ReadByte();
switch (argType)
{
case 0x00:
Args.Add(reader.ReadInt());
break;
case 0x01:
Args.Add(reader.ReadBool());
break;
case 0x02:
Args.Add(reader.ReadFloat());
break;
case 0x03:
int stringLength = reader.ReadInt();
Args.Add(reader.ReadString(stringLength));
break;
case 0x04:
Args.Add(new LVector3()
{
X = reader.ReadFloat(),
Y = reader.ReadFloat(),
Z = reader.ReadFloat()
});
break;
}
}
ID = reader.ReadLong();
// Read type of result
if (reader.CanRead(1))
{
ResultType = reader.ReadByte();
}
#endregion
}
}
#endregion // ===== NATIVECALL =====
}
public static class CoopSerializer
{
public static byte[] Serialize(this object obj)
{
if (obj == null)
{
return null;
}
string jsonString = JsonConvert.SerializeObject(obj);
return System.Text.Encoding.UTF8.GetBytes(jsonString);
}
public static T Deserialize<T>(this byte[] bytes) where T : class
{
if (bytes == null)
{
return null;
}
var jsonString = System.Text.Encoding.UTF8.GetString(bytes);
return JsonConvert.DeserializeObject<T>(jsonString);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +0,0 @@
using System.Linq;
namespace CoopServer
{
public struct PlayerData
{
public string Username { get; internal set; }
private int _lastPedHandle { get; set; }
private int _currentPedHandle { get; set; }
public int PedHandle
{
get => _currentPedHandle;
internal set
{
_lastPedHandle = _currentPedHandle == default ? value : _currentPedHandle;
_currentPedHandle = value;
if (_currentPedHandle != _lastPedHandle && Server.RunningResource != null)
{
Server.RunningResource.InvokePlayerPedHandleUpdate(Username);
}
}
}
private int _lastVehicleHandle { get; set; }
private int _currentVehicleHandle { get; set; }
public int VehicleHandle
{
get => _currentVehicleHandle;
internal set
{
_lastVehicleHandle = _currentVehicleHandle == default ? value : _currentVehicleHandle;
_currentVehicleHandle = value;
if (_currentVehicleHandle != _lastVehicleHandle && Server.RunningResource != null)
{
Server.RunningResource.InvokePlayerPedHandleUpdate(Username);
}
}
}
public bool IsInVehicle { get; internal set; }
private LVector3 _lastPosition { get; set; }
private LVector3 _currentPosition { get; set; }
public LVector3 Position
{
get => _currentPosition;
internal set
{
_lastPosition = _currentPosition.Equals(default(LVector3)) ? value : _currentPosition;
_currentPosition = value;
if (Server.RunningResource != null && !LVector3.Equals(_currentPosition, _lastPosition))
{
Server.RunningResource.InvokePlayerPositionUpdate(Username);
}
}
}
private int _lastHealth { get; set; }
private int _currentHealth { get; set; }
public int Health
{
get => _currentHealth;
internal set
{
_lastHealth = _currentHealth == default ? value : _currentHealth;
_currentHealth = value;
if (_currentHealth != _lastHealth && Server.RunningResource != null)
{
Server.RunningResource.InvokePlayerHealthUpdate(Username);
}
}
}
public bool IsInRangeOf(LVector3 position, float distance)
{
return LVector3.Subtract(Position, position).Length() < distance;
}
}
}

View File

@ -4,7 +4,7 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace CoopServer
namespace RageCoop.Server
{
class Program
{

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net6.0\publish\win-x64\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>net6.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>True</PublishSingleFile>
<PublishReadyToRun>True</PublishReadyToRun>
<PublishTrimmed>True</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<History>True|2022-05-18T05:35:57.1402751Z;True|2022-05-18T13:10:28.4995253+08:00;True|2022-05-01T18:35:01.9624101+08:00;True|2022-05-01T12:32:20.8671319+08:00;False|2022-05-01T12:30:25.4596227+08:00;</History>
</PropertyGroup>
</Project>

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
@ -14,6 +14,16 @@
<Authors>RAGECOOP</Authors>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Obsolete\**" />
<EmbeddedResource Remove="Obsolete\**" />
<None Remove="Obsolete\**" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\RageCoop.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Lidgren.Network">
<HintPath>..\Libs\Release\scripts\Lidgren.Network.dll</HintPath>
@ -23,4 +33,5 @@
</Reference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_LastSelectedProfileId>M:\SandBox-Shared\OneDrive\OneDrive - 教育部\Personal\repos\_ACTIVE\RageCOOP-V\Server\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
</PropertyGroup>
</Project>

View File

@ -7,20 +7,20 @@ using System.Threading;
using System.Reflection;
using System.IO;
using System.Net.Http;
using RageCoop.Core;
using Newtonsoft.Json;
using System.Threading.Tasks;
using Lidgren.Network;
namespace CoopServer
namespace RageCoop.Server
{
internal struct IpInfo
public struct IpInfo
{
[JsonProperty("ip")]
public string Address { get; set; }
}
internal class Server
public class Server
{
private static readonly string _compatibleVersion = "V1_4";
private static long _currentTick = 0;
@ -233,7 +233,7 @@ namespace CoopServer
{
if (!client.FilesSent)
{
DownloadManager.InsertClient(client.NetHandle);
DownloadManager.InsertClient(client.ClientID);
client.FilesSent = true;
}
});
@ -249,64 +249,72 @@ namespace CoopServer
switch (message.MessageType)
{
case NetIncomingMessageType.ConnectionApproval:
Logging.Info($"New incoming connection from: [{message.SenderConnection.RemoteEndPoint}]");
if (message.ReadByte() != (byte)PacketTypes.Handshake)
{
Logging.Info($"IP [{message.SenderConnection.RemoteEndPoint.Address}] was blocked, reason: Wrong packet!");
message.SenderConnection.Deny("Wrong packet!");
}
else
{
try
Logging.Info($"New incoming connection from: [{message.SenderConnection.RemoteEndPoint}]");
if (message.ReadByte() != (byte)PacketTypes.Handshake)
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
Packets.Handshake packet = new();
packet.NetIncomingMessageToPacket(data);
GetHandshake(message.SenderConnection, packet);
Logging.Info($"IP [{message.SenderConnection.RemoteEndPoint.Address}] was blocked, reason: Wrong packet!");
message.SenderConnection.Deny("Wrong packet!");
}
catch (Exception e)
else
{
Logging.Info($"IP [{message.SenderConnection.RemoteEndPoint.Address}] was blocked, reason: {e.Message}");
message.SenderConnection.Deny(e.Message);
try
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
Packets.Handshake packet = new();
packet.Unpack(data);
GetHandshake(message.SenderConnection, packet);
}
catch (Exception e)
{
Logging.Info($"IP [{message.SenderConnection.RemoteEndPoint.Address}] was blocked, reason: {e.Message}");
message.SenderConnection.Deny(e.Message);
}
}
break;
}
break;
case NetIncomingMessageType.StatusChanged:
NetConnectionStatus status = (NetConnectionStatus)message.ReadByte();
if (status == NetConnectionStatus.Disconnected)
{
long nethandle = message.SenderConnection.RemoteUniqueIdentifier;
NetConnectionStatus status = (NetConnectionStatus)message.ReadByte();
DownloadManager.RemoveClient(nethandle);
if (status == NetConnectionStatus.Disconnected)
{
long nethandle = message.SenderConnection.RemoteUniqueIdentifier;
SendPlayerDisconnectPacket(nethandle);
DownloadManager.RemoveClient(nethandle);
SendPlayerDisconnectPacket(nethandle);
}
else if (status == NetConnectionStatus.Connected)
{
SendPlayerConnectPacket(message.SenderConnection);
}
break;
}
else if (status == NetConnectionStatus.Connected)
{
SendPlayerConnectPacket(message.SenderConnection);
}
break;
case NetIncomingMessageType.Data:
// Get packet type
byte type = message.ReadByte();
byte btype= message.ReadByte();
var type = (PacketTypes)btype;
switch (type)
{
case (byte)PacketTypes.FullSyncPlayer:
#region SyncData
case PacketTypes.CharacterStateSync:
{
try
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
Packets.FullSyncPlayer packet = new();
packet.NetIncomingMessageToPacket(data);
Packets.PedStateSync packet = new();
packet.Unpack(data);
FullSyncPlayer(packet);
CharacterStateSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
}
catch (Exception e)
{
@ -314,17 +322,17 @@ namespace CoopServer
}
}
break;
case (byte)PacketTypes.FullSyncPlayerVeh:
case PacketTypes.VehicleStateSync:
{
try
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
Packets.FullSyncPlayerVeh packet = new();
packet.NetIncomingMessageToPacket(data);
Packets.VehicleStateSync packet = new();
packet.Unpack(data);
FullSyncPlayerVeh(packet);
VehicleStateSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
}
catch (Exception e)
{
@ -332,17 +340,17 @@ namespace CoopServer
}
}
break;
case (byte)PacketTypes.LightSyncPlayer:
case PacketTypes.CharacterSync:
{
try
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
Packets.LightSyncPlayer packet = new();
packet.NetIncomingMessageToPacket(data);
Packets.PedSync packet = new();
packet.Unpack(data);
LightSyncPlayer(packet);
CharacterSync(packet, message.SenderConnection.RemoteUniqueIdentifier);
}
catch (Exception e)
{
@ -350,17 +358,17 @@ namespace CoopServer
}
}
break;
case (byte)PacketTypes.LightSyncPlayerVeh:
case PacketTypes.VehicleSync:
{
try
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
Packets.LightSyncPlayerVeh packet = new();
packet.NetIncomingMessageToPacket(data);
Packets.VehicleSync packet = new();
packet.Unpack(data);
LightSyncPlayerVeh(packet);
VehicleSync(packet,message.SenderConnection.RemoteUniqueIdentifier);
}
catch (Exception e)
{
@ -368,7 +376,11 @@ namespace CoopServer
}
}
break;
case (byte)PacketTypes.ChatMessage:
#endregion
case PacketTypes.ChatMessage:
{
try
{
@ -376,7 +388,7 @@ namespace CoopServer
byte[] data = message.ReadBytes(len);
Packets.ChatMessage packet = new();
packet.NetIncomingMessageToPacket(data);
packet.Unpack(data);
SendChatMessage(packet);
}
@ -386,57 +398,8 @@ namespace CoopServer
}
}
break;
case (byte)PacketTypes.FullSyncNpc:
{
if (MainSettings.NpcsAllowed)
{
try
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
Packets.FullSyncNpc packet = new();
packet.NetIncomingMessageToPacket(data);
FullSyncNpc(message.SenderConnection, packet);
}
catch (Exception e)
{
DisconnectAndLog(message.SenderConnection, type, e);
}
}
else
{
message.SenderConnection.Disconnect("Npcs are not allowed!");
}
}
break;
case (byte)PacketTypes.FullSyncNpcVeh:
{
if (MainSettings.NpcsAllowed)
{
try
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
Packets.FullSyncNpcVeh packet = new();
packet.NetIncomingMessageToPacket(data);
FullSyncNpcVeh(message.SenderConnection, packet);
}
catch (Exception e)
{
DisconnectAndLog(message.SenderConnection, type, e);
}
}
else
{
message.SenderConnection.Disconnect("Npcs are not allowed!");
}
}
break;
case (byte)PacketTypes.NativeResponse:
case PacketTypes.NativeResponse:
{
try
{
@ -444,9 +407,9 @@ namespace CoopServer
byte[] data = message.ReadBytes(len);
Packets.NativeResponse packet = new();
packet.NetIncomingMessageToPacket(data);
packet.Unpack(data);
Client client = Clients.Find(x => x.NetHandle == message.SenderConnection.RemoteUniqueIdentifier);
Client client = Clients.Find(x => x.ClientID == message.SenderConnection.RemoteUniqueIdentifier);
if (client != null)
{
if (client.Callbacks.ContainsKey(packet.ID))
@ -462,7 +425,7 @@ namespace CoopServer
}
}
break;
case (byte)PacketTypes.Mod:
case PacketTypes.Mod:
{
if (MainSettings.ModsAllowed)
{
@ -472,7 +435,7 @@ namespace CoopServer
byte[] data = message.ReadBytes(len);
Packets.Mod packet = new Packets.Mod();
packet.NetIncomingMessageToPacket(data);
packet.Unpack(data);
bool resourceResult = false;
if (RunningResource != null)
@ -486,7 +449,7 @@ namespace CoopServer
if (!resourceResult && packet.Target != -1)
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
packet.Pack(outgoingMessage);
if (packet.Target != 0)
{
@ -519,7 +482,7 @@ namespace CoopServer
}
}
break;
case (byte)PacketTypes.FileTransferComplete:
case PacketTypes.FileTransferComplete:
{
try
{
@ -529,12 +492,12 @@ namespace CoopServer
byte[] data = message.ReadBytes(len);
Packets.FileTransferComplete packet = new();
packet.NetIncomingMessageToPacket(data);
packet.Unpack(data);
Client client = Clients.Find(x => x.NetHandle == message.SenderConnection.RemoteUniqueIdentifier);
Client client = Clients.Find(x => x.ClientID == message.SenderConnection.RemoteUniqueIdentifier);
if (client != null && !client.FilesReceived)
{
DownloadManager.TryToRemoveClient(client.NetHandle, packet.ID);
DownloadManager.TryToRemoveClient(client.ClientID, packet.ID);
}
}
}
@ -544,7 +507,7 @@ namespace CoopServer
}
}
break;
case (byte)PacketTypes.ServerClientEvent:
case PacketTypes.ServerClientEvent:
{
try
{
@ -552,13 +515,13 @@ namespace CoopServer
byte[] data = message.ReadBytes(len);
Packets.ServerClientEvent packet = new Packets.ServerClientEvent();
packet.NetIncomingMessageToPacket(data);
packet.Unpack(data);
long senderNetHandle = message.SenderConnection.RemoteUniqueIdentifier;
Client client = null;
lock (Clients)
{
client = Util.GetClientByNetHandle(senderNetHandle);
client = Util.GetClientByID(senderNetHandle);
}
if (client != null)
@ -586,13 +549,39 @@ namespace CoopServer
}
break;
default:
Logging.Error("Unhandled Data / Packet type");
if (type.IsSyncEvent())
{
// Sync Events
try
{
int len = message.ReadInt32();
byte[] data = message.ReadBytes(len);
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
outgoingMessage.Write(btype);
outgoingMessage.Write(len);
outgoingMessage.Write(data);
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != message.SenderConnection.RemoteUniqueIdentifier).ForEach(x =>
{
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.CharacterSync);
});
}
catch (Exception e)
{
DisconnectAndLog(message.SenderConnection, type, e);
}
}
else
{
Logging.Error("Unhandled Data / Packet type");
}
break;
}
break;
case NetIncomingMessageType.ConnectionLatencyUpdated:
{
Client client = Clients.Find(x => x.NetHandle == message.SenderConnection.RemoteUniqueIdentifier);
Client client = Clients.Find(x => x.ClientID == message.SenderConnection.RemoteUniqueIdentifier);
if (client != null)
{
client.Latency = message.ReadFloat();
@ -641,7 +630,7 @@ namespace CoopServer
}
}
private void DisconnectAndLog(NetConnection senderConnection, byte type, Exception e)
private void DisconnectAndLog(NetConnection senderConnection,PacketTypes type, Exception e)
{
Logging.Error($"Error receiving a packet of type {type}");
Logging.Error(e.Message);
@ -691,7 +680,7 @@ namespace CoopServer
return;
}
long localNetHandle = local.RemoteUniqueIdentifier;
Client tmpClient;
@ -701,25 +690,26 @@ namespace CoopServer
Clients.Add(
tmpClient = new Client()
{
NetHandle = localNetHandle,
ClientID = local.RemoteUniqueIdentifier,
Player = new()
{
Username = packet.Username
Username = packet.Username,
PedID=packet.PedID
}
}
);
);;
}
Logging.Info($"HandShake sucess, Player:{packet.Username} PedID:{packet.PedID}");
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
// Create a new handshake packet
new Packets.Handshake()
{
NetHandle = localNetHandle,
PedID = packet.PedID,
Username = string.Empty,
ModVersion = string.Empty,
NPCsAllowed = MainSettings.NpcsAllowed
}.PacketToNetOutGoingMessage(outgoingMessage);
}.Pack(outgoingMessage);
// Accept the connection and send back a new handshake packet with the connection ID
local.Approve(outgoingMessage);
@ -733,7 +723,7 @@ namespace CoopServer
// The connection has been approved, now we need to send all other players to the new player and the new player to all players
private static void SendPlayerConnectPacket(NetConnection local)
{
Client localClient = Clients.Find(x => x.NetHandle == local.RemoteUniqueIdentifier);
Client localClient = Clients.Find(x => x.ClientID == local.RemoteUniqueIdentifier);
if (localClient == null)
{
local.Disconnect("No data found!");
@ -748,15 +738,17 @@ namespace CoopServer
{
long targetNetHandle = targetPlayer.RemoteUniqueIdentifier;
Client targetClient = Clients.Find(x => x.NetHandle == targetNetHandle);
Client targetClient = Clients.Find(x => x.ClientID == targetNetHandle);
if (targetClient != null)
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new Packets.PlayerConnect()
{
NetHandle = targetNetHandle,
Username = targetClient.Player.Username
}.PacketToNetOutGoingMessage(outgoingMessage);
// NetHandle = targetNetHandle,
Username = targetClient.Player.Username,
PedID=targetClient.Player.PedID,
}.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, local, NetDeliveryMethod.ReliableOrdered, 0);
}
});
@ -765,9 +757,10 @@ namespace CoopServer
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new Packets.PlayerConnect()
{
NetHandle = local.RemoteUniqueIdentifier,
// NetHandle = local.RemoteUniqueIdentifier,
PedID=localClient.Player.PedID,
Username = localClient.Player.Username
}.PacketToNetOutGoingMessage(outgoingMessage);
}.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.ReliableOrdered, 0);
}
@ -790,17 +783,19 @@ namespace CoopServer
private static void SendPlayerDisconnectPacket(long nethandle)
{
List<NetConnection> clients = MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != nethandle);
int playerPedID = Clients.Where(x => x.ClientID==nethandle).First().Player.PedID;
if (clients.Count > 0)
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new Packets.PlayerDisconnect()
{
NetHandle = nethandle
}.PacketToNetOutGoingMessage(outgoingMessage);
PedID=playerPedID,
}.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.ReliableOrdered, 0);
}
Client localClient = Clients.FirstOrDefault(x => x.NetHandle == nethandle);
Client localClient = Clients.FirstOrDefault(x => x.ClientID == nethandle);
if (localClient == null)
{
return;
@ -814,10 +809,131 @@ namespace CoopServer
}
else
{
Logging.Info($"Player {localClient.Player.Username} disconnected!");
Logging.Info($"Player {localClient.Player.Username} disconnected! ID:{playerPedID}");
}
}
#region SyncEntities
private static void CharacterStateSync(Packets.PedStateSync packet,long ClientID)
{
Client client = Util.GetClientByID(ClientID);
if (client == null)
{
return;
}
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != ClientID).ForEach(x =>
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.CharacterSync);
});
if (RunningResource != null && packet.ID==client.Player.PedID)
{
RunningResource.InvokePlayerUpdate(client);
}
}
private static void VehicleStateSync(Packets.VehicleStateSync packet, long ClientID)
{
Client client = Util.GetClientByID(ClientID);
if (client == null)
{
return;
}
// Save the new data
if (packet.Passengers.ContainsValue(client.Player.PedID))
{
client.Player.VehicleID = packet.ID;
}
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != ClientID).ForEach(x =>
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.VehicleSync);
});
}
private static void CharacterSync(Packets.PedSync packet, long ClientID)
{
Client client = Util.GetClientByID(ClientID);
if (client == null)
{
return;
}
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != ClientID).ForEach(x =>
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.CharacterSync);
});
if (RunningResource != null && packet.ID==client.Player.PedID)
{
RunningResource.InvokePlayerUpdate(client);
}
}
private static void VehicleSync(Packets.VehicleSync packet, long ClientID)
{
Client client = Util.GetClientByID(ClientID);
if (client == null)
{
return;
}
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != ClientID).ForEach(x =>
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.VehicleSync);
});
/*
Client client = Util.GetClientByID(ClientID);
if (client == null)
{
return;
}
// Save the new data
client.Player.PedHandle = packet.PedHandle;
client.Player.VehicleHandle = packet.VehicleHandle;
client.Player.IsInVehicle = true;
client.Player.Position = packet.Position;
client.Player.Health = packet.Health;
// Override the latency
packet.Latency = client.Latency;
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != ClientID).ForEach(x =>
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PlayerFull);
});
if (RunningResource != null)
{
RunningResource.InvokePlayerUpdate(client);
}
*/
}
#region Obsolete
/*
private static void FullSyncPlayer(Packets.FullSyncPlayer packet)
{
Client client = Util.GetClientByNetHandle(packet.NetHandle);
@ -985,7 +1101,9 @@ namespace CoopServer
RunningResource.InvokePlayerUpdate(client);
}
}
*/
#endregion
#endregion
// Send a message to targets or all players
private static void SendChatMessage(Packets.ChatMessage packet, List<NetConnection> targets = null)
{
@ -1048,47 +1166,20 @@ namespace CoopServer
Logging.Info(packet.Username + ": " + packet.Message);
}
internal static void SendChatMessage(string username, string message, List<NetConnection> targets = null)
public static void SendChatMessage(string username, string message, List<NetConnection> targets = null)
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new Packets.ChatMessage() { Username = username, Message = message }.PacketToNetOutGoingMessage(outgoingMessage);
new Packets.ChatMessage() { Username = username, Message = message }.Pack(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, targets ?? MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Chat);
}
internal static void SendChatMessage(string username, string message, NetConnection target)
public static void SendChatMessage(string username, string message, NetConnection target)
{
SendChatMessage(username, message, new List<NetConnection>() { target });
}
#endregion
#region -- NPC --
private static void FullSyncNpc(NetConnection local, Packets.FullSyncNpc packet)
{
List<NetConnection> clients;
if ((clients = Util.GetAllInRange(packet.Position, 550f, local)).Count == 0)
{
return;
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.NPCFull);
}
private static void FullSyncNpcVeh(NetConnection local, Packets.FullSyncNpcVeh packet)
{
List<NetConnection> clients;
if ((clients = Util.GetAllInRange(packet.Position, 550f, local)).Count == 0)
{
return;
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.NPCFull);
}
#endregion
public static void RegisterCommand(string name, string usage, short argsLength, Action<CommandContext> callback)
{

View File

@ -5,17 +5,17 @@ using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using RageCoop.Core;
using Lidgren.Network;
namespace CoopServer
namespace RageCoop.Server
{
public abstract class ServerScript
{
public API API { get; } = new();
}
internal class Resource
public class Resource
{
public bool ReadyToStop = false;
@ -218,69 +218,69 @@ namespace CoopServer
/// </summary>
public event ModEvent OnModPacketReceived;
internal void InvokeTick(long tick)
public void InvokeTick(long tick)
{
OnTick?.Invoke(tick);
}
internal void InvokeStart()
public void InvokeStart()
{
OnStart?.Invoke();
}
internal void InvokeStop()
public void InvokeStop()
{
OnStop?.Invoke();
}
internal void InvokePlayerHandshake(Client client)
public void InvokePlayerHandshake(Client client)
{
OnPlayerHandshake?.Invoke(client);
}
internal void InvokePlayerConnected(Client client)
public void InvokePlayerConnected(Client client)
{
OnPlayerConnected?.Invoke(client);
}
internal void InvokePlayerDisconnected(Client client)
public void InvokePlayerDisconnected(Client client)
{
OnPlayerDisconnected?.Invoke(client);
}
internal void InvokePlayerUpdate(Client client)
public void InvokePlayerUpdate(Client client)
{
OnPlayerUpdate?.Invoke(client);
}
internal void InvokePlayerHealthUpdate(string username)
public void InvokePlayerHealthUpdate(string username)
{
OnPlayerHealthUpdate?.Invoke(Server.Clients.FirstOrDefault(x => x.Player.Username == username));
}
internal bool InvokeChatMessage(string username, string message)
public bool InvokeChatMessage(string username, string message)
{
CancelEventArgs args = new(false);
OnChatMessage?.Invoke(username, message, args);
return args.Cancel;
}
internal void InvokePlayerPositionUpdate(string username)
public void InvokePlayerPositionUpdate(string username)
{
OnPlayerPositionUpdate?.Invoke(Server.Clients.FirstOrDefault(x => x.Player.Username == username));
}
internal void InvokePlayerPedHandleUpdate(string username)
public void InvokePlayerPedHandleUpdate(string username)
{
OnPlayerPedHandleUpdate?.Invoke(Server.Clients.FirstOrDefault(x => x.Player.Username == username));
}
internal void InvokePlayerVehicleHandleUpdate(string username)
public void InvokePlayerVehicleHandleUpdate(string username)
{
OnPlayerVehicleHandleUpdate?.Invoke(Server.Clients.FirstOrDefault(x => x.Player.Username == username));
}
internal bool InvokeModPacketReceived(long from, long target, string modName, byte customID, byte[] bytes)
public bool InvokeModPacketReceived(long from, long target, string modName, byte customID, byte[] bytes)
{
CancelEventArgs args = new(false);
OnModPacketReceived?.Invoke(from, target, modName, customID, bytes, args);
@ -315,7 +315,7 @@ namespace CoopServer
Name = modName,
CustomPacketID = customID,
Bytes = bytes
}.PacketToNetOutGoingMessage(outgoingMessage);
}.Pack(outgoingMessage);
Logging.Debug($"SendModPacketToAll recipients list {connections.Count}");
Server.MainNetServer.SendMessage(outgoingMessage, connections, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Mod);
Server.MainNetServer.FlushSendQueue();
@ -355,7 +355,7 @@ namespace CoopServer
};
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
packet.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Native);
}
catch (Exception e)

View File

@ -1,4 +1,4 @@
namespace CoopServer
namespace RageCoop.Server
{
public class Settings
{

View File

@ -4,12 +4,12 @@ using System.Xml;
using System.Xml.Serialization;
using System.Linq;
using System.Collections.Generic;
using RageCoop.Core;
using Lidgren.Network;
namespace CoopServer
namespace RageCoop.Server
{
internal class Util
static partial class Util
{
public static (byte, byte[]) GetBytesFromObject(object obj)
{
@ -28,12 +28,12 @@ namespace CoopServer
};
}
public static Client GetClientByNetHandle(long netHandle)
public static Client GetClientByID(long id)
{
Client result = Server.Clients.Find(x => x.NetHandle == netHandle);
Client result = Server.Clients.Find(x => x.ClientID == id);
if (result == null)
{
NetConnection localConn = Server.MainNetServer.Connections.Find(x => netHandle == x.RemoteUniqueIdentifier);
NetConnection localConn = Server.MainNetServer.Connections.Find(x => id == x.RemoteUniqueIdentifier);
if (localConn != null)
{
localConn.Disconnect("No data found!");
@ -52,7 +52,7 @@ namespace CoopServer
return null;
}
return Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == client.NetHandle);
return Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == client.ClientID);
}
// Return a list of all connections but not the local connection
@ -70,7 +70,7 @@ namespace CoopServer
{
return new(Server.MainNetServer.Connections.FindAll(e =>
{
Client client = Server.Clients.First(x => x.NetHandle == e.RemoteUniqueIdentifier);
Client client = Server.Clients.First(x => x.ClientID == e.RemoteUniqueIdentifier);
return client != null && client.Player.IsInRangeOf(position, range);
}));
}
@ -79,7 +79,7 @@ namespace CoopServer
{
return new(Server.MainNetServer.Connections.Where(e =>
{
Client client = Server.Clients.First(x => x.NetHandle == e.RemoteUniqueIdentifier);
Client client = Server.Clients.First(x => x.ClientID == e.RemoteUniqueIdentifier);
return e != local && client != null && client.Player.IsInRangeOf(position, range);
}));
}

View File

@ -1 +0,0 @@
API.SendLocalMessage('test.js loaded lalala');

View File

@ -1,24 +0,0 @@
function testFunction(message)
{
SHVDN.GTA.UI.Notification.Show(message);
}
var messageCount = 0;
// Called every tick
API.OnTick.connect(function() {
if (messageCount < 5)
{
API.SendLocalMessage("testFunction " + ++messageCount);
}
});
// Called on connect
API.OnStart.connect(function() {
testFunction("hello test2.js!");
});
// Called on disconnect
API.OnStop.connect(function() {
testFunction("bye test2.js!");
});