diff --git a/VStancer.Client/Config.cs b/VStancer.Client/Config.cs deleted file mode 100644 index b9717b7..0000000 --- a/VStancer.Client/Config.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Vstancer.Client -{ - public class Config - { - protected Dictionary Entries { get; set; } - - public Config(string content) - { - Entries = new Dictionary(); - - if (string.IsNullOrEmpty(content)) - return; - - var splitted = content - .Split('\n') - .Where((line) => !line.Trim().StartsWith("#")) - .Select((line) => line.Trim().Split('=')) - .Where((line) => line.Length == 2); - - foreach (var tuple in splitted) - { - Entries.Add(tuple[0], tuple[1]); - } - } - - public string Get(string key, string fallback = null) - { - if (!string.IsNullOrEmpty(key) && Entries.TryGetValue(key, out string value)) - return value; - else - return fallback; - } - - public int GetIntValue(string key, int fallback) - { - if (!string.IsNullOrEmpty(key) && Entries.TryGetValue(key, out string value)) - { - if (int.TryParse(value, out int tmp)) - return tmp; - } - return fallback; - } - - public float GetFloatValue(string key, float fallback) - { - if (!string.IsNullOrEmpty(key) && Entries.TryGetValue(key, out string value)) - { - if (float.TryParse(value, out float tmp)) - return tmp; - } - return fallback; - } - - public bool GetBoolValue(string key, bool fallback) - { - if (!string.IsNullOrEmpty(key) && Entries.TryGetValue(key, out string value)) - { - if (bool.TryParse(value, out bool tmp)) - return tmp; - } - return fallback; - } - - public long GetLongValue(string key, long fallback) - { - if (!string.IsNullOrEmpty(key) && Entries.TryGetValue(key, out string value)) - { - if (long.TryParse(value, out long tmp)) - return tmp; - } - return fallback; - } - } -} diff --git a/VStancer.Client/Utilities.cs b/VStancer.Client/Utilities.cs index b02762d..1bf1fe1 100644 --- a/VStancer.Client/Utilities.cs +++ b/VStancer.Client/Utilities.cs @@ -1,4 +1,5 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using static CitizenFX.Core.Native.API; @@ -25,4 +26,21 @@ IEnumerator IEnumerable.GetEnumerator() return GetEnumerator(); } } + + public static class Helpers + { + public static string RemoveByteOrderMarks(string xml) + { + /* + string bom = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()); + if (xml.StartsWith(bom)) + xml = xml.Remove(0, bom.Length); + */ + + // Workaround + if (!xml.StartsWith("<", StringComparison.Ordinal)) + xml = xml.Substring(xml.IndexOf("<")); + return xml; + } + } } diff --git a/VStancer.Client/VStancer.Client.csproj b/VStancer.Client/VStancer.Client.csproj index 90c6372..3e1f85c 100644 --- a/VStancer.Client/VStancer.Client.csproj +++ b/VStancer.Client/VStancer.Client.csproj @@ -39,7 +39,7 @@ - + diff --git a/VStancer.Client/VStancerConfig.cs b/VStancer.Client/VStancerConfig.cs new file mode 100644 index 0000000..0ba5068 --- /dev/null +++ b/VStancer.Client/VStancerConfig.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace Vstancer.Client +{ + public class VStancerConfig + { + public bool Debug { get; set; } + public bool ExposeCommand { get; set; } + public bool ExposeEvent { get; set; } + public float ScriptRange { get; set; } + public long Timer { get; set; } + public int ToggleMenuControl { get; set; } + public float FloatStep { get; set; } + public WheelLimits FrontLimits { get; set; } + public WheelLimits RearLimits { get; set; } + + public VStancerConfig() + { + Debug = false; + ExposeCommand = false; + ExposeEvent = false; + ScriptRange = 150.0f; + Timer = 1000; + ToggleMenuControl = 167; + FloatStep = 0.01f; + FrontLimits = new WheelLimits { PositionX = 0.25f, RotationY = 0.20f }; + RearLimits = new WheelLimits { PositionX = 0.25f, RotationY = 0.20f }; + } + + public void LoadXml(string xml) + { + string txt = Helpers.RemoveByteOrderMarks(xml); + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(txt); + + var rootNode = doc[nameof(VStancerConfig)]; + + foreach (XmlNode node in rootNode?.ChildNodes) + { + if (node.NodeType != XmlNodeType.Element) + continue; + + if (node.Name == nameof(Debug) && bool.TryParse(node.InnerText, out bool debugValue)) + Debug = debugValue; + + else if (node.Name == nameof(ExposeCommand) && bool.TryParse(node.InnerText, out bool exposeCommandValue)) + ExposeCommand = exposeCommandValue; + + else if (node.Name == nameof(ExposeEvent) && bool.TryParse(node.InnerText, out bool exposeEventValue)) + ExposeEvent = exposeEventValue; + + else if (node.Name == nameof(ScriptRange) && float.TryParse(node.InnerText, out float scriptRangeValue)) + ScriptRange = scriptRangeValue; + + else if (node.Name == nameof(Timer) && long.TryParse(node.InnerText, out long timerValue)) + Timer = timerValue; + + else if (node.Name == nameof(ToggleMenuControl) && int.TryParse(node.InnerText, out int toggleMenuControlValue)) + ToggleMenuControl = toggleMenuControlValue; + + else if (node.Name == nameof(FloatStep) && float.TryParse(node.InnerText, out float floatStepValue)) + FloatStep = floatStepValue; + + else if (node.Name == nameof(FrontLimits)) + { + var frontLimits = new WheelLimits(); + + foreach (XmlNode child in node.ChildNodes) + { + if (node.NodeType != XmlNodeType.Element) + continue; + + if (child.Name == nameof(WheelLimits.PositionX) && float.TryParse(child.InnerText, out float positionXValue)) + frontLimits.PositionX = positionXValue; + + if (child.Name == nameof(WheelLimits.RotationY) && float.TryParse(child.InnerText, out float rotationYValue)) + frontLimits.RotationY = rotationYValue; + + FrontLimits = frontLimits; + } + } + + else if (node.Name == nameof(RearLimits)) + { + var rearLimits = new WheelLimits(); + + foreach (XmlNode child in node.ChildNodes) + { + if (node.NodeType == XmlNodeType.Comment) + continue; + + if (child.Name == nameof(WheelLimits.PositionX) && float.TryParse(child.InnerText, out float positionXValue)) + rearLimits.PositionX = positionXValue; + + if (child.Name == nameof(WheelLimits.RotationY) && float.TryParse(child.InnerText, out float rotationYValue)) + rearLimits.RotationY = rotationYValue; + + RearLimits = rearLimits; + } + } + + else continue; + } + } + } + + public struct WheelLimits + { + public float PositionX { get; set; } + public float RotationY { get; set; } + } +} diff --git a/VStancer.Client/VStancerEditor.cs b/VStancer.Client/VStancerEditor.cs index 4d47bfd..59f4cfa 100644 --- a/VStancer.Client/VStancerEditor.cs +++ b/VStancer.Client/VStancerEditor.cs @@ -58,7 +58,7 @@ public class VStancerEditor : BaseScript #region Config Fields public int toggleMenu = 167; - public float ScriptRange = 150.0f; + public float scriptRange = 150.0f; public float FloatStep = 0.01f; public float frontMaxOffset = 0.25f; public float frontMaxCamber = 0.20f; @@ -208,8 +208,8 @@ public VStancerEditor() if (float.TryParse(args[0], out float value)) { - ScriptRange = value; - Debug.WriteLine($"{ScriptName}: Received new {nameof(ScriptRange)} value {value}"); + scriptRange = value; + Debug.WriteLine($"{ScriptName}: Received new {nameof(scriptRange)} value {value}"); } else Debug.WriteLine($"{ScriptName}: Error parsing {args[0]} as float"); @@ -382,7 +382,7 @@ private async Task UpdateWorldVehicles() { Vector3 coords = GetEntityCoords(entity, true); - if (Vector3.Distance(currentCoords, coords) <= ScriptRange) + if (Vector3.Distance(currentCoords, coords) <= scriptRange) RefreshVehicleUsingDecorators(entity); } } @@ -794,37 +794,37 @@ private bool HasDecorators(int entity) /// Loads the config file containing all the customizable properties /// /// The name of the file - private void LoadConfig(string filename = "config.ini") + private void LoadConfig(string filename = "config.xml") { - string strings = null; + VStancerConfig config = new VStancerConfig(); try { - strings = LoadResourceFile(ResourceName, filename); + string strings = LoadResourceFile(ResourceName, filename); - Debug.WriteLine($"{ScriptName}: Loaded settings from {filename}"); + config.LoadXml(strings); + + Debug.WriteLine($"{ScriptName}: Loaded config from {filename}"); } catch (Exception e) { - Debug.WriteLine($"{ScriptName}: Impossible to load {filename}"); + Debug.WriteLine($"{ScriptName}: Impossible to load {filename}", e.Message); Debug.WriteLine(e.StackTrace); } finally { - Config config = new Config(strings); - - toggleMenu = config.GetIntValue("toggleMenu", toggleMenu); - FloatStep = config.GetFloatValue("FloatStep", FloatStep); - ScriptRange = config.GetFloatValue("ScriptRange", ScriptRange); - frontMaxOffset = config.GetFloatValue("frontMaxOffset", frontMaxOffset); - frontMaxCamber = config.GetFloatValue("frontMaxCamber", frontMaxCamber); - rearMaxOffset = config.GetFloatValue("rearMaxOffset", rearMaxOffset); - rearMaxCamber = config.GetFloatValue("rearMaxCamber", rearMaxCamber); - timer = config.GetLongValue("timer", timer); - debug = config.GetBoolValue("debug", debug); - exposeCommand = config.GetBoolValue("exposeCommand", exposeCommand); - exposeEvent = config.GetBoolValue("exposeEvent", exposeEvent); - - Debug.WriteLine($"{ScriptName}: Settings {nameof(frontMaxOffset)}={frontMaxOffset} {nameof(frontMaxCamber)}={frontMaxCamber} {nameof(rearMaxOffset)}={rearMaxOffset} {nameof(rearMaxCamber)}={rearMaxCamber} {nameof(timer)}={timer} {nameof(debug)}={debug} {nameof(ScriptRange)}={ScriptRange}"); + toggleMenu = config.ToggleMenuControl; + FloatStep = config.FloatStep; + scriptRange = config.ScriptRange; + frontMaxOffset = config.FrontLimits.PositionX; + frontMaxCamber = config.FrontLimits.RotationY; + rearMaxOffset = config.RearLimits.PositionX; + rearMaxCamber = config.RearLimits.RotationY; + timer = config.Timer; + debug = config.Debug; + exposeCommand = config.ExposeCommand; + exposeEvent = config.ExposeEvent; + + Debug.WriteLine($"{ScriptName}: Settings {nameof(frontMaxOffset)}={frontMaxOffset} {nameof(frontMaxCamber)}={frontMaxCamber} {nameof(rearMaxOffset)}={rearMaxOffset} {nameof(rearMaxCamber)}={rearMaxCamber} {nameof(timer)}={timer} {nameof(debug)}={debug} {nameof(scriptRange)}={scriptRange}"); } } diff --git a/dist/config.ini b/dist/config.ini deleted file mode 100644 index 97a76a2..0000000 --- a/dist/config.ini +++ /dev/null @@ -1,32 +0,0 @@ -#The max distance within each the client refreshes others clients' vehicles -ScriptRange=150.0 - -#The value in milliseconds used by each client to check if its preset requires to be synched again -timer=1000 - -#Enables the debug mode which prints some logs in the console -debug=false - -#Enables the /vstancer command -exposeCommand=false - -#Enable the "vstancer:toggleMenu" event -exposeEvent=false - -#The amount each value changes when you increase or decrease it -FloatStep=0.01 - -#The max value you can increase or decrease the front Track Width -frontMaxOffset=0.25 - -#The max value you can increase or decrease the front Camber -frontMaxCamber=0.20 - -#The max value you can increase or decrease the rear Track Width -rearMaxOffset=0.25 - -#The max value you can increase or decrease the rear Camber -rearMaxCamber=0.20 - -#The Control to toggle the Menu (default is 167=F6) list at https://wiki.fivem.net/wiki/Controls -toggleMenu=167 \ No newline at end of file diff --git a/dist/config.xml b/dist/config.xml new file mode 100644 index 0000000..987b664 --- /dev/null +++ b/dist/config.xml @@ -0,0 +1,18 @@ + + + false + false + false + 150 + 1000 + 167 + 0.01 + + 0.25 + 0.2 + + + 0.25 + 0.2 + + \ No newline at end of file diff --git a/dist/__resource.lua b/dist/fxmanifest.lua similarity index 68% rename from dist/__resource.lua rename to dist/fxmanifest.lua index 8961ee7..dcefed7 100644 --- a/dist/__resource.lua +++ b/dist/fxmanifest.lua @@ -1,11 +1,11 @@ -resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937' - +fx_version 'adamant' +games { 'gta5' } --dependency 'MenuAPI' files { --'@MenuAPI/MenuAPI.dll', 'MenuAPI.dll', - 'config.ini' + 'config.xml' } client_scripts { diff --git a/fivem-vstancer.sln b/fivem-vstancer.sln index 689294f..9e94c20 100644 --- a/fivem-vstancer.sln +++ b/fivem-vstancer.sln @@ -3,12 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28803.202 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VStancer.Client", "VStancer.Client\VStancer.Client.csproj", "{5CB92879-4500-47FC-BD3E-FE29369A621D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VStancer.Client", "VStancer.Client\VStancer.Client.csproj", "{5CB92879-4500-47FC-BD3E-FE29369A621D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{886C4B07-F58C-4E89-A80F-849679435A18}" ProjectSection(SolutionItems) = preProject - dist\__resource.lua = dist\__resource.lua - dist\config.ini = dist\config.ini + dist\config.xml = dist\config.xml + dist\fxmanifest.lua = dist\fxmanifest.lua LICENSE = LICENSE postbuild.bat = postbuild.bat README.md = README.md diff --git a/postbuild.bat b/postbuild.bat index 5d9f093..6db9733 100644 --- a/postbuild.bat +++ b/postbuild.bat @@ -1 +1 @@ -copy /y %1 E:\Carmine\neos7\cfx-server\server-data\resources\[customscripts]\vstancer \ No newline at end of file +copy /y %1 E:\Carmine\neos7\cfx-server\server-data\resources\[neos7]\[customscripts]\vstancer \ No newline at end of file