LAST UPDATE

This commit is contained in:
EntenKoeniq
2021-08-26 17:01:32 +02:00
parent 2e8fbfc169
commit be921ba310
21 changed files with 595 additions and 389 deletions

View File

@ -39,11 +39,14 @@ namespace CoopClient
get { return CurrentHidden; }
set
{
if (value && !CurrentHidden)
if (value)
{
MainScaleForm.CallFunction("hide");
if (!CurrentHidden)
{
MainScaleForm.CallFunction("hide");
}
}
else if (!value && CurrentHidden)
else if (CurrentHidden)
{
MainScaleForm.CallFunction("showFeed");
}

View File

@ -73,8 +73,6 @@ namespace CoopClient
public bool VehIsEngineRunning { get; set; }
public bool VehAreLightsOn { get; set; }
public bool VehAreHighBeamsOn { get; set; }
private bool LastVehIsInBurnout = false;
public bool VehIsInBurnout { get; set; }
public bool VehIsSireneActive { get; set; }
private VehicleDoors[] LastVehDoors;
public VehicleDoors[] VehDoors { get; set; }
@ -95,16 +93,31 @@ namespace CoopClient
{
if (!LastSyncWasFull)
{
if (Position != 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;
}
AllDataAvailable = true;
}
#region NOT_IN_RANGE
if (!Game.Player.Character.IsInRange(Position, 250f))
#region NOT_IN_RANGE OR !AllDataAvailable
if (!Game.Player.Character.IsInRange(Position, 500f))
{
if (MainVehicle != null && MainVehicle.Exists() && MainVehicle.PassengerCount <= 1)
if (MainVehicle != null && MainVehicle.Exists() && MainVehicle.PassengerCount == 0)
{
MainVehicle.Delete();
MainVehicle = null;
@ -118,17 +131,17 @@ namespace CoopClient
if (username != null)
{
if (PedBlip == null || !PedBlip.Exists())
if (PedBlip != null && PedBlip.Exists())
{
PedBlip.Position = Position;
}
else
{
PedBlip = World.CreateBlip(Position);
PedBlip.Color = BlipColor.White;
PedBlip.Scale = 0.8f;
PedBlip.Name = username;
}
else
{
PedBlip.Position = Position;
}
}
return;
@ -136,11 +149,6 @@ namespace CoopClient
#endregion
#region IS_IN_RANGE
if (PedBlip != null && PedBlip.Exists())
{
PedBlip.Delete();
}
bool characterExist = Character != null && Character.Exists();
if (!characterExist)
@ -405,19 +413,6 @@ namespace CoopClient
LastVehDoors = VehDoors;
}
if (VehIsInBurnout && !LastVehIsInBurnout)
{
Function.Call(Hash.SET_VEHICLE_BURNOUT, MainVehicle, true);
Function.Call(Hash.TASK_VEHICLE_TEMP_ACTION, Character, MainVehicle, 23, 120000); // 30 - burnout
}
else if (!VehIsInBurnout && LastVehIsInBurnout)
{
Function.Call(Hash.SET_VEHICLE_BURNOUT, MainVehicle, false);
Function.Call(Hash.CLEAR_PED_TASKS_IMMEDIATELY, Character); // Buggy but we need this to stop this burnout
}
LastVehIsInBurnout = VehIsInBurnout;
}
if (VehicleSteeringAngle != MainVehicle.SteeringAngle)
@ -426,7 +421,7 @@ namespace CoopClient
}
// Good enough for now, but we need to create a better sync
if ((CurrentVehicleSpeed > 0.2f || VehIsInBurnout) && MainVehicle.IsInRange(VehiclePosition, 7.0f))
if (CurrentVehicleSpeed > 0.05f && MainVehicle.IsInRange(VehiclePosition, 7.0f))
{
int forceMultiplier = (Game.Player.Character.IsInVehicle() && MainVehicle.IsTouching(Game.Player.Character.CurrentVehicle)) ? 1 : 3;
@ -597,6 +592,12 @@ namespace CoopClient
private bool CreateCharacter(string username)
{
if (PedBlip != null && PedBlip.Exists())
{
PedBlip.Delete();
PedBlip = null;
}
LastModelHash = ModelHash;
LastProps = Props;

View File

@ -18,7 +18,7 @@ namespace CoopClient
private bool GameLoaded = false;
public static readonly string CurrentModVersion = "V0_6_0";
public static readonly string CurrentModVersion = "V0_7_0";
public static bool ShareNpcsWithPlayers = false;
public static bool DisableTraffic = false;
@ -33,7 +33,7 @@ namespace CoopClient
public static Chat MainChat = new Chat();
public static long LocalPlayerID = 0;
public static long LocalClientID = 0;
public static readonly Dictionary<long, EntitiesPlayer> Players = new Dictionary<long, EntitiesPlayer>();
public static readonly Dictionary<long, EntitiesNpc> Npcs = new Dictionary<long, EntitiesNpc>();
@ -291,7 +291,6 @@ namespace CoopClient
DebugSyncPed.VehIsEngineRunning = (flags.Value & (byte)VehicleDataFlags.IsEngineRunning) > 0;
DebugSyncPed.VehAreLightsOn = (flags.Value & (byte)VehicleDataFlags.AreLightsOn) > 0;
DebugSyncPed.VehAreHighBeamsOn = (flags.Value & (byte)VehicleDataFlags.AreHighBeamsOn) > 0;
DebugSyncPed.VehIsInBurnout = (flags.Value & (byte)VehicleDataFlags.IsInBurnout) > 0;
DebugSyncPed.VehIsSireneActive = (flags.Value & (byte)VehicleDataFlags.IsSirenActive) > 0;
DebugSyncPed.VehicleDead = (flags.Value & (byte)VehicleDataFlags.IsDead) > 0;

View File

@ -25,7 +25,7 @@ namespace CoopClient
if (IsOnServer())
{
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
new PlayerDisconnectPacket() { Player = Main.LocalPlayerID }.PacketToNetOutGoingMessage(outgoingMessage);
new PlayerDisconnectPacket() { ID = Main.LocalClientID }.PacketToNetOutGoingMessage(outgoingMessage);
Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableOrdered);
Client.FlushSendQueue();
@ -107,7 +107,7 @@ namespace CoopClient
remoteHailMessagePacket.NetIncomingMessageToPacket(message.SenderConnection.RemoteHailMessage);
HandshakePacket handshakePacket = (HandshakePacket)remoteHailMessagePacket;
Main.LocalPlayerID = handshakePacket.ID;
Main.LocalClientID = handshakePacket.ID;
Main.NpcsAllowed = handshakePacket.NpcsAllowed;
Main.CleanUp();
@ -122,7 +122,7 @@ namespace CoopClient
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
new PlayerConnectPacket()
{
Player = Main.LocalPlayerID,
ID = Main.LocalClientID,
SocialClubName = string.Empty,
Username = string.Empty
}.PacketToNetOutGoingMessage(outgoingMessage);
@ -211,6 +211,11 @@ namespace CoopClient
packet.NetIncomingMessageToPacket(message);
FullSyncNpcVeh((FullSyncNpcVehPacket)packet);
break;
case (byte)PacketTypes.SuperLightSyncPlayerPacket:
packet = new SuperLightSyncPlayerPacket();
packet.NetIncomingMessageToPacket(message);
SuperLightSyncPlayer((SuperLightSyncPlayerPacket)packet);
break;
case (byte)PacketTypes.ChatMessagePacket:
packet = new ChatMessagePacket();
packet.NetIncomingMessageToPacket(message);
@ -252,14 +257,14 @@ namespace CoopClient
LastUpdateReceived = Environment.TickCount
};
Main.Players.Add(packet.Player, player);
Main.Players.Add(packet.ID, player);
}
private void PlayerDisconnect(PlayerDisconnectPacket packet)
{
if (Main.Players.ContainsKey(packet.Player))
if (Main.Players.ContainsKey(packet.ID))
{
EntitiesPlayer player = Main.Players[packet.Player];
EntitiesPlayer player = Main.Players[packet.ID];
if (player.Character != null && player.Character.Exists())
{
player.Character.Kill();
@ -268,18 +273,15 @@ namespace CoopClient
player.PedBlip?.Delete();
Main.Players.Remove(packet.Player);
Main.Players.Remove(packet.ID);
}
}
private void FullSyncPlayer(FullSyncPlayerPacket packet)
{
if (Main.Players.ContainsKey(packet.Extra.Player))
if (Main.Players.ContainsKey(packet.Extra.ID))
{
EntitiesPlayer player = Main.Players[packet.Extra.Player];
player.Latency = packet.Extra.Latency;
player.LastUpdateReceived = Environment.TickCount;
EntitiesPlayer player = Main.Players[packet.Extra.ID];
player.ModelHash = packet.ModelHash;
player.Props = packet.Props;
@ -298,17 +300,17 @@ namespace CoopClient
player.IsRagdoll = (packet.Flag.Value & (byte)PedDataFlags.IsRagdoll) > 0;
player.IsOnFire = (packet.Flag.Value & (byte)PedDataFlags.IsOnFire) > 0;
player.IsInVehicle = (packet.Flag.Value & (byte)PedDataFlags.IsInVehicle) > 0;
player.Latency = packet.Extra.Latency;
player.LastUpdateReceived = Environment.TickCount;
}
}
private void FullSyncPlayerVeh(FullSyncPlayerVehPacket packet)
{
if (Main.Players.ContainsKey(packet.Extra.Player))
if (Main.Players.ContainsKey(packet.Extra.ID))
{
EntitiesPlayer player = Main.Players[packet.Extra.Player];
player.Latency = packet.Extra.Latency;
player.LastUpdateReceived = Environment.TickCount;
EntitiesPlayer player = Main.Players[packet.Extra.ID];
player.ModelHash = packet.ModelHash;
player.Props = packet.Props;
@ -330,20 +332,19 @@ namespace CoopClient
player.VehIsEngineRunning = (packet.Flag.Value & (byte)VehicleDataFlags.IsEngineRunning) > 0;
player.VehAreLightsOn = (packet.Flag.Value & (byte)VehicleDataFlags.AreLightsOn) > 0;
player.VehAreHighBeamsOn = (packet.Flag.Value & (byte)VehicleDataFlags.AreHighBeamsOn) > 0;
player.VehIsInBurnout = (packet.Flag.Value & (byte)VehicleDataFlags.IsInBurnout) > 0;
player.VehIsSireneActive = (packet.Flag.Value & (byte)VehicleDataFlags.IsSirenActive) > 0;
player.VehicleDead = (packet.Flag.Value & (byte)VehicleDataFlags.IsDead) > 0;
player.Latency = packet.Extra.Latency;
player.LastUpdateReceived = Environment.TickCount;
}
}
private void LightSyncPlayer(LightSyncPlayerPacket packet)
{
if (Main.Players.ContainsKey(packet.Extra.Player))
if (Main.Players.ContainsKey(packet.Extra.ID))
{
EntitiesPlayer player = Main.Players[packet.Extra.Player];
player.Latency = packet.Extra.Latency;
player.LastUpdateReceived = Environment.TickCount;
EntitiesPlayer player = Main.Players[packet.Extra.ID];
player.Health = packet.Extra.Health;
player.Position = packet.Extra.Position.ToVector();
@ -360,17 +361,17 @@ namespace CoopClient
player.IsRagdoll = (packet.Flag.Value & (byte)PedDataFlags.IsRagdoll) > 0;
player.IsOnFire = (packet.Flag.Value & (byte)PedDataFlags.IsOnFire) > 0;
player.IsInVehicle = (packet.Flag.Value & (byte)PedDataFlags.IsInVehicle) > 0;
player.Latency = packet.Extra.Latency;
player.LastUpdateReceived = Environment.TickCount;
}
}
private void LightSyncPlayerVeh(LightSyncPlayerVehPacket packet)
{
if (Main.Players.ContainsKey(packet.Extra.Player))
if (Main.Players.ContainsKey(packet.Extra.ID))
{
EntitiesPlayer player = Main.Players[packet.Extra.Player];
player.Latency = packet.Extra.Latency;
player.LastUpdateReceived = Environment.TickCount;
EntitiesPlayer player = Main.Players[packet.Extra.ID];
player.Health = packet.Extra.Health;
player.Position = packet.Extra.Position.ToVector();
@ -386,9 +387,25 @@ namespace CoopClient
player.VehIsEngineRunning = (packet.Flag.Value & (byte)VehicleDataFlags.IsEngineRunning) > 0;
player.VehAreLightsOn = (packet.Flag.Value & (byte)VehicleDataFlags.AreLightsOn) > 0;
player.VehAreHighBeamsOn = (packet.Flag.Value & (byte)VehicleDataFlags.AreHighBeamsOn) > 0;
player.VehIsInBurnout = (packet.Flag.Value & (byte)VehicleDataFlags.IsInBurnout) > 0;
player.VehIsSireneActive = (packet.Flag.Value & (byte)VehicleDataFlags.IsSirenActive) > 0;
player.VehicleDead = (packet.Flag.Value & (byte)VehicleDataFlags.IsDead) > 0;
player.Latency = packet.Extra.Latency;
player.LastUpdateReceived = Environment.TickCount;
}
}
private void SuperLightSyncPlayer(SuperLightSyncPlayerPacket packet)
{
if (Main.Players.ContainsKey(packet.Extra.ID))
{
EntitiesPlayer player = Main.Players[packet.Extra.ID];
player.Health = packet.Extra.Health;
player.Position = packet.Extra.Position.ToVector();
player.Latency = packet.Extra.Latency;
player.LastUpdateReceived = Environment.TickCount;
}
}
@ -519,7 +536,6 @@ namespace CoopClient
npc.VehIsEngineRunning = (packet.Flag.Value & (byte)VehicleDataFlags.IsEngineRunning) > 0;
npc.VehAreLightsOn = (packet.Flag.Value & (byte)VehicleDataFlags.AreLightsOn) > 0;
npc.VehAreHighBeamsOn = (packet.Flag.Value & (byte)VehicleDataFlags.AreHighBeamsOn) > 0;
npc.VehIsInBurnout = (packet.Flag.Value & (byte)VehicleDataFlags.IsInBurnout) > 0;
npc.VehIsSireneActive = (packet.Flag.Value & (byte)VehicleDataFlags.IsSirenActive) > 0;
npc.VehicleDead = (packet.Flag.Value & (byte)VehicleDataFlags.IsDead) > 0;
}
@ -548,7 +564,6 @@ namespace CoopClient
VehIsEngineRunning = (packet.Flag.Value & (byte)VehicleDataFlags.IsEngineRunning) > 0,
VehAreLightsOn = (packet.Flag.Value & (byte)VehicleDataFlags.AreLightsOn) > 0,
VehAreHighBeamsOn = (packet.Flag.Value & (byte)VehicleDataFlags.AreHighBeamsOn) > 0,
VehIsInBurnout = (packet.Flag.Value & (byte)VehicleDataFlags.IsInBurnout) > 0,
VehIsSireneActive = (packet.Flag.Value & (byte)VehicleDataFlags.IsSirenActive) > 0,
VehicleDead = (packet.Flag.Value & (byte)VehicleDataFlags.IsDead) > 0
});
@ -577,7 +592,7 @@ namespace CoopClient
{
Extra = new PlayerPacket()
{
Player = Main.LocalPlayerID,
ID = Main.LocalClientID,
Health = player.Health,
Position = player.Position.ToLVector()
},
@ -610,7 +625,7 @@ namespace CoopClient
{
Extra = new PlayerPacket()
{
Player = Main.LocalPlayerID,
ID = Main.LocalClientID,
Health = player.Health,
Position = player.Position.ToLVector()
},
@ -643,7 +658,7 @@ namespace CoopClient
{
Extra = new PlayerPacket()
{
Player = Main.LocalPlayerID,
ID = Main.LocalClientID,
Health = player.Health,
Position = player.Position.ToLVector()
},
@ -663,7 +678,7 @@ namespace CoopClient
{
Extra = new PlayerPacket()
{
Player = Main.LocalPlayerID,
ID = Main.LocalClientID,
Health = player.Health,
Position = player.Position.ToLVector()
},
@ -698,7 +713,7 @@ namespace CoopClient
{
new FullSyncNpcPacket()
{
ID = Main.LocalPlayerID + npc.Handle,
ID = Main.LocalClientID + npc.Handle,
ModelHash = npc.Model.Hash,
Props = Util.GetPedProps(npc),
Health = npc.Health,
@ -728,7 +743,7 @@ namespace CoopClient
new FullSyncNpcVehPacket()
{
ID = Main.LocalPlayerID + npc.Handle,
ID = Main.LocalClientID + npc.Handle,
ModelHash = npc.Model.Hash,
Props = Util.GetPedProps(npc),
Health = npc.Health,

View File

@ -123,6 +123,7 @@ namespace CoopClient
FullSyncPlayerVehPacket,
LightSyncPlayerPacket,
LightSyncPlayerVehPacket,
SuperLightSyncPlayerPacket,
FullSyncNpcPacket,
FullSyncNpcVehPacket,
ChatMessagePacket,
@ -151,9 +152,8 @@ namespace CoopClient
IsEngineRunning = 1 << 2,
AreLightsOn = 1 << 3,
AreHighBeamsOn = 1 << 4,
IsInBurnout = 1 << 5,
IsSirenActive = 1 << 6,
IsDead = 1 << 7
IsSirenActive = 1 << 5,
IsDead = 1 << 6
}
[ProtoContract]
@ -242,7 +242,7 @@ namespace CoopClient
class PlayerConnectPacket : Packet
{
[ProtoMember(1)]
public long Player { get; set; }
public long ID { get; set; }
[ProtoMember(2)]
public string SocialClubName { get; set; }
@ -266,7 +266,7 @@ namespace CoopClient
PlayerConnectPacket data = CoopSerializer.Deserialize<PlayerConnectPacket>(message.ReadBytes(len));
Player = data.Player;
ID = data.ID;
SocialClubName = data.SocialClubName;
Username = data.Username;
}
@ -276,7 +276,7 @@ namespace CoopClient
class PlayerDisconnectPacket : Packet
{
[ProtoMember(1)]
public long Player { get; set; }
public long ID { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
@ -294,7 +294,7 @@ namespace CoopClient
PlayerDisconnectPacket data = CoopSerializer.Deserialize<PlayerDisconnectPacket>(message.ReadBytes(len));
Player = data.Player;
ID = data.ID;
}
}
@ -302,7 +302,7 @@ namespace CoopClient
struct PlayerPacket
{
[ProtoMember(1)]
public long Player { get; set; }
public long ID { get; set; }
[ProtoMember(2)]
public int Health { get; set; }
@ -562,6 +562,32 @@ namespace CoopClient
}
}
[ProtoContract]
class SuperLightSyncPlayerPacket : Packet
{
[ProtoMember(1)]
public PlayerPacket Extra { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
message.Write((byte)PacketTypes.SuperLightSyncPlayerPacket);
byte[] result = CoopSerializer.Serialize(this);
message.Write(result.Length);
message.Write(result);
}
public override void NetIncomingMessageToPacket(NetIncomingMessage message)
{
int len = message.ReadInt32();
SuperLightSyncPlayerPacket data = CoopSerializer.Deserialize<SuperLightSyncPlayerPacket>(message.ReadBytes(len));
Extra = data.Extra;
}
}
[ProtoContract]
class ChatMessagePacket : Packet
{

View File

@ -195,11 +195,6 @@ namespace CoopClient
flags |= (byte)VehicleDataFlags.AreHighBeamsOn;
}
if (veh.IsInBurnout)
{
flags |= (byte)VehicleDataFlags.IsInBurnout;
}
if (veh.IsSirenActive)
{
flags |= (byte)VehicleDataFlags.IsSirenActive;

View File

@ -9,26 +9,26 @@ namespace FirstGameMode
[Command("hello")]
public static void HelloCommand(CommandContext ctx)
{
API.SendChatMessageToPlayer(ctx.Player.Username, "Hello " + ctx.Player.Username + " :)");
ctx.Client.SendChatMessage("Hello " + ctx.Client.Player.Username + " :)");
}
[Command("inrange")]
public static void InRangeCommand(CommandContext ctx)
{
if (ctx.Player.IsInRangeOf(new LVector3(0f, 0f, 75f), 7f))
if (ctx.Client.Player.IsInRangeOf(new LVector3(0f, 0f, 75f), 7f))
{
API.SendChatMessageToPlayer(ctx.Player.Username, "You are in range! :)");
ctx.Client.SendChatMessage("You are in range! :)");
}
else
{
API.SendChatMessageToPlayer(ctx.Player.Username, "You are not in range! :(");
ctx.Client.SendChatMessage("You are not in range! :(");
}
}
[Command("online")]
public static void OnlineCommand(CommandContext ctx)
{
API.SendChatMessageToPlayer(ctx.Player.Username, API.GetAllPlayersCount() + " player online!");
ctx.Client.SendChatMessage(API.GetAllClientsCount() + " player online!");
}
[Command("kick")]
@ -36,11 +36,11 @@ namespace FirstGameMode
{
if (ctx.Args.Length < 2)
{
API.SendChatMessageToPlayer(ctx.Player.Username, "Please use \"/kick <USERNAME> <REASON>\"");
ctx.Client.SendChatMessage("Please use \"/kick <USERNAME> <REASON>\"");
return;
}
API.KickPlayerByUsername(ctx.Args[0], ctx.Args.Skip(1).ToArray());
ctx.Client.Kick(ctx.Args.Skip(1).ToArray());
}
[Command("setweather")]
@ -50,16 +50,16 @@ namespace FirstGameMode
if (ctx.Args.Length < 3)
{
API.SendChatMessageToPlayer(ctx.Player.Username, "Please use \"/setweather <HOURS> <MINUTES> <SECONDS>\"");
ctx.Client.SendChatMessage("Please use \"/setweather <HOURS> <MINUTES> <SECONDS>\"");
return;
}
else if (!int.TryParse(ctx.Args[0], out hours) || !int.TryParse(ctx.Args[1], out minutes) || !int.TryParse(ctx.Args[2], out seconds))
{
API.SendChatMessageToPlayer(ctx.Player.Username, "Please use \"/setweather <NUMBER> <NUMBER> <NUMBER>\"");
ctx.Client.SendChatMessage("Please use \"/setweather <NUMBER> <NUMBER> <NUMBER>\"");
return;
}
API.SendNativeCallToPlayer(ctx.Player.Username, 0x47C3B5848C3E45D8, hours, minutes, seconds);
ctx.Client.SendNativeCall(0x47C3B5848C3E45D8, hours, minutes, seconds);
}
[Command("upp")]

View File

@ -3,7 +3,6 @@ using System.ComponentModel;
using System.Timers;
using CoopServer;
using CoopServer.Entities;
namespace FirstGameMode
{
@ -30,17 +29,17 @@ namespace FirstGameMode
public static void RunningCommand(CommandContext ctx)
{
API.SendChatMessageToPlayer(ctx.Player.Username, "Server has been running for: " + RunningSince + " seconds!");
ctx.Client.SendChatMessage("Server has been running for: " + RunningSince + " seconds!");
}
public static void OnPlayerConnected(EntitiesPlayer player)
public static void OnPlayerConnected(Client client)
{
API.SendChatMessageToAll("Player " + player.Username + " connected!");
API.SendChatMessageToAll("Player " + client.Player.Username + " connected!");
}
public static void OnPlayerDisconnected(EntitiesPlayer player)
public static void OnPlayerDisconnected(Client client)
{
API.SendChatMessageToAll("Player " + player.Username + " disconnected!");
API.SendChatMessageToAll("Player " + client.Player.Username + " disconnected!");
}
public static void OnChatMessage(string username, string message, CancelEventArgs e)
@ -49,21 +48,25 @@ namespace FirstGameMode
if (message.StartsWith("EASTEREGG"))
{
API.SendChatMessageToPlayer(username, "You found the EASTEREGG! *-*");
Client client;
if ((client = API.GetClientByUsername(username)) != null)
{
client.SendChatMessage("You found the EASTEREGG! *-*");
}
return;
}
API.SendChatMessageToAll(message, username);
}
public static void OnPlayerPositionUpdate(EntitiesPlayer player)
public static void OnPlayerPositionUpdate(Client client)
{
if (ShowPlayerPosition)
{
if (!SecretLocation.Contains(player.Username) && player.IsInRangeOf(new LVector3(0, 0, 75), 7f))
if (!SecretLocation.Contains(client.Player.Username) && client.Player.IsInRangeOf(new LVector3(0, 0, 75), 7f))
{
API.SendChatMessageToPlayer(player.Username, "Hey! you find this secret location!");
SecretLocation.Add(player.Username);
client.SendChatMessage("Hey! you find this secret location!");
SecretLocation.Add(client.Player.Username);
return;
}
}

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31423.177
# Visual Studio Version 16
VisualStudioVersion = 16.0.31605.320
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoopServer", "Server\CoopServer.csproj", "{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}"
EndProject
@ -9,16 +9,26 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoopClient", "Client\CoopCl
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}.Debug|Any CPU.Build.0 = Debug|Any CPU
{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}.Debug|x64.ActiveCfg = Debug|Any CPU
{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}.Debug|x64.Build.0 = Debug|Any CPU
{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}.Release|Any CPU.ActiveCfg = Release|Any CPU
{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}.Release|Any CPU.Build.0 = Release|Any CPU
{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}.Release|x64.ActiveCfg = Release|Any CPU
{84AB99D9-5E00-4CA2-B1DD-56B8419AAD24}.Release|x64.Build.0 = Release|Any CPU
{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}.Debug|x64.ActiveCfg = Debug|Any CPU
{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}.Debug|x64.Build.0 = Debug|Any CPU
{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}.Release|Any CPU.ActiveCfg = Release|Any CPU
{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
EndGlobalSection

60
MasterServer/Logging.cs Normal file
View File

@ -0,0 +1,60 @@
using System;
using System.IO;
namespace MasterServer
{
class Logging
{
private static readonly object Lock = new();
public static void Info(string message)
{
lock (Lock)
{
string msg = string.Format("[{0}] [INFO] {1}", Date(), message);
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(msg);
Console.ResetColor();
using StreamWriter sw = new("log.txt", true);
sw.WriteLine(msg);
}
}
public static void Warning(string message)
{
lock (Lock)
{
string msg = string.Format("[{0}] [WARNING] {1}", Date(), message);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(msg);
Console.ResetColor();
using StreamWriter sw = new("log.txt", true);
sw.WriteLine(msg);
}
}
public static void Error(string message)
{
lock (Lock)
{
string msg = string.Format("[{0}] [ERROR] {1}", Date(), message);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(msg);
Console.ResetColor();
using StreamWriter sw = new("log.txt", true);
sw.WriteLine(msg);
}
}
private static string Date()
{
return DateTime.Now.ToString();
}
}
}

View File

@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>

89
MasterServer/Program.cs Normal file
View File

@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Threading;
namespace MasterServer
{
class Program
{
static readonly List<Server> Servers = new();
static readonly Dictionary<string, int> SpamSecurity = new();
static void Main()
{
try
{
Console.Title = "MasterServer v0.1.0";
Logging.Info("Trying to start the socket...");
}
catch (Exception e)
{
Logging.Error(e.Message.ToString());
}
Listen();
}
static void Listen()
{
while (true)
{
// 16 milliseconds to sleep to reduce CPU usage
Thread.Sleep(1000 / 60);
}
}
#region ===== FUNCTIONS =====
static bool CheckSpam(string address)
{
return SpamSecurity.TryGetValue(address, out int lastCheck) && (Environment.TickCount - lastCheck) < 10000;
}
static Server GetServerForClient()
{
return Servers.Find(x => x.Players < x.MaxPlayers);
}
static bool AddServer(Server server)
{
if (Servers.Exists(x => x.Address == server.Address))
{
return false;
}
try
{
Servers.Add(server);
}
catch (Exception e)
{
Logging.Error(e.Message.ToString());
return false;
}
return true;
}
static bool RemoveServer(Server server)
{
if (!Servers.Exists(x => x.Address == server.Address))
{
return true;
}
try
{
Servers.Remove(server);
}
catch (Exception e)
{
Logging.Error(e.Message.ToString());
return false;
}
return true;
}
#endregion
}
}

9
MasterServer/Server.cs Normal file
View File

@ -0,0 +1,9 @@
namespace MasterServer
{
struct Server
{
public string Address { get; set; }
public int Players { get; set; }
public int MaxPlayers { get; set; }
}
}

54
Server/Client.cs Normal file
View File

@ -0,0 +1,54 @@
using System.Collections.Generic;
using Lidgren.Network;
namespace CoopServer
{
public class Client
{
public long ID = 0;
public float Latency = 0.0f;
public PlayerData Player;
public void Kick(string[] reason)
{
Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ID).Disconnect(string.Join(" ", reason));
}
public void SendChatMessage(string message, string from = "Server")
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ID);
ChatMessagePacket packet = new()
{
Username = from,
Message = message
};
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, 0);
}
public void SendNativeCall(ulong hash, params object[] args)
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ID);
List<NativeArgument> arguments = Util.ParseNativeArguments(args);
if (arguments == null)
{
return;
}
NativeCallPacket packet = new()
{
Hash = hash,
Args = arguments
};
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, 0);
}
}
}

