NOT FINISHED YET!
More info later...
This commit is contained in:
@ -1,22 +1,20 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace CoopClient
|
||||
{
|
||||
public static class Interface
|
||||
{
|
||||
#region DELEGATES
|
||||
public delegate void ConnectEvent(bool connected, string reason = null);
|
||||
public delegate void MessageEvent(NetIncomingMessage message);
|
||||
public delegate void ChatMessage(string from, string message, CancelEventArgs args);
|
||||
public delegate void ModEvent(long from, string mod, byte customID, byte[] bytes);
|
||||
#endregion
|
||||
|
||||
#region EVENTS
|
||||
public static event ConnectEvent OnConnection;
|
||||
public static event MessageEvent OnMessage;
|
||||
public static event ChatMessage OnChatMessage;
|
||||
public static event ModEvent OnModPacketReceived;
|
||||
|
||||
internal static void Connected()
|
||||
{
|
||||
@ -28,9 +26,9 @@ namespace CoopClient
|
||||
OnConnection?.Invoke(false, reason);
|
||||
}
|
||||
|
||||
internal static void MessageReceived(NetIncomingMessage message)
|
||||
internal static void ModPacketReceived(long from, string mod, byte customID, byte[] bytes)
|
||||
{
|
||||
OnMessage?.Invoke(message);
|
||||
OnModPacketReceived?.Invoke(from, mod, customID, bytes);
|
||||
}
|
||||
|
||||
internal static bool ChatMessageReceived(string from, string message)
|
||||
@ -51,14 +49,28 @@ namespace CoopClient
|
||||
Main.MainNetworking.DisConnectFromServer(serverAddress);
|
||||
}
|
||||
|
||||
public static void Disconnect()
|
||||
{
|
||||
Main.MainNetworking.DisConnectFromServer(null);
|
||||
}
|
||||
|
||||
public static bool IsOnServer()
|
||||
{
|
||||
return Main.MainNetworking.IsOnServer();
|
||||
}
|
||||
|
||||
public static long GetLocalID()
|
||||
{
|
||||
return Main.LocalClientID;
|
||||
}
|
||||
|
||||
public static bool IsMenuVisible()
|
||||
{
|
||||
#if NON_INTERACTIVE
|
||||
return false;
|
||||
#else
|
||||
return Main.MainMenu.MenuPool.AreAnyVisible;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsChatFocused()
|
||||
@ -76,6 +88,12 @@ namespace CoopClient
|
||||
return Main.CurrentVersion;
|
||||
}
|
||||
|
||||
// Send bytes to all players
|
||||
public static void SendDataToAll(string mod, byte customID, byte[] bytes)
|
||||
{
|
||||
Main.MainNetworking.SendModData(mod, customID, bytes);
|
||||
}
|
||||
|
||||
public static void Configure(string playerName, bool shareNpcsWithPlayers, int streamedNpcs, bool debug = false)
|
||||
{
|
||||
Main.MainSettings.Username = playerName;
|
||||
|
@ -224,6 +224,12 @@ namespace CoopClient
|
||||
packet.NetIncomingMessageToPacket(message);
|
||||
DecodeNativeCall((NativeCallPacket)packet);
|
||||
break;
|
||||
case (byte)PacketTypes.ModPacket:
|
||||
packet = new ModPacket();
|
||||
packet.NetIncomingMessageToPacket(message);
|
||||
ModPacket modPacket = (ModPacket)packet;
|
||||
Interface.ModPacketReceived(modPacket.ID, modPacket.Mod, modPacket.CustomPacketID, modPacket.Bytes);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NetIncomingMessageType.ConnectionLatencyUpdated:
|
||||
@ -238,13 +244,12 @@ namespace CoopClient
|
||||
break;
|
||||
}
|
||||
|
||||
Interface.MessageReceived(message);
|
||||
Client.Recycle(message);
|
||||
}
|
||||
}
|
||||
|
||||
#region -- GET --
|
||||
#region -- PLAYER --
|
||||
#region -- GET --
|
||||
#region -- PLAYER --
|
||||
private void PlayerConnect(PlayerConnectPacket packet)
|
||||
{
|
||||
EntitiesPlayer player = new EntitiesPlayer()
|
||||
@ -445,9 +450,9 @@ namespace CoopClient
|
||||
|
||||
Function.Call((Hash)packet.Hash, arguments.ToArray());
|
||||
}
|
||||
#endregion // -- PLAYER --
|
||||
#endregion // -- PLAYER --
|
||||
|
||||
#region -- NPC --
|
||||
#region -- NPC --
|
||||
private void FullSyncNpc(FullSyncNpcPacket packet)
|
||||
{
|
||||
lock (Main.Npcs)
|
||||
@ -567,10 +572,10 @@ namespace CoopClient
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion // -- NPC --
|
||||
#endregion
|
||||
#endregion // -- NPC --
|
||||
#endregion
|
||||
|
||||
#region -- SEND --
|
||||
#region -- SEND --
|
||||
private int LastPlayerFullSync = 0;
|
||||
public void SendPlayerData()
|
||||
{
|
||||
@ -694,12 +699,12 @@ namespace CoopClient
|
||||
Client.SendMessage(outgoingMessage, messageType);
|
||||
Client.FlushSendQueue();
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG
|
||||
if (ShowNetworkInfo)
|
||||
{
|
||||
BytesSend += outgoingMessage.LengthBytes;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SendNpcData(Ped npc)
|
||||
@ -763,12 +768,12 @@ namespace CoopClient
|
||||
Client.SendMessage(outgoingMessage, NetDeliveryMethod.Unreliable);
|
||||
Client.FlushSendQueue();
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG
|
||||
if (ShowNetworkInfo)
|
||||
{
|
||||
BytesSend += outgoingMessage.LengthBytes;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SendChatMessage(string message)
|
||||
@ -782,13 +787,34 @@ namespace CoopClient
|
||||
Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableOrdered);
|
||||
Client.FlushSendQueue();
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG
|
||||
if (ShowNetworkInfo)
|
||||
{
|
||||
BytesSend += outgoingMessage.LengthBytes;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void SendModData(string mod, byte customID, byte[] bytes)
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage = Client.CreateMessage();
|
||||
new ModPacket()
|
||||
{
|
||||
ID = Main.LocalClientID,
|
||||
Mod = mod,
|
||||
CustomPacketID = customID,
|
||||
Bytes = bytes
|
||||
}.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableOrdered);
|
||||
Client.FlushSendQueue();
|
||||
|
||||
#if DEBUG
|
||||
if (ShowNetworkInfo)
|
||||
{
|
||||
BytesSend += outgoingMessage.LengthBytes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,8 @@ namespace CoopClient
|
||||
FullSyncNpcPacket,
|
||||
FullSyncNpcVehPacket,
|
||||
ChatMessagePacket,
|
||||
NativeCallPacket
|
||||
NativeCallPacket,
|
||||
ModPacket
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@ -195,6 +196,44 @@ namespace CoopClient
|
||||
public abstract void NetIncomingMessageToPacket(NetIncomingMessage message);
|
||||
}
|
||||
|
||||
[ProtoContract]
|
||||
class ModPacket : Packet
|
||||
{
|
||||
[ProtoMember(1)]
|
||||
public long ID { get; set; }
|
||||
|
||||
[ProtoMember(2)]
|
||||
public string Mod { get; set; }
|
||||
|
||||
[ProtoMember(3)]
|
||||
public byte CustomPacketID { get; set; }
|
||||
|
||||
[ProtoMember(4)]
|
||||
public byte[] Bytes { get; set; }
|
||||
|
||||
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
|
||||
{
|
||||
message.Write((byte)PacketTypes.ModPacket);
|
||||
|
||||
byte[] result = CoopSerializer.Serialize(this);
|
||||
|
||||
message.Write(result.Length);
|
||||
message.Write(result);
|
||||
}
|
||||
|
||||
public override void NetIncomingMessageToPacket(NetIncomingMessage message)
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
|
||||
ModPacket data = CoopSerializer.Deserialize<ModPacket>(message.ReadBytes(len));
|
||||
|
||||
ID = data.ID;
|
||||
Mod = data.Mod;
|
||||
CustomPacketID = data.CustomPacketID;
|
||||
Bytes = data.Bytes;
|
||||
}
|
||||
}
|
||||
|
||||
#region -- PLAYER --
|
||||
[ProtoContract]
|
||||
class HandshakePacket : Packet
|
||||
|
@ -1,71 +1,42 @@
|
||||
using System.Linq;
|
||||
|
||||
using CoopServer;
|
||||
using CoopServer;
|
||||
|
||||
namespace FirstGameMode
|
||||
{
|
||||
class Commands
|
||||
{
|
||||
[Command("hello")]
|
||||
public static void HelloCommand(CommandContext ctx)
|
||||
[Command("set")]
|
||||
public static void TimeCommand(CommandContext ctx)
|
||||
{
|
||||
ctx.Client.SendChatMessage("Hello " + ctx.Client.Player.Username + " :)");
|
||||
if (ctx.Args.Length < 1)
|
||||
{
|
||||
ctx.Client.SendChatMessage("Please use \"/set <OPTION> ...\"");
|
||||
return;
|
||||
}
|
||||
|
||||
[Command("inrange")]
|
||||
public static void InRangeCommand(CommandContext ctx)
|
||||
else if (ctx.Args.Length < 2)
|
||||
{
|
||||
if (ctx.Client.Player.IsInRangeOf(new LVector3(0f, 0f, 75f), 7f))
|
||||
{
|
||||
ctx.Client.SendChatMessage("You are in range! :)");
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.Client.SendChatMessage("You are not in range! :(");
|
||||
}
|
||||
}
|
||||
|
||||
[Command("online")]
|
||||
public static void OnlineCommand(CommandContext ctx)
|
||||
{
|
||||
ctx.Client.SendChatMessage(API.GetAllClientsCount() + " player online!");
|
||||
}
|
||||
|
||||
[Command("kick")]
|
||||
public static void KickCommand(CommandContext ctx)
|
||||
{
|
||||
if (ctx.Args.Length < 2)
|
||||
{
|
||||
ctx.Client.SendChatMessage("Please use \"/kick <USERNAME> <REASON>\"");
|
||||
ctx.Client.SendChatMessage($"Please use \"/set {ctx.Args[0]} ...\"");
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.Client.Kick(ctx.Args.Skip(1).ToArray());
|
||||
}
|
||||
|
||||
[Command("setweather")]
|
||||
public static void SetWeatherCommand(CommandContext ctx)
|
||||
switch (ctx.Args[0])
|
||||
{
|
||||
case "time":
|
||||
int hours, minutes, seconds;
|
||||
|
||||
if (ctx.Args.Length < 3)
|
||||
if (ctx.Args.Length < 4)
|
||||
{
|
||||
ctx.Client.SendChatMessage("Please use \"/setweather <HOURS> <MINUTES> <SECONDS>\"");
|
||||
ctx.Client.SendChatMessage("Please use \"/set time <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))
|
||||
else if (!int.TryParse(ctx.Args[1], out hours) || !int.TryParse(ctx.Args[2], out minutes) || !int.TryParse(ctx.Args[3], out seconds))
|
||||
{
|
||||
ctx.Client.SendChatMessage("Please use \"/setweather <NUMBER> <NUMBER> <NUMBER>\"");
|
||||
ctx.Client.SendChatMessage($"Please use \"/set time <NUMBER> <NUMBER> <NUMBER>\"");
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.Client.SendNativeCall(0x47C3B5848C3E45D8, hours, minutes, seconds);
|
||||
break;
|
||||
}
|
||||
|
||||
[Command("upp")]
|
||||
public static void UpdatePlayerPositionCommand(CommandContext ctx)
|
||||
{
|
||||
ctx.Client.SetData("ShowPlayerPosition", !ctx.Client.GetData<bool>("ShowPlayerPosition"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.ComponentModel;
|
||||
using System.Timers;
|
||||
|
||||
@ -6,11 +8,18 @@ using CoopServer;
|
||||
|
||||
namespace FirstGameMode
|
||||
{
|
||||
[Serializable]
|
||||
public class SetPlayerTime
|
||||
{
|
||||
public int Hours { get; set; }
|
||||
public int Minutes { get; set; }
|
||||
public int Seconds { get; set; }
|
||||
}
|
||||
|
||||
public class Main : ServerScript
|
||||
{
|
||||
private static readonly Timer RunningSinceTimer = new() { Interval = 1000 };
|
||||
private static int RunningSince = 0;
|
||||
private static readonly List<string> SecretLocation = new();
|
||||
|
||||
public Main()
|
||||
{
|
||||
@ -20,12 +29,26 @@ namespace FirstGameMode
|
||||
API.OnPlayerConnected += OnPlayerConnected;
|
||||
API.OnPlayerDisconnected += OnPlayerDisconnected;
|
||||
API.OnChatMessage += OnChatMessage;
|
||||
API.OnPlayerPositionUpdate += OnPlayerPositionUpdate;
|
||||
API.OnModPacketReceived += OnModPacketReceived;
|
||||
|
||||
API.RegisterCommand("running", RunningCommand);
|
||||
API.RegisterCommands<Commands>();
|
||||
}
|
||||
|
||||
private void OnModPacketReceived(long from, string mod, byte customID, byte[] bytes, CancelEventArgs args)
|
||||
{
|
||||
if (mod == "FirstScript" && customID == 1)
|
||||
{
|
||||
args.Cancel = true;
|
||||
|
||||
// Get data from bytes
|
||||
SetPlayerTime setPlayerTime = bytes.Deserialize<SetPlayerTime>();
|
||||
|
||||
// Find the client by 'from' and send the time back as a nativecall
|
||||
API.GetAllClients().Find(x => x.ID == from).SendNativeCall(0x47C3B5848C3E45D8, setPlayerTime.Hours, setPlayerTime.Minutes, setPlayerTime.Seconds);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RunningCommand(CommandContext ctx)
|
||||
{
|
||||
ctx.Client.SendChatMessage("Server has been running for: " + RunningSince + " seconds!");
|
||||
@ -57,17 +80,39 @@ namespace FirstGameMode
|
||||
|
||||
API.SendChatMessageToAll(message, username);
|
||||
}
|
||||
|
||||
public static void OnPlayerPositionUpdate(Client client)
|
||||
{
|
||||
if (client.HasData("ShowPlayerPosition") && client.GetData<bool>("ShowPlayerPosition"))
|
||||
{
|
||||
if (!SecretLocation.Contains(client.Player.Username) && client.Player.IsInRangeOf(new LVector3(0, 0, 75), 7f))
|
||||
{
|
||||
client.SendChatMessage("Hey! you find this secret location!");
|
||||
SecretLocation.Add(client.Player.Username);
|
||||
return;
|
||||
}
|
||||
|
||||
public static class CustomSerializer
|
||||
{
|
||||
public static byte[] SerializeToByteArray(this object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
bf.Serialize(ms, obj);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static T Deserialize<T>(this byte[] byteArray) where T : class
|
||||
{
|
||||
if (byteArray == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using (MemoryStream memStream = new MemoryStream())
|
||||
{
|
||||
BinaryFormatter binForm = new BinaryFormatter();
|
||||
memStream.Write(byteArray, 0, byteArray.Length);
|
||||
memStream.Seek(0, SeekOrigin.Begin);
|
||||
T obj = (T)binForm.Deserialize(memStream);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
25
FirstScript/FirstScript.sln
Normal file
25
FirstScript/FirstScript.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31717.71
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FirstScript", "FirstScript\FirstScript.csproj", "{9524435E-24F3-4BDB-B7AA-351A00C2D209}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{9524435E-24F3-4BDB-B7AA-351A00C2D209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9524435E-24F3-4BDB-B7AA-351A00C2D209}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9524435E-24F3-4BDB-B7AA-351A00C2D209}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9524435E-24F3-4BDB-B7AA-351A00C2D209}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {398E3E84-30E0-408E-89E5-91CB0F001E14}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
54
FirstScript/FirstScript/FirstScript.csproj
Normal file
54
FirstScript/FirstScript/FirstScript.csproj
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{9524435E-24F3-4BDB-B7AA-351A00C2D209}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>FirstScript</RootNamespace>
|
||||
<AssemblyName>FirstScript</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="CoopClient">
|
||||
<HintPath>..\..\Client\bin\Debug\CoopClient.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ScriptHookVDotNet3">
|
||||
<HintPath>..\..\Libs\Release\ScriptHookVDotNet3.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
116
FirstScript/FirstScript/Main.cs
Normal file
116
FirstScript/FirstScript/Main.cs
Normal file
@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
using GTA;
|
||||
|
||||
namespace FirstScript
|
||||
{
|
||||
[Serializable]
|
||||
public class TestPacketClass
|
||||
{
|
||||
public int A { get; set; }
|
||||
public int B { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class SetPlayerTimePacket
|
||||
{
|
||||
public int Hours { get; set; }
|
||||
public int Minutes { get; set; }
|
||||
public int Seconds { get; set; }
|
||||
}
|
||||
|
||||
public class Main : Script
|
||||
{
|
||||
public Main()
|
||||
{
|
||||
Tick += OnTick;
|
||||
Interval += 3000;
|
||||
|
||||
CoopClient.Interface.OnModPacketReceived += OnModPacketReceived;
|
||||
CoopClient.Interface.OnConnection += OnConnection;
|
||||
}
|
||||
|
||||
private void OnConnection(bool connected, string reason = null)
|
||||
{
|
||||
if (connected)
|
||||
{
|
||||
CoopClient.Interface.SendChatMessage("Mod", "Welcome!");
|
||||
}
|
||||
else
|
||||
{
|
||||
GTA.UI.Notification.Show("~r~Mod~s~: ~b~C(°-°)D");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTick(object sender, EventArgs e)
|
||||
{
|
||||
if (!CoopClient.Interface.IsOnServer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CoopClient.Interface.SendDataToAll("FirstScript", 0, new TestPacketClass() { A = 5, B = 15 }.SerializeToByteArray());
|
||||
CoopClient.Interface.SendDataToAll("FirstScript", 1, new SetPlayerTimePacket() { Hours = 0, Minutes = 0, Seconds = 0 }.SerializeToByteArray());
|
||||
}
|
||||
|
||||
private void OnModPacketReceived(long from, string mod, byte customID, byte[] bytes)
|
||||
{
|
||||
if (mod != "FirstScript")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (customID)
|
||||
{
|
||||
case 0:
|
||||
TestPacketClass testPacketClass = bytes.Deserialize<TestPacketClass>();
|
||||
|
||||
GTA.UI.Notification.Show($"ModPacket(0)({from}): A[{testPacketClass.A}] B[{testPacketClass.B}]");
|
||||
break;
|
||||
case 1:
|
||||
GTA.UI.Notification.Show($"ModPacket(0)({from}): Nice!");
|
||||
break;
|
||||
default:
|
||||
GTA.UI.Notification.Show($"ModPacket({from}): ~r~Unknown customID!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomSerializer
|
||||
{
|
||||
public static byte[] SerializeToByteArray(this object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
bf.Serialize(ms, obj);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static T Deserialize<T>(this byte[] byteArray) where T : class
|
||||
{
|
||||
if (byteArray == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using (MemoryStream memStream = new MemoryStream())
|
||||
{
|
||||
BinaryFormatter binForm = new BinaryFormatter();
|
||||
memStream.Write(byteArray, 0, byteArray.Length);
|
||||
memStream.Seek(0, SeekOrigin.Begin);
|
||||
T obj = (T)binForm.Deserialize(memStream);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
FirstScript/FirstScript/Properties/AssemblyInfo.cs
Normal file
36
FirstScript/FirstScript/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
// die einer Assembly zugeordnet sind.
|
||||
[assembly: AssemblyTitle("FirstScript")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("FirstScript")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
|
||||
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
|
||||
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||
[assembly: Guid("9524435e-24f3-4bdb-b7aa-351a00c2d209")]
|
||||
|
||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
//
|
||||
// Hauptversion
|
||||
// Nebenversion
|
||||
// Buildnummer
|
||||
// Revision
|
||||
//
|
||||
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
|
||||
// indem Sie "*" wie unten gezeigt eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
||||
<AssemblyVersion>1.1.0.0001</AssemblyVersion>
|
||||
<FileVersion>1.0.0.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -70,7 +70,8 @@ namespace CoopServer
|
||||
FullSyncNpcPacket,
|
||||
FullSyncNpcVehPacket,
|
||||
ChatMessagePacket,
|
||||
NativeCallPacket
|
||||
NativeCallPacket,
|
||||
ModPacket
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@ -128,6 +129,44 @@ namespace CoopServer
|
||||
public abstract void NetIncomingMessageToPacket(NetIncomingMessage message);
|
||||
}
|
||||
|
||||
[ProtoContract]
|
||||
class ModPacket : Packet
|
||||
{
|
||||
[ProtoMember(1)]
|
||||
public long ID { get; set; }
|
||||
|
||||
[ProtoMember(2)]
|
||||
public string Mod { get; set; }
|
||||
|
||||
[ProtoMember(3)]
|
||||
public byte CustomPacketID { get; set; }
|
||||
|
||||
[ProtoMember(4)]
|
||||
public byte[] Bytes { get; set; }
|
||||
|
||||
public override void PacketToNetOutGoingMessage(NetOutgoingMessage message)
|
||||
{
|
||||
message.Write((byte)PacketTypes.ModPacket);
|
||||
|
||||
byte[] result = CoopSerializer.Serialize(this);
|
||||
|
||||
message.Write(result.Length);
|
||||
message.Write(result);
|
||||
}
|
||||
|
||||
public override void NetIncomingMessageToPacket(NetIncomingMessage message)
|
||||
{
|
||||
int len = message.ReadInt32();
|
||||
|
||||
ModPacket data = CoopSerializer.Deserialize<ModPacket>(message.ReadBytes(len));
|
||||
|
||||
ID = data.ID;
|
||||
Mod = data.Mod;
|
||||
CustomPacketID = data.CustomPacketID;
|
||||
Bytes = data.Bytes;
|
||||
}
|
||||
}
|
||||
|
||||
#region -- PLAYER --
|
||||
[ProtoContract]
|
||||
class HandshakePacket : Packet
|
||||
|
@ -280,6 +280,38 @@ namespace CoopServer
|
||||
message.SenderConnection.Disconnect("Npcs are not allowed!");
|
||||
}
|
||||
break;
|
||||
case (byte)PacketTypes.ModPacket:
|
||||
if (MainSettings.ModsAllowed)
|
||||
{
|
||||
try
|
||||
{
|
||||
packet = new ModPacket();
|
||||
packet.NetIncomingMessageToPacket(message);
|
||||
|
||||
ModPacket modPacket = (ModPacket)packet;
|
||||
if (GameMode != null)
|
||||
{
|
||||
if (GameMode.API.InvokeModPacketReceived(modPacket.ID, modPacket.Mod, modPacket.CustomPacketID, modPacket.Bytes))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Send back to all players
|
||||
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
|
||||
modPacket.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
MainNetServer.SendMessage(outgoingMessage, MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
message.SenderConnection.Disconnect(e.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
message.SenderConnection.Disconnect("Mods are not allowed!");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Logging.Error("Unhandled Data / Packet type");
|
||||
break;
|
||||
|
@ -17,6 +17,7 @@ namespace CoopServer
|
||||
#region DELEGATES
|
||||
public delegate void ChatEvent(string username, string message, CancelEventArgs cancel);
|
||||
public delegate void PlayerEvent(Client client);
|
||||
public delegate void ModEvent(long from, string mod, byte customID, byte[] bytes, CancelEventArgs args);
|
||||
#endregion
|
||||
|
||||
#region EVENTS
|
||||
@ -25,6 +26,7 @@ namespace CoopServer
|
||||
public event PlayerEvent OnPlayerConnected;
|
||||
public event PlayerEvent OnPlayerDisconnected;
|
||||
public event PlayerEvent OnPlayerPositionUpdate;
|
||||
public event ModEvent OnModPacketReceived;
|
||||
|
||||
internal void InvokeStart()
|
||||
{
|
||||
@ -52,6 +54,13 @@ namespace CoopServer
|
||||
{
|
||||
OnPlayerPositionUpdate?.Invoke(Server.Clients.First(x => x.Player.Username == playerData.Username));
|
||||
}
|
||||
|
||||
internal bool InvokeModPacketReceived(long from, string mod, byte customID, byte[] bytes)
|
||||
{
|
||||
CancelEventArgs args = new(false);
|
||||
OnModPacketReceived?.Invoke(from, mod, customID, bytes, args);
|
||||
return args.Cancel;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FUNCTIONS
|
||||
|
@ -9,6 +9,7 @@
|
||||
public string GameMode { get; set; } = "";
|
||||
public bool Allowlist { get; set; } = false;
|
||||
public bool NpcsAllowed { get; set; } = true;
|
||||
public bool ModsAllowed { get; set; } = false;
|
||||
public bool UPnP { get; set; } = true;
|
||||
public bool DebugMode { get; set; } = false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user