diff --git a/.gitignore b/.gitignore index a53bb84..28c4ff8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ *.zip -_releases \ No newline at end of file +_releases +.vs +.sln +bin +obj \ No newline at end of file diff --git a/FiveM_TimeSync.sln b/FiveM_TimeSync.sln new file mode 100644 index 0000000..0207f82 --- /dev/null +++ b/FiveM_TimeSync.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30114.105 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FiveM_TimeSync", "FiveM_TimeSync\FiveM_TimeSync.csproj", "{E43819C4-7F54-408A-B097-794CBD245BAD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FiveM_TimeSyncServer", "FiveM_TimeSyncServer\FiveM_TimeSyncServer.csproj", "{A4E0CA53-9DCD-453F-83CD-3F7AB0F25807}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E43819C4-7F54-408A-B097-794CBD245BAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E43819C4-7F54-408A-B097-794CBD245BAD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E43819C4-7F54-408A-B097-794CBD245BAD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E43819C4-7F54-408A-B097-794CBD245BAD}.Release|Any CPU.Build.0 = Release|Any CPU + {A4E0CA53-9DCD-453F-83CD-3F7AB0F25807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4E0CA53-9DCD-453F-83CD-3F7AB0F25807}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4E0CA53-9DCD-453F-83CD-3F7AB0F25807}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4E0CA53-9DCD-453F-83CD-3F7AB0F25807}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6433BD9B-8AB9-4772-BC1B-9C06B796AC4F} + EndGlobalSection +EndGlobal diff --git a/FiveM_TimeSync/Client.cs b/FiveM_TimeSync/Client.cs new file mode 100644 index 0000000..ed33e97 --- /dev/null +++ b/FiveM_TimeSync/Client.cs @@ -0,0 +1,13 @@ +using VinaFrameworkClient.Core; +using FiveM_TimeSync.Modules; + +namespace FiveM_TimeSync +{ + public class Client : BaseClient + { + public Client() + { + AddModule(typeof(TimeSyncModule)); + } + } +} diff --git a/FiveM_TimeSync/FiveM_TimeSync.csproj b/FiveM_TimeSync/FiveM_TimeSync.csproj new file mode 100644 index 0000000..ec65cf6 --- /dev/null +++ b/FiveM_TimeSync/FiveM_TimeSync.csproj @@ -0,0 +1,62 @@ + + + + + Debug + AnyCPU + {E43819C4-7F54-408A-B097-794CBD245BAD} + Library + Properties + FiveM_TimeSync + FiveM_TimeSync.net + v4.5.2 + 512 + true + + + false + none + false + ..\..\_resources\fivemtimesync\ + DEBUG;TRACE + prompt + 4 + Off + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\..\..\FiveM.app\citizen\clr2\lib\mono\4.5\CitizenFX.Core.dll + False + + + + + + + + + + + False + ..\..\_dependencies\VinaFrameworkClient.dll + + + + + + + + + + + + + \ No newline at end of file diff --git a/FiveM_TimeSync/Modules/TimeSyncModule.cs b/FiveM_TimeSync/Modules/TimeSyncModule.cs new file mode 100644 index 0000000..60836c5 --- /dev/null +++ b/FiveM_TimeSync/Modules/TimeSyncModule.cs @@ -0,0 +1,80 @@ +using System; +using System.Threading.Tasks; + +using CitizenFX.Core.Native; + +using VinaFrameworkClient.Core; + +namespace FiveM_TimeSync.Modules +{ + public class TimeSyncModule : Module + { + public TimeSyncModule(Client client) : base(client) + { + script.AddEvent("TimeSync.UpdateDateTime", new Action(OnUpdateDateTime)); + script.AddTick(OverrideTime); + } + + #region ACCESSORS + + public DateTime CurrentDate + { + get + { + return lastServerTime.AddMilliseconds(timeElapsed); + } + } + + public TimeSpan CurrentTime + { + get + { + return CurrentDate.TimeOfDay; + } + } + + private double timeElapsed + { + get + { + return DateTime.Now.Subtract(startingDate).TotalMilliseconds * timeRate; + } + } + + #endregion + #region VARIABLES + + private int timeRate; + private DateTime startingDate; + private DateTime lastServerTime; + + #endregion + #region MODULE EVENTS + + private void OnUpdateDateTime(int newTimeRate, long currentTicks) + { + timeRate = newTimeRate; + startingDate = DateTime.Now; + lastServerTime = new DateTime(currentTicks); + + script.Log($"Received update from server [TimeRate: {timeRate}, Server Time: ${lastServerTime}]"); + } + + #endregion + #region MODULES TICKS + + private async Task OverrideTime() + { + while (true) + { + await Client.Delay(33); + + if (startingDate == null || lastServerTime == null) continue; + + API.NetworkOverrideClockTime(CurrentTime.Hours, CurrentTime.Minutes, CurrentTime.Seconds); + } + } + + #endregion + } +} diff --git a/FiveM_TimeSync/Properties/AssemblyInfo.cs b/FiveM_TimeSync/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..47df24f --- /dev/null +++ b/FiveM_TimeSync/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FiveM_TimeSync")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FiveM_TimeSync")] +[assembly: AssemblyCopyright("Copyright © VinaStar 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e43819c4-7f54-408a-b097-794cbd245bad")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/FiveM_TimeSyncServer/FiveM_TimeSyncServer.csproj b/FiveM_TimeSyncServer/FiveM_TimeSyncServer.csproj new file mode 100644 index 0000000..4fde351 --- /dev/null +++ b/FiveM_TimeSyncServer/FiveM_TimeSyncServer.csproj @@ -0,0 +1,62 @@ + + + + + Debug + AnyCPU + {A4E0CA53-9DCD-453F-83CD-3F7AB0F25807} + Library + Properties + FiveM_TimeSyncServer + FiveM_TimeSyncServer.net + v4.5.2 + 512 + true + + + false + none + false + ..\..\_resources\fivemtimesync\ + DEBUG;TRACE + prompt + 4 + Off + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\..\fivem_server\citizen\clr2\lib\mono\4.5\CitizenFX.Core.dll + False + + + + + + + + + + + False + ..\..\_dependencies\VinaFrameworkServer.dll + + + + + + + + + + + + + \ No newline at end of file diff --git a/FiveM_TimeSyncServer/Modules/TimeSyncModule.cs b/FiveM_TimeSyncServer/Modules/TimeSyncModule.cs new file mode 100644 index 0000000..a0ea5eb --- /dev/null +++ b/FiveM_TimeSyncServer/Modules/TimeSyncModule.cs @@ -0,0 +1,217 @@ +using System; +using System.IO; +using System.Threading.Tasks; + +using CitizenFX.Core; +using CitizenFX.Core.Native; + +using VinaFrameworkServer.Core; + +namespace FiveM_TimeSyncServer.Modules +{ + public class TimeSyncModule : Module + { + public TimeSyncModule(Server server) : base(server) + { + endingDate = LoadCurrentTime(); + lastServerTime = DateTime.Now; + + script.AddTick(NetworkResync); + script.AddTick(AutosaveTime); + script.AddTick(PeriodicConsolePrint); + + script.SetExport("CurrentDateTicks", new Func(ExportCurrentDateTicks)); + } + + #region ACCESSORS + + public DateTime RealDate + { + get + { + return DateTime.Now; + } + } + + public TimeSpan RealTime + { + get + { + return RealDate.TimeOfDay; + } + } + + public DateTime CurrentDate + { + get + { + return endingDate.AddMilliseconds(timeElapsed); + } + } + + public TimeSpan CurrentTime + { + get + { + return CurrentDate.TimeOfDay; + } + } + + private double timeElapsed + { + get + { + return DateTime.Now.Subtract(lastServerTime).TotalMilliseconds * timeRate; + } + } + + #endregion + #region VARIABLES + + private bool verbose; + private bool printEnabled; + private string printFormat; + private int printDelay; + private int clientUpdateDelay; + private int timeRate; + private DateTime endingDate; + private DateTime lastServerTime; + + #endregion + #region BASE EVENTS + + protected override void OnModuleInitialized() + { + // Print more informations + verbose = API.GetConvarInt("timesync_network_verbose", 0) == 0; + + // Peridically print current time + printEnabled = API.GetConvarInt("timesync_console_print_time", 0) == 0; + + // Console Print Time Format + printFormat = API.GetConvar("timesync_console_print_format", "MMMM d yyyy, HH:mm:ss tt"); + + // Console Print Time Delay + printDelay = API.GetConvarInt("timesync_console_print_delay", 1000 * 60 * 5); + + // Sync players every 10 secs + clientUpdateDelay = API.GetConvarInt("timesync_update_delay", 60000); + + // 10 x realtime + timeRate = API.GetConvarInt("timesync_timerate", 1); + + Debug.WriteLine($@" +===================================== +FIVEM TIME SYNC SETTINGS: +===================================== + timesync_console_print = {printEnabled} + timesync_console_print_format = {printFormat} + timesync_console_print_delay (ms) = {printDelay} + timesync_update_delay (ms) = {clientUpdateDelay} + timesync_timerate (1sec * timerate) = {timeRate} + Current Date = {CurrentDate.ToString(printFormat)} +====================================="); + } + + protected override void OnPlayerConnecting(Player player) + { + + } + + protected override void OnPlayerDropped(Player player, string reason) + { + + } + + protected override void OnPlayerClientInitialized(Player player) + { + UpdatePlayerDateTime(player); + } + + #endregion + #region MODULE TICKS + + private async Task NetworkResync() + { + await Server.Delay(clientUpdateDelay); + + UpdatePlayerDateTime(); + } + + private async Task AutosaveTime() + { + await Server.Delay(30000); + + await SaveCurrentTime(); + } + + private async Task PeriodicConsolePrint() + { + await Server.Delay(printDelay); + + if (!printEnabled) return; + + script.Log($@"SERVER CURRENT TIME: {CurrentDate.ToString(printFormat)}"); + } + + #endregion + #region MODULE METHODS + + private void UpdatePlayerDateTime(Player player = null) + { + if (player != null) + { + Server.TriggerClientEvent(player, "TimeSync.UpdateDateTime", timeRate, CurrentDate.Ticks); + if (verbose) script.Log($"FiveM TimeSync syncing player ${player.Name} time!"); + } + else + { + if (API.GetNumPlayerIndices() > 0) + { + Server.TriggerClientEvent("TimeSync.UpdateDateTime", timeRate, CurrentDate.Ticks); + if (verbose) script.Log($"FiveM TimeSync syncing all players time!"); + } + else if (verbose) script.Log($"FiveM TimeSync no online players, skipping syncing..."); + } + } + + private DateTime LoadCurrentTime() + { + try + { + string fileData = File.ReadAllText("server_time.txt"); + script.Log("Loaded time from server_time.txt"); + return DateTime.Parse(fileData); + } + catch (Exception exception) + { + script.Log("Could not get time from server_time.txt, starting with real time."); + } + + return DateTime.Now; + } + + private async Task SaveCurrentTime() + { + try + { + using (StreamWriter writer = File.CreateText("server_time.txt")) + { + await writer.WriteAsync(CurrentDate.ToString()); + writer.Close(); + } + } + catch (Exception exception) + { + script.LogError(exception); + } + } + + private long ExportCurrentDateTicks() + { + return CurrentDate.Ticks; + } + + #endregion + } +} diff --git a/FiveM_TimeSyncServer/Properties/AssemblyInfo.cs b/FiveM_TimeSyncServer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f7794af --- /dev/null +++ b/FiveM_TimeSyncServer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FiveM_TimeSyncServer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FiveM_TimeSyncServer")] +[assembly: AssemblyCopyright("Copyright © VinaStar 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a4e0ca53-9dcd-453f-83cd-3f7ab0f25807")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/FiveM_TimeSyncServer/Server.cs b/FiveM_TimeSyncServer/Server.cs new file mode 100644 index 0000000..24707fe --- /dev/null +++ b/FiveM_TimeSyncServer/Server.cs @@ -0,0 +1,13 @@ +using VinaFrameworkServer.Core; +using FiveM_TimeSyncServer.Modules; + +namespace FiveM_TimeSyncServer +{ + public class Server : BaseServer + { + public Server() + { + AddModule(typeof(TimeSyncModule)); + } + } +} diff --git a/Resources/fivemtimesync/FiveM_TimeSync.net.dll b/Resources/fivemtimesync/FiveM_TimeSync.net.dll deleted file mode 100644 index 1de6668..0000000 Binary files a/Resources/fivemtimesync/FiveM_TimeSync.net.dll and /dev/null differ diff --git a/Resources/fivemtimesync/FiveM_TimeSyncServer.net.dll b/Resources/fivemtimesync/FiveM_TimeSyncServer.net.dll deleted file mode 100644 index 90ca7c5..0000000 Binary files a/Resources/fivemtimesync/FiveM_TimeSyncServer.net.dll and /dev/null differ diff --git a/Resources/fivemtimesync/__resource.lua b/Resources/fivemtimesync/__resource.lua deleted file mode 100644 index 0f33155..0000000 --- a/Resources/fivemtimesync/__resource.lua +++ /dev/null @@ -1,2 +0,0 @@ -client_script 'FiveM_TimeSync.net.dll' -server_script 'FiveM_TimeSyncServer.net.dll' \ No newline at end of file