View File

@ -6,7 +6,6 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="protobuf-net" Version="2.4.6" />
</ItemGroup>

View File

@ -66,6 +66,7 @@ namespace CoopServer
FullSyncPlayerVehPacket,
LightSyncPlayerPacket,
LightSyncPlayerVehPacket,
SuperLightSyncPlayerPacket,
FullSyncNpcPacket,
FullSyncNpcVehPacket,
ChatMessagePacket,
@ -94,9 +95,8 @@ namespace CoopServer
IsEngineRunning = 1 << 2,
AreLightsOn = 1 << 3,
AreHighBeamsOn = 1 << 4,
IsInBurnout = 1 << 5,
IsSirenActive = 1 << 6,
IsDead = 1 << 7
IsSirenActive = 1 << 5,
IsDead = 1 << 6
}
[ProtoContract]
@ -175,7 +175,7 @@ namespace CoopServer
class PlayerConnectPacket : Packet
{
[ProtoMember(1)]
public long Player { get; set; }
public long ID { get; set; }
[ProtoMember(2)]
public string SocialClubName { get; set; }
@ -199,7 +199,7 @@ namespace CoopServer
PlayerConnectPacket data = CoopSerializer.Deserialize<PlayerConnectPacket>(message.ReadBytes(len));
Player = data.Player;
ID = data.ID;
SocialClubName = data.SocialClubName;
Username = data.Username;
}
@ -209,7 +209,7 @@ namespace CoopServer
class PlayerDisconnectPacket : Packet
{
[ProtoMember(1)]
public long Player { get; set; }
public long ID { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
@ -227,7 +227,7 @@ namespace CoopServer
PlayerDisconnectPacket data = CoopSerializer.Deserialize<PlayerDisconnectPacket>(message.ReadBytes(len));
Player = data.Player;
ID = data.ID;
}
}
@ -235,7 +235,7 @@ namespace CoopServer
struct PlayerPacket
{
[ProtoMember(1)]
public long Player { get; set; }
public long ID { get; set; }
[ProtoMember(2)]
public int Health { get; set; }
@ -495,6 +495,32 @@ namespace CoopServer
}
}
[ProtoContract]
class SuperLightSyncPlayerPacket : Packet
{
[ProtoMember(1)]
public PlayerPacket Extra { get; set; }
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
{
message.Write((byte)PacketTypes.SuperLightSyncPlayerPacket);
byte[] result = CoopSerializer.Serialize(this);
message.Write(result.Length);
message.Write(result);
}
public override void NetIncomingMessageToPacket(NetIncomingMessage message)
{
int len = message.ReadInt32();
SuperLightSyncPlayerPacket data = CoopSerializer.Deserialize<SuperLightSyncPlayerPacket>(message.ReadBytes(len));
Extra = data.Extra;
}
}
[ProtoContract]
class ChatMessagePacket : Packet
{

View File

@ -1,12 +1,11 @@
namespace CoopServer.Entities
namespace CoopServer
{
public class EntitiesPlayer
public struct PlayerData
{
public string SocialClubName { get; set; }
public string Username { get; set; }
public float Latency { get; set; }
private LVector3 LastPosition = new();
private LVector3 CurrentPosition = new();
private LVector3 LastPosition { get; set; }
private LVector3 CurrentPosition { get; set; }
public LVector3 Position
{
get

View File

@ -2,26 +2,16 @@
using System.Linq;
using System.Collections.Generic;
using System.Threading;
using System.Text;
using System.Net.Http;
using System.Reflection;
using System.IO;
using Newtonsoft.Json;
using Lidgren.Network;
using CoopServer.Entities;
namespace CoopServer
{
class IpInfo
{
public string Country { get; set; }
}
class Server
{
public static readonly string CurrentModVersion = "V0_6_0";
public static readonly string CurrentModVersion = "V0_7_0";
public static readonly Settings MainSettings = Util.Read<Settings>("CoopSettings.xml");
private readonly Blocklist MainBlocklist = Util.Read<Blocklist>("Blocklist.xml");
@ -29,10 +19,10 @@ namespace CoopServer
public static NetServer MainNetServer;
public static readonly Dictionary<long, EntitiesPlayer> Players = new();
public static ServerScript GameMode;
public static readonly Dictionary<Command, Action<CommandContext>> Commands = new Dictionary<Command, Action<CommandContext>>();
public static Dictionary<Command, Action<CommandContext>> Commands;
public static readonly List<Client> Clients = new();
public Server()
{
@ -67,67 +57,6 @@ namespace CoopServer
}
}
if (MainSettings.AnnounceSelf)
{
#region -- MASTERSERVER --
new Thread(async () =>
{
try
{
HttpClient httpClient = new();
IpInfo info;
try
{
string data = await httpClient.GetStringAsync("https://ipinfo.io/json");
info = JsonConvert.DeserializeObject<IpInfo>(data);
}
catch
{
info = new() { Country = "?" };
}
bool responseError = false;
while (!responseError)
{
string msg =
"{ " +
"\"port\": \"" + MainSettings.ServerPort + "\", " +
"\"name\": \"" + MainSettings.ServerName + "\", " +
"\"version\": \"" + CurrentModVersion.Replace("_", ".") + "\", " +
"\"players\": \"" + MainNetServer.ConnectionsCount + "\", " +
"\"maxPlayers\": \"" + MainSettings.MaxPlayers + "\", " +
"\"allowlist\": \"" + MainSettings.Allowlist + "\", " +
"\"country\": \"" + info.Country + "\"" +
" }";
HttpResponseMessage response = await httpClient.PostAsync(MainSettings.MasterServer, new StringContent(msg, Encoding.UTF8, "application/json"));
string responseContent = await response.Content.ReadAsStringAsync();
if (responseContent != "OK!")
{
Logging.Error(responseContent);
responseError = true;
}
else
{
// Sleep for 12.5s
Thread.Sleep(12500);
}
}
}
catch (Exception ex)
{
Logging.Error(ex.Message);
}
}).Start();
#endregion
}
if (!string.IsNullOrEmpty(MainSettings.GameMode))
{
try
@ -145,6 +74,8 @@ namespace CoopServer
}
else
{
Commands = new();
GameMode = Activator.CreateInstance(enumerable.ToArray()[0]) as ServerScript;
if (GameMode == null)
{
@ -169,7 +100,7 @@ namespace CoopServer
{
Logging.Info("Listening for clients");
while (!Console.KeyAvailable || Console.ReadKey().Key != ConsoleKey.Escape)
while (true)
{
// 16 milliseconds to sleep to reduce CPU usage
Thread.Sleep(1000 / 60);
@ -178,15 +109,13 @@ namespace CoopServer
while ((message = MainNetServer.ReadMessage()) != null)
{
long player;
switch (message.MessageType)
{
case NetIncomingMessageType.ConnectionApproval:
Logging.Info("New incoming connection from: " + message.SenderConnection.RemoteEndPoint.ToString());
if (message.ReadByte() != (byte)PacketTypes.HandshakePacket)
{
Logging.Info(string.Format("Player with IP {0} blocked, reason: Wrong packet!", message.SenderConnection.RemoteEndPoint.ToString()));
Logging.Info(string.Format("Player with IP {0} blocked, reason: Wrong packet!", message.SenderConnection.RemoteEndPoint.Address.ToString()));
message.SenderConnection.Deny("Wrong packet!");
}
else
@ -200,7 +129,7 @@ namespace CoopServer
}
catch (Exception e)
{
Logging.Info(string.Format("Player with IP {0} blocked, reason: {1}", message.SenderConnection.RemoteEndPoint.ToString(), e.Message));
Logging.Info(string.Format("Player with IP {0} blocked, reason: {1}", message.SenderConnection.RemoteEndPoint.Address.ToString(), e.Message));
message.SenderConnection.Deny(e.Message);
}
}
@ -208,11 +137,11 @@ namespace CoopServer
case NetIncomingMessageType.StatusChanged:
NetConnectionStatus status = (NetConnectionStatus)message.ReadByte();
player = message.SenderConnection.RemoteUniqueIdentifier;
long clientID = message.SenderConnection.RemoteUniqueIdentifier;
if (status == NetConnectionStatus.Disconnected && Players.ContainsKey(player))
if (status == NetConnectionStatus.Disconnected && Clients.Any(x => x.ID == clientID))
{
SendPlayerDisconnectPacket(new PlayerDisconnectPacket() { Player = player }, message.ReadString());
SendPlayerDisconnectPacket(new PlayerDisconnectPacket() { ID = clientID });
}
break;
case NetIncomingMessageType.Data:
@ -296,6 +225,18 @@ namespace CoopServer
message.SenderConnection.Disconnect(e.Message);
}
break;
case (byte)PacketTypes.ChatMessagePacket:
try
{
packet = new ChatMessagePacket();
packet.NetIncomingMessageToPacket(message);
SendChatMessage((ChatMessagePacket)packet);
}
catch (Exception e)
{
message.SenderConnection.Disconnect(e.Message);
}
break;
case (byte)PacketTypes.FullSyncNpcPacket:
if (MainSettings.NpcsAllowed)
{
@ -334,27 +275,16 @@ namespace CoopServer
message.SenderConnection.Disconnect("Npcs are not allowed!");
}
break;
case (byte)PacketTypes.ChatMessagePacket:
try
{
packet = new ChatMessagePacket();
packet.NetIncomingMessageToPacket(message);
SendChatMessage((ChatMessagePacket)packet);
}
catch (Exception e)
{
message.SenderConnection.Disconnect(e.Message);
}
break;
default:
Logging.Error("Unhandled Data / Packet type");
break;
}
break;
case NetIncomingMessageType.ConnectionLatencyUpdated:
if (Players.ContainsKey(message.SenderConnection.RemoteUniqueIdentifier))
Client client = Clients.FirstOrDefault(x => x.ID == message.SenderConnection.RemoteUniqueIdentifier);
if (client != default)
{
Players[message.SenderConnection.RemoteUniqueIdentifier].Latency = message.ReadFloat();
client.Latency = message.ReadFloat();
}
break;
case NetIncomingMessageType.ErrorMessage:
@ -381,7 +311,7 @@ namespace CoopServer
// Before we approve the connection, we must shake hands
private void GetHandshake(NetConnection local, HandshakePacket packet)
{
Logging.Debug("New handshake from: [" + packet.SocialClubName + " | " + packet.Username + "]");
Logging.Debug("New handshake from: [SC: " + packet.SocialClubName + " | Name: " + packet.Username + " | Address: " + local.RemoteEndPoint.Address.ToString() + "]");
if (string.IsNullOrWhiteSpace(packet.Username))
{
@ -425,25 +355,29 @@ namespace CoopServer
return;
}
if (Players.Any(x => x.Value.SocialClubName == packet.SocialClubName))
if (Clients.Any(x => x.Player.SocialClubName == packet.SocialClubName))
{
local.Deny("The name of the Social Club is already taken!");
return;
}
else if (Players.Any(x => x.Value.Username == packet.Username))
else if (Clients.Any(x => x.Player.Username == packet.Username))
{
local.Deny("Username is already taken!");
return;
}
long localPlayerID = local.RemoteUniqueIdentifier;
long localID = local.RemoteUniqueIdentifier;
// Add the player to Players
Players.Add(localPlayerID,
new EntitiesPlayer()
Clients.Add(
new Client()
{
SocialClubName = packet.SocialClubName,
Username = packet.Username
ID = localID,
Player = new()
{
SocialClubName = packet.SocialClubName,
Username = packet.Username
}
}
);
@ -452,7 +386,7 @@ namespace CoopServer
// Create a new handshake packet
new HandshakePacket()
{
ID = localPlayerID,
ID = localID,
SocialClubName = string.Empty,
Username = string.Empty,
ModVersion = string.Empty,
@ -473,148 +407,182 @@ namespace CoopServer
if (GameMode != null)
{
GameMode.API.InvokePlayerConnected(Players[packet.Player]);
GameMode.API.InvokePlayerConnected(Clients.Find(x => x.ID == packet.ID));
}
List<NetConnection> playerList = Util.FilterAllLocal(local);
if (playerList.Count == 0)
List<NetConnection> clients;
if ((clients = Util.FilterAllLocal(local)).Count == 0)
{
return;
}
// Send all players to local
playerList.ForEach(targetPlayer =>
clients.ForEach(targetPlayer =>
{
long targetPlayerID = targetPlayer.RemoteUniqueIdentifier;
EntitiesPlayer targetEntity = Players[targetPlayerID];
Client targetEntity = Clients.First(x => x.ID == targetPlayerID);
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new PlayerConnectPacket()
{
Player = targetPlayerID,
SocialClubName = targetEntity.SocialClubName,
Username = targetEntity.Username
ID = targetPlayerID,
SocialClubName = targetEntity.Player.SocialClubName,
Username = targetEntity.Player.Username
}.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, local, NetDeliveryMethod.ReliableOrdered, 0);
});
// Send local to all players
Client localClient = Clients.First(x => x.ID == packet.ID);
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new PlayerConnectPacket()
{
Player = packet.Player,
SocialClubName = Players[packet.Player].SocialClubName,
Username = Players[packet.Player].Username
ID = packet.ID,
SocialClubName = localClient.Player.SocialClubName,
Username = localClient.Player.Username
}.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, playerList, NetDeliveryMethod.ReliableOrdered, 0);
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.ReliableOrdered, 0);
}
// Send all players a message that someone has left the server
private static void SendPlayerDisconnectPacket(PlayerDisconnectPacket packet, string reason = "Disconnected")
private static void SendPlayerDisconnectPacket(PlayerDisconnectPacket packet)
{
if (GameMode != null)
{
GameMode.API.InvokePlayerDisconnected(Players[packet.Player]);
GameMode.API.InvokePlayerDisconnected(Clients.Find(x => x.ID == packet.ID));
}
List<NetConnection> playerList = Util.FilterAllLocal(packet.Player);
if (playerList.Count != 0)
List<NetConnection> clients;
if ((clients = Util.FilterAllLocal(packet.ID)).Count == 0)
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, playerList, NetDeliveryMethod.ReliableOrdered, 0);
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.ReliableOrdered, 0);
}
Players.Remove(packet.Player);
Clients.Remove(Clients.Find(x => x.ID == packet.ID));
}
private static void FullSyncPlayer(FullSyncPlayerPacket packet)
{
EntitiesPlayer player = Players[packet.Extra.Player];
Client client = Clients.First(x => x.ID == packet.Extra.ID);
client.Player.Position = packet.Extra.Position;
player.Position = packet.Extra.Position;
PlayerPacket playerPacket = packet.Extra;
playerPacket.Latency = client.Latency;
List<NetConnection> playerList = Util.FilterAllLocal(packet.Extra.Player);
if (playerList.Count == 0)
packet.Extra = playerPacket;
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != packet.Extra.ID).ForEach(x =>
{
return;
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
PlayerPacket localPacket = packet.Extra;
localPacket.Latency = player.Latency;
if (Clients.First(y => y.ID == x.RemoteUniqueIdentifier).Player.IsInRangeOf(packet.Extra.Position, 550f))
{
packet.PacketToNetOutGoingMessage(outgoingMessage);
}
else
{
new SuperLightSyncPlayerPacket()
{
Extra = packet.Extra
}.PacketToNetOutGoingMessage(outgoingMessage);
}
packet.Extra = localPacket;
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, playerList, NetDeliveryMethod.UnreliableSequenced, 0);
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, 0);
});
}
private static void FullSyncPlayerVeh(FullSyncPlayerVehPacket packet)
{
EntitiesPlayer player = Players[packet.Extra.Player];
Client client = Clients.First(x => x.ID == packet.Extra.ID);
client.Player.Position = packet.Extra.Position;
player.Position = packet.Extra.Position;
PlayerPacket playerPacket = packet.Extra;
playerPacket.Latency = client.Latency;
List<NetConnection> playerList = Util.FilterAllLocal(packet.Extra.Player);
if (playerList.Count == 0)
packet.Extra = playerPacket;
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != packet.Extra.ID).ForEach(x =>
{
return;
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
PlayerPacket localPacket = packet.Extra;
localPacket.Latency = player.Latency;
if (Clients.First(y => y.ID == x.RemoteUniqueIdentifier).Player.IsInRangeOf(packet.Extra.Position, 550f))
{
packet.PacketToNetOutGoingMessage(outgoingMessage);
}
else
{
new SuperLightSyncPlayerPacket()
{
Extra = packet.Extra
}.PacketToNetOutGoingMessage(outgoingMessage);
}
packet.Extra = localPacket;
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, playerList, NetDeliveryMethod.UnreliableSequenced, 0);
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, 0);
});
}
private static void LightSyncPlayer(LightSyncPlayerPacket packet)
{
EntitiesPlayer player = Players[packet.Extra.Player];
Client client = Clients.First(x => x.ID == packet.Extra.ID);
client.Player.Position = packet.Extra.Position;
player.Position = packet.Extra.Position;
PlayerPacket playerPacket = packet.Extra;
playerPacket.Latency = client.Latency;
List<NetConnection> playerList = Util.FilterAllLocal(packet.Extra.Player);
if (playerList.Count == 0)
packet.Extra = playerPacket;
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != packet.Extra.ID).ForEach(x =>
{
return;
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
PlayerPacket localPacket = packet.Extra;
localPacket.Latency = player.Latency;
if (Clients.First(y => y.ID == x.RemoteUniqueIdentifier).Player.IsInRangeOf(packet.Extra.Position, 550f))
{
packet.PacketToNetOutGoingMessage(outgoingMessage);
}
else
{
new SuperLightSyncPlayerPacket()
{
Extra = packet.Extra
}.PacketToNetOutGoingMessage(outgoingMessage);
}
packet.Extra = localPacket;
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, playerList, NetDeliveryMethod.ReliableSequenced, 0);
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, 0);
});
}
private static void LightSyncPlayerVeh(LightSyncPlayerVehPacket packet)
{
EntitiesPlayer player = Players[packet.Extra.Player];
Client client = Clients.First(x => x.ID == packet.Extra.ID);
client.Player.Position = packet.Extra.Position;
player.Position = packet.Extra.Position;
PlayerPacket playerPacket = packet.Extra;
playerPacket.Latency = client.Latency;
List<NetConnection> playerList = Util.FilterAllLocal(packet.Extra.Player);
if (playerList.Count == 0)
packet.Extra = playerPacket;
MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != packet.Extra.ID).ForEach(x =>
{
return;
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
PlayerPacket localPacket = packet.Extra;
localPacket.Latency = player.Latency;
if (Clients.First(y => y.ID == x.RemoteUniqueIdentifier).Player.IsInRangeOf(packet.Extra.Position, 550f))
{
packet.PacketToNetOutGoingMessage(outgoingMessage);
}
else
{
new SuperLightSyncPlayerPacket()
{
Extra = packet.Extra
}.PacketToNetOutGoingMessage(outgoingMessage);
}
packet.Extra = localPacket;
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, playerList, NetDeliveryMethod.ReliableSequenced, 0);
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, 0);
});
}
// Send a message to targets or all players
@ -632,7 +600,7 @@ namespace CoopServer
{
CommandContext ctx = new()
{
Player = Players.First(x => x.Value.Username == packet.Username).Value,
Client = Clients.First(x => x.Player.Username == packet.Username),
Args = cmdArgs.Skip(1).ToArray()
};
@ -677,24 +645,28 @@ namespace CoopServer
#region -- NPC --
private static void FullSyncNpc(NetConnection local, FullSyncNpcPacket packet)
{
List<NetConnection> playerList = Util.GetAllInRange(packet.Position, 300f, local);
if (playerList.Count == 0)
List<NetConnection> clients;
if ((clients = Util.GetAllInRange(packet.Position, 300f, local)).Count == 0)
{
return;
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, playerList, NetDeliveryMethod.UnreliableSequenced, 0);
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.UnreliableSequenced, 0);
}
private static void FullSyncNpcVeh(NetConnection local, FullSyncNpcVehPacket packet)
{
List<NetConnection> clients;
if ((clients = Util.GetAllInRange(packet.Position, 300f, local)).Count == 0)
{
return;
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, MainNetServer.Connections, NetDeliveryMethod.UnreliableSequenced, 0);
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.UnreliableSequenced, 0);
}
#endregion

