stuff
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
**/bin
|
||||
**/obj
|
||||
**/packages
|
||||
.vs/*
|
||||
**/.vs
|
@ -143,19 +143,22 @@ namespace CoopClient
|
||||
|
||||
if (!characterExist)
|
||||
{
|
||||
CreateCharacter(username);
|
||||
if (!CreateCharacter(username))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (LastSyncWasFull)
|
||||
{
|
||||
if (ModelHash != LastModelHash)
|
||||
{
|
||||
if (characterExist)
|
||||
{
|
||||
Character.Kill();
|
||||
Character.Delete();
|
||||
}
|
||||
Character.Kill();
|
||||
Character.Delete();
|
||||
|
||||
CreateCharacter(username);
|
||||
if (!CreateCharacter(username))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (Props != LastProps)
|
||||
{
|
||||
@ -232,30 +235,45 @@ namespace CoopClient
|
||||
|
||||
private void DisplayInVehicle()
|
||||
{
|
||||
if (MainVehicle == null || !MainVehicle.Exists() || MainVehicle.Model.Hash != VehicleModelHash)
|
||||
try
|
||||
{
|
||||
List<Vehicle> vehs = World.GetNearbyVehicles(Character, 7f, new Model[] { VehicleModelHash }).OrderBy(v => (v.Position - Character.Position).Length()).Take(3).ToList();
|
||||
|
||||
bool vehFound = false;
|
||||
|
||||
foreach (Vehicle veh in vehs)
|
||||
if (MainVehicle == null || !MainVehicle.Exists() || MainVehicle.Model.Hash != VehicleModelHash)
|
||||
{
|
||||
if (veh.IsSeatFree((VehicleSeat)VehicleSeatIndex))
|
||||
bool vehFound = false;
|
||||
|
||||
List<Vehicle> vehs = World.GetNearbyVehicles(Character, 7f, new Model[] { VehicleModelHash }).OrderBy(v => (v.Position - Character.Position).Length()).Take(3).ToList();
|
||||
|
||||
foreach (Vehicle veh in vehs)
|
||||
{
|
||||
MainVehicle = veh;
|
||||
vehFound = true;
|
||||
break;
|
||||
if (veh.IsSeatFree((VehicleSeat)VehicleSeatIndex))
|
||||
{
|
||||
MainVehicle = veh;
|
||||
vehFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vehFound)
|
||||
{
|
||||
Model vehicleModel = Util.ModelRequest(VehicleModelHash);
|
||||
if (vehicleModel == null)
|
||||
{
|
||||
GTA.UI.Notification.Show($"~r~Model ({VehicleModelHash}) cannot be loaded!");
|
||||
return;
|
||||
}
|
||||
|
||||
MainVehicle = World.CreateVehicle(vehicleModel, VehiclePosition);
|
||||
MainVehicle.Quaternion = VehicleRotation;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vehFound)
|
||||
{
|
||||
MainVehicle = World.CreateVehicle(new Model(VehicleModelHash), VehiclePosition);
|
||||
MainVehicle.Quaternion = VehicleRotation;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
GTA.UI.Notification.Show("~r~" + e.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Character.IsInVehicle() || (int)Character.SeatIndex != VehicleSeatIndex || Character.CurrentVehicle.Model.Hash != VehicleModelHash)
|
||||
if (!Character.IsInVehicle() || (int)Character.SeatIndex != VehicleSeatIndex || Character.CurrentVehicle?.Model.Hash != VehicleModelHash)
|
||||
{
|
||||
if (VehicleSeatIndex == -1 &&
|
||||
Game.Player.Character.IsInVehicle() &&
|
||||
@ -573,12 +591,20 @@ namespace CoopClient
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateCharacter(string username)
|
||||
private bool CreateCharacter(string username)
|
||||
{
|
||||
LastModelHash = ModelHash;
|
||||
LastProps = Props;
|
||||
|
||||
Character = World.CreatePed(new Model(ModelHash), Position, Rotation.Z);
|
||||
Model characterModel = Util.ModelRequest(ModelHash);
|
||||
|
||||
if (characterModel == null)
|
||||
{
|
||||
GTA.UI.Notification.Show($"~r~Model ({ModelHash}) cannot be loaded!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Character = World.CreatePed(characterModel, Position, Rotation.Z);
|
||||
Character.RelationshipGroup = Main.RelationshipGroup;
|
||||
if (IsInVehicle)
|
||||
{
|
||||
@ -606,6 +632,8 @@ namespace CoopClient
|
||||
{
|
||||
Function.Call(Hash.SET_PED_COMPONENT_VARIATION, Character.Handle, prop.Key, prop.Value, 0, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool LastMoving;
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
using CoopClient.Entities;
|
||||
using CoopClient.Menus;
|
||||
@ -20,16 +21,18 @@ namespace CoopClient
|
||||
public static readonly string CurrentModVersion = "V0_5_0";
|
||||
|
||||
public static bool ShareNpcsWithPlayers = false;
|
||||
public static bool DisableTraffic = false;
|
||||
public static bool NpcsAllowed = false;
|
||||
private static bool IsGoingToCar = false;
|
||||
|
||||
public static Settings MainSettings = Util.ReadSettings();
|
||||
|
||||
public static MenusMain MainMenu = new MenusMain();
|
||||
public static Chat MainChat = new Chat();
|
||||
|
||||
public static Networking MainNetworking = new Networking();
|
||||
|
||||
public static MenusMain MainMenu = new MenusMain();
|
||||
|
||||
public static Chat MainChat = new Chat();
|
||||
|
||||
public static long LocalPlayerID = 0;
|
||||
public static readonly Dictionary<long, EntitiesPlayer> Players = new Dictionary<long, EntitiesPlayer>();
|
||||
public static readonly Dictionary<long, EntitiesNpc> Npcs = new Dictionary<long, EntitiesNpc>();
|
||||
@ -73,6 +76,15 @@ namespace CoopClient
|
||||
return;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if (MainNetworking.ShowNetworkInfo)
|
||||
{
|
||||
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: {MainNetworking.BytesReceived} bytes", 0.5f) { Alignment = GTA.UI.Alignment.Center }.Draw();
|
||||
new LemonUI.Elements.ScaledText(new PointF(Screen.PrimaryScreen.Bounds.Width / 2, 60), $"S: {MainNetworking.BytesSend} bytes", 0.5f) { Alignment = GTA.UI.Alignment.Center }.Draw();
|
||||
}
|
||||
#endif
|
||||
|
||||
MainChat.Tick();
|
||||
|
||||
// Display all players
|
||||
@ -81,10 +93,12 @@ namespace CoopClient
|
||||
player.Value.DisplayLocally(player.Value.Username);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if (UseDebug)
|
||||
{
|
||||
Debug();
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((Environment.TickCount - LastDataSend) >= (1000 / 60))
|
||||
{
|
||||
@ -156,25 +170,13 @@ namespace CoopClient
|
||||
|
||||
private void OnAbort(object sender, EventArgs e)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<long, EntitiesNpc> Npc in Npcs)
|
||||
{
|
||||
Npc.Value.Character?.CurrentVehicle?.Delete();
|
||||
Npc.Value.Character?.Kill();
|
||||
Npc.Value.Character?.Delete();
|
||||
}
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
public static void CleanUp()
|
||||
{
|
||||
MainChat.Clear();
|
||||
|
||||
foreach (KeyValuePair<long, EntitiesPlayer> player in Players)
|
||||
{
|
||||
player.Value.Character?.AttachedBlip?.Delete();
|
||||
@ -193,33 +195,15 @@ namespace CoopClient
|
||||
}
|
||||
Npcs.Clear();
|
||||
|
||||
foreach (Ped entity in World.GetAllPeds())
|
||||
foreach (Ped entity in World.GetAllPeds().Where(p => p.Handle != Game.Player.Character.Handle))
|
||||
{
|
||||
if (entity.Handle != Game.Player.Character.Handle)
|
||||
{
|
||||
entity.Kill();
|
||||
entity.Delete();
|
||||
}
|
||||
entity.Kill();
|
||||
entity.Delete();
|
||||
}
|
||||
|
||||
if (!Game.Player.Character.IsInVehicle())
|
||||
foreach (Vehicle veh in World.GetAllVehicles().Where(v => v.Handle != Game.Player.Character.Handle))
|
||||
{
|
||||
foreach (Vehicle vehicle in World.GetAllVehicles())
|
||||
{
|
||||
vehicle.Delete();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int? playerVehicleHandle = Game.Player.Character.CurrentVehicle?.Handle;
|
||||
|
||||
foreach (Vehicle vehicle in World.GetAllVehicles())
|
||||
{
|
||||
if (playerVehicleHandle != vehicle.Handle)
|
||||
{
|
||||
vehicle.Delete();
|
||||
}
|
||||
}
|
||||
veh.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,26 +9,32 @@ namespace CoopClient.Menus.Sub
|
||||
UseMouse = false,
|
||||
Alignment = Main.MainSettings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
|
||||
};
|
||||
|
||||
|
||||
private readonly NativeCheckboxItem DisableTraffic = new NativeCheckboxItem("Disable Traffic", Main.DisableTraffic);
|
||||
private readonly NativeCheckboxItem ShareNpcsItem = new NativeCheckboxItem("Share Npcs", Main.ShareNpcsWithPlayers) { Enabled = false };
|
||||
private readonly NativeSliderItem StreamedNpcsItem = new NativeSliderItem(string.Format("Streamed Npcs ({0})", Main.MainSettings.StreamedNpc), 20, Main.MainSettings.StreamedNpc);
|
||||
private readonly NativeCheckboxItem FlipMenuItem = new NativeCheckboxItem("Flip menu", Main.MainSettings.FlipMenu);
|
||||
private readonly NativeCheckboxItem UseDebugItem = new NativeCheckboxItem("Debug", Main.UseDebug);
|
||||
private readonly NativeCheckboxItem ShowNetworkInfo = new NativeCheckboxItem("Show Network Info", Main.MainNetworking.ShowNetworkInfo);
|
||||
|
||||
public Settings()
|
||||
{
|
||||
DisableTraffic.CheckboxChanged += DisableTrafficCheckboxChanged;
|
||||
ShareNpcsItem.CheckboxChanged += (item, check) => { Main.ShareNpcsWithPlayers = ShareNpcsItem.Checked; };
|
||||
StreamedNpcsItem.ValueChanged += StreamedNpcsValueChanged;
|
||||
FlipMenuItem.CheckboxChanged += FlipMenuCheckboxChanged;
|
||||
#if DEBUG
|
||||
UseDebugItem.CheckboxChanged += UseDebugCheckboxChanged;
|
||||
ShowNetworkInfo.CheckboxChanged += ShowNetworkInfoCheckboxChanged;
|
||||
#endif
|
||||
|
||||
MainMenu.Add(DisableTraffic);
|
||||
MainMenu.Add(ShareNpcsItem);
|
||||
MainMenu.Add(StreamedNpcsItem);
|
||||
MainMenu.Add(FlipMenuItem);
|
||||
#if DEBUG
|
||||
MainMenu.Add(UseDebugItem);
|
||||
MainMenu.Add(ShowNetworkInfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -65,5 +71,35 @@ namespace CoopClient.Menus.Sub
|
||||
Main.Players.Remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowNetworkInfoCheckboxChanged(object a, System.EventArgs b)
|
||||
{
|
||||
Main.MainNetworking.ShowNetworkInfo = ShowNetworkInfo.Checked;
|
||||
|
||||
if (!Main.MainNetworking.ShowNetworkInfo)
|
||||
{
|
||||
Main.MainNetworking.BytesReceived = 0;
|
||||
Main.MainNetworking.BytesSend = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void DisableTrafficCheckboxChanged(object a, System.EventArgs b)
|
||||
{
|
||||
Main.DisableTraffic = DisableTraffic.Checked;
|
||||
|
||||
if (DisableTraffic.Checked)
|
||||
{
|
||||
if (ShareNpcsItem.Checked)
|
||||
{
|
||||
ShareNpcsItem.Checked = false;
|
||||
}
|
||||
|
||||
ShareNpcsItem.Enabled = false;
|
||||
}
|
||||
else if (Main.NpcsAllowed && !ShareNpcsItem.Enabled)
|
||||
{
|
||||
ShareNpcsItem.Enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,11 @@ namespace CoopClient
|
||||
public NetClient Client;
|
||||
public float Latency;
|
||||
|
||||
public bool ShowNetworkInfo = false;
|
||||
|
||||
public int BytesReceived = 0;
|
||||
public int BytesSend = 0;
|
||||
|
||||
public void DisConnectFromServer(string address)
|
||||
{
|
||||
if (IsOnServer())
|
||||
@ -72,6 +77,8 @@ namespace CoopClient
|
||||
|
||||
while ((message = Client.ReadMessage()) != null)
|
||||
{
|
||||
BytesReceived += message.LengthBytes;
|
||||
|
||||
switch (message.MessageType)
|
||||
{
|
||||
case NetIncomingMessageType.StatusChanged:
|
||||
@ -125,7 +132,7 @@ namespace CoopClient
|
||||
|
||||
Main.MainMenu.MainMenu.Items[2].Enabled = true;
|
||||
Main.MainMenu.MainMenu.Items[2].Title = "Disconnect";
|
||||
Main.MainMenu.SubSettings.MainMenu.Items[0].Enabled = Main.NpcsAllowed;
|
||||
Main.MainMenu.SubSettings.MainMenu.Items[1].Enabled = !Main.DisableTraffic && Main.NpcsAllowed;
|
||||
|
||||
Main.MainMenu.MainMenu.Visible = false;
|
||||
Main.MainMenu.MenuPool.RefreshAll();
|
||||
@ -144,15 +151,13 @@ namespace CoopClient
|
||||
Main.MainChat.Focused = false;
|
||||
}
|
||||
|
||||
Main.MainChat.Clear();
|
||||
|
||||
Main.CleanUp();
|
||||
|
||||
Main.MainMenu.MainMenu.Items[0].Enabled = true;
|
||||
Main.MainMenu.MainMenu.Items[1].Enabled = true;
|
||||
Main.MainMenu.MainMenu.Items[2].Enabled = true;
|
||||
Main.MainMenu.MainMenu.Items[2].Title = "Connect";
|
||||
Main.MainMenu.SubSettings.MainMenu.Items[0].Enabled = false;
|
||||
Main.MainMenu.SubSettings.MainMenu.Items[1].Enabled = false;
|
||||
|
||||
Main.MainMenu.MenuPool.RefreshAll();
|
||||
break;
|
||||
@ -654,6 +659,13 @@ namespace CoopClient
|
||||
|
||||
Client.SendMessage(outgoingMessage, messageType);
|
||||
Client.FlushSendQueue();
|
||||
|
||||
#if DEBUG
|
||||
if (ShowNetworkInfo)
|
||||
{
|
||||
BytesSend += outgoingMessage.LengthBytes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SendNpcData(Ped npc)
|
||||
@ -710,6 +722,13 @@ namespace CoopClient
|
||||
|
||||
Client.SendMessage(outgoingMessage, NetDeliveryMethod.Unreliable);
|
||||
Client.FlushSendQueue();
|
||||
|
||||
#if DEBUG
|
||||
if (ShowNetworkInfo)
|
||||
{
|
||||
BytesSend += outgoingMessage.LengthBytes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SendChatMessage(string message)
|
||||
@ -722,6 +741,13 @@ namespace CoopClient
|
||||
}.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableOrdered);
|
||||
Client.FlushSendQueue();
|
||||
|
||||
#if DEBUG
|
||||
if (ShowNetworkInfo)
|
||||
{
|
||||
BytesSend += outgoingMessage.LengthBytes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
@ -79,6 +79,26 @@ namespace CoopClient
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static Model ModelRequest(int hash)
|
||||
{
|
||||
Model model = new Model(hash);
|
||||
short counter = 0;
|
||||
|
||||
while (counter++ < 1000)
|
||||
{
|
||||
model.Request();
|
||||
|
||||
Script.Yield();
|
||||
|
||||
if (model.IsLoaded)
|
||||
{
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool IsBetween<T>(this T item, T start, T end)
|
||||
{
|
||||
return Comparer<T>.Default.Compare(item, start) >= 0 && Comparer<T>.Default.Compare(item, end) <= 0;
|
||||
@ -438,7 +458,7 @@ namespace CoopClient
|
||||
dir.Normalize();
|
||||
RaycastResult raycastResults = World.Raycast(source3D + dir * raycastFromDist,
|
||||
source3D + dir * raycastToDist,
|
||||
(IntersectFlags)(1 | 16 | 256 | 2 | 4 | 8), // | peds + vehicles
|
||||
IntersectFlags.Everything,
|
||||
ignoreEntity);
|
||||
|
||||
if (raycastResults.DidHit)
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using GTA;
|
||||
using GTA.Native;
|
||||
@ -7,10 +8,19 @@ namespace CoopClient
|
||||
{
|
||||
public class WorldThread : Script
|
||||
{
|
||||
private static bool LastDisableTraffic = false;
|
||||
|
||||
public WorldThread()
|
||||
{
|
||||
Tick += OnTick;
|
||||
Interval = 1000 / 60;
|
||||
Aborted += (sender, e) =>
|
||||
{
|
||||
if (LastDisableTraffic)
|
||||
{
|
||||
Traffic(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void OnTick(object sender, EventArgs e)
|
||||
@ -24,6 +34,75 @@ namespace CoopClient
|
||||
|
||||
Function.Call(Hash.SET_CAN_ATTACK_FRIENDLY, Game.Player.Character.Handle, true, false);
|
||||
Function.Call(Hash.SET_PED_CAN_BE_TARGETTED, Game.Player.Character.Handle, true);
|
||||
|
||||
if (Main.DisableTraffic)
|
||||
{
|
||||
if (!LastDisableTraffic)
|
||||
{
|
||||
Traffic(false);
|
||||
}
|
||||
|
||||
Function.Call(Hash.SET_VEHICLE_POPULATION_BUDGET, 0);
|
||||
Function.Call(Hash.SET_PED_POPULATION_BUDGET, 0);
|
||||
Function.Call(Hash.SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME, 0f);
|
||||
Function.Call(Hash.SET_RANDOM_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME, 0f);
|
||||
Function.Call(Hash.SET_PARKED_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME, 0f);
|
||||
Function.Call((Hash)0x2F9A292AD0A3BD89);
|
||||
Function.Call((Hash)0x5F3B7749C112D552);
|
||||
}
|
||||
else if (LastDisableTraffic)
|
||||
{
|
||||
Traffic(true);
|
||||
}
|
||||
|
||||
LastDisableTraffic = Main.DisableTraffic;
|
||||
}
|
||||
|
||||
private static void Traffic(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
Function.Call(Hash.REMOVE_SCENARIO_BLOCKING_AREAS);
|
||||
Function.Call(Hash.SET_CREATE_RANDOM_COPS, true);
|
||||
Function.Call(Hash.SET_RANDOM_TRAINS, true);
|
||||
Function.Call(Hash.SET_RANDOM_BOATS, true);
|
||||
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_ALL_VEHICLE_GENERATORS_ACTIVE);
|
||||
Function.Call(Hash.SET_ALL_LOW_PRIORITY_VEHICLE_GENERATORS_ACTIVE, true);
|
||||
Function.Call(Hash.SET_NUMBER_OF_PARKED_VEHICLES, -1);
|
||||
Function.Call((Hash)0xF796359A959DF65D, true); // Display distant vehicles
|
||||
Function.Call(Hash.DISABLE_VEHICLE_DISTANTLIGHTS, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Function.Call(Hash.ADD_SCENARIO_BLOCKING_AREA, -10000.0f, -10000.0f, -1000.0f, 10000.0f, 10000.0f, 1000.0f, 0, 1, 1, 1);
|
||||
Function.Call(Hash.SET_CREATE_RANDOM_COPS, false);
|
||||
Function.Call(Hash.SET_RANDOM_TRAINS, false);
|
||||
Function.Call(Hash.SET_RANDOM_BOATS, false);
|
||||
Function.Call(Hash.SET_GARBAGE_TRUCKS, false);
|
||||
Function.Call(Hash.DELETE_ALL_TRAINS);
|
||||
Function.Call(Hash.SET_PED_POPULATION_BUDGET, 0);
|
||||
Function.Call(Hash.SET_VEHICLE_POPULATION_BUDGET, 0);
|
||||
Function.Call(Hash.SET_ALL_LOW_PRIORITY_VEHICLE_GENERATORS_ACTIVE, false);
|
||||
Function.Call(Hash.SET_FAR_DRAW_VEHICLES, false);
|
||||
Function.Call(Hash.SET_NUMBER_OF_PARKED_VEHICLES, 0);
|
||||
Function.Call((Hash)0xF796359A959DF65D, false); //Display distant vehicles
|
||||
Function.Call(Hash.DISABLE_VEHICLE_DISTANTLIGHTS, true);
|
||||
|
||||
foreach (Ped ped in World.GetAllPeds().Where(p => p.RelationshipGroup != "SYNCPED"))
|
||||
{
|
||||
ped.CurrentVehicle?.Delete();
|
||||
ped.Kill();
|
||||
ped.Delete();
|
||||
}
|
||||
|
||||
foreach (Vehicle veh in World.GetAllVehicles().Where(v => v.IsSeatFree(VehicleSeat.Driver) && v.PassengerCount == 0))
|
||||
{
|
||||
veh.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
25
FirstGameMod/FirstGameMode.sln
Normal file
25
FirstGameMod/FirstGameMode.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31605.320
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FirstGameMode", "FirstGameMode\FirstGameMode.csproj", "{212B1A61-0C03-4B0E-A53C-2CC6B667E0DA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{212B1A61-0C03-4B0E-A53C-2CC6B667E0DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{212B1A61-0C03-4B0E-A53C-2CC6B667E0DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{212B1A61-0C03-4B0E-A53C-2CC6B667E0DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{212B1A61-0C03-4B0E-A53C-2CC6B667E0DA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3C329584-BE48-469B-85D8-FD24F47BD033}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
46
FirstGameMod/FirstGameMode/Commands.cs
Normal file
46
FirstGameMod/FirstGameMode/Commands.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System.Linq;
|
||||
|
||||
using CoopServer;
|
||||
|
||||
namespace FirstGameMode
|
||||
{
|
||||
class Commands
|
||||
{
|
||||
[Command("hello")]
|
||||
public static void HelloCommand(CommandContext ctx)
|
||||
{
|
||||
ServerScript.SendChatMessageToPlayer(ctx.Player.Username, "Hello " + ctx.Player.Username + " :)");
|
||||
}
|
||||
|
||||
[Command("inrange")]
|
||||
public static void InRangeCommand(CommandContext ctx)
|
||||
{
|
||||
if (ctx.Player.Ped.IsInRangeOf(new LVector3(0f, 0f, 75f), 7f))
|
||||
{
|
||||
ServerScript.SendChatMessageToPlayer(ctx.Player.Username, "You are in range! :)");
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerScript.SendChatMessageToPlayer(ctx.Player.Username, "You are not in range! :(");
|
||||
}
|
||||
}
|
||||
|
||||
[Command("online")]
|
||||
public static void OnlineCommand(CommandContext ctx)
|
||||
{
|
||||
ServerScript.SendChatMessageToPlayer(ctx.Player.Username, ServerScript.GetAllPlayersCount() + " player online!");
|
||||
}
|
||||
|
||||
[Command("kick")]
|
||||
public static void KickCommand(CommandContext ctx)
|
||||
{
|
||||
if (ctx.Args.Length < 2)
|
||||
{
|
||||
ServerScript.SendChatMessageToPlayer(ctx.Player.Username, "Please use \"/kick <USERNAME> <REASON>\"");
|
||||
return;
|
||||
}
|
||||
|
||||
ServerScript.KickPlayerByUsername(ctx.Args[0], ctx.Args.Skip(1).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
13
FirstGameMod/FirstGameMode/FirstGameMode.csproj
Normal file
13
FirstGameMod/FirstGameMode/FirstGameMode.csproj
Normal file
@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="CoopServer">
|
||||
<HintPath>..\..\Server\bin\Debug\net5.0\CoopServer.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
47
FirstGameMod/FirstGameMode/Main.cs
Normal file
47
FirstGameMod/FirstGameMode/Main.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using CoopServer;
|
||||
using CoopServer.Entities;
|
||||
using System.Timers;
|
||||
|
||||
namespace FirstGameMode
|
||||
{
|
||||
public class Main : ServerScript
|
||||
{
|
||||
private static readonly Timer RunningSinceTimer = new() { Interval = 1000 };
|
||||
private static int RunningSince = 0;
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
RunningSinceTimer.Start();
|
||||
RunningSinceTimer.Elapsed += new ElapsedEventHandler((sender, e) => RunningSince += 1);
|
||||
|
||||
RegisterCommand("running", RunningCommand);
|
||||
RegisterCommands<Commands>();
|
||||
}
|
||||
|
||||
public static void RunningCommand(CommandContext ctx)
|
||||
{
|
||||
SendChatMessageToPlayer(ctx.Player.Username, "Server has been running for: " + RunningSince + " seconds!");
|
||||
}
|
||||
|
||||
public override void OnPlayerConnect(EntitiesPlayer client)
|
||||
{
|
||||
SendChatMessageToAll("Player " + client.Username + " connected!");
|
||||
}
|
||||
|
||||
public override void OnPlayerDisconnect(EntitiesPlayer player, string reason)
|
||||
{
|
||||
SendChatMessageToAll(player.Username + " left the server, reason: " + reason);
|
||||
}
|
||||
|
||||
public override bool OnChatMessage(string username, string message)
|
||||
{
|
||||
if (message.StartsWith("EASTEREGG"))
|
||||
{
|
||||
SendChatMessageToPlayer(username, "You found the EASTEREGG! *-*");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
116
Server/Server.cs
116
Server/Server.cs
@ -32,6 +32,7 @@ namespace CoopServer
|
||||
public static readonly Dictionary<long, EntitiesPlayer> Players = new();
|
||||
|
||||
private static ServerScript GameMode;
|
||||
public static readonly Dictionary<Command, Action<CommandContext>> Commands = new Dictionary<Command, Action<CommandContext>>();
|
||||
|
||||
public Server()
|
||||
{
|
||||
@ -127,12 +128,7 @@ namespace CoopServer
|
||||
#endregion
|
||||
}
|
||||
|
||||
if (MainSettings.DefaultGameMode)
|
||||
{
|
||||
GameMode = new DefaultScript();
|
||||
GameMode.Start();
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(MainSettings.GameMode))
|
||||
if (!string.IsNullOrEmpty(MainSettings.GameMode))
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -381,27 +377,6 @@ namespace CoopServer
|
||||
}
|
||||
}
|
||||
|
||||
// Return a list of all connections but not the local connection
|
||||
private static List<NetConnection> FilterAllLocal(NetConnection local)
|
||||
{
|
||||
return new(MainNetServer.Connections.Where(e => e != local));
|
||||
}
|
||||
private static List<NetConnection> FilterAllLocal(long local)
|
||||
{
|
||||
return new(MainNetServer.Connections.Where(e => e.RemoteUniqueIdentifier != local));
|
||||
}
|
||||
|
||||
// Return a list of players within range of ...
|
||||
private static List<NetConnection> GetAllInRange(LVector3 position, float range)
|
||||
{
|
||||
return new(MainNetServer.Connections.FindAll(e => Players[e.RemoteUniqueIdentifier].Ped.IsInRangeOf(position, range)));
|
||||
}
|
||||
// Return a list of players within range of ... but not the local one
|
||||
private static List<NetConnection> GetAllInRange(LVector3 position, float range, NetConnection local)
|
||||
{
|
||||
return new(MainNetServer.Connections.Where(e => e != local && Players[e.RemoteUniqueIdentifier].Ped.IsInRangeOf(position, range)));
|
||||
}
|
||||
|
||||
#region -- PLAYER --
|
||||
// Before we approve the connection, we must shake hands
|
||||
private void GetHandshake(NetConnection local, HandshakePacket packet)
|
||||
@ -504,7 +479,7 @@ namespace CoopServer
|
||||
GameMode.OnPlayerConnect(Players[packet.Player]);
|
||||
}
|
||||
|
||||
List<NetConnection> playerList = FilterAllLocal(local);
|
||||
List<NetConnection> playerList = Util.FilterAllLocal(local);
|
||||
if (playerList.Count == 0)
|
||||
{
|
||||
return;
|
||||
@ -546,7 +521,7 @@ namespace CoopServer
|
||||
GameMode.OnPlayerDisconnect(Players[packet.Player], reason);
|
||||
}
|
||||
|
||||
List<NetConnection> playerList = FilterAllLocal(packet.Player);
|
||||
List<NetConnection> playerList = Util.FilterAllLocal(packet.Player);
|
||||
if (playerList.Count != 0)
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
@ -563,7 +538,7 @@ namespace CoopServer
|
||||
|
||||
player.Ped.Position = packet.Extra.Position;
|
||||
|
||||
List<NetConnection> playerList = FilterAllLocal(packet.Extra.Player);
|
||||
List<NetConnection> playerList = Util.FilterAllLocal(packet.Extra.Player);
|
||||
if (playerList.Count == 0)
|
||||
{
|
||||
return;
|
||||
@ -585,7 +560,7 @@ namespace CoopServer
|
||||
|
||||
player.Ped.Position = packet.Extra.Position;
|
||||
|
||||
List<NetConnection> playerList = FilterAllLocal(packet.Extra.Player);
|
||||
List<NetConnection> playerList = Util.FilterAllLocal(packet.Extra.Player);
|
||||
if (playerList.Count == 0)
|
||||
{
|
||||
return;
|
||||
@ -607,7 +582,7 @@ namespace CoopServer
|
||||
|
||||
player.Ped.Position = packet.Extra.Position;
|
||||
|
||||
List<NetConnection> playerList = FilterAllLocal(packet.Extra.Player);
|
||||
List<NetConnection> playerList = Util.FilterAllLocal(packet.Extra.Player);
|
||||
if (playerList.Count == 0)
|
||||
{
|
||||
return;
|
||||
@ -629,7 +604,7 @@ namespace CoopServer
|
||||
|
||||
player.Ped.Position = packet.Extra.Position;
|
||||
|
||||
List<NetConnection> playerList = FilterAllLocal(packet.Extra.Player);
|
||||
List<NetConnection> playerList = Util.FilterAllLocal(packet.Extra.Player);
|
||||
if (playerList.Count == 0)
|
||||
{
|
||||
return;
|
||||
@ -648,25 +623,62 @@ namespace CoopServer
|
||||
// Send a message to targets or all players
|
||||
private static void SendChatMessage(ChatMessagePacket packet, List<NetConnection> targets = null)
|
||||
{
|
||||
if (GameMode != null && GameMode.OnChatMessage(packet.Username, packet.Message))
|
||||
NetOutgoingMessage outgoingMessage;
|
||||
|
||||
if (GameMode != null)
|
||||
{
|
||||
return;
|
||||
if (packet.Message.StartsWith("/"))
|
||||
{
|
||||
string[] cmdArgs = packet.Message.Split(" ");
|
||||
string cmdName = cmdArgs[0].Remove(0, 1);
|
||||
if (Commands.Any(x => x.Key.Name == cmdName))
|
||||
{
|
||||
CommandContext ctx = new()
|
||||
{
|
||||
Player = Players.First(x => x.Value.Username == packet.Username).Value,
|
||||
Args = cmdArgs.Skip(1).ToArray()
|
||||
};
|
||||
|
||||
KeyValuePair<Command, Action<CommandContext>> command = Commands.First(x => x.Key.Name == cmdName);
|
||||
command.Value.Invoke(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
string username = packet.Username;
|
||||
|
||||
packet = new()
|
||||
{
|
||||
Username = "Server",
|
||||
Message = "Command not found!"
|
||||
};
|
||||
|
||||
outgoingMessage = MainNetServer.CreateMessage();
|
||||
packet.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
MainNetServer.SendMessage(outgoingMessage, MainNetServer.Connections.Find(con => con.RemoteUniqueIdentifier == Players.First(x => x.Value.Username == username).Key), NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (GameMode.OnChatMessage(packet.Username, packet.Message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
packet.Message = packet.Message.Replace("~", "");
|
||||
|
||||
Logging.Info(packet.Username + ": " + packet.Message);
|
||||
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
outgoingMessage = MainNetServer.CreateMessage();
|
||||
packet.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
MainNetServer.SendMessage(outgoingMessage, targets ?? MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
|
||||
Logging.Info(packet.Username + ": " + packet.Message);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region -- NPC --
|
||||
private static void FullSyncNpc(NetConnection local, FullSyncNpcPacket packet)
|
||||
{
|
||||
List<NetConnection> playerList = GetAllInRange(packet.Position, 300f, local);
|
||||
List<NetConnection> playerList = Util.GetAllInRange(packet.Position, 300f, local);
|
||||
if (playerList.Count == 0)
|
||||
{
|
||||
return;
|
||||
@ -679,7 +691,7 @@ namespace CoopServer
|
||||
|
||||
private static void FullSyncNpcVeh(NetConnection local, FullSyncNpcVehPacket packet)
|
||||
{
|
||||
List<NetConnection> playerList = GetAllInRange(packet.Position, 300f, local);
|
||||
List<NetConnection> playerList = Util.GetAllInRange(packet.Position, 300f, local);
|
||||
if (playerList.Count == 0)
|
||||
{
|
||||
return;
|
||||
@ -690,5 +702,29 @@ namespace CoopServer
|
||||
MainNetServer.SendMessage(outgoingMessage, playerList, NetDeliveryMethod.UnreliableSequenced, 0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static void RegisterCommand(string name, Action<CommandContext> callback)
|
||||
{
|
||||
Command command = new() { Name = name };
|
||||
|
||||
if (Commands.ContainsKey(command))
|
||||
{
|
||||
throw new Exception("Command \"" + command.Name + "\" was already been registered!");
|
||||
}
|
||||
|
||||
Commands.Add(command, callback);
|
||||
}
|
||||
|
||||
public static void RegisterCommands<T>()
|
||||
{
|
||||
IEnumerable<MethodInfo> commands = typeof(T).GetMethods().Where(method => method.GetCustomAttributes(typeof(CommandAttribute), false).Any());
|
||||
|
||||
foreach (MethodInfo method in commands)
|
||||
{
|
||||
CommandAttribute attribute = method.GetCustomAttribute<CommandAttribute>(true);
|
||||
|
||||
RegisterCommand(attribute.Name, (Action<CommandContext>)Delegate.CreateDelegate(typeof(Action<CommandContext>), method));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,100 +5,9 @@ using Lidgren.Network;
|
||||
|
||||
namespace CoopServer
|
||||
{
|
||||
class DefaultScript : ServerScript
|
||||
{
|
||||
private List<string> Admins = new();
|
||||
private string AdminPassword = "test123";
|
||||
|
||||
public override void OnPlayerConnect(Entities.EntitiesPlayer client)
|
||||
{
|
||||
SendChatMessageToAll("Say hello to " + client.Username);
|
||||
}
|
||||
|
||||
public override void OnPlayerDisconnect(Entities.EntitiesPlayer player, string reason)
|
||||
{
|
||||
Logging.Info(player.Username + " left the server, reason: " + reason);
|
||||
|
||||
if (Admins.Contains(player.Username))
|
||||
{
|
||||
Admins.Remove(player.Username);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnChatMessage(string username, string message)
|
||||
{
|
||||
if (!message.StartsWith("/"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string[] messageSplitted = message.Split(" ");
|
||||
int messageSplittedLength = messageSplitted.Length;
|
||||
|
||||
if (messageSplittedLength == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Admins.Contains(username))
|
||||
{
|
||||
if (messageSplitted[0] != "/rcon")
|
||||
{
|
||||
SendChatMessageToPlayer(username, "Please login with \"/rcon <PASSWORD>\"!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (messageSplitted.Length < 2)
|
||||
{
|
||||
SendChatMessageToPlayer(username, "Password missing!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (messageSplitted[1] != AdminPassword)
|
||||
{
|
||||
SendChatMessageToPlayer(username, "Wrong password!");
|
||||
Logging.Warning("Player [" + username + "] tried to login rcon with [" + messageSplitted[1] + "]");
|
||||
return true;
|
||||
}
|
||||
|
||||
Admins.Add(username);
|
||||
|
||||
SendChatMessageToPlayer(username, "Login successfully!");
|
||||
Logging.Info("Login successfully! [RCON][" + username + "]");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (messageSplitted[0] == "/kick")
|
||||
{
|
||||
if (messageSplittedLength < 3)
|
||||
{
|
||||
SendChatMessageToPlayer(username, "Please use \"/kick <USERNAME> <REASON>\"");
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
KickPlayerByUsername(messageSplitted[1], messageSplittedLength >= 3 ? messageSplitted[2] : "Kicked by " + username + "!");
|
||||
SendChatMessageToPlayer(username, "Player [" + messageSplitted[1] + "] kicked!");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
SendChatMessageToPlayer(username, e.Message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SendChatMessageToPlayer(username, "Command \"" + messageSplitted[0] + "\" not found!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class ServerScript
|
||||
{
|
||||
public virtual void Start()
|
||||
{
|
||||
Logging.Info("Gamemode loaded successfully!");
|
||||
}
|
||||
public virtual void Start() { }
|
||||
|
||||
public virtual void OnPlayerConnect(Entities.EntitiesPlayer player)
|
||||
{
|
||||
@ -110,78 +19,139 @@ namespace CoopServer
|
||||
Logging.Info(player.Username + " left the server, reason: " + reason);
|
||||
}
|
||||
|
||||
public virtual bool OnChatMessage(string username, string message) { return false; }
|
||||
|
||||
protected static List<string> GetAllConnections()
|
||||
public virtual bool OnChatMessage(string username, string message)
|
||||
{
|
||||
List<string> result = new();
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<long> GetAllConnections()
|
||||
{
|
||||
List<long> result = new();
|
||||
|
||||
lock (Server.MainNetServer.Connections)
|
||||
{
|
||||
Server.MainNetServer.Connections.ForEach(con => result.Add(NetUtility.ToHexString(con.RemoteUniqueIdentifier)));
|
||||
Server.MainNetServer.Connections.ForEach(x => result.Add(x.RemoteUniqueIdentifier));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected static int GetAllPlayersCount() { lock (Server.Players) return Server.Players.Count; }
|
||||
protected static Dictionary<long, Entities.EntitiesPlayer> GetAllPlayers() { lock (Server.Players) return Server.Players; }
|
||||
|
||||
protected static void KickPlayerByUsername(string username, string reason)
|
||||
public static int GetAllPlayersCount()
|
||||
{
|
||||
lock (Server.Players)
|
||||
{
|
||||
foreach (KeyValuePair<long, Entities.EntitiesPlayer> player in Server.Players)
|
||||
{
|
||||
if (player.Value.Username == username)
|
||||
{
|
||||
Server.MainNetServer.Connections.Find(e => e.RemoteUniqueIdentifier == player.Key).Disconnect(reason);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return Server.Players.Count;
|
||||
}
|
||||
|
||||
throw new Exception("Player [" + username + "] not found!");
|
||||
}
|
||||
|
||||
protected static void SendChatMessageToAll(string message, string username = "Server")
|
||||
{
|
||||
ChatMessagePacket packet = new()
|
||||
{
|
||||
Username = username,
|
||||
Message = message
|
||||
};
|
||||
|
||||
Logging.Info(username + ": " + packet.Message);
|
||||
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
packet.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
|
||||
protected static void SendChatMessageToPlayer(string username, string message, string from = "Server")
|
||||
public static Dictionary<long, Entities.EntitiesPlayer> GetAllPlayers()
|
||||
{
|
||||
lock (Server.Players)
|
||||
{
|
||||
foreach (KeyValuePair<long, Entities.EntitiesPlayer> player in Server.Players)
|
||||
{
|
||||
if (player.Value.Username == username)
|
||||
{
|
||||
ChatMessagePacket packet = new()
|
||||
{
|
||||
Username = from,
|
||||
Message = message
|
||||
};
|
||||
|
||||
Logging.Info(from + ": " + packet.Message);
|
||||
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
packet.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections.Find(con => con.RemoteUniqueIdentifier == player.Key), NetDeliveryMethod.ReliableOrdered, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return Server.Players;
|
||||
}
|
||||
}
|
||||
|
||||
public static void KickPlayerByUsername(string username, string[] reason)
|
||||
{
|
||||
lock (Server.MainNetServer.Connections)
|
||||
{
|
||||
NetConnection userConnection = Util.GetConnectionByUsername(username);
|
||||
if (userConnection == null)
|
||||
{
|
||||
Logging.Warning("[ServerScript->KickPlayerByUsername(\"" + username + "\", \"" + string.Join(" ", reason) + "\")]: User not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
userConnection.Disconnect(string.Join(" ", reason));
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendChatMessageToAll(string message, string username = "Server")
|
||||
{
|
||||
List<NetConnection> connections = Server.MainNetServer.Connections;
|
||||
|
||||
if (connections.Count != 0)
|
||||
{
|
||||
ChatMessagePacket packet = new()
|
||||
{
|
||||
Username = username,
|
||||
Message = message
|
||||
};
|
||||
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
packet.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
|
||||
Logging.Info(username + ": " + message);
|
||||
}
|
||||
|
||||
public static void SendChatMessageToPlayer(string username, string message, string from = "Server")
|
||||
{
|
||||
lock (Server.MainNetServer.Connections)
|
||||
{
|
||||
NetConnection userConnection = Util.GetConnectionByUsername(username);
|
||||
if (userConnection == null)
|
||||
{
|
||||
Logging.Warning("[ServerScript->SendChatMessageToPlayer(\"" + username + "\", \"" + message + "\", \"" + from + "\")]: User not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
ChatMessagePacket packet = new()
|
||||
{
|
||||
Username = from,
|
||||
Message = message
|
||||
};
|
||||
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
packet.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
|
||||
Logging.Info(from + ": " + message);
|
||||
}
|
||||
|
||||
public static void RegisterCommand(string name, Action<CommandContext> callback)
|
||||
{
|
||||
Server.RegisterCommand(name, callback);
|
||||
}
|
||||
|
||||
public static void RegisterCommands<T>()
|
||||
{
|
||||
Server.RegisterCommands<T>();
|
||||
}
|
||||
}
|
||||
|
||||
public class Command
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class CommandAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets name of the command
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
public CommandAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public class CommandContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the client which executed the command
|
||||
/// </summary>
|
||||
public Entities.EntitiesPlayer Player { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the chatdata associated with the command
|
||||
/// </summary>
|
||||
public string[] Args { get; internal set; }
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
public int MaxPlayers { get; set; } = 16;
|
||||
public string ServerName { get; set; } = "GTACoop:R server";
|
||||
public string WelcomeMessage { get; set; } = "Welcome on this server :)";
|
||||
public bool DefaultGameMode { get; set; } = true;
|
||||
public string GameMode { get; set; } = "";
|
||||
public bool Allowlist { get; set; } = false;
|
||||
public bool NpcsAllowed { get; set; } = true;
|
||||
|
@ -1,11 +1,52 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace CoopServer
|
||||
{
|
||||
class Util
|
||||
{
|
||||
public static NetConnection GetConnectionByUsername(string username)
|
||||
{
|
||||
long? userID = GetIdByUsername(username);
|
||||
if (userID == null || !Server.MainNetServer.Connections.Any(x => x.RemoteUniqueIdentifier == userID))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Server.MainNetServer.Connections.First(x => x.RemoteUniqueIdentifier == userID);
|
||||
}
|
||||
|
||||
public static long? GetIdByUsername(string username)
|
||||
{
|
||||
return Server.Players.Any(x => x.Value.Username == username) ? Server.Players.First(x => x.Value.Username == username).Key : null;
|
||||
}
|
||||
|
||||
// Return a list of all connections but not the local connection
|
||||
public static List<NetConnection> FilterAllLocal(NetConnection local)
|
||||
{
|
||||
return new(Server.MainNetServer.Connections.Where(e => e != local));
|
||||
}
|
||||
public static List<NetConnection> FilterAllLocal(long local)
|
||||
{
|
||||
return new(Server.MainNetServer.Connections.Where(e => e.RemoteUniqueIdentifier != local));
|
||||
}
|
||||
|
||||
// Return a list of players within range of ...
|
||||
public static List<NetConnection> GetAllInRange(LVector3 position, float range)
|
||||
{
|
||||
return new(Server.MainNetServer.Connections.FindAll(e => Server.Players[e.RemoteUniqueIdentifier].Ped.IsInRangeOf(position, range)));
|
||||
}
|
||||
// Return a list of players within range of ... but not the local one
|
||||
public static List<NetConnection> GetAllInRange(LVector3 position, float range, NetConnection local)
|
||||
{
|
||||
return new(Server.MainNetServer.Connections.Where(e => e != local && Server.Players[e.RemoteUniqueIdentifier].Ped.IsInRangeOf(position, range)));
|
||||
}
|
||||
|
||||
public static T Read<T>(string file) where T : new()
|
||||
{
|
||||
XmlSerializer ser = new(typeof(T));
|
||||
|
Reference in New Issue
Block a user