RAGECOOP-V/Client/Main.cs

585 lines
21 KiB
C#
Raw Normal View History

2022-05-22 15:55:26 +08:00
#undef DEBUG
using System;
using System.IO;
2021-07-07 13:36:25 +02:00
using System.Linq;
using System.Windows.Forms;
using System.Collections.Generic;
2021-08-18 11:47:59 +02:00
using System.Drawing;
2022-05-22 15:55:26 +08:00
using System.Threading;
using System.Diagnostics;
using RageCoop.Client.Menus;
using RageCoop.Core;
2021-07-07 13:36:25 +02:00
using GTA;
using GTA.Native;
2022-05-22 15:55:26 +08:00
using GTA.Math;
2021-07-07 13:36:25 +02:00
2022-05-22 15:55:26 +08:00
namespace RageCoop.Client
2021-07-07 13:36:25 +02:00
{
2021-12-03 20:30:00 +01:00
/// <summary>
/// Don't use it!
/// </summary>
public class Main : Script
2021-07-07 13:36:25 +02:00
{
private bool _gameLoaded = false;
2022-05-22 15:55:26 +08:00
private static bool _isGoingToCar = false;
2021-07-07 13:36:25 +02:00
2022-05-22 15:55:26 +08:00
public static readonly string CurrentVersion = "V1_4_1";
2021-07-07 13:36:25 +02:00
2022-05-22 15:55:26 +08:00
public static int MyPlayerID=0;
public static bool DisableTraffic = true;
public static bool NPCsAllowed = false;
internal static RelationshipGroup SyncedPedsGroup;
2021-07-07 13:36:25 +02:00
2022-05-22 15:55:26 +08:00
public static Settings Settings = null;
public static Networking MainNetworking = null;
2021-08-18 11:47:59 +02:00
#if !NON_INTERACTIVE
2022-05-22 15:55:26 +08:00
public static MenusMain MainMenu = null;
#endif
2022-05-22 15:55:26 +08:00
public static Chat MainChat = null;
public static PlayerList MainPlayerList = new PlayerList();
public static Stopwatch Counter = new Stopwatch();
2021-07-07 13:36:25 +02:00
2022-05-22 15:55:26 +08:00
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>>();
2021-07-07 13:36:25 +02:00
2021-12-03 20:30:00 +01:00
/// <summary>
/// Don't use it!
/// </summary>
2021-07-07 13:36:25 +02:00
public Main()
{
// Required for some synchronization!
2022-05-22 15:55:26 +08:00
/*if (Game.Version < GameVersion.v1_0_1290_1_Steam)
{
Tick += (object sender, EventArgs e) =>
{
if (Game.IsLoading)
{
return;
}
2022-05-22 15:55:26 +08:00
if (!_gameLoaded)
{
GTA.UI.Notification.Show("~r~Please update your GTA5 to v1.0.1290 or newer!", true);
_gameLoaded = true;
}
};
return;
2022-05-22 15:55:26 +08:00
}*/
SyncedPedsGroup=World.AddRelationshipGroup("SYNCPED");
Game.Player.Character.RelationshipGroup.SetRelationshipBetweenGroups(SyncedPedsGroup, Relationship.Neutral, true);
Settings = Util.ReadSettings();
MainNetworking = new Networking();
2022-05-22 15:55:26 +08:00
MainNetworking.Start();
#if !NON_INTERACTIVE
MainMenu = new MenusMain();
#endif
MainChat = new Chat();
2022-05-22 15:55:26 +08:00
Logger.LogLevel =0;
2021-07-07 13:36:25 +02:00
Tick += OnTick;
KeyDown += OnKeyDown;
2021-08-21 16:52:17 +02:00
Aborted += (object sender, EventArgs e) => CleanUp();
2022-05-22 15:55:26 +08:00
2021-07-13 16:32:45 +02:00
Util.NativeMemory();
2022-05-22 15:55:26 +08:00
Counter.Restart();
2021-07-07 13:36:25 +02:00
}
2022-05-22 15:55:26 +08:00
#if DEBUG
private ulong _lastDebugData;
private int _debugBytesSend;
private int _debugBytesReceived;
#endif
2021-07-07 13:36:25 +02:00
private void OnTick(object sender, EventArgs e)
{
if (Game.IsLoading)
{
return;
}
else if (!_gameLoaded && (_gameLoaded = true))
2021-07-07 13:36:25 +02:00
{
#if !NON_INTERACTIVE
2022-04-06 02:18:24 +02:00
GTA.UI.Notification.Show(GTA.UI.NotificationIcon.AllPlayersConf, "RAGECOOP", "Welcome!", "Press ~g~F9~s~ to open the menu.");
#endif
2021-07-07 13:36:25 +02:00
}
#if !NON_INTERACTIVE
MainMenu.MenuPool.Process();
#endif
2022-05-22 15:55:26 +08:00
2021-07-07 13:36:25 +02:00
if (_isGoingToCar && Game.Player.Character.IsInVehicle())
2021-07-13 08:30:10 +02:00
{
_isGoingToCar = false;
2021-07-13 08:30:10 +02:00
}
2022-05-22 15:55:26 +08:00
DoQueuedActions();
2021-07-07 13:36:25 +02:00
if (!MainNetworking.IsOnServer())
{
return;
}
2022-05-22 15:55:26 +08:00
if (Game.TimeScale!=1)
2022-04-11 15:10:27 +02:00
{
2022-05-22 15:55:26 +08:00
Game.TimeScale=1;
2022-04-11 15:10:27 +02:00
}
2022-05-22 15:55:26 +08:00
try
{
2022-05-22 15:55:26 +08:00
MainNetworking.Tick();
}
catch (Exception ex)
{
Logger.Error(ex);
}
if (!DownloadManager.DownloadComplete)
{
DownloadManager.RenderProgress();
}
2022-05-22 15:55:26 +08:00
MapLoader.LoadAll();
2021-08-18 11:47:59 +02:00
#if DEBUG
if (MainNetworking.ShowNetworkInfo)
{
ulong time = Util.GetTickCount64();
if (time - _lastDebugData > 1000)
{
_lastDebugData = time;
_debugBytesReceived = MainNetworking.BytesReceived;
MainNetworking.BytesReceived = 0;
_debugBytesSend = MainNetworking.BytesSend;
MainNetworking.BytesSend = 0;
}
2021-08-18 11:47:59 +02:00
new LemonUI.Elements.ScaledText(new PointF(Screen.PrimaryScreen.Bounds.Width / 2, 0), $"L: {MainNetworking.Latency * 1000:N0}ms", 0.5f) { Alignment = GTA.UI.Alignment.Center }.Draw();
new LemonUI.Elements.ScaledText(new PointF(Screen.PrimaryScreen.Bounds.Width / 2, 30), $"R: {Lidgren.Network.NetUtility.ToHumanReadable(_debugBytesReceived)}/s", 0.5f) { Alignment = GTA.UI.Alignment.Center }.Draw();
new LemonUI.Elements.ScaledText(new PointF(Screen.PrimaryScreen.Bounds.Width / 2, 60), $"S: {Lidgren.Network.NetUtility.ToHumanReadable(_debugBytesSend)}/s", 0.5f) { Alignment = GTA.UI.Alignment.Center }.Draw();
2021-08-18 11:47:59 +02:00
}
#endif
2022-05-22 15:55:26 +08:00
2021-07-07 13:36:25 +02:00
MainChat.Tick();
2022-03-28 14:49:26 +02:00
MainPlayerList.Tick();
2021-07-07 13:36:25 +02:00
2021-08-18 11:47:59 +02:00
#if DEBUG
2021-07-07 13:36:25 +02:00
if (UseDebug)
{
Debug();
}
2021-08-18 11:47:59 +02:00
#endif
2021-07-07 13:36:25 +02:00
2022-05-22 15:55:26 +08:00
Ticked++;
2021-07-07 13:36:25 +02:00
}
#if !NON_INTERACTIVE
2022-05-22 15:55:26 +08:00
bool _lastEnteringVeh=false;
2021-07-07 13:36:25 +02:00
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (MainChat.Focused)
{
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);
return;
}
2021-07-07 13:36:25 +02:00
switch (e.KeyCode)
{
case Keys.F9:
if (MainMenu.MenuPool.AreAnyVisible)
2021-07-07 13:36:25 +02:00
{
MainMenu.MainMenu.Visible = false;
MainMenu.SubSettings.MainMenu.Visible = false;
2021-07-07 13:36:25 +02:00
}
else
{
MainMenu.MainMenu.Visible = true;
2021-07-07 13:36:25 +02:00
}
break;
2022-05-22 15:55:26 +08:00
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());
2021-07-13 08:30:10 +02:00
break;
2021-09-28 14:44:10 +02:00
default:
if (Game.IsControlJustPressed(GTA.Control.MultiplayerInfo))
{
if (MainNetworking.IsOnServer())
{
2021-11-19 22:08:15 +01:00
ulong currentTimestamp = Util.GetTickCount64();
2022-03-28 14:49:26 +02:00
MainPlayerList.Pressed = (currentTimestamp - MainPlayerList.Pressed) < 5000 ? (currentTimestamp - 6000) : currentTimestamp;
2021-09-28 14:44:10 +02:00
}
}
else if (Game.IsControlJustPressed(GTA.Control.MpTextChatAll))
{
if (MainNetworking.IsOnServer())
{
MainChat.Focused = true;
}
}
break;
2021-07-07 13:36:25 +02:00
}
2022-05-22 15:55:26 +08:00
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;
}
}
}
2021-07-07 13:36:25 +02:00
}
#else
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (MainChat.Focused)
{
MainChat.OnKeyDown(e.KeyCode);
return;
}
if (Game.IsControlJustPressed(GTA.Control.MultiplayerInfo))
{
if (MainNetworking.IsOnServer())
{
ulong currentTimestamp = Util.GetTickCount64();
PlayerList.Pressed = (currentTimestamp - PlayerList.Pressed) < 5000 ? (currentTimestamp - 6000) : currentTimestamp;
}
}
else if (Game.IsControlJustPressed(GTA.Control.MpTextChatAll))
{
if (MainNetworking.IsOnServer())
{
MainChat.Focused = true;
}
}
}
#endif
2021-07-07 13:36:25 +02:00
2022-05-22 15:55:26 +08:00
public static void CleanUp()
{
2021-08-18 11:47:59 +02:00
2022-05-22 15:55:26 +08:00
MainChat.Clear();
EntityPool.Cleanup();
MainPlayerList=new PlayerList();
2022-05-22 15:55:26 +08:00
Main.MyPlayerID=default;
}
2022-05-22 15:55:26 +08:00
public static readonly Dictionary<ulong, byte> CheckNativeHash = new Dictionary<ulong, byte>()
{
{ 0xD49F9B0955C367DE, 1 }, // Entities
{ 0xEF29A16337FACADB, 1 }, //
{ 0xB4AC7D0CF06BFE8F, 1 }, //
{ 0x9B62392B474F44A0, 1 }, //
{ 0x7DD959874C1FD534, 1 }, //
{ 0xAF35D0D2583051B0, 2 }, // Vehicles
{ 0x63C6CCA8E68AE8C8, 2 }, //
{ 0x509D5878EB39E842, 3 }, // Props
{ 0x9A294B2138ABB884, 3 }, //
{ 0x46818D79B1F7499A, 4 }, // Blips
{ 0x5CDE92C702A8FCE7, 4 }, //
{ 0xBE339365C863BD36, 4 }, //
{ 0x5A039BB0BCA604B6, 4 }, //
{ 0x0134F0835AB6BFCB, 5 } // Checkpoints
};
2022-05-22 15:55:26 +08:00
public static Dictionary<int, byte> ServerItems = new Dictionary<int, byte>();
public static void CleanUpWorld()
{
if (ServerItems.Count == 0)
{
return;
}
lock (ServerItems)
{
foreach (KeyValuePair<int, byte> item in ServerItems)
{
try
{
switch (item.Value)
{
case 1:
World.GetAllEntities().FirstOrDefault(x => x.Handle == item.Key)?.Delete();
break;
case 2:
World.GetAllVehicles().FirstOrDefault(x => x.Handle == item.Key)?.Delete();
break;
case 3:
World.GetAllProps().FirstOrDefault(x => x.Handle == item.Key)?.Delete();
break;
case 4:
Blip blip = new Blip(item.Key);
if (blip.Exists())
{
blip.Delete();
}
break;
case 5:
Checkpoint checkpoint = new Checkpoint(item.Key);
if (checkpoint.Exists())
{
checkpoint.Delete();
}
break;
}
}
catch
{
2022-03-29 00:28:57 +02:00
GTA.UI.Notification.Show("~r~~h~CleanUpWorld() Error");
2022-05-22 15:55:26 +08:00
Logger.Error($"CleanUpWorld(): ~r~Item {item.Value} cannot be deleted!");
}
}
ServerItems.Clear();
}
}
2022-05-22 15:55:26 +08:00
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;
}
2021-08-22 13:59:15 +02:00
#if DEBUG
private ulong _artificialLagCounter;
2022-05-22 15:55:26 +08:00
public static EntitiesPlayer DebugSyncPed;
public static ulong LastFullDebugSync = 0;
public static bool UseDebug = false;
2021-07-07 13:36:25 +02:00
private void Debug()
{
2021-08-13 15:20:26 +02:00
Ped player = Game.Player.Character;
2021-08-16 14:03:05 +02:00
if (!Players.ContainsKey(0))
2021-07-07 13:36:25 +02:00
{
Players.Add(0, new EntitiesPlayer() { Username = "DebugPlayer" });
2021-08-16 14:03:05 +02:00
DebugSyncPed = Players[0];
2021-07-07 13:36:25 +02:00
}
if ((Util.GetTickCount64() - _artificialLagCounter) < 147)
2021-07-07 13:36:25 +02:00
{
return;
}
2021-07-07 13:36:25 +02:00
2022-04-08 22:30:34 +02:00
bool fullSync = (Util.GetTickCount64() - LastFullDebugSync) > 39;
2021-08-15 11:33:52 +02:00
if (fullSync)
{
DebugSyncPed.ModelHash = player.Model.Hash;
DebugSyncPed.Clothes = player.GetPedClothes();
}
DebugSyncPed.Health = player.Health;
DebugSyncPed.Position = player.Position;
ushort? flags;
2021-07-10 23:41:28 +02:00
2021-12-13 20:35:07 +01:00
if (player.IsInVehicle())
{
2021-12-13 20:35:07 +01:00
Vehicle veh = player.CurrentVehicle;
2021-07-12 07:06:52 +02:00
veh.Opacity = 75;
flags = player.GetVehicleFlags(veh);
2021-07-10 23:41:28 +02:00
byte secondaryColor;
byte primaryColor;
2021-08-13 15:52:30 +02:00
unsafe
{
Function.Call<byte>(Hash.GET_VEHICLE_COLOURS, veh, &primaryColor, &secondaryColor);
2021-08-13 15:52:30 +02:00
}
DebugSyncPed.VehicleModelHash = veh.Model.Hash;
DebugSyncPed.VehicleSeatIndex = (short)player.SeatIndex;
DebugSyncPed.Position = veh.Position;
DebugSyncPed.VehicleRotation = veh.Quaternion;
2021-08-17 15:04:50 +02:00
DebugSyncPed.VehicleEngineHealth = veh.EngineHealth;
DebugSyncPed.VehRPM = veh.CurrentRPM;
DebugSyncPed.Velocity = veh.Velocity;
2021-07-10 10:52:43 +02:00
DebugSyncPed.VehicleSpeed = veh.Speed;
2021-07-13 16:30:33 +02:00
DebugSyncPed.VehicleSteeringAngle = veh.SteeringAngle;
DebugSyncPed.AimCoords = veh.IsTurretSeat((int)player.SeatIndex) ? Util.GetVehicleAimCoords() : new GTA.Math.Vector3();
DebugSyncPed.VehicleColors = new byte[] { primaryColor, secondaryColor };
DebugSyncPed.VehicleMods = veh.Mods.GetVehicleMods();
DebugSyncPed.VehDamageModel = veh.GetVehicleDamageModel();
DebugSyncPed.LastSyncWasFull = true;
2021-11-19 09:24:06 +01:00
DebugSyncPed.IsInVehicle = true;
DebugSyncPed.VehIsEngineRunning = (flags.Value & (ushort)VehicleDataFlags.IsEngineRunning) > 0;
DebugSyncPed.VehAreLightsOn = (flags.Value & (ushort)VehicleDataFlags.AreLightsOn) > 0;
2022-01-01 17:24:55 +01:00
DebugSyncPed.VehAreBrakeLightsOn = (flags.Value & (ushort)VehicleDataFlags.AreBrakeLightsOn) > 0;
DebugSyncPed.VehAreHighBeamsOn = (flags.Value & (ushort)VehicleDataFlags.AreHighBeamsOn) > 0;
DebugSyncPed.VehIsSireneActive = (flags.Value & (ushort)VehicleDataFlags.IsSirenActive) > 0;
DebugSyncPed.VehicleDead = (flags.Value & (ushort)VehicleDataFlags.IsDead) > 0;
DebugSyncPed.IsHornActive = (flags.Value & (ushort)VehicleDataFlags.IsHornActive) > 0;
DebugSyncPed.Transformed = (flags.Value & (ushort)VehicleDataFlags.IsTransformed) > 0;
DebugSyncPed.VehRoofOpened = (flags.Value & (ushort)VehicleDataFlags.RoofOpened) > 0;
2021-12-14 14:46:10 +01:00
DebugSyncPed.VehLandingGear = veh.IsPlane ? (byte)veh.LandingGearState : (byte)0;
2022-01-01 17:24:55 +01:00
2021-08-04 18:54:56 +02:00
if (DebugSyncPed.MainVehicle != null && DebugSyncPed.MainVehicle.Exists() && player.IsInVehicle())
{
Function.Call(Hash.SET_ENTITY_NO_COLLISION_ENTITY, DebugSyncPed.MainVehicle.Handle, veh.Handle, false);
Function.Call(Hash.SET_ENTITY_NO_COLLISION_ENTITY, veh.Handle, DebugSyncPed.MainVehicle.Handle, false);
}
}
else
{
flags = player.GetPedFlags(true);
DebugSyncPed.Rotation = player.Rotation;
DebugSyncPed.Velocity = player.Velocity;
DebugSyncPed.Speed = player.GetPedSpeed();
DebugSyncPed.AimCoords = player.GetPedAimCoords(false);
DebugSyncPed.CurrentWeaponHash = (uint)player.Weapons.Current.Hash;
DebugSyncPed.WeaponComponents = player.Weapons.Current.GetWeaponComponents();
DebugSyncPed.LastSyncWasFull = true;
DebugSyncPed.IsAiming = (flags.Value & (ushort)PedDataFlags.IsAiming) > 0;
DebugSyncPed.IsShooting = (flags.Value & (ushort)PedDataFlags.IsShooting) > 0;
DebugSyncPed.IsReloading = (flags.Value & (ushort)PedDataFlags.IsReloading) > 0;
DebugSyncPed.IsJumping = (flags.Value & (ushort)PedDataFlags.IsJumping) > 0;
DebugSyncPed.IsRagdoll = (flags.Value & (ushort)PedDataFlags.IsRagdoll) > 0;
DebugSyncPed.IsOnFire = (flags.Value & (ushort)PedDataFlags.IsOnFire) > 0;
DebugSyncPed.IsInParachuteFreeFall = (flags.Value & (ushort)PedDataFlags.IsInParachuteFreeFall) > 0;
2022-01-01 04:16:24 +01:00
DebugSyncPed.IsParachuteOpen = (flags.Value & (ushort)PedDataFlags.IsParachuteOpen) > 0;
DebugSyncPed.IsOnLadder = (flags.Value & (ushort)PedDataFlags.IsOnLadder) > 0;
DebugSyncPed.IsVaulting = (flags.Value & (ushort)PedDataFlags.IsVaulting) > 0;
DebugSyncPed.IsInVehicle = false;
if (DebugSyncPed.Character != null && DebugSyncPed.Character.Exists())
{
Function.Call(Hash.SET_ENTITY_NO_COLLISION_ENTITY, DebugSyncPed.Character.Handle, player.Handle, false);
Function.Call(Hash.SET_ENTITY_NO_COLLISION_ENTITY, player.Handle, DebugSyncPed.Character.Handle, false);
2021-08-04 18:54:56 +02:00
}
}
2021-11-19 22:08:15 +01:00
ulong currentTimestamp = Util.GetTickCount64();
2021-08-15 11:33:52 +02:00
DebugSyncPed.LastUpdateReceived = currentTimestamp;
DebugSyncPed.Latency = (currentTimestamp - _artificialLagCounter) / 1000f;
2021-08-15 11:33:52 +02:00
_artificialLagCounter = currentTimestamp;
2021-08-13 15:20:26 +02:00
2021-08-15 11:33:52 +02:00
if (fullSync)
{
LastFullDebugSync = currentTimestamp;
}
2021-07-07 13:36:25 +02:00
}
2021-08-22 13:59:15 +02:00
#endif
2021-07-07 13:36:25 +02:00
}
}