View File

@ -16,7 +16,7 @@ namespace CoopServer
{
#region DELEGATES
public delegate void ChatEvent(string username, string message, CancelEventArgs cancel);
public delegate void PlayerEvent(Entities.EntitiesPlayer player);
public delegate void PlayerEvent(Client client);
#endregion
#region EVENTS
@ -31,14 +31,14 @@ namespace CoopServer
OnStart?.Invoke(this, EventArgs.Empty);
}
internal void InvokePlayerConnected(Entities.EntitiesPlayer player)
internal void InvokePlayerConnected(Client client)
{
OnPlayerConnected?.Invoke(player);
OnPlayerConnected?.Invoke(client);
}
internal void InvokePlayerDisconnected(Entities.EntitiesPlayer player)
internal void InvokePlayerDisconnected(Client client)
{
OnPlayerDisconnected?.Invoke(player);
OnPlayerDisconnected?.Invoke(client);
}
internal bool InvokeChatMessage(string username, string message)
@ -48,23 +48,22 @@ namespace CoopServer
return args.Cancel;
}
internal void InvokePlayerPositionUpdate(Entities.EntitiesPlayer player)
internal void InvokePlayerPositionUpdate(PlayerData playerData)
{
OnPlayerPositionUpdate?.Invoke(player);
OnPlayerPositionUpdate?.Invoke(Server.Clients.First(x => x.Player.Username == playerData.Username));
}
#endregion
#region FUNCTIONS
public static void SendNativeCallToAll(ulong hash, params object[] args)
{
List<NetConnection> connections = Server.MainNetServer.Connections;
if (connections.Count == 0)
if (Server.MainNetServer.ConnectionsCount == 0)
{
return;
}
List<NativeArgument> arguments = Util.ParseNativeArguments(args);
if (arguments == null)
List<NativeArgument> arguments;
if ((arguments = Util.ParseNativeArguments(args)) == null)
{
return;
}
@ -80,32 +79,6 @@ namespace CoopServer
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
}
public static void SendNativeCallToPlayer(string username, ulong hash, params object[] args)
{
NetConnection userConnection = Util.GetConnectionByUsername(username);
if (userConnection == default)
{
Logging.Warning("[ServerScript->SendNativeCallToPlayer(\"" + username + "\", \"" + hash + "\", params object[] args)]: User not found!");
return;
}
List<NativeArgument> arguments = Util.ParseNativeArguments(args);
if (arguments == null)
{
return;
}
NativeCallPacket packet = new()
{
Hash = hash,
Args = arguments
};
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, 0);
}
public static List<long> GetAllConnections()
{
List<long> result = new();
@ -115,37 +88,24 @@ namespace CoopServer
return result;
}
public static int GetAllPlayersCount()
public static int GetAllClientsCount()
{
return Server.Players.Count;
return Server.Clients.Count;
}
public static Dictionary<long, Entities.EntitiesPlayer> GetAllPlayers()
public static List<Client> GetAllClients()
{
return Server.Players;
return Server.Clients;
}
public static Entities.EntitiesPlayer GetPlayerByUsername(string username)
public static Client GetClientByUsername(string username)
{
return Server.Players.FirstOrDefault(x => x.Value.Username == username).Value;
}
public static void KickPlayerByUsername(string username, string[] reason)
{
NetConnection userConnection = Util.GetConnectionByUsername(username);
if (userConnection == default)
{
Logging.Warning("[ServerScript->KickPlayerByUsername(\"" + username + "\", \"" + string.Join(" ", reason) + "\")]: User not found!");
return;
}
userConnection.Disconnect(string.Join(" ", reason));
return Server.Clients.FirstOrDefault(x => x.Player.Username == username);
}
public static void SendChatMessageToAll(string message, string username = "Server")
{
List<NetConnection> connections = Server.MainNetServer.Connections;
if (connections.Count == 0)
if (Server.MainNetServer.ConnectionsCount == 0)
{
return;
}
@ -161,26 +121,6 @@ namespace CoopServer
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
}
public static void SendChatMessageToPlayer(string username, string message, string from = "Server")
{
NetConnection userConnection = Util.GetConnectionByUsername(username);
if (userConnection == default)
{
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);
}
public static void RegisterCommand(string name, Action<CommandContext> callback)
{
Server.RegisterCommand(name, callback);
@ -217,7 +157,7 @@ namespace CoopServer
/// <summary>
/// Gets the client which executed the command
/// </summary>
public Entities.EntitiesPlayer Player { get; internal set; }
public Client Client { get; internal set; }
/// <summary>
/// Gets the chatdata associated with the command

View File

@ -9,8 +9,6 @@
public string GameMode { get; set; } = "";
public bool Allowlist { get; set; } = false;
public bool NpcsAllowed { get; set; } = true;
public string MasterServer { get; set; } = "https://gtacoopr.entenkoeniq.de/servers";
public bool AnnounceSelf { get; set; } = true;
public bool UPnP { get; set; } = true;
public bool DebugMode { get; set; } = false;
}

View File

@ -50,13 +50,13 @@ namespace CoopServer
public static NetConnection GetConnectionByUsername(string username)
{
long? userID = Server.Players.FirstOrDefault(x => x.Value.Username == username).Key;
if (userID == default || !Server.MainNetServer.Connections.Any(x => x.RemoteUniqueIdentifier == userID))
long clientID;
if ((clientID = Server.Clients.FirstOrDefault(x => x.Player.Username == username).ID) == default)
{
return null;
}
return Server.MainNetServer.Connections.FirstOrDefault(x => x.RemoteUniqueIdentifier == userID);
return Server.MainNetServer.Connections.FirstOrDefault(x => x.RemoteUniqueIdentifier == clientID);
}
// Return a list of all connections but not the local connection
@ -72,12 +72,12 @@ namespace CoopServer
// 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].IsInRangeOf(position, range)));
return new(Server.MainNetServer.Connections.FindAll(e => Server.Clients.First(x => x.ID == e.RemoteUniqueIdentifier).Player.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].IsInRangeOf(position, range)));
return new(Server.MainNetServer.Connections.Where(e => e != local && Server.Clients.First(x => x.ID == e.RemoteUniqueIdentifier).Player.IsInRangeOf(position, range)));
}
public static T Read<T>(string file) where T : new()