diff --git a/.editorconfig b/.editorconfig index 10dbb73..738d363 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,9 +17,9 @@ tab_width = 2 # Microsoft .NET properties csharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion -csharp_style_var_elsewhere = false:none -csharp_style_var_for_built_in_types = false:none -csharp_style_var_when_type_is_apparent = false:none +csharp_style_var_elsewhere = true +csharp_style_var_for_built_in_types = true +csharp_style_var_when_type_is_apparent = true dotnet_naming_rule.constants_rule.severity = warning dotnet_naming_rule.constants_rule.style = all_upper_style dotnet_naming_rule.constants_rule.symbols = constants_symbols @@ -66,11 +66,13 @@ resharper_align_multiline_for_stmt = true resharper_align_multline_type_parameter_constrains = true resharper_align_multline_type_parameter_list = true resharper_align_tuple_components = true -resharper_blank_lines_after_multiline_statements = 1 -resharper_blank_lines_around_multiline_case_section = 1 +resharper_blank_lines_after_block_statements = 0 +resharper_blank_lines_after_control_transfer_statements = 0 +resharper_blank_lines_after_multiline_statements = 0 +resharper_blank_lines_around_multiline_case_section = 0 resharper_blank_lines_around_single_line_type = 0 -resharper_blank_lines_before_control_transfer_statements = 1 -resharper_blank_lines_before_multiline_statements = 1 +resharper_blank_lines_before_control_transfer_statements = 0 +resharper_blank_lines_before_multiline_statements = 0 resharper_braces_for_for = required resharper_braces_for_foreach = required resharper_braces_for_ifelse = required @@ -78,11 +80,12 @@ resharper_braces_for_while = required resharper_csharp_align_multiline_parameter = true resharper_csharp_align_multiple_declaration = true resharper_csharp_blank_lines_around_field = 0 -resharper_csharp_max_line_length = 180 +resharper_csharp_max_line_length = 120 resharper_csharp_naming_rule.enum_member = AA_BB resharper_csharp_stick_comment = false resharper_csharp_wrap_after_declaration_lpar = true resharper_csharp_wrap_after_invocation_lpar = true +resharper_csharp_wrap_arguments_style = chop_if_long resharper_csharp_wrap_before_declaration_lpar = true resharper_csharp_wrap_before_invocation_lpar = true resharper_csharp_wrap_before_ternary_opsigns = false diff --git a/CentrED/Application.cs b/CentrED/Application.cs index d957ec3..4d53c4e 100644 --- a/CentrED/Application.cs +++ b/CentrED/Application.cs @@ -5,10 +5,10 @@ using CentrED.Client; using CentrED.Server; -namespace CentrED; +namespace CentrED; -public class Application { - +public class Application +{ static private AssemblyLoadContext _loadContext; static private string? _rootDir; @@ -87,7 +87,7 @@ static private IntPtr ResolveUnmanagedDll(Assembly assembly, string unmanagedDll public static CentrEDGame CEDGame { get; private set; } = null!; public static CEDServer? CEDServer; public static readonly CentrEDClient CEDClient = new(); - + [STAThread] public static void Main(string[] args) { @@ -100,11 +100,14 @@ public static void Main(string[] args) _loadContext.ResolvingUnmanagedDll += ResolveUnmanagedDll; _loadContext.Resolving += ResolveAssembly; - using (CEDGame = new CentrEDGame()) { - try { + using (CEDGame = new CentrEDGame()) + { + try + { CEDGame.Run(); } - catch (Exception e) { + catch (Exception e) + { Console.WriteLine(e.ToString()); File.WriteAllText("Crash.log", e.ToString()); } diff --git a/CentrED/Camera.cs b/CentrED/Camera.cs index 7da6dad..bc32c15 100644 --- a/CentrED/Camera.cs +++ b/CentrED/Camera.cs @@ -17,16 +17,12 @@ public class Camera private Vector3 _up = new(-1, -1, 0); /* This takes the coordinates (x, y, z) and turns it into the screen point (x, y + z, z) */ - private Matrix _oblique = new Matrix( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 1, 1, 0, - 0, 0, 0, 1); + private Matrix _oblique = new Matrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1); private Matrix _translation = Matrix.CreateTranslation(new Vector3(0, 128 * 4, 0)); public Vector3 Position = new(0, 0, 128 * 4); - + //Look directly below camera public Vector3 LookAt => new(Position.X, Position.Y, 0); @@ -38,13 +34,15 @@ public class Camera public bool Moved; - public void Move(float xDelta, float yDelta) { + public void Move(float xDelta, float yDelta) + { Position.X += xDelta; Position.Y += yDelta; Moved = true; } - public void ZoomIn(float delta) { + public void ZoomIn(float delta) + { Zoom += delta; Moved = true; } @@ -61,7 +59,7 @@ public void Update() Matrix ortho = Matrix.CreateOrthographic(ScreenSize.Width, ScreenSize.Height, 0, 128 * 8); Matrix scale = Matrix.CreateScale(Zoom, Zoom, 1f); - + proj = _mirrorX * _oblique * _translation * ortho * scale; Matrix.Multiply(ref world, ref view, out var worldView); diff --git a/CentrED/CentrED.csproj b/CentrED/CentrED.csproj index 430b0bc..7de998f 100644 --- a/CentrED/CentrED.csproj +++ b/CentrED/CentrED.csproj @@ -1,73 +1,73 @@ - - Exe - net7.0 - x64 + + Exe + net7.0 + x64 - enable - enable - true + enable + enable + true - false - true + false + true - true - true + true + true - ../output - ../publish - icon.ico - + ../output + ../publish + icon.ico + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - ..\lib\x64\ClassicUO.Assets.dll - - - ..\lib\x64\ClassicUO.IO.dll - - - ..\lib\x64\ClassicUO.Utility.dll - - - - - - PreserveNewest - - + + + - - - + + + - - - + + + + + + + + + + + ..\lib\x64\ClassicUO.Assets.dll + + + ..\lib\x64\ClassicUO.IO.dll + + + ..\lib\x64\ClassicUO.Utility.dll + + + + + + PreserveNewest + + + + + + + + + + diff --git a/CentrED/CentrEDGame.cs b/CentrED/CentrEDGame.cs index 1cda5e0..19a7c99 100644 --- a/CentrED/CentrEDGame.cs +++ b/CentrED/CentrEDGame.cs @@ -22,7 +22,11 @@ public CentrEDGame() PreferredDepthStencilFormat = DepthFormat.Depth24 }; - _gdm.PreparingDeviceSettings += (sender, e) => { e.GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage = RenderTargetUsage.DiscardContents; }; + _gdm.PreparingDeviceSettings += (sender, e) => + { + e.GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage = + RenderTargetUsage.DiscardContents; + }; IsMouseVisible = true; Window.AllowUserResizing = true; @@ -35,7 +39,7 @@ protected override void Initialize() { _gdm.GraphicsProfile = GraphicsProfile.HiDef; } - + _gdm.ApplyChanges(); NativeLibrary.Load(Path.Combine(AppContext.BaseDirectory, "x64", "zlib.dll")); @@ -68,18 +72,19 @@ protected override void Update(GameTime gameTime) protected override void Draw(GameTime gameTime) { // if (!IsActive) - // return; - + // return; + MapManager.Draw(); UIManager.Draw(gameTime); base.Draw(gameTime); } - - - private void OnWindowResized(object? sender, EventArgs e) { + + + private void OnWindowResized(object? sender, EventArgs e) + { GameWindow window = sender as GameWindow; - if (window != null) + if (window != null) MapManager.OnWindowsResized(window); } } \ No newline at end of file diff --git a/CentrED/Config.cs b/CentrED/Config.cs index 4037c59..4f6dcda 100644 --- a/CentrED/Config.cs +++ b/CentrED/Config.cs @@ -1,37 +1,43 @@ using System.Text.Json; -namespace CentrED; +namespace CentrED; -public class ConfigRoot { +public class ConfigRoot +{ public string ActiveProfile { get; set; } = ""; public string ServerConfigPath { get; set; } = "cedserver.xml"; } -public static class Config { - +public static class Config +{ private static ConfigRoot _configRoot; private static string _configFilePath = "settings.json"; - - static Config() { - if (!File.Exists(_configFilePath)) { + + static Config() + { + if (!File.Exists(_configFilePath)) + { var newConfig = new ConfigRoot(); File.WriteAllText(_configFilePath, JsonSerializer.Serialize(newConfig)); } var jsonText = File.ReadAllText(_configFilePath); - _configRoot = JsonSerializer.Deserialize(jsonText); + _configRoot = JsonSerializer.Deserialize(jsonText); } - public static void Save() { + public static void Save() + { File.WriteAllText(_configFilePath, JsonSerializer.Serialize(_configRoot)); } - public static string ActiveProfile { + public static string ActiveProfile + { get => _configRoot.ActiveProfile; set => _configRoot.ActiveProfile = value; } - - public static string ServerConfigPath { + + public static string ServerConfigPath + { get => _configRoot.ServerConfigPath; set => _configRoot.ServerConfigPath = value; } diff --git a/CentrED/HuesManager.cs b/CentrED/HuesManager.cs index b02bdd3..fa8f111 100644 --- a/CentrED/HuesManager.cs +++ b/CentrED/HuesManager.cs @@ -4,7 +4,8 @@ namespace CentrED; -public class HuesManager { +public class HuesManager +{ private static HuesManager _instance; public static HuesManager Instance => _instance; @@ -14,26 +15,30 @@ public class HuesManager { public readonly string[] Names; public readonly ushort[][] Colors; - private unsafe HuesManager(GraphicsDevice gd) { + private unsafe HuesManager(GraphicsDevice gd) + { var huesLoader = HuesLoader.Instance; HuesCount = huesLoader.HuesCount + 1; Texture = new Texture2D(gd, TEXTURE_WIDTH, HuesCount - 1); uint[] buffer = System.Buffers.ArrayPool.Shared.Rent(TEXTURE_WIDTH * HuesCount); - fixed (uint* ptr = buffer) { + fixed (uint* ptr = buffer) + { huesLoader.CreateShaderColors(buffer); Texture.SetDataPointerEXT(0, null, (IntPtr)ptr, TEXTURE_WIDTH * HuesCount * sizeof(uint)); } System.Buffers.ArrayPool.Shared.Return(buffer); - + Colors = new ushort[HuesCount + 1][]; Names = new string[HuesCount + 1]; Colors[0] = huesLoader.HuesRange[0].Entries[0].ColorTable; Names[0] = "No Hue"; var i = 1; - foreach (var huesGroup in huesLoader.HuesRange) { - foreach (var hueEntry in huesGroup.Entries) { + foreach (var huesGroup in huesLoader.HuesRange) + { + foreach (var hueEntry in huesGroup.Entries) + { Colors[i] = hueEntry.ColorTable; Names[i] = new string(hueEntry.Name); i++; @@ -41,39 +46,47 @@ private unsafe HuesManager(GraphicsDevice gd) { } } - public static void Initialize(GraphicsDevice gd) { + public static void Initialize(GraphicsDevice gd) + { _instance = new HuesManager(gd); } - public enum HueMode { + public enum HueMode + { NONE = 0, HUED = 1, PARTIAL = 2 } - public Vector3 GetHueVector(StaticTile tile, float alpha = 1) { + public Vector3 GetHueVector(StaticTile tile, float alpha = 1) + { return GetHueVector(tile.Id, tile.Hue, alpha); } - - public Vector3 GetHueVector(ushort id, ushort hue, float alpha = 1) { + + public Vector3 GetHueVector(ushort id, ushort hue, float alpha = 1) + { var partial = TileDataLoader.Instance.StaticData[id].IsPartialHue; var translucent = TileDataLoader.Instance.StaticData[id].IsTranslucent; return GetHueVector(hue, partial, translucent ? 0.6f : alpha); } - public Vector3 GetHueVector(ushort hue, bool partial, float alpha = 1) { + public Vector3 GetHueVector(ushort hue, bool partial, float alpha = 1) + { HueMode mode; - if ((hue & 0x8000) != 0) { + if ((hue & 0x8000) != 0) + { partial = true; hue &= 0x7FFF; } - if (hue != 0) { + if (hue != 0) + { // hue -= 1; mode = partial ? HueMode.PARTIAL : HueMode.HUED; } - else { + else + { mode = HueMode.NONE; } diff --git a/CentrED/IO/Models/Profile.cs b/CentrED/IO/Models/Profile.cs index 88caa7a..a19ef23 100644 --- a/CentrED/IO/Models/Profile.cs +++ b/CentrED/IO/Models/Profile.cs @@ -1,16 +1,14 @@ using System.Text.Json.Serialization; -namespace CentrED.IO.Models +namespace CentrED.IO.Models; + +public class Profile { - public class Profile - { - [JsonIgnore] - public string Name { get; set; } - public string Hostname { get; set; } = "127.0.0.1"; - public int Port { get; set; } = 2597; - public string Username { get; set; } = ""; - public string ClientPath { get; set; } = ""; - public string ClientVersion { get; set; } = ""; - public Dictionary RadarFavorites { get; set; } = new(); - } -} + [JsonIgnore] public string Name { get; set; } + public string Hostname { get; set; } = "127.0.0.1"; + public int Port { get; set; } = 2597; + public string Username { get; set; } = ""; + public string ClientPath { get; set; } = ""; + public string ClientVersion { get; set; } = ""; + public Dictionary RadarFavorites { get; set; } = new(); +} \ No newline at end of file diff --git a/CentrED/IO/Models/RadarFavorite.cs b/CentrED/IO/Models/RadarFavorite.cs index 5ffc0bf..fdfbf55 100644 --- a/CentrED/IO/Models/RadarFavorite.cs +++ b/CentrED/IO/Models/RadarFavorite.cs @@ -1,8 +1,7 @@ -namespace CentrED.IO.Models +namespace CentrED.IO.Models; + +public class RadarFavorite { - public class RadarFavorite - { - public int X { get; set; } - public int Y { get; set; } - } -} + public int X { get; set; } + public int Y { get; set; } +} \ No newline at end of file diff --git a/CentrED/IO/ProfileManager.cs b/CentrED/IO/ProfileManager.cs index 9b42d75..b68def9 100644 --- a/CentrED/IO/ProfileManager.cs +++ b/CentrED/IO/ProfileManager.cs @@ -3,7 +3,6 @@ namespace CentrED.IO; - public static class ProfileManager { private const string ProfilesDir = "profiles"; @@ -24,6 +23,7 @@ static ProfileManager() Profiles.Add(profile); } } + public static string[] ProfileNames => Profiles.Select(p => p.Name).ToArray(); public static Profile ActiveProfile => Profiles.Find(p => p.Name == Config.ActiveProfile) ?? new Profile(); diff --git a/CentrED/Map/Epsilon.cs b/CentrED/Map/Epsilon.cs index 6766e46..1c0b767 100644 --- a/CentrED/Map/Epsilon.cs +++ b/CentrED/Map/Epsilon.cs @@ -1,6 +1,7 @@ -namespace CentrED.Map; +namespace CentrED.Map; -public class Epsilon { +public class Epsilon +{ public static readonly float value = GetMachineEpsilonFloat(); private static float GetMachineEpsilonFloat() @@ -15,8 +16,7 @@ private static float GetMachineEpsilonFloat() { machineEpsilon *= 0.5f; comparison = 1.0f + machineEpsilon; - } - while (comparison > 1.0f); + } while (comparison > 1.0f); return machineEpsilon; } diff --git a/CentrED/Map/LandObject.cs b/CentrED/Map/LandObject.cs index 763167f..2d0c541 100644 --- a/CentrED/Map/LandObject.cs +++ b/CentrED/Map/LandObject.cs @@ -5,12 +5,14 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -namespace CentrED.Map; +namespace CentrED.Map; -public class LandObject : MapObject { +public class LandObject : MapObject +{ public LandTile LandTile; - public LandObject(CentrEDClient client, LandTile tile) { + public LandObject(CentrEDClient client, LandTile tile) + { Tile = tile; LandTile = tile; ref var tileData = ref TileDataLoader.Instance.LandData[tile.Id]; @@ -20,25 +22,28 @@ public LandObject(CentrEDClient client, LandTile tile) { Vector3 normalRight; Vector3 normalLeft; Vector3 normalBottom; - - if ((tileData.Flags & TileFlag.Wet) != 0) { // Water tiles are always flat + + if ((tileData.Flags & TileFlag.Wet) != 0) + { + // Water tiles are always flat cornerZ = new Vector4(tile.Z * TILE_Z_SCALE); normalTop = normalRight = normalLeft = normalBottom = Vector3.UnitZ; } - else { + else + { cornerZ = GetCornerZ(client, tile); normalTop = ComputeNormal(client, tile.X, tile.Y); normalRight = ComputeNormal(client, tile.X + 1, tile.Y); normalLeft = ComputeNormal(client, tile.X, tile.Y + 1); normalBottom = ComputeNormal(client, tile.X + 1, tile.Y + 1); } - + var normals = new Vector3[4]; normals[0] = normalTop; normals[1] = normalRight; normals[2] = normalLeft; normals[3] = normalBottom; - + var posX = (tile.X - 1) * TILE_SIZE; var posY = (tile.Y - 1) * TILE_SIZE; @@ -51,16 +56,20 @@ public LandObject(CentrEDClient client, LandTile tile) { Texture2D? tileTex = null; Rectangle bounds; - var diamondTexture = IsFlat(cornerZ.X, cornerZ.Y, cornerZ.Z, cornerZ.W) || TexmapsLoader.Instance.GetValidRefEntry(tile.Id).Equals(UOFileIndex.Invalid); - if (diamondTexture) { + var diamondTexture = IsFlat + (cornerZ.X, cornerZ.Y, cornerZ.Z, cornerZ.W) || TexmapsLoader.Instance.GetValidRefEntry(tile.Id).Equals + (UOFileIndex.Invalid); + if (diamondTexture) + { Texture = ArtLoader.Instance.GetLandTexture(tile.Id, out bounds); } - else { + else + { Texture = TexmapsLoader.Instance.GetLandTexture(tile.Id, out bounds); } - + float onePixel = Math.Max(1.0f / Texture.Width, Epsilon.value); - + var texX = bounds.X / (float)Texture.Width + (onePixel / 2f); var texY = bounds.Y / (float)Texture.Height + (onePixel / 2f); var texWidth = (bounds.Width / (float)Texture.Width) - onePixel; @@ -82,17 +91,19 @@ public LandObject(CentrEDClient client, LandTile tile) { texCoords[3] = new Vector3(texX + texWidth, texY + texHeight, 0); } - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) + { Vertices[i] = new MapVertex(coordinates[i], normals[i], texCoords[i], Vector3.Zero); } } - - private bool IsFlat(float x, float y, float z, float w) { + + private bool IsFlat(float x, float y, float z, float w) + { return x == y && x == z && x == w; } - - private Vector4 - GetCornerZ(CentrEDClient client, LandTile tile) { + + private Vector4 GetCornerZ(CentrEDClient client, LandTile tile) + { var x = tile.X; var y = tile.Y; var top = tile; @@ -100,26 +111,21 @@ private Vector4 var left = client.GetLandTile(x, Math.Min(client.Height * 8 - 1, y + 1)); var bottom = client.GetLandTile(Math.Min(client.Width * 8 - 1, x + 1), Math.Min(client.Height * 8 - 1, y + 1)); - return new Vector4( - top.Z * TILE_Z_SCALE, - right.Z * TILE_Z_SCALE, - left.Z * TILE_Z_SCALE, - bottom.Z * TILE_Z_SCALE - ); + return new Vector4 + (top.Z * TILE_Z_SCALE, right.Z * TILE_Z_SCALE, left.Z * TILE_Z_SCALE, bottom.Z * TILE_Z_SCALE); } - - private static (Vector2, Vector2)[] _normalOffsets = + + private static (Vector2, Vector2)[] _normalOffsets = { - (new Vector2(1, 0), new Vector2(0, 1)), - (new Vector2(0, 1), new Vector2(-1, 0)), - (new Vector2(-1, 0), new Vector2(0, -1)), - (new Vector2(0, -1), new Vector2(1, 0)) + (new Vector2(1, 0), new Vector2(0, 1)), (new Vector2(0, 1), new Vector2(-1, 0)), + (new Vector2(-1, 0), new Vector2(0, -1)), (new Vector2(0, -1), new Vector2(1, 0)) }; - - + + private Vector3 ComputeNormal(CentrEDClient client, int tileX, int tileY) { - var t = client.GetLandTile(Math.Clamp(tileX, 0, client.Width * 8 - 1), Math.Clamp(tileY, 0, client.Height * 8 - 1)); + var t = client.GetLandTile + (Math.Clamp(tileX, 0, client.Width * 8 - 1), Math.Clamp(tileY, 0, client.Height * 8 - 1)); Vector3 normal = Vector3.Zero; @@ -127,8 +133,16 @@ private Vector3 ComputeNormal(CentrEDClient client, int tileX, int tileY) { (var tu, var tv) = _normalOffsets[i]; - var tx = client.GetLandTile(Math.Clamp((int)(tileX + tu.X), 0, client.Width * 8 - 1), Math.Clamp((int)(tileY + tu.Y), 0, client.Height * 8 - 1)); - var ty = client.GetLandTile(Math.Clamp((int)(tileX + tv.X), 0, client.Width * 8 - 1), Math.Clamp((int)(tileY + tu.Y), 0, client.Height * 8 - 1)); + var tx = client.GetLandTile + ( + Math.Clamp((int)(tileX + tu.X), 0, client.Width * 8 - 1), + Math.Clamp((int)(tileY + tu.Y), 0, client.Height * 8 - 1) + ); + var ty = client.GetLandTile + ( + Math.Clamp((int)(tileX + tv.X), 0, client.Width * 8 - 1), + Math.Clamp((int)(tileY + tu.Y), 0, client.Height * 8 - 1) + ); if (tx.Id == 0 || ty.Id == 0) continue; @@ -143,20 +157,24 @@ private Vector3 ComputeNormal(CentrEDClient client, int tileX, int tileY) return Vector3.Normalize(normal); } - public void UpdateId(ushort newId) { + public void UpdateId(ushort newId) + { Texture2D? tileTex = null; Rectangle bounds; - var isFlat = IsFlat(Vertices[0].Position.Z, Vertices[1].Position.Z, Vertices[2].Position.Z, Vertices[3].Position.Z); + var isFlat = IsFlat + (Vertices[0].Position.Z, Vertices[1].Position.Z, Vertices[2].Position.Z, Vertices[3].Position.Z); var diamondTexture = isFlat || TexmapsLoader.Instance.GetValidRefEntry(newId).Equals(UOFileIndex.Invalid); - if (diamondTexture) { + if (diamondTexture) + { Texture = ArtLoader.Instance.GetLandTexture(newId, out bounds); } - else { + else + { Texture = TexmapsLoader.Instance.GetLandTexture(newId, out bounds); } - + float onePixel = Math.Max(1.0f / Texture.Width, Epsilon.value); - + var texX = bounds.X / (float)Texture.Width + (onePixel / 2f); var texY = bounds.Y / (float)Texture.Height + (onePixel / 2f); var texWidth = (bounds.Width / (float)Texture.Width) - onePixel; @@ -177,8 +195,9 @@ public void UpdateId(ushort newId) { texCoords[2] = new Vector3(texX, texY + texHeight, 0); texCoords[3] = new Vector3(texX + texWidth, texY + texHeight, 0); } - - for (int i = 0; i < 4; i++) { + + for (int i = 0; i < 4; i++) + { Vertices[i].TextureCoordinate = texCoords[i]; } } diff --git a/CentrED/Map/MapManager.cs b/CentrED/Map/MapManager.cs index ebf23aa..cd697f2 100644 --- a/CentrED/Map/MapManager.cs +++ b/CentrED/Map/MapManager.cs @@ -14,8 +14,8 @@ namespace CentrED.Map; -public class MapManager { - +public class MapManager +{ private readonly GraphicsDevice _gfxDevice; private readonly MapEffect _mapEffect; @@ -76,84 +76,93 @@ public MapManager(GraphicsDevice gd) _gfxDevice = gd; _mapEffect = new MapEffect(gd); _mapRenderer = new MapRenderer(gd); - _shadowTarget = new RenderTarget2D( - gd, - gd.PresentationParameters.BackBufferWidth * 2, - gd.PresentationParameters.BackBufferHeight * 2, - false, - SurfaceFormat.Single, - DepthFormat.Depth24); - - _selectionTarget = new RenderTarget2D( + _shadowTarget = new RenderTarget2D + ( + gd, + gd.PresentationParameters.BackBufferWidth * 2, + gd.PresentationParameters.BackBufferHeight * 2, + false, + SurfaceFormat.Single, + DepthFormat.Depth24 + ); + + _selectionTarget = new RenderTarget2D + ( gd, gd.PresentationParameters.BackBufferWidth, gd.PresentationParameters.BackBufferHeight, false, SurfaceFormat.Color, - DepthFormat.Depth24); + DepthFormat.Depth24 + ); _postProcessRenderer = new PostProcessRenderer(gd); _spriteBatch = new SpriteBatch(gd); _background = CEDGame.Content.Load("background"); Client = CEDClient; - Client.LandTileReplaced += (tile, newId) => { - LandTiles.Find(l => l.LandTile.Equals(tile))?.UpdateId(newId); - }; - Client.LandTileElevated += (tile, newZ) => { - Vector2[] offsets = { - new(0, 0), //top + Client.LandTileReplaced += (tile, newId) => { LandTiles.Find(l => l.LandTile.Equals(tile))?.UpdateId(newId); }; + Client.LandTileElevated += (tile, newZ) => + { + Vector2[] offsets = + { + new(0, 0), //top new(-1, 0), //right new(0, -1), //left new(-1, -1) //bottom }; - - for (var i = 0; i < offsets.Length; i++) { + + for (var i = 0; i < offsets.Length; i++) + { var offset = offsets[i]; - var landObject = LandTiles.Find(l => - l.LandTile.X == (ushort)(tile.X + offset.X) && - l.LandTile.Y == (ushort)(tile.Y + offset.Y)); - if (landObject != null) { + var landObject = LandTiles.Find + (l => l.LandTile.X == (ushort)(tile.X + offset.X) && l.LandTile.Y == (ushort)(tile.Y + offset.Y)); + if (landObject != null) + { landObject.Vertices[i].Position.Z = newZ * MapObject.TILE_Z_SCALE; landObject.UpdateId(landObject.LandTile.Id); //Just refresh ID to refresh if it's flat } } //We need to update normals too }; - Client.BlockLoaded += block => { - block.StaticBlock.SortTiles(ref TileDataLoader.Instance.StaticData); - }; - Client.BlockUnloaded += block => { - var tiles = block.StaticBlock.AllTiles(); - foreach (var tile in tiles) { - StaticTiles.RemoveAll(so => so.StaticTile.Equals(tile)); - } - }; - Client.StaticTileRemoved += tile => { - StaticTiles.RemoveAll(so => so.StaticTile.Equals(tile)); + Client.BlockLoaded += block => { block.StaticBlock.SortTiles(ref TileDataLoader.Instance.StaticData); }; + Client.BlockUnloaded += block => + { + var tiles = block.StaticBlock.AllTiles(); + foreach (var tile in tiles) + { + StaticTiles.RemoveAll(so => so.StaticTile.Equals(tile)); + } }; - Client.StaticTileAdded += tile => { + Client.StaticTileRemoved += tile => { StaticTiles.RemoveAll(so => so.StaticTile.Equals(tile)); }; + Client.StaticTileAdded += tile => + { tile.Block?.SortTiles(ref TileDataLoader.Instance.StaticData); StaticTiles.Add(new StaticObject(tile)); }; - Client.StaticTileMoved += (tile, newX, newY) => { + Client.StaticTileMoved += (tile, newX, newY) => + { StaticTiles.RemoveAll(so => so.StaticTile.Equals(tile)); var newTile = new StaticTile(tile.Id, newX, newY, tile.Z, tile.Hue, tile.Block); StaticTiles.Add(new StaticObject(newTile)); }; - Client.StaticTileElevated += (tile, newZ) => { + Client.StaticTileElevated += (tile, newZ) => + { StaticTiles.RemoveAll(so => so.StaticTile.Equals(tile)); var newTile = new StaticTile(tile.Id, tile.X, tile.Y, newZ, tile.Hue, tile.Block); StaticTiles.Add(new StaticObject(newTile)); }; - Client.StaticTileHued += (tile, newHue) => { + Client.StaticTileHued += (tile, newHue) => + { StaticTiles.First(so => so.StaticTile.Equals(tile)).Hue = newHue; }; Client.Moved += SetPos; - Client.Connected += () => { + Client.Connected += () => + { LandTiles.Clear(); StaticTiles.Clear(); }; - Client.Disconnected += () => { + Client.Disconnected += () => + { LandTiles.Clear(); StaticTiles.Clear(); }; @@ -175,48 +184,60 @@ public MapManager(GraphicsDevice gd) _lightingState.LightDirection = new Vector3(0, -1, -1f); _lightingState.LightDiffuseColor = Vector3.Normalize(new Vector3(1, 1, 1)); _lightingState.LightSpecularColor = Vector3.Zero; - _lightingState.AmbientLightColor = new Vector3( + _lightingState.AmbientLightColor = new Vector3 + ( 1f - _lightingState.LightDiffuseColor.X, 1f - _lightingState.LightDiffuseColor.Y, 1f - _lightingState.LightDiffuseColor.Z ); } - public void Load(string clientPath, string clientVersion) { + public void Load(string clientPath, string clientVersion) + { var valid = ClientVersionHelper.IsClientVersionValid(clientVersion, out UOFileManager.Version); UOFileManager.BasePath = clientPath; - UOFileManager.IsUOPInstallation = UOFileManager.Version >= ClientVersion.CV_7000 && File.Exists(UOFileManager.GetUOFilePath("MainMisc.uop")); - - if (!Task.WhenAll( new List - { - ArtLoader.Instance.Load(), - HuesLoader.Instance.Load(), - TileDataLoader.Instance.Load(), - TexmapsLoader.Instance.Load(), - }).Wait(TimeSpan.FromSeconds(10.0))) + UOFileManager.IsUOPInstallation = UOFileManager.Version >= ClientVersion.CV_7000 && File.Exists + (UOFileManager.GetUOFilePath("MainMisc.uop")); + + if (!Task.WhenAll + ( + new List + { + ArtLoader.Instance.Load(), + HuesLoader.Instance.Load(), + TileDataLoader.Instance.Load(), + TexmapsLoader.Instance.Load(), + } + ).Wait(TimeSpan.FromSeconds(10.0))) Log.Panic("Loading files timeout."); - + TextureAtlas.InitializeSharedTexture(_gfxDevice); HuesManager.Initialize(_gfxDevice); RadarMap.Initialize(_gfxDevice); - + var landIds = new List(); - for (int i = 0; i < TileDataLoader.Instance.LandData.Length; i++) { - if (!ArtLoader.Instance.GetValidRefEntry(i).Equals(UOFileIndex.Invalid)) { + for (int i = 0; i < TileDataLoader.Instance.LandData.Length; i++) + { + if (!ArtLoader.Instance.GetValidRefEntry(i).Equals(UOFileIndex.Invalid)) + { landIds.Add(i); } } ValidLandIds = landIds.ToArray(); var staticIds = new List(); - for (int i = 0; i < TileDataLoader.Instance.StaticData.Length; i++) { - if (!ArtLoader.Instance.GetValidRefEntry(i + ArtLoader.MAX_LAND_DATA_INDEX_COUNT).Equals(UOFileIndex.Invalid)) { + for (int i = 0; i < TileDataLoader.Instance.StaticData.Length; i++) + { + if (!ArtLoader.Instance.GetValidRefEntry(i + ArtLoader.MAX_LAND_DATA_INDEX_COUNT).Equals + (UOFileIndex.Invalid)) + { staticIds.Add(i); } } ValidStaticIds = staticIds.ToArray(); } - public void SetPos(ushort x, ushort y) { + public void SetPos(ushort x, ushort y) + { Camera.Position.X = x * TILE_SIZE; Camera.Position.Y = y * TILE_SIZE; Camera.Moved = true; @@ -237,7 +258,8 @@ private enum MouseDirection // This is all just a fast math way to figure out what the direction of the mouse is. private MouseDirection ProcessMouseMovement(ref MouseState mouseState, out float distance) { - Vector2 vec = new Vector2(mouseState.X - (Camera.ScreenSize.Width / 2), mouseState.Y - (Camera.ScreenSize.Height / 2)); + Vector2 vec = new Vector2 + (mouseState.X - (Camera.ScreenSize.Width / 2), mouseState.Y - (Camera.ScreenSize.Height / 2)); int hashf = 100 * (Math.Sign(vec.X) + 2) + 10 * (Math.Sign(vec.Y) + 2); @@ -295,8 +317,10 @@ private MouseDirection ProcessMouseMovement(ref MouseState mouseState, out float private MouseState _prevMouseState = Mouse.GetState(); private Rectangle _prevViewRange; - public void Update(GameTime gameTime, bool isActive, bool processMouse, bool processKeyboard) { - if (!Client.Initialized) return; + public void Update(GameTime gameTime, bool isActive, bool processMouse, bool processKeyboard) + { + if (!Client.Initialized) + return; if (isActive && processMouse) { var mouse = Mouse.GetState(); @@ -339,19 +363,24 @@ public void Update(GameTime gameTime, bool isActive, bool processMouse, bool pro { Camera.ZoomIn((mouse.ScrollWheelValue - _prevMouseState.ScrollWheelValue) / WHEEL_DELTA); } - - if (_gfxDevice.Viewport.Bounds.Contains(new Point(mouse.X, mouse.Y))) { + + if (_gfxDevice.Viewport.Bounds.Contains(new Point(mouse.X, mouse.Y))) + { var newSelected = GetMouseSelection(mouse.X, mouse.Y); - if (newSelected != Selected) { + if (newSelected != Selected) + { ActiveTool?.OnMouseLeave(Selected); Selected = newSelected; ActiveTool?.OnMouseEnter(Selected); } - if (Selected != null) { - if (mouse.LeftButton == ButtonState.Pressed) { + if (Selected != null) + { + if (mouse.LeftButton == ButtonState.Pressed) + { ActiveTool?.OnMousePressed(Selected); } - if (mouse.LeftButton == ButtonState.Released) { + if (mouse.LeftButton == ButtonState.Released) + { ActiveTool?.OnMouseReleased(Selected); } } @@ -387,34 +416,43 @@ public void Update(GameTime gameTime, bool isActive, bool processMouse, bool pro } CalculateViewRange(Camera, out var viewRange); - if (_prevViewRange != viewRange) { + if (_prevViewRange != viewRange) + { List requested = new List(); - for (var x = viewRange.Left / 8 - 1; x < viewRange.Right / 8 + 1; x++) { - for (var y = viewRange.Top / 8 - 1; y < viewRange.Bottom / 8 + 1; y++) { - if(_prevViewRange.Contains(x,y)) continue; + for (var x = viewRange.Left / 8 - 1; x < viewRange.Right / 8 + 1; x++) + { + for (var y = viewRange.Top / 8 - 1; y < viewRange.Bottom / 8 + 1; y++) + { + if (_prevViewRange.Contains(x, y)) + continue; requested.Add(new BlockCoords((ushort)x, (ushort)y)); } } - if (Client.Running) { + if (Client.Running) + { Client.ResizeCache(viewRange.Width * viewRange.Height / 8); Client.LoadBlocks(requested); } LandTiles.RemoveAll(o => !viewRange.Contains(o.Tile.X, o.Tile.Y)); StaticTiles.RemoveAll(o => !viewRange.Contains(o.Tile.X, o.Tile.Y)); - - for (int x = viewRange.Left; x < viewRange.Right; x++) { - for (int y = viewRange.Top; y < viewRange.Bottom; y++) { - if(_prevViewRange.Contains(x, y)) continue; - LandTiles.Add(new LandObject(Client, Client.GetLandTile(x,y))); + + for (int x = viewRange.Left; x < viewRange.Right; x++) + { + for (int y = viewRange.Top; y < viewRange.Bottom; y++) + { + if (_prevViewRange.Contains(x, y)) + continue; + LandTiles.Add(new LandObject(Client, Client.GetLandTile(x, y))); var staticTiles = Client.GetStaticTiles(x, y); - foreach (var staticTile in staticTiles) { + foreach (var staticTile in staticTiles) + { StaticTiles.Add(new StaticObject(staticTile)); } } } - + Camera.Update(); _lightSourceCamera.Position = Camera.Position; @@ -430,7 +468,8 @@ public void Update(GameTime gameTime, bool isActive, bool processMouse, bool pro _prevMouseState = Mouse.GetState(); } - public void Reset() { + public void Reset() + { Client.ResizeCache(0); LandTiles.Clear(); StaticTiles.Clear(); @@ -438,20 +477,22 @@ public void Reset() { } public MapObject? Selected; - - public MapObject? GetMouseSelection(int x, int y) { + + public MapObject? GetMouseSelection(int x, int y) + { Color[] pixels = new Color[1]; _selectionTarget.GetData(0, new Rectangle(x, y, 1, 1), pixels, 0, 1); var pixel = pixels[0]; var selectedIndex = pixel.R | (pixel.G << 8) | (pixel.B << 16); - if (selectedIndex < 1 || selectedIndex > LandTiles.Count + StaticTiles.Count) + if (selectedIndex < 1 || selectedIndex > LandTiles.Count + StaticTiles.Count) return null; - if(selectedIndex > LandTiles.Count) + if (selectedIndex > LandTiles.Count) return StaticTiles[selectedIndex - 1 - LandTiles.Count]; return LandTiles[selectedIndex - 1]; } - public void CalculateViewRange(Camera camera, out Rectangle rect) { + public void CalculateViewRange(Camera camera, out Rectangle rect) + { float zoom = camera.Zoom; int screenWidth = camera.ScreenSize.Width; @@ -461,15 +502,17 @@ public void CalculateViewRange(Camera camera, out Rectangle rect) { float screenDiamondDiagonal = (screenWidth + screenHeight) / zoom / 2f; Vector3 center = camera.Position; - + // Render a few extra rows at the top to deal with things at lower z var minTileX = Math.Max(0, (int)Math.Ceiling((center.X - screenDiamondDiagonal) / TILE_SIZE) - 8); var minTileY = Math.Max(0, (int)Math.Ceiling((center.Y - screenDiamondDiagonal) / TILE_SIZE) - 8); // Render a few extra rows at the bottom to deal with things at higher z - var maxTileX = Math.Min(Client.Width * 8 - 1, (int)Math.Ceiling((center.X + screenDiamondDiagonal) / TILE_SIZE) + 8); - var maxTileY = Math.Min(Client.Height * 8 - 1, (int)Math.Ceiling((center.Y + screenDiamondDiagonal) / TILE_SIZE) + 8); - + var maxTileX = Math.Min + (Client.Width * 8 - 1, (int)Math.Ceiling((center.X + screenDiamondDiagonal) / TILE_SIZE) + 8); + var maxTileY = Math.Min + (Client.Height * 8 - 1, (int)Math.Ceiling((center.Y + screenDiamondDiagonal) / TILE_SIZE) + 8); + rect = new Rectangle(minTileX, minTileY, maxTileX - minTileX, maxTileY - minTileY); } @@ -485,11 +528,9 @@ private bool IsRock(ushort id) case 4958: case 4959: case 4960: - case 4962: - return true; + case 4962: return true; - default: - return id >= 6001 && id <= 6012; + default: return id >= 6001 && id <= 6012; } } @@ -556,13 +597,12 @@ private bool IsTree(ushort id) case 39225: case 39284: case 46822: - case 14492: - return true; + case 14492: return true; } return false; } - + private bool CanDrawStatic(ushort id) { if (id >= TileDataLoader.Instance.StaticData.Length) @@ -578,17 +618,15 @@ private bool CanDrawStatic(ushort id) { case 0x0001: case 0x21BC: - case 0x63D3: - return false; + case 0x63D3: return false; case 0x9E4C: case 0x9E64: case 0x9E65: case 0x9E7D: - return ((data.Flags & TileFlag.Background) == 0 && - (data.Flags & TileFlag.Surface) == 0 - // && (data.Flags & TileFlag.NoDraw) == 0 - ); + return ((data.Flags & TileFlag.Background) == 0 && (data.Flags & TileFlag.Surface) == 0 + // && (data.Flags & TileFlag.NoDraw) == 0 + ); case 0x2198: case 0x2199: @@ -596,149 +634,232 @@ private bool CanDrawStatic(ushort id) case 0x21A1: case 0x21A2: case 0x21A3: - case 0x21A4: - return false; + case 0x21A4: return false; } return true; } - - private bool ShouldRender(short z) { + + private bool ShouldRender(short z) + { return z >= MIN_Z && z <= MAX_Z; } - - private void DrawStatic(StaticObject so, Vector3 hueOverride = default) { + + private void DrawStatic(StaticObject so, Vector3 hueOverride = default) + { var tile = so.Tile; - if (!CanDrawStatic(tile.Id) ) + if (!CanDrawStatic(tile.Id)) return; - + var landTile = Client.GetLandTile(tile.X, tile.Y); if (!ShouldRender(tile.Z) || (ShouldRender(landTile.Z) && landTile.Z > tile.Z + 5)) return; - + _mapRenderer.DrawMapObject(so, hueOverride); } - + private void DrawLand(LandObject lo, Vector3 hueOverride = default) { - if (lo.Tile.Id > TileDataLoader.Instance.LandData.Length) return; - if (!ShouldRender(lo.Tile.Z)) return; - + if (lo.Tile.Id > TileDataLoader.Instance.LandData.Length) + return; + if (!ShouldRender(lo.Tile.Z)) + return; + _mapRenderer.DrawMapObject(lo, hueOverride); } - public void Draw() { - if (!Client.Initialized) { + public void Draw() + { + if (!Client.Initialized) + { DrawBackground(); return; } - _gfxDevice.Viewport = new Viewport(0, 0, _gfxDevice.PresentationParameters.BackBufferWidth, - _gfxDevice.PresentationParameters.BackBufferHeight); + _gfxDevice.Viewport = new Viewport + ( + 0, + 0, + _gfxDevice.PresentationParameters.BackBufferWidth, + _gfxDevice.PresentationParameters.BackBufferHeight + ); CalculateViewRange(Camera, out var rect); - + _mapEffect.WorldViewProj = _lightSourceCamera.WorldViewProj; _mapEffect.LightSource.Enabled = false; _mapEffect.CurrentTechnique = _mapEffect.Techniques["ShadowMap"]; - _mapRenderer.Begin(_shadowTarget, _mapEffect, _lightSourceCamera, RasterizerState.CullNone, - SamplerState.PointClamp, _depthStencilState, BlendState.AlphaBlend, null, null, true); - if (IsDrawShadows) { - foreach (var staticTile in StaticTiles) { - if (!IsRock(staticTile.Tile.Id) && !IsTree(staticTile.Tile.Id) && !TileDataLoader.Instance.StaticData[staticTile.Tile.Id].IsFoliage) + _mapRenderer.Begin + ( + _shadowTarget, + _mapEffect, + _lightSourceCamera, + RasterizerState.CullNone, + SamplerState.PointClamp, + _depthStencilState, + BlendState.AlphaBlend, + null, + null, + true + ); + if (IsDrawShadows) + { + foreach (var staticTile in StaticTiles) + { + if (!IsRock(staticTile.Tile.Id) && !IsTree(staticTile.Tile.Id) && + !TileDataLoader.Instance.StaticData[staticTile.Tile.Id].IsFoliage) continue; DrawStatic(staticTile); } - foreach (var landTile in LandTiles) { + foreach (var landTile in LandTiles) + { DrawLand(landTile); } } _mapRenderer.End(); - + _mapEffect.WorldViewProj = Camera.WorldViewProj; - + _mapEffect.CurrentTechnique = _mapEffect.Techniques["Selection"]; - _mapRenderer.Begin(_selectionTarget, _mapEffect, Camera, RasterizerState.CullNone, SamplerState.PointClamp, - _depthStencilState, BlendState.AlphaBlend, null, null, true); + _mapRenderer.Begin + ( + _selectionTarget, + _mapEffect, + Camera, + RasterizerState.CullNone, + SamplerState.PointClamp, + _depthStencilState, + BlendState.AlphaBlend, + null, + null, + true + ); //0 is no tile in selection buffer var i = 1; - foreach (var tile in LandTiles) { + foreach (var tile in LandTiles) + { var color = new Color(i & 0xFF, (i >> 8) & 0xFF, (i >> 16) & 0xFF); DrawLand(tile, color.ToVector3()); i++; } - foreach (var tile in StaticTiles) { + foreach (var tile in StaticTiles) + { var color = new Color(i & 0xFF, (i >> 8) & 0xFF, (i >> 16) & 0xFF); DrawStatic(tile, color.ToVector3()); i++; } - + _mapRenderer.End(); - + _mapEffect.LightWorldViewProj = _lightSourceCamera.WorldViewProj; _mapEffect.AmbientLightColor = _lightingState.AmbientLightColor; _mapEffect.LightSource.Direction = _lightingState.LightDirection; _mapEffect.LightSource.DiffuseColor = _lightingState.LightDiffuseColor; _mapEffect.LightSource.SpecularColor = _lightingState.LightSpecularColor; _mapEffect.LightSource.Enabled = true; - + _mapEffect.CurrentTechnique = _mapEffect.Techniques["Terrain"]; - _mapRenderer.Begin(null, _mapEffect, Camera, RasterizerState.CullNone, SamplerState.PointClamp, - _depthStencilState, BlendState.AlphaBlend, _shadowTarget, HuesManager.Instance.Texture, true); + _mapRenderer.Begin + ( + null, + _mapEffect, + Camera, + RasterizerState.CullNone, + SamplerState.PointClamp, + _depthStencilState, + BlendState.AlphaBlend, + _shadowTarget, + HuesManager.Instance.Texture, + true + ); _spriteBatch.Begin(); - var backgroundRect = new Rectangle( + var backgroundRect = new Rectangle + ( _gfxDevice.PresentationParameters.BackBufferWidth / 2 - _background.Width / 2, _gfxDevice.PresentationParameters.BackBufferHeight / 2 - _background.Height / 2, _background.Width, - _background.Height); + _background.Height + ); _spriteBatch.Draw(_background, backgroundRect, Color.White); _spriteBatch.End(); - if (IsDrawLand) { - foreach (var tile in LandTiles) { - if(tile.Visible) + if (IsDrawLand) + { + foreach (var tile in LandTiles) + { + if (tile.Visible) DrawLand(tile); } - foreach (var tile in GhostLandTiles) { + foreach (var tile in GhostLandTiles) + { DrawLand(tile); } } _mapRenderer.End(); - + _mapEffect.CurrentTechnique = _mapEffect.Techniques["Statics"]; - _mapRenderer.Begin(null, _mapEffect, Camera, RasterizerState.CullNone, SamplerState.PointClamp, - _depthStencilState, BlendState.AlphaBlend, _shadowTarget, HuesManager.Instance.Texture, false); - if (IsDrawStatic) { - foreach (var tile in StaticTiles) { - if(tile.Visible) + _mapRenderer.Begin + ( + null, + _mapEffect, + Camera, + RasterizerState.CullNone, + SamplerState.PointClamp, + _depthStencilState, + BlendState.AlphaBlend, + _shadowTarget, + HuesManager.Instance.Texture, + false + ); + if (IsDrawStatic) + { + foreach (var tile in StaticTiles) + { + if (tile.Visible) DrawStatic(tile); } - foreach (var tile in GhostStaticTiles) { + foreach (var tile in GhostStaticTiles) + { DrawStatic(tile); } } _mapRenderer.End(); } - private void DrawBackground() { + private void DrawBackground() + { _mapEffect.CurrentTechnique = _mapEffect.Techniques["Terrain"]; - _mapRenderer.Begin(null, _mapEffect, Camera, RasterizerState.CullNone, SamplerState.PointClamp, - _depthStencilState, BlendState.AlphaBlend, null,null, true); + _mapRenderer.Begin + ( + null, + _mapEffect, + Camera, + RasterizerState.CullNone, + SamplerState.PointClamp, + _depthStencilState, + BlendState.AlphaBlend, + null, + null, + true + ); _spriteBatch.Begin(); - var backgroundRect = new Rectangle( + var backgroundRect = new Rectangle + ( _gfxDevice.PresentationParameters.BackBufferWidth / 2 - _background.Width / 2, _gfxDevice.PresentationParameters.BackBufferHeight / 2 - _background.Height / 2, _background.Width, - _background.Height); + _background.Height + ); _spriteBatch.Draw(_background, backgroundRect, Color.White); _spriteBatch.End(); _mapRenderer.End(); } //TODO: Bring me back! - public void DrawHighRes() { + public void DrawHighRes() + { // Console.WriteLine("HIGH RES!"); // var myRenderTarget = new RenderTarget2D(_gfxDevice, 15360, 8640, false, SurfaceFormat.Color, DepthFormat.Depth24); // @@ -786,24 +907,29 @@ public void DrawHighRes() { // Console.WriteLine("HIGH RES DONE!"); } - public void OnWindowsResized(GameWindow window) { + public void OnWindowsResized(GameWindow window) + { Camera.ScreenSize = window.ClientBounds; Camera.Update(); - - _shadowTarget = new RenderTarget2D( + + _shadowTarget = new RenderTarget2D + ( _gfxDevice, _gfxDevice.PresentationParameters.BackBufferWidth * 2, _gfxDevice.PresentationParameters.BackBufferHeight * 2, false, SurfaceFormat.Single, - DepthFormat.Depth24); - - _selectionTarget = new RenderTarget2D( + DepthFormat.Depth24 + ); + + _selectionTarget = new RenderTarget2D + ( _gfxDevice, _gfxDevice.PresentationParameters.BackBufferWidth, _gfxDevice.PresentationParameters.BackBufferHeight, false, SurfaceFormat.Color, - DepthFormat.Depth24); + DepthFormat.Depth24 + ); } } \ No newline at end of file diff --git a/CentrED/Map/MapObject.cs b/CentrED/Map/MapObject.cs index 697b0c4..60fd984 100644 --- a/CentrED/Map/MapObject.cs +++ b/CentrED/Map/MapObject.cs @@ -3,7 +3,8 @@ namespace CentrED.Map; -public abstract class MapObject { +public abstract class MapObject +{ public const float INVERSE_SQRT2 = 0.70711f; public const float TILE_SIZE = 31.11f; public const float TILE_Z_SCALE = 4.0f; @@ -14,17 +15,23 @@ public abstract class MapObject { public Texture2D Texture; public MapVertex[] Vertices = new MapVertex[4]; - public ushort Hue { - set { - for (var index = 0; index < Vertices.Length; index++) { + public ushort Hue + { + set + { + for (var index = 0; index < Vertices.Length; index++) + { Vertices[index].HueVec = HuesManager.Instance.GetHueVector(Tile.Id, value, Vertices[index].HueVec.Z); } } } - - public float Alpha { - set { - for (var index = 0; index < Vertices.Length; index++) { + + public float Alpha + { + set + { + for (var index = 0; index < Vertices.Length; index++) + { Vertices[index].HueVec.Z = value; } } diff --git a/CentrED/Map/RadarMap.cs b/CentrED/Map/RadarMap.cs index 5900064..1fabace 100644 --- a/CentrED/Map/RadarMap.cs +++ b/CentrED/Map/RadarMap.cs @@ -4,45 +4,54 @@ using Microsoft.Xna.Framework.Graphics; using static CentrED.Application; -namespace CentrED.Map; +namespace CentrED.Map; -public class RadarMap { +public class RadarMap +{ private static RadarMap _instance; public static RadarMap Instance => _instance; - + private Texture2D _texture = null!; public Texture2D Texture => _texture; - - private RadarMap(GraphicsDevice gd) { - CEDClient.Connected += () => { - _texture = new Texture2D(gd, CEDClient.Width, CEDClient.Height ); + + private RadarMap(GraphicsDevice gd) + { + CEDClient.Connected += () => + { + _texture = new Texture2D(gd, CEDClient.Width, CEDClient.Height); CEDClient.Send(new RequestRadarMapPacket()); }; - + CEDClient.RadarData += RadarData; CEDClient.RadarUpdate += RadarUpdate; } - public static void Initialize(GraphicsDevice gd) { + public static void Initialize(GraphicsDevice gd) + { _instance = new RadarMap(gd); } - private unsafe void RadarData(ushort[] data) { + private unsafe void RadarData(ushort[] data) + { var width = CEDClient.Width; var height = CEDClient.Height; uint[] buffer = System.Buffers.ArrayPool.Shared.Rent(data.Length); - for (ushort x = 0; x < width; x++) { - for (ushort y = 0; y < height; y++) { + for (ushort x = 0; x < width; x++) + { + for (ushort y = 0; y < height; y++) + { buffer[y * width + x] = HuesHelper.Color16To32(data[x * height + y]) | 0xFF_00_00_00; } } - fixed (uint* ptr = buffer) { + fixed (uint* ptr = buffer) + { _texture.SetDataPointerEXT(0, null, (IntPtr)ptr, data.Length * sizeof(uint)); } } - private void RadarUpdate(ushort x, ushort y, ushort color) { - _texture.SetData(0, new Rectangle(x, y,1,1), new []{HuesHelper.Color16To32(color) | 0xFF_00_00_00},0,1); + private void RadarUpdate(ushort x, ushort y, ushort color) + { + _texture.SetData(0, new Rectangle(x, y, 1, 1), new[] { HuesHelper.Color16To32(color) | 0xFF_00_00_00 }, 0, 1); } } \ No newline at end of file diff --git a/CentrED/Map/StaticObject.cs b/CentrED/Map/StaticObject.cs index 55aba3d..814688e 100644 --- a/CentrED/Map/StaticObject.cs +++ b/CentrED/Map/StaticObject.cs @@ -2,23 +2,25 @@ using ClassicUO.Assets; using Microsoft.Xna.Framework; -namespace CentrED.Map; +namespace CentrED.Map; -public class StaticObject : MapObject { +public class StaticObject : MapObject +{ public StaticTile StaticTile; - - public StaticObject(StaticTile tile) { + + public StaticObject(StaticTile tile) + { Tile = tile; StaticTile = tile; var posX = tile.X * TILE_SIZE; var posY = tile.Y * TILE_SIZE; var posZ = tile.Z * TILE_Z_SCALE; - + Texture = ArtLoader.Instance.GetStaticTexture(tile.Id, out var bounds); var projectedWidth = (bounds.Width / 2f) * INVERSE_SQRT2; var depthOffset = tile.CellIndex * 0.0001f; - + var coordinates = new Vector3[4]; coordinates[0] = new Vector3(posX - projectedWidth, posY + projectedWidth, posZ + bounds.Height); coordinates[1] = new Vector3(posX + projectedWidth, posY - projectedWidth, posZ + bounds.Height); @@ -30,7 +32,7 @@ public StaticObject(StaticTile tile) { var texY = bounds.Y / (float)Texture.Height + onePixel / 2f; var texWidth = bounds.Width / (float)Texture.Width - onePixel; var texHeight = bounds.Height / (float)Texture.Height - onePixel; - + var texCoords = new Vector3[4]; texCoords[0] = new Vector3(texX, texY, depthOffset); texCoords[1] = new Vector3(texX + texWidth, texY, depthOffset); @@ -38,7 +40,8 @@ public StaticObject(StaticTile tile) { texCoords[3] = new Vector3(texX + texWidth, texY + texHeight, depthOffset); var hue = HuesManager.Instance.GetHueVector(tile); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) + { Vertices[i] = new MapVertex(coordinates[i], Vector3.UnitZ, texCoords[i], hue); } } diff --git a/CentrED/Renderer/Effects/MapEffect.cs b/CentrED/Renderer/Effects/MapEffect.cs index 3d8e485..7590ca2 100644 --- a/CentrED/Renderer/Effects/MapEffect.cs +++ b/CentrED/Renderer/Effects/MapEffect.cs @@ -15,25 +15,29 @@ public class MapEffect : Effect private Vector3 _ambientLightColor = Vector3.One; - public Matrix WorldViewProj { + public Matrix WorldViewProj + { get { return _worldViewProj; } set { _worldViewProj = value; } } - public Matrix LightWorldViewProj { + public Matrix LightWorldViewProj + { get { return _lightWorldViewProj; } set { _lightWorldViewProj = value; } } - public Vector3 AmbientLightColor { + public Vector3 AmbientLightColor + { get { return _ambientLightColor; } - set { - _ambientLightColor = value; - } + set { _ambientLightColor = value; } } - public DirectionalLight LightSource { get { return _lightSource; } } + public DirectionalLight LightSource + { + get { return _lightSource; } + } protected static byte[] GetResource(string name) { @@ -52,17 +56,20 @@ protected static byte[] GetResource(string name) } } - public MapEffect(GraphicsDevice device) - : base(device, GetResource("CentrED.Renderer.Effects.Shaders.MapEffect.fxc")) + public MapEffect(GraphicsDevice device) : base + (device, GetResource("CentrED.Renderer.Effects.Shaders.MapEffect.fxc")) { _ambientLightColorParam = Parameters["AmbientLightColor"]; _worldViewProjParam = Parameters["WorldViewProj"]; _lightWorldViewProjParam = Parameters["LightWorldViewProj"]; - _lightSource = new DirectionalLight(Parameters["DirectionalLightDirection"], - Parameters["DirectionalLightDiffuseColor"], - Parameters["DirectionalLightSpecularColor"], - null); + _lightSource = new DirectionalLight + ( + Parameters["DirectionalLightDirection"], + Parameters["DirectionalLightDiffuseColor"], + Parameters["DirectionalLightSpecularColor"], + null + ); } protected override void OnApply() @@ -71,4 +78,4 @@ protected override void OnApply() _lightWorldViewProjParam.SetValue(_lightWorldViewProj); _ambientLightColorParam.SetValue(new Vector4(_ambientLightColor, 1)); } -} +} \ No newline at end of file diff --git a/CentrED/Renderer/MapRenderer.cs b/CentrED/Renderer/MapRenderer.cs index e04c2eb..1788f24 100644 --- a/CentrED/Renderer/MapRenderer.cs +++ b/CentrED/Renderer/MapRenderer.cs @@ -19,10 +19,9 @@ public class LightingState [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MapVertex : IVertexType { - VertexDeclaration IVertexType.VertexDeclaration { - get { - return VertexDeclaration; - } + VertexDeclaration IVertexType.VertexDeclaration + { + get { return VertexDeclaration; } } public Vector3 Position; @@ -34,43 +33,19 @@ VertexDeclaration IVertexType.VertexDeclaration { static MapVertex() { - VertexDeclaration = new VertexDeclaration( + VertexDeclaration = new VertexDeclaration + ( new VertexElement[] { - new VertexElement( - 0, - VertexElementFormat.Vector3, - VertexElementUsage.Position, - 0 - ), - new VertexElement( - 12, - VertexElementFormat.Vector3, - VertexElementUsage.Normal, - 0 - ), - new VertexElement( - 24, - VertexElementFormat.Vector3, - VertexElementUsage.TextureCoordinate, - 0 - ), - new VertexElement( - 36, - VertexElementFormat.Vector3, - VertexElementUsage.TextureCoordinate, - 0 - ) + new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), + new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0), + new VertexElement(24, VertexElementFormat.Vector3, VertexElementUsage.TextureCoordinate, 0), + new VertexElement(36, VertexElementFormat.Vector3, VertexElementUsage.TextureCoordinate, 0) } ); } - public MapVertex( - Vector3 position, - Vector3 normal, - Vector3 textureCoordinate, - Vector3 hueVec - ) + public MapVertex(Vector3 position, Vector3 normal, Vector3 textureCoordinate, Vector3 hueVec) { Position = position; Normal = normal; @@ -79,10 +54,10 @@ Vector3 hueVec } } - public class MapRenderer { #region Draw Batcher + private class DrawBatcher { private const int MAX_TILES_PER_BATCH = 4096; @@ -134,24 +109,15 @@ public DrawBatcher(GraphicsDevice device) _vertexInfo = new MapVertex[MAX_VERTICES]; - _vertexBuffer = new DynamicVertexBuffer( - device, - typeof(MapVertex), - MAX_VERTICES, - BufferUsage.WriteOnly - ); + _vertexBuffer = new DynamicVertexBuffer(device, typeof(MapVertex), MAX_VERTICES, BufferUsage.WriteOnly); - _indexBuffer = new IndexBuffer( - device, - IndexElementSize.SixteenBits, - MAX_INDICES, - BufferUsage.WriteOnly - ); + _indexBuffer = new IndexBuffer(device, IndexElementSize.SixteenBits, MAX_INDICES, BufferUsage.WriteOnly); _indexBuffer.SetData(_indexData); } - public void Begin( + public void Begin + ( RenderTarget2D output, MapEffect effect, Camera camera, @@ -192,7 +158,8 @@ private unsafe void Flush() fixed (MapVertex* p = &_vertexInfo[0]) { - _vertexBuffer.SetDataPointerEXT(0, (IntPtr)p, Unsafe.SizeOf() * _numTiles * 4, SetDataOptions.Discard); + _vertexBuffer.SetDataPointerEXT + (0, (IntPtr)p, Unsafe.SizeOf() * _numTiles * 4, SetDataOptions.Discard); } _gfxDevice.SetVertexBuffer(_vertexBuffer); @@ -222,23 +189,27 @@ public unsafe void End() _beginCalled = false; } - - public void DrawMapObject(MapObject o, Vector3 hueOverride) { + + public void DrawMapObject(MapObject o, Vector3 hueOverride) + { if (_numTiles + 1 >= MAX_TILES_PER_BATCH) Flush(); int cur = _numTiles * 4; - for (var i = 0; i < 4; i++) { + for (var i = 0; i < 4; i++) + { _vertexInfo[cur + i] = o.Vertices[i]; - if (hueOverride != default) { + if (hueOverride != default) + { _vertexInfo[cur + i].HueVec = hueOverride; } } _numTiles++; } } -#endregion + + #endregion private readonly GraphicsDevice _gfxDevice; @@ -265,12 +236,24 @@ private DrawBatcher GetBatcher(Texture2D texture) } } - for (int i = 0; i < _batchers.Length; i++) + for (int i = 0; i < _batchers.Length; i++) { if (_textures[i] == null) { _textures[i] = texture; - _batchers[i].Begin(_mapTarget, _effect, _camera, texture, _rasterizerState, _samplerState, _depthStencilState, _blendState, _shadowMap, _huesTexture); + _batchers[i].Begin + ( + _mapTarget, + _effect, + _camera, + texture, + _rasterizerState, + _samplerState, + _depthStencilState, + _blendState, + _shadowMap, + _huesTexture + ); return _batchers[i]; } } @@ -278,7 +261,19 @@ private DrawBatcher GetBatcher(Texture2D texture) /* TODO: Don't always evict the first one */ _batchers[0].End(); _textures[0] = texture; - _batchers[0].Begin(_mapTarget, _effect, _camera, texture, _rasterizerState, _samplerState, _depthStencilState, _blendState, _shadowMap, _huesTexture); + _batchers[0].Begin + ( + _mapTarget, + _effect, + _camera, + texture, + _rasterizerState, + _samplerState, + _depthStencilState, + _blendState, + _shadowMap, + _huesTexture + ); return _batchers[0]; } @@ -294,7 +289,8 @@ public MapRenderer(GraphicsDevice device) } } - public void Begin( + public void Begin + ( RenderTarget2D output, MapEffect effect, Camera camera, @@ -330,7 +326,7 @@ bool clear _textures[i] = null; } _gfxDevice.SetRenderTarget(output); - if(clear) + if (clear) _gfxDevice.Clear(Color.Black); } @@ -350,8 +346,9 @@ public unsafe void End() _beginCalled = false; } - public void DrawMapObject(MapObject mapObject, Vector3 hueOverride) { + public void DrawMapObject(MapObject mapObject, Vector3 hueOverride) + { var batcher = GetBatcher(mapObject.Texture); batcher.DrawMapObject(mapObject, hueOverride); } -} +} \ No newline at end of file diff --git a/CentrED/Renderer/PostProcessRenderer.cs b/CentrED/Renderer/PostProcessRenderer.cs index d68ad21..364355c 100644 --- a/CentrED/Renderer/PostProcessRenderer.cs +++ b/CentrED/Renderer/PostProcessRenderer.cs @@ -13,10 +13,7 @@ public class PostProcessRenderer private readonly VertexPositionTexture[] _vertexInfo = new VertexPositionTexture[4]; - private static readonly short[] _indexData = new short[6] - { - 0, 1, 2, 3, 2, 1 - }; + private static readonly short[] _indexData = new short[6] { 0, 1, 2, 3, 2, 1 }; private RasterizerState _rasterizerState; private SamplerState _samplerState; @@ -28,55 +25,31 @@ public PostProcessRenderer(GraphicsDevice device) { _gfxDevice = device; - _vertexBuffer = new DynamicVertexBuffer( - device, - typeof(VertexPositionTexture), - 4, - BufferUsage.WriteOnly - ); + _vertexBuffer = new DynamicVertexBuffer(device, typeof(VertexPositionTexture), 4, BufferUsage.WriteOnly); - _indexBuffer = new IndexBuffer( - device, - IndexElementSize.SixteenBits, - 6, - BufferUsage.WriteOnly - ); + _indexBuffer = new IndexBuffer(device, IndexElementSize.SixteenBits, 6, BufferUsage.WriteOnly); _indexBuffer.SetData(_indexData); } // Draw the input texture to fill the output target. Output can be null to draw to the back buffer. // This is a simple point clamp scaling. - public unsafe void Scale( - Texture2D input, - RenderTarget2D output - ) + public unsafe void Scale(Texture2D input, RenderTarget2D output) { var width = output == null ? _gfxDevice.PresentationParameters.BackBufferWidth : output.Width; var height = output == null ? _gfxDevice.PresentationParameters.BackBufferHeight : output.Height; _gfxDevice.SetRenderTarget(output); - _vertexInfo[0] = new VertexPositionTexture( - new Vector3(0, 0, 0), - new Vector2(0, 0) - ); - _vertexInfo[1] = new VertexPositionTexture( - new Vector3(width, 0, 0), - new Vector2(1, 0) - ); - _vertexInfo[2] = new VertexPositionTexture( - new Vector3(0, height, 0), - new Vector2(0, 1) - ); - _vertexInfo[3] = new VertexPositionTexture( - new Vector3(width, height, 0), - new Vector2(1, 1) - ); + _vertexInfo[0] = new VertexPositionTexture(new Vector3(0, 0, 0), new Vector2(0, 0)); + _vertexInfo[1] = new VertexPositionTexture(new Vector3(width, 0, 0), new Vector2(1, 0)); + _vertexInfo[2] = new VertexPositionTexture(new Vector3(0, height, 0), new Vector2(0, 1)); + _vertexInfo[3] = new VertexPositionTexture(new Vector3(width, height, 0), new Vector2(1, 1)); fixed (VertexPositionTexture* p = &_vertexInfo[0]) { - _vertexBuffer.SetDataPointerEXT(0, (IntPtr)p, Unsafe.SizeOf() * 4, SetDataOptions.Discard); + _vertexBuffer.SetDataPointerEXT + (0, (IntPtr)p, Unsafe.SizeOf() * 4, SetDataOptions.Discard); } _gfxDevice.SetVertexBuffer(_vertexBuffer); diff --git a/CentrED/Renderer/StbRectPack/CRuntime.cs b/CentrED/Renderer/StbRectPack/CRuntime.cs index aea5a1f..12eadf3 100644 --- a/CentrED/Renderer/StbRectPack/CRuntime.cs +++ b/CentrED/Renderer/StbRectPack/CRuntime.cs @@ -1,86 +1,85 @@ using System.Runtime.InteropServices; -namespace CentrED.Renderer.StbRectPack +namespace CentrED.Renderer.StbRectPack; + +internal static unsafe class CRuntime { - internal static unsafe class CRuntime + public static void* malloc(ulong size) { - public static void* malloc(ulong size) - { - return malloc((long)size); - } + return malloc((long)size); + } - public static void* malloc(long size) - { - var ptr = Marshal.AllocHGlobal((int)size); + public static void* malloc(long size) + { + var ptr = Marshal.AllocHGlobal((int)size); - return ptr.ToPointer(); - } + return ptr.ToPointer(); + } - public static void free(void* a) - { - var ptr = new IntPtr(a); - Marshal.FreeHGlobal(ptr); - } + public static void free(void* a) + { + var ptr = new IntPtr(a); + Marshal.FreeHGlobal(ptr); + } - public delegate int QSortComparer(void* a, void* b); + public delegate int QSortComparer(void* a, void* b); - private static void qsortSwap(byte* data, long size, long pos1, long pos2) - { - var a = data + size * pos1; - var b = data + size * pos2; + private static void qsortSwap(byte* data, long size, long pos1, long pos2) + { + var a = data + size * pos1; + var b = data + size * pos2; - for (long k = 0; k < size; ++k) - { - var tmp = *a; - *a = *b; - *b = tmp; + for (long k = 0; k < size; ++k) + { + var tmp = *a; + *a = *b; + *b = tmp; - a++; - b++; - } + a++; + b++; } + } - private static long qsortPartition(byte* data, long size, QSortComparer comparer, long left, long right) + private static long qsortPartition(byte* data, long size, QSortComparer comparer, long left, long right) + { + void* pivot = data + size * left; + var i = left - 1; + var j = right + 1; + for (;;) { - void* pivot = data + size * left; - var i = left - 1; - var j = right + 1; - for (; ; ) + do { - do - { - ++i; - } while (comparer(data + size * i, pivot) < 0); - - do - { - --j; - } while (comparer(data + size * j, pivot) > 0); - - if (i >= j) - { - return j; - } - - qsortSwap(data, size, i, j); - } - } - + ++i; + } while (comparer(data + size * i, pivot) < 0); - private static void qsortInternal(byte* data, long size, QSortComparer comparer, long left, long right) - { - if (left < right) + do { - var p = qsortPartition(data, size, comparer, left, right); + --j; + } while (comparer(data + size * j, pivot) > 0); - qsortInternal(data, size, comparer, left, p); - qsortInternal(data, size, comparer, p + 1, right); + if (i >= j) + { + return j; } + + qsortSwap(data, size, i, j); } + } - public static void qsort(void* data, ulong count, ulong size, QSortComparer comparer) + + private static void qsortInternal(byte* data, long size, QSortComparer comparer, long left, long right) + { + if (left < right) { - qsortInternal((byte*)data, (long)size, comparer, 0, (long)count - 1); + var p = qsortPartition(data, size, comparer, left, right); + + qsortInternal(data, size, comparer, left, p); + qsortInternal(data, size, comparer, p + 1, right); } } + + public static void qsort(void* data, ulong count, ulong size, QSortComparer comparer) + { + qsortInternal((byte*)data, (long)size, comparer, 0, (long)count - 1); + } } \ No newline at end of file diff --git a/CentrED/Renderer/StbRectPack/Packer.cs b/CentrED/Renderer/StbRectPack/Packer.cs index 457e947..2f3f54a 100644 --- a/CentrED/Renderer/StbRectPack/Packer.cs +++ b/CentrED/Renderer/StbRectPack/Packer.cs @@ -1,85 +1,79 @@ using Microsoft.Xna.Framework; using static CentrED.Renderer.StbRectPack.StbRectPack; -namespace CentrED.Renderer.StbRectPack +namespace CentrED.Renderer.StbRectPack; + +/// +/// Simple Packer class that doubles size of the atlas if the place runs out +/// +unsafe class Packer : IDisposable { - /// - /// Simple Packer class that doubles size of the atlas if the place runs out - /// - unsafe class Packer : IDisposable - { - private readonly stbrp_context _context; + private readonly stbrp_context _context; - public int Width => _context.width; - public int Height => _context.height; - public int PackeRectanglesCount { get; private set; } + public int Width => _context.width; + public int Height => _context.height; + public int PackeRectanglesCount { get; private set; } - public Packer(int width = 256, int height = 256) + public Packer(int width = 256, int height = 256) + { + if (width <= 0) { - if (width <= 0) - { - throw new ArgumentOutOfRangeException(nameof(width)); - } - - if (height <= 0) - { - throw new ArgumentOutOfRangeException(nameof(height)); - } - - // Initialize the context - var num_nodes = width; - _context = new stbrp_context(num_nodes); + throw new ArgumentOutOfRangeException(nameof(width)); + } - fixed (stbrp_context* contextPtr = &_context) - { - stbrp_init_target(contextPtr, width, height, _context.all_nodes, num_nodes); - } + if (height <= 0) + { + throw new ArgumentOutOfRangeException(nameof(height)); } - public void Dispose() + // Initialize the context + var num_nodes = width; + _context = new stbrp_context(num_nodes); + + fixed (stbrp_context* contextPtr = &_context) { - _context.Dispose(); + stbrp_init_target(contextPtr, width, height, _context.all_nodes, num_nodes); } + } - /// - /// Packs a rect. Returns null, if there's no more place left. - /// - /// - /// - /// - public bool PackRect(int width, int height, out Rectangle packRectangle, int offset = 2) + public void Dispose() + { + _context.Dispose(); + } + + /// + /// Packs a rect. Returns null, if there's no more place left. + /// + /// + /// + /// + public bool PackRect(int width, int height, out Rectangle packRectangle, int offset = 2) + { + var rect = new stbrp_rect { - var rect = new stbrp_rect - { - id = PackeRectanglesCount, - w = width + offset, - h = height + offset - }; + id = PackeRectanglesCount, + w = width + offset, + h = height + offset + }; - int result; - fixed (stbrp_context* contextPtr = &_context) - { - result = stbrp_pack_rects(contextPtr, &rect, 1); - } + int result; + fixed (stbrp_context* contextPtr = &_context) + { + result = stbrp_pack_rects(contextPtr, &rect, 1); + } - if (result == 0) - { - packRectangle = Rectangle.Empty; - return false; - } + if (result == 0) + { + packRectangle = Rectangle.Empty; + return false; + } - packRectangle = new Rectangle - ( - rect.x + (int)(offset / 2f), - rect.y + (int)(offset / 2f), - rect.w - offset, - rect.h - offset - ); + packRectangle = new Rectangle + (rect.x + (int)(offset / 2f), rect.y + (int)(offset / 2f), rect.w - offset, rect.h - offset); - ++PackeRectanglesCount; + ++PackeRectanglesCount; - return true; - } + return true; } -} +} \ No newline at end of file diff --git a/CentrED/Renderer/StbRectPack/StbRectPack.cs b/CentrED/Renderer/StbRectPack/StbRectPack.cs index 81a0468..b978480 100644 --- a/CentrED/Renderer/StbRectPack/StbRectPack.cs +++ b/CentrED/Renderer/StbRectPack/StbRectPack.cs @@ -1,52 +1,51 @@ -namespace CentrED.Renderer.StbRectPack +namespace CentrED.Renderer.StbRectPack; + +static unsafe partial class StbRectPack { - static unsafe partial class StbRectPack + public struct stbrp_context : IDisposable { - public struct stbrp_context : IDisposable + public int width; + public int height; + public int align; + public int init_mode; + public int heuristic; + public int num_nodes; + public stbrp_node* active_head; + public stbrp_node* free_head; + public stbrp_node* extra; + public stbrp_node* all_nodes; + + + public stbrp_context(int nodesCount) { - public int width; - public int height; - public int align; - public int init_mode; - public int heuristic; - public int num_nodes; - public stbrp_node* active_head; - public stbrp_node* free_head; - public stbrp_node* extra; - public stbrp_node* all_nodes; - - - public stbrp_context(int nodesCount) + if (nodesCount <= 0) { - if (nodesCount <= 0) - { - throw new ArgumentOutOfRangeException(nameof(nodesCount)); - } + throw new ArgumentOutOfRangeException(nameof(nodesCount)); + } - width = height = align = init_mode = heuristic = num_nodes = 0; - active_head = free_head = null; + width = height = align = init_mode = heuristic = num_nodes = 0; + active_head = free_head = null; - //Allocate nodes - all_nodes = (stbrp_node*)CRuntime.malloc(sizeof(stbrp_node) * nodesCount); + //Allocate nodes + all_nodes = (stbrp_node*)CRuntime.malloc(sizeof(stbrp_node) * nodesCount); - //Allocate extras - extra = (stbrp_node*)CRuntime.malloc(sizeof(stbrp_node) * 2); + //Allocate extras + extra = (stbrp_node*)CRuntime.malloc(sizeof(stbrp_node) * 2); + } + + public void Dispose() + { + if (all_nodes != null) + { + CRuntime.free(all_nodes); + all_nodes = null; } - public void Dispose() + if (extra != null) { - if (all_nodes != null) - { - CRuntime.free(all_nodes); - all_nodes = null; - } - - if (extra != null) - { - CRuntime.free(extra); - extra = null; - } + CRuntime.free(extra); + extra = null; } } } -} +} \ No newline at end of file diff --git a/CentrED/Renderer/UIRenderer.cs b/CentrED/Renderer/UIRenderer.cs index ca27d33..2dd9ef5 100644 --- a/CentrED/Renderer/UIRenderer.cs +++ b/CentrED/Renderer/UIRenderer.cs @@ -13,9 +13,13 @@ public static class DrawVertDeclaration static DrawVertDeclaration() { - unsafe { Size = sizeof(ImDrawVert); } + unsafe + { + Size = sizeof(ImDrawVert); + } - Declaration = new VertexDeclaration( + Declaration = new VertexDeclaration + ( Size, // Position @@ -82,14 +86,18 @@ public virtual unsafe void RebuildFontAtlas() // Copy the data to a managed array var pixels = new byte[width * height * bytesPerPixel]; - unsafe { Marshal.Copy(new IntPtr(pixelData), pixels, 0, pixels.Length); } + unsafe + { + Marshal.Copy(new IntPtr(pixelData), pixels, 0, pixels.Length); + } // Create and register the texture as an XNA texture var tex2d = new Texture2D(_graphicsDevice, width, height, false, SurfaceFormat.Color); tex2d.SetData(pixels); // Should a texture already have been build previously, unbind it first so it can be deallocated - if (_fontTextureId.HasValue) UnbindTexture(_fontTextureId.Value); + if (_fontTextureId.HasValue) + UnbindTexture(_fontTextureId.Value); // Bind the new texture to an ImGui-friendly id _fontTextureId = BindTexture(tex2d); @@ -102,9 +110,11 @@ public virtual unsafe void RebuildFontAtlas() /// /// Creates a pointer to a texture, which can be passed through ImGui calls such as . That pointer is then used by ImGui to let us know what texture to draw /// - public virtual IntPtr BindTexture(Texture2D texture) { + public virtual IntPtr BindTexture(Texture2D texture) + { var id = _loadedTextures.IndexOf(texture); - if (id == -1) { + if (id == -1) + { _loadedTextures.Add(texture); id = _loadedTextures.Count - 1; } @@ -166,7 +176,13 @@ public void RenderDrawData(ImDrawDataPtr drawData) drawData.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale); // Setup projection - _graphicsDevice.Viewport = new Viewport(0, 0, _graphicsDevice.PresentationParameters.BackBufferWidth, _graphicsDevice.PresentationParameters.BackBufferHeight); + _graphicsDevice.Viewport = new Viewport + ( + 0, + 0, + _graphicsDevice.PresentationParameters.BackBufferWidth, + _graphicsDevice.PresentationParameters.BackBufferHeight + ); UpdateBuffers(drawData); @@ -190,7 +206,8 @@ private unsafe void UpdateBuffers(ImDrawDataPtr drawData) _vertexBuffer?.Dispose(); _vertexBufferSize = (int)(drawData.TotalVtxCount * 1.5f); - _vertexBuffer = new VertexBuffer(_graphicsDevice, DrawVertDeclaration.Declaration, _vertexBufferSize, BufferUsage.None); + _vertexBuffer = new VertexBuffer + (_graphicsDevice, DrawVertDeclaration.Declaration, _vertexBufferSize, BufferUsage.None); _vertexData = new byte[_vertexBufferSize * DrawVertDeclaration.Size]; } @@ -199,7 +216,8 @@ private unsafe void UpdateBuffers(ImDrawDataPtr drawData) _indexBuffer?.Dispose(); _indexBufferSize = (int)(drawData.TotalIdxCount * 1.5f); - _indexBuffer = new IndexBuffer(_graphicsDevice, IndexElementSize.SixteenBits, _indexBufferSize, BufferUsage.None); + _indexBuffer = new IndexBuffer + (_graphicsDevice, IndexElementSize.SixteenBits, _indexBufferSize, BufferUsage.None); _indexData = new byte[_indexBufferSize * sizeof(ushort)]; } @@ -214,8 +232,20 @@ private unsafe void UpdateBuffers(ImDrawDataPtr drawData) fixed (void* vtxDstPtr = &_vertexData[vtxOffset * DrawVertDeclaration.Size]) fixed (void* idxDstPtr = &_indexData[idxOffset * sizeof(ushort)]) { - Buffer.MemoryCopy((void*)cmdList.VtxBuffer.Data, vtxDstPtr, _vertexData.Length, cmdList.VtxBuffer.Size * DrawVertDeclaration.Size); - Buffer.MemoryCopy((void*)cmdList.IdxBuffer.Data, idxDstPtr, _indexData.Length, cmdList.IdxBuffer.Size * sizeof(ushort)); + Buffer.MemoryCopy + ( + (void*)cmdList.VtxBuffer.Data, + vtxDstPtr, + _vertexData.Length, + cmdList.VtxBuffer.Size * DrawVertDeclaration.Size + ); + Buffer.MemoryCopy + ( + (void*)cmdList.IdxBuffer.Data, + idxDstPtr, + _indexData.Length, + cmdList.IdxBuffer.Size * sizeof(ushort) + ); } vtxOffset += cmdList.VtxBuffer.Size; @@ -250,10 +280,12 @@ private unsafe void RenderCommandLists(ImDrawDataPtr drawData) if (_loadedTextures.Count < drawCmd.TextureId.ToInt32()) { - throw new InvalidOperationException($"Could not find a texture with id '{drawCmd.TextureId}', please check your bindings"); + throw new InvalidOperationException + ($"Could not find a texture with id '{drawCmd.TextureId}', please check your bindings"); } - _graphicsDevice.ScissorRectangle = new Rectangle( + _graphicsDevice.ScissorRectangle = new Rectangle + ( (int)drawCmd.ClipRect.X, (int)drawCmd.ClipRect.Y, (int)(drawCmd.ClipRect.Z - drawCmd.ClipRect.X), @@ -267,13 +299,14 @@ private unsafe void RenderCommandLists(ImDrawDataPtr drawData) pass.Apply(); #pragma warning disable CS0618 // // FNA does not expose an alternative method. - _graphicsDevice.DrawIndexedPrimitives( - primitiveType: PrimitiveType.TriangleList, - baseVertex: (int)drawCmd.VtxOffset + vtxOffset, - minVertexIndex: 0, - numVertices: cmdList.VtxBuffer.Size, - startIndex: (int)drawCmd.IdxOffset + idxOffset, - primitiveCount: (int)drawCmd.ElemCount / 3 + _graphicsDevice.DrawIndexedPrimitives + ( + PrimitiveType.TriangleList, + (int)drawCmd.VtxOffset + vtxOffset, + 0, + cmdList.VtxBuffer.Size, + (int)drawCmd.IdxOffset + idxOffset, + (int)drawCmd.ElemCount / 3 ); #pragma warning restore CS0618 } @@ -285,4 +318,4 @@ private unsafe void RenderCommandLists(ImDrawDataPtr drawData) } #endregion Internals -} +} \ No newline at end of file diff --git a/CentrED/Tools/DrawTool.cs b/CentrED/Tools/DrawTool.cs index 22675f9..4bbf0c2 100644 --- a/CentrED/Tools/DrawTool.cs +++ b/CentrED/Tools/DrawTool.cs @@ -6,14 +6,16 @@ namespace CentrED.Tools; -public class DrawTool : Tool { +public class DrawTool : Tool +{ public override string Name => "DrawTool"; private bool _pressed; private MapObject _focusObject; [Flags] - enum DrawMode { + enum DrawMode + { ON_TOP = 0, REPLACE = 1, SAME_POS = 2, @@ -22,7 +24,8 @@ enum DrawMode { private bool _withHue; private int _drawMode; - internal override void DrawWindow() { + internal override void DrawWindow() + { ImGui.SetNextWindowSize(new System.Numerics.Vector2(200, 100), ImGuiCond.FirstUseEver); ImGui.Begin(Name, ImGuiWindowFlags.NoTitleBar); ImGui.Checkbox("With Hue", ref _withHue); @@ -32,71 +35,91 @@ internal override void DrawWindow() { ImGui.End(); } - public override void OnMouseEnter(MapObject? o) { - if (o == null) return; + public override void OnMouseEnter(MapObject? o) + { + if (o == null) + return; ushort tileX = o.Tile.X; ushort tileY = o.Tile.Y; sbyte tileZ = o.Tile.Z; - byte height = o switch { + byte height = o switch + { StaticObject so => TileDataLoader.Instance.StaticData[so.Tile.Id].Height, _ => 0 }; var newId = CEDGame.UIManager._tilesWindow._selectedId; - if (TilesWindow.IsLandTile(newId)) { - if (o is LandObject lo) { + if (TilesWindow.IsLandTile(newId)) + { + if (o is LandObject lo) + { lo.Visible = false; var newTile = new LandTile((ushort)newId, lo.Tile.X, lo.Tile.Y, lo.Tile.Z); CEDGame.MapManager.GhostLandTiles.Add(new LandObject(CEDClient, newTile)); } } - else { - var newZ = (DrawMode)_drawMode switch { + else + { + var newZ = (DrawMode)_drawMode switch + { DrawMode.ON_TOP => tileZ + height, _ => tileZ }; - if (o is StaticObject && (DrawMode)_drawMode == DrawMode.REPLACE) { + if (o is StaticObject && (DrawMode)_drawMode == DrawMode.REPLACE) + { o.Visible = false; } - var newTile = new StaticTile( + var newTile = new StaticTile + ( (ushort)(newId - ArtLoader.MAX_LAND_DATA_INDEX_COUNT), tileX, tileY, (sbyte)newZ, - (ushort)(_withHue ? CEDGame.UIManager._huesWindow.SelectedId + 1 : 0)); + (ushort)(_withHue ? CEDGame.UIManager._huesWindow.SelectedId + 1 : 0) + ); CEDGame.MapManager.GhostStaticTiles.Add(new StaticObject(newTile)); } } - public override void OnMouseLeave(MapObject? o) { - if (TilesWindow.IsLandTile(CEDGame.UIManager._tilesWindow._selectedId)) { - if (o is LandObject lo) { + public override void OnMouseLeave(MapObject? o) + { + if (TilesWindow.IsLandTile(CEDGame.UIManager._tilesWindow._selectedId)) + { + if (o is LandObject lo) + { lo.Visible = true; CEDGame.MapManager.GhostLandTiles.Clear(); } } - else { + else + { if (o != null) o.Visible = true; CEDGame.MapManager.GhostStaticTiles.Clear(); } } - public override void OnMousePressed(MapObject? o) { - if (_pressed || o == null) return; + public override void OnMousePressed(MapObject? o) + { + if (_pressed || o == null) + return; _pressed = true; _focusObject = o; } - public override void OnMouseReleased(MapObject? o) { - if (_pressed && o == _focusObject) { + public override void OnMouseReleased(MapObject? o) + { + if (_pressed && o == _focusObject) + { var newId = CEDGame.UIManager._tilesWindow._selectedId; - if (TilesWindow.IsLandTile(newId) && o is LandObject lo) { + if (TilesWindow.IsLandTile(newId) && o is LandObject lo) + { lo.LandTile.Id = (ushort)CEDGame.UIManager._tilesWindow._selectedId; } - else { + else + { var newTile = CEDGame.MapManager.GhostStaticTiles[0].StaticTile; CEDGame.MapManager.Client.Add(newTile); } diff --git a/CentrED/Tools/ElevateTool.cs b/CentrED/Tools/ElevateTool.cs index 41ba0fa..204d0df 100644 --- a/CentrED/Tools/ElevateTool.cs +++ b/CentrED/Tools/ElevateTool.cs @@ -2,11 +2,13 @@ using ImGuiNET; using static CentrED.Application; -namespace CentrED.Tools; +namespace CentrED.Tools; -public class ElevateTool : Tool { +public class ElevateTool : Tool +{ [Flags] - enum ZMode { + enum ZMode + { INC = 0, DEC = 1, SET = 2, @@ -19,57 +21,71 @@ enum ZMode { private MapObject _focusObject; public override string Name => "ElevateTool"; - internal override void DrawWindow() { - ImGui.SetNextWindowSize(new System.Numerics.Vector2(200, 100), ImGuiCond.FirstUseEver ); + internal override void DrawWindow() + { + ImGui.SetNextWindowSize(new System.Numerics.Vector2(200, 100), ImGuiCond.FirstUseEver); ImGui.Begin(Name, ImGuiWindowFlags.NoTitleBar); ImGui.RadioButton("Inc", ref zMode, (int)ZMode.INC); ImGui.RadioButton("Dec", ref zMode, (int)ZMode.DEC); ImGui.RadioButton("Set", ref zMode, (int)ZMode.SET); - + ImGui.InputInt("Value", ref value); ImGui.End(); } - - private sbyte NewZ(BaseTile tile) => (sbyte)((ZMode)zMode switch { + + private sbyte NewZ(BaseTile tile) => (sbyte)((ZMode)zMode switch + { ZMode.INC => tile.Z + value, ZMode.DEC => tile.Z - value, ZMode.SET => value, _ => throw new ArgumentOutOfRangeException() }); - - public override void OnMouseEnter(MapObject? o) { - if (o is StaticObject so) { + + public override void OnMouseEnter(MapObject? o) + { + if (o is StaticObject so) + { var tile = so.StaticTile; so.Alpha = 0.3f; var newTile = new StaticTile(tile.Id, tile.X, tile.Y, NewZ(tile), tile.Hue); CEDGame.MapManager.GhostStaticTiles.Add(new StaticObject(newTile)); - } else if (o is LandObject lo) { + } + else if (o is LandObject lo) + { var tile = lo.LandTile; lo.Visible = false; var newTile = new LandTile(tile.Id, tile.X, tile.Y, NewZ(tile)); CEDGame.MapManager.GhostLandTiles.Add(new LandObject(CEDGame.MapManager.Client, newTile)); } } - - public override void OnMouseLeave(MapObject? o) { - if (o is StaticObject so) { + + public override void OnMouseLeave(MapObject? o) + { + if (o is StaticObject so) + { so.Alpha = 1f; CEDGame.MapManager.GhostStaticTiles.Clear(); - } else if (o is LandObject lo) { + } + else if (o is LandObject lo) + { lo.Visible = true; CEDGame.MapManager.GhostLandTiles.Clear(); } } - public override void OnMousePressed(MapObject? o) { - if (!_pressed && o != null) { + public override void OnMousePressed(MapObject? o) + { + if (!_pressed && o != null) + { _pressed = true; _focusObject = o; } } - - public override void OnMouseReleased(MapObject? o) { - if (_pressed && o == _focusObject) { + + public override void OnMouseReleased(MapObject? o) + { + if (_pressed && o == _focusObject) + { o.Tile.Z = NewZ(o.Tile); } _pressed = false; diff --git a/CentrED/Tools/HueTool.cs b/CentrED/Tools/HueTool.cs index f3a29b4..5abaa1e 100644 --- a/CentrED/Tools/HueTool.cs +++ b/CentrED/Tools/HueTool.cs @@ -3,39 +3,48 @@ namespace CentrED.Tools; -public class HueTool : Tool { - +public class HueTool : Tool +{ public override string Name => "HueTool"; - + private bool _pressed; private StaticObject _focusObject; - public override void OnActivated(MapObject? o) { + public override void OnActivated(MapObject? o) + { CEDGame.UIManager._huesWindow.Show = true; } - public override void OnMouseEnter(MapObject? o) { - if (o is StaticObject so) { + public override void OnMouseEnter(MapObject? o) + { + if (o is StaticObject so) + { so.Hue = (ushort)CEDGame.UIManager._huesWindow.SelectedId; } } - - public override void OnMouseLeave(MapObject? o) { - if (o is StaticObject so) { + + public override void OnMouseLeave(MapObject? o) + { + if (o is StaticObject so) + { so.Hue = so.StaticTile.Hue; } } - public override void OnMousePressed(MapObject? o) { - if (!_pressed && o is StaticObject so) { + public override void OnMousePressed(MapObject? o) + { + if (!_pressed && o is StaticObject so) + { _pressed = true; _focusObject = so; } } - - public override void OnMouseReleased(MapObject? o) { - if (_pressed && o is StaticObject so && so == _focusObject) { - if(CEDGame.UIManager._huesWindow.SelectedId != -1) + + public override void OnMouseReleased(MapObject? o) + { + if (_pressed && o is StaticObject so && so == _focusObject) + { + if (CEDGame.UIManager._huesWindow.SelectedId != -1) so.StaticTile.Hue = (ushort)CEDGame.UIManager._huesWindow.SelectedId; } _pressed = false; diff --git a/CentrED/Tools/MoveTool.cs b/CentrED/Tools/MoveTool.cs index 6864bab..2ad622a 100644 --- a/CentrED/Tools/MoveTool.cs +++ b/CentrED/Tools/MoveTool.cs @@ -4,27 +4,32 @@ namespace CentrED.Tools; -public class MoveTool : Tool { +public class MoveTool : Tool +{ public override string Name => "MoveTool"; private int _xDelta; private int _yDelta; - + private bool _pressed; private StaticObject _focusObject; - internal override void DrawWindow() { - ImGui.SetNextWindowSize(new System.Numerics.Vector2(200, 100), ImGuiCond.FirstUseEver ); + internal override void DrawWindow() + { + ImGui.SetNextWindowSize(new System.Numerics.Vector2(200, 100), ImGuiCond.FirstUseEver); ImGui.Begin(Name, ImGuiWindowFlags.NoTitleBar); ImGui.InputInt("X", ref _xDelta); ImGui.InputInt("Y", ref _yDelta); ImGui.End(); } - public override void OnMouseEnter(MapObject? o) { - if (o is StaticObject so) { + public override void OnMouseEnter(MapObject? o) + { + if (o is StaticObject so) + { so.Alpha = 0.3f; - var newTile = new StaticTile( + var newTile = new StaticTile + ( so.StaticTile.Id, (ushort)(so.StaticTile.X + _xDelta), (ushort)(so.StaticTile.Y + _yDelta), @@ -34,24 +39,31 @@ public override void OnMouseEnter(MapObject? o) { CEDGame.MapManager.GhostStaticTiles.Add(new StaticObject(newTile)); } } - - public override void OnMouseLeave(MapObject? o) { - if (o is StaticObject so) { + + public override void OnMouseLeave(MapObject? o) + { + if (o is StaticObject so) + { so.Alpha = 1f; CEDGame.MapManager.GhostStaticTiles.Clear(); } } - public override void OnMousePressed(MapObject? o) { - if (!_pressed && o is StaticObject so) { + public override void OnMousePressed(MapObject? o) + { + if (!_pressed && o is StaticObject so) + { _pressed = true; _focusObject = so; } } - - public override void OnMouseReleased(MapObject? o) { - if (_pressed && o is StaticObject so && so == _focusObject) { - so.StaticTile.UpdatePos((ushort)(so.StaticTile.X + _xDelta), (ushort)(so.StaticTile.Y + _yDelta), so.StaticTile.Z); + + public override void OnMouseReleased(MapObject? o) + { + if (_pressed && o is StaticObject so && so == _focusObject) + { + so.StaticTile.UpdatePos + ((ushort)(so.StaticTile.X + _xDelta), (ushort)(so.StaticTile.Y + _yDelta), so.StaticTile.Z); } _pressed = false; } diff --git a/CentrED/Tools/RemoveTool.cs b/CentrED/Tools/RemoveTool.cs index 005a67d..57ce246 100644 --- a/CentrED/Tools/RemoveTool.cs +++ b/CentrED/Tools/RemoveTool.cs @@ -1,35 +1,44 @@ using CentrED.Map; using static CentrED.Application; -namespace CentrED.Tools; +namespace CentrED.Tools; -public class RemoveTool : Tool { +public class RemoveTool : Tool +{ public override string Name => "RemoveTool"; private bool _pressed; private StaticObject _focusObject; - - public override void OnMouseEnter(MapObject? o) { - if (o is StaticObject so) { + + public override void OnMouseEnter(MapObject? o) + { + if (o is StaticObject so) + { so.Alpha = 0.2f; } } - public override void OnMouseLeave(MapObject? o) { - if (o is StaticObject so) { + public override void OnMouseLeave(MapObject? o) + { + if (o is StaticObject so) + { so.Alpha = 1.0f; } } - public override void OnMousePressed(MapObject? o) { - if (!_pressed && o is StaticObject so) { + public override void OnMousePressed(MapObject? o) + { + if (!_pressed && o is StaticObject so) + { _pressed = true; _focusObject = so; } } - - public override void OnMouseReleased(MapObject? o) { - if (_pressed && o is StaticObject so && so == _focusObject) { + + public override void OnMouseReleased(MapObject? o) + { + if (_pressed && o is StaticObject so && so == _focusObject) + { CEDClient.Remove(_focusObject.StaticTile); } _pressed = false; diff --git a/CentrED/Tools/SelectTool.cs b/CentrED/Tools/SelectTool.cs index d236805..e0521f0 100644 --- a/CentrED/Tools/SelectTool.cs +++ b/CentrED/Tools/SelectTool.cs @@ -1,17 +1,19 @@ using CentrED.Map; using static CentrED.Application; -namespace CentrED.Tools; - -public class SelectTool : Tool { +namespace CentrED.Tools; +public class SelectTool : Tool +{ public override string Name => "Select"; - public override void OnMousePressed(MapObject? selected) { + public override void OnMousePressed(MapObject? selected) + { CEDGame.UIManager._infoWindow.Selected = selected; } - public override void OnActivated(MapObject? o) { + public override void OnActivated(MapObject? o) + { CEDGame.UIManager._infoWindow.Show = true; } } \ No newline at end of file diff --git a/CentrED/Tools/Tool.cs b/CentrED/Tools/Tool.cs index 1d1091d..8eccee6 100644 --- a/CentrED/Tools/Tool.cs +++ b/CentrED/Tools/Tool.cs @@ -1,35 +1,36 @@ using CentrED.Map; -namespace CentrED.Tools; +namespace CentrED.Tools; -public abstract class Tool { +public abstract class Tool +{ public abstract string Name { get; } - - internal virtual void DrawWindow() { - + + internal virtual void DrawWindow() + { } - public virtual void OnActivated(MapObject? o) { - + public virtual void OnActivated(MapObject? o) + { } - public virtual void OnDeactivated(MapObject? o) { - + public virtual void OnDeactivated(MapObject? o) + { } - public virtual void OnMouseEnter(MapObject? o) { - + public virtual void OnMouseEnter(MapObject? o) + { } - public virtual void OnMouseLeave(MapObject? o) { - + public virtual void OnMouseLeave(MapObject? o) + { } - public virtual void OnMousePressed(MapObject? o) { - + public virtual void OnMousePressed(MapObject? o) + { } - public virtual void OnMouseReleased(MapObject? o) { - + public virtual void OnMouseReleased(MapObject? o) + { } } \ No newline at end of file diff --git a/CentrED/UI/FilePicker.cs b/CentrED/UI/FilePicker.cs index 1c6ab22..5451382 100644 --- a/CentrED/UI/FilePicker.cs +++ b/CentrED/UI/FilePicker.cs @@ -4,182 +4,182 @@ using Microsoft.Xna.Framework; using Num = System.Numerics; -namespace CentrED.UI +namespace CentrED.UI; + +public class FilePicker { - public class FilePicker - { - static readonly Dictionary _filePickers = new(); - - public string RootFolder; - public string CurrentFolder; - public string SelectedFile; - public List AllowedExtensions; - public bool OnlyAllowFolders; - - public static FilePicker GetFolderPicker(object o, string startingPath) - => GetFilePicker(o, startingPath, null, true); - - public static FilePicker GetFilePicker(object o, string startingPath, string searchFilter = null, bool onlyAllowFolders = false) - { - if (File.Exists(startingPath)) - { - startingPath = new FileInfo(startingPath).DirectoryName; - } - else if (string.IsNullOrEmpty(startingPath) || !Directory.Exists(startingPath)) - { - startingPath = Environment.CurrentDirectory; - if (string.IsNullOrEmpty(startingPath)) - startingPath = AppContext.BaseDirectory; - } - - if (!_filePickers.TryGetValue(o, out FilePicker fp)) - { - fp = new FilePicker(); - fp.RootFolder = "/"; - fp.CurrentFolder = startingPath; - fp.OnlyAllowFolders = onlyAllowFolders; - - if (searchFilter != null) - { - if (fp.AllowedExtensions != null) - fp.AllowedExtensions.Clear(); - else - fp.AllowedExtensions = new List(); - - fp.AllowedExtensions.AddRange(searchFilter.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)); - } - - _filePickers.Add(o, fp); - } - - return fp; - } - - public static void RemoveFilePicker(object o) => _filePickers.Remove(o); - - public bool Draw() - { - ImGui.Text("Current Folder: " + Path.GetFileName(RootFolder) + CurrentFolder.Replace(RootFolder, "")); - bool result = false; - - if (ImGui.BeginChildFrame(1, new Num.Vector2(400, 400))) - { - var di = new DirectoryInfo(CurrentFolder); - if (di.Exists) - { - if (di.Parent != null && CurrentFolder != RootFolder) - { - ImGui.PushStyleColor(ImGuiCol.Text, Color.Yellow.PackedValue); - if (ImGui.Selectable("../", false, ImGuiSelectableFlags.DontClosePopups)) - CurrentFolder = di.Parent.FullName; - - ImGui.PopStyleColor(); - } - - var fileSystemEntries = GetFileSystemEntries(di.FullName); - foreach (var fse in fileSystemEntries) - { - if (Directory.Exists(fse)) - { - var name = Path.GetFileName(fse); - ImGui.PushStyleColor(ImGuiCol.Text, Color.Yellow.PackedValue); - if (ImGui.Selectable(name + "/", false, ImGuiSelectableFlags.DontClosePopups)) - CurrentFolder = fse; - ImGui.PopStyleColor(); - } - else - { - var name = Path.GetFileName(fse); - bool isSelected = SelectedFile == fse; - if (ImGui.Selectable(name, isSelected, ImGuiSelectableFlags.DontClosePopups)) - SelectedFile = fse; - - if (ImGui.IsMouseDoubleClicked(0)) - { - result = true; - ImGui.CloseCurrentPopup(); - } - } - } - } - } - ImGui.EndChildFrame(); - - - if (ImGui.Button("Cancel")) - { - result = false; - ImGui.CloseCurrentPopup(); - } - - if (OnlyAllowFolders) - { - ImGui.SameLine(); - if (ImGui.Button("Open")) - { - result = true; - SelectedFile = CurrentFolder; - ImGui.CloseCurrentPopup(); - } - } - else if (SelectedFile != null) - { - ImGui.SameLine(); - if (ImGui.Button("Open")) - { - result = true; - ImGui.CloseCurrentPopup(); - } - } - - return result; - } - - bool TryGetFileInfo(string fileName, out FileInfo realFile) - { - try - { - realFile = new FileInfo(fileName); - return true; - } - catch - { - realFile = null; - return false; - } - } - - List GetFileSystemEntries(string fullName) - { - var files = new List(); - var dirs = new List(); - - foreach (var fse in Directory.GetFileSystemEntries(fullName, "")) - { - if (Directory.Exists(fse)) - { - dirs.Add(fse); - } - else if (!OnlyAllowFolders) - { - if (AllowedExtensions != null) - { - var ext = Path.GetExtension(fse); - if (AllowedExtensions.Contains(ext)) - files.Add(fse); - } - else - { - files.Add(fse); - } - } - } - - var ret = new List(dirs); - ret.AddRange(files); - - return ret; - } - - } + static readonly Dictionary _filePickers = new(); + + public string RootFolder; + public string CurrentFolder; + public string SelectedFile; + public List AllowedExtensions; + public bool OnlyAllowFolders; + + public static FilePicker GetFolderPicker(object o, string startingPath) => GetFilePicker + (o, startingPath, null, true); + + public static FilePicker GetFilePicker + (object o, string startingPath, string searchFilter = null, bool onlyAllowFolders = false) + { + if (File.Exists(startingPath)) + { + startingPath = new FileInfo(startingPath).DirectoryName; + } + else if (string.IsNullOrEmpty(startingPath) || !Directory.Exists(startingPath)) + { + startingPath = Environment.CurrentDirectory; + if (string.IsNullOrEmpty(startingPath)) + startingPath = AppContext.BaseDirectory; + } + + if (!_filePickers.TryGetValue(o, out FilePicker fp)) + { + fp = new FilePicker(); + fp.RootFolder = "/"; + fp.CurrentFolder = startingPath; + fp.OnlyAllowFolders = onlyAllowFolders; + + if (searchFilter != null) + { + if (fp.AllowedExtensions != null) + fp.AllowedExtensions.Clear(); + else + fp.AllowedExtensions = new List(); + + fp.AllowedExtensions.AddRange + (searchFilter.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)); + } + + _filePickers.Add(o, fp); + } + + return fp; + } + + public static void RemoveFilePicker(object o) => _filePickers.Remove(o); + + public bool Draw() + { + ImGui.Text("Current Folder: " + Path.GetFileName(RootFolder) + CurrentFolder.Replace(RootFolder, "")); + bool result = false; + + if (ImGui.BeginChildFrame(1, new Num.Vector2(400, 400))) + { + var di = new DirectoryInfo(CurrentFolder); + if (di.Exists) + { + if (di.Parent != null && CurrentFolder != RootFolder) + { + ImGui.PushStyleColor(ImGuiCol.Text, Color.Yellow.PackedValue); + if (ImGui.Selectable("../", false, ImGuiSelectableFlags.DontClosePopups)) + CurrentFolder = di.Parent.FullName; + + ImGui.PopStyleColor(); + } + + var fileSystemEntries = GetFileSystemEntries(di.FullName); + foreach (var fse in fileSystemEntries) + { + if (Directory.Exists(fse)) + { + var name = Path.GetFileName(fse); + ImGui.PushStyleColor(ImGuiCol.Text, Color.Yellow.PackedValue); + if (ImGui.Selectable(name + "/", false, ImGuiSelectableFlags.DontClosePopups)) + CurrentFolder = fse; + ImGui.PopStyleColor(); + } + else + { + var name = Path.GetFileName(fse); + bool isSelected = SelectedFile == fse; + if (ImGui.Selectable(name, isSelected, ImGuiSelectableFlags.DontClosePopups)) + SelectedFile = fse; + + if (ImGui.IsMouseDoubleClicked(0)) + { + result = true; + ImGui.CloseCurrentPopup(); + } + } + } + } + } + ImGui.EndChildFrame(); + + + if (ImGui.Button("Cancel")) + { + result = false; + ImGui.CloseCurrentPopup(); + } + + if (OnlyAllowFolders) + { + ImGui.SameLine(); + if (ImGui.Button("Open")) + { + result = true; + SelectedFile = CurrentFolder; + ImGui.CloseCurrentPopup(); + } + } + else if (SelectedFile != null) + { + ImGui.SameLine(); + if (ImGui.Button("Open")) + { + result = true; + ImGui.CloseCurrentPopup(); + } + } + + return result; + } + + bool TryGetFileInfo(string fileName, out FileInfo realFile) + { + try + { + realFile = new FileInfo(fileName); + return true; + } + catch + { + realFile = null; + return false; + } + } + + List GetFileSystemEntries(string fullName) + { + var files = new List(); + var dirs = new List(); + + foreach (var fse in Directory.GetFileSystemEntries(fullName, "")) + { + if (Directory.Exists(fse)) + { + dirs.Add(fse); + } + else if (!OnlyAllowFolders) + { + if (AllowedExtensions != null) + { + var ext = Path.GetExtension(fse); + if (AllowedExtensions.Contains(ext)) + files.Add(fse); + } + else + { + files.Add(fse); + } + } + } + + var ret = new List(dirs); + ret.AddRange(files); + + return ret; + } } \ No newline at end of file diff --git a/CentrED/UI/UIManager.cs b/CentrED/UI/UIManager.cs index 4608f37..d7f9dc7 100644 --- a/CentrED/UI/UIManager.cs +++ b/CentrED/UI/UIManager.cs @@ -12,14 +12,15 @@ namespace CentrED.UI; -public class UIManager { - public static Vector4 Red = new (1, 0, 0, 1); - public static Vector4 Green = new (0, 1, 0, 1); - public static Vector4 Blue = new (0, 0, 1, 1); - +public class UIManager +{ + public static Vector4 Red = new(1, 0, 0, 1); + public static Vector4 Green = new(0, 1, 0, 1); + public static Vector4 Blue = new(0, 0, 1, 1); + internal UIRenderer _uiRenderer; internal GraphicsDevice _graphicsDevice; - + // Input private int _scrollWheelValue; private readonly float WHEEL_DELTA = 120; @@ -36,22 +37,24 @@ public class UIManager { internal List mainWindows = new(); internal List toolsWindows = new(); - public UIManager(GraphicsDevice gd) { + public UIManager(GraphicsDevice gd) + { _graphicsDevice = gd; _uiRenderer = new UIRenderer(_graphicsDevice); var context = ImGui.CreateContext(); ImGui.SetCurrentContext(context); - + TextInputEXT.TextInput += c => { - if (c == '\t') return; + if (c == '\t') + return; ImGui.GetIO().AddInputCharacter(c); }; _uiRenderer.RebuildFontAtlas(); - + mainWindows.Add(new ConnectWindow()); mainWindows.Add(new ServerWindow()); mainWindows.Add(new OptionsWindow()); @@ -72,7 +75,7 @@ public UIManager(GraphicsDevice gd) { tools.Add(new DrawTool()); tools.Add(new RemoveTool()); tools.Add(new MoveTool()); - tools.Add( new ElevateTool()); + tools.Add(new ElevateTool()); tools.Add(new HueTool()); _debugWindow = new DebugWindow(); @@ -83,8 +86,9 @@ public void Update(GameTime gameTime, bool isActive) var io = ImGui.GetIO(); io.DeltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds; - - if(!isActive) return; + + if (!isActive) + return; var mouse = Mouse.GetState(); var keyboard = Keyboard.GetState(); @@ -106,19 +110,27 @@ public void Update(GameTime gameTime, bool isActive) } } - io.DisplaySize = new Vector2(_graphicsDevice.PresentationParameters.BackBufferWidth, _graphicsDevice.PresentationParameters.BackBufferHeight); + io.DisplaySize = new Vector2 + ( + _graphicsDevice.PresentationParameters.BackBufferWidth, + _graphicsDevice.PresentationParameters.BackBufferHeight + ); io.DisplayFramebufferScale = new Vector2(1f, 1f); } internal double _framesPerSecond; - - public void Draw(GameTime gameTime) { + + public void Draw(GameTime gameTime) + { _framesPerSecond = 1 / gameTime.ElapsedGameTime.TotalSeconds; ImGui.NewFrame(); DrawUI(); ImGui.Render(); - unsafe { _uiRenderer.RenderDrawData(ImGui.GetDrawData()); } + unsafe + { + _uiRenderer.RenderDrawData(ImGui.GetDrawData()); + } } public bool CapturingMouse => ImGui.GetIO().WantCaptureMouse; @@ -185,59 +197,73 @@ private bool TryMapKeys(Keys key, out ImGuiKey imguikey) return imguikey != ImGuiKey.None; } - - protected virtual void DrawUI() { + + protected virtual void DrawUI() + { DrawContextMenu(); DrawMainMenu(); mainWindows.ForEach(w => w.Draw()); toolsWindows.ForEach(w => w.Draw()); _debugWindow.Draw(); } - + internal float _mainMenuHeight; - private void DrawContextMenu() { - if (ImGui.IsMouseReleased(ImGuiMouseButton.Right) && !ImGui.IsAnyItemActive()) { + private void DrawContextMenu() + { + if (ImGui.IsMouseReleased(ImGuiMouseButton.Right) && !ImGui.IsAnyItemActive()) + { ImGui.OpenPopup("MainPopup"); } if (ImGui.BeginPopup("MainPopup")) { var mousePos = ImGui.GetMousePosOnOpeningCurrentPopup(); var selected = CEDGame.MapManager.GetMouseSelection((int)mousePos.X, (int)mousePos.Y); - if (selected != null) { - if (ImGui.Button("Grab TileId")) { + if (selected != null) + { + if (ImGui.Button("Grab TileId")) + { _tilesWindow.UpdateSelectedId(selected); ImGui.CloseCurrentPopup(); } - if (selected is StaticObject so) { - if (ImGui.Button("Grab Hue")) { + if (selected is StaticObject so) + { + if (ImGui.Button("Grab Hue")) + { _huesWindow.UpdateSelectedHue(so.StaticTile.Hue); ImGui.CloseCurrentPopup(); } } } - else { + else + { ImGui.Text("Nothing to see here"); } ImGui.EndPopup(); } } - - private void DrawMainMenu() { - if (ImGui.BeginMainMenuBar()) { - if (ImGui.BeginMenu("CentrED")) { + + private void DrawMainMenu() + { + if (ImGui.BeginMainMenuBar()) + { + if (ImGui.BeginMenu("CentrED")) + { mainWindows.ForEach(w => w.DrawMenuItem()); ImGui.Separator(); - if (ImGui.MenuItem("Quit")) CEDGame.Exit(); + if (ImGui.MenuItem("Quit")) + CEDGame.Exit(); ImGui.EndMenu(); } - if (ImGui.BeginMenu("Tools")) { + if (ImGui.BeginMenu("Tools")) + { toolsWindows.ForEach(w => w.DrawMenuItem()); ImGui.EndMenu(); } - if (ImGui.BeginMenu("Help")) { + if (ImGui.BeginMenu("Help")) + { //Credits //About ImGui.Separator(); @@ -250,29 +276,32 @@ private void DrawMainMenu() { _mainMenuHeight = ImGui.GetItemRectSize().Y; } - - internal void DrawImage(Texture2D tex, Rectangle bounds) { + + internal void DrawImage(Texture2D tex, Rectangle bounds) + { DrawImage(tex, bounds, new Vector2(bounds.Width, bounds.Height)); } - - internal void DrawImage(Texture2D tex, Rectangle bounds, Vector2 size) { + + internal void DrawImage(Texture2D tex, Rectangle bounds, Vector2 size) + { var texPtr = _uiRenderer.BindTexture(tex); var fWidth = (float)tex.Width; var fHeight = (float)tex.Height; var uv0 = new Vector2(bounds.X / fWidth, bounds.Y / fHeight); - var uv1 = new Vector2( - (bounds.X + bounds.Width) / fWidth, - (bounds.Y + bounds.Height) / fHeight - ); + var uv1 = new Vector2((bounds.X + bounds.Width) / fWidth, (bounds.Y + bounds.Height) / fHeight); ImGui.Image(texPtr, size, uv0, uv1); } - - internal void CenterWindow() { - ImGui.SetWindowPos( - new Vector2( + + internal void CenterWindow() + { + ImGui.SetWindowPos + ( + new Vector2 + ( _graphicsDevice.PresentationParameters.BackBufferWidth / 2 - ImGui.GetWindowSize().X / 2, - _graphicsDevice.PresentationParameters.BackBufferHeight / 2 - ImGui.GetWindowSize().Y / 2) - , ImGuiCond.FirstUseEver + _graphicsDevice.PresentationParameters.BackBufferHeight / 2 - ImGui.GetWindowSize().Y / 2 + ), + ImGuiCond.FirstUseEver ); } } \ No newline at end of file diff --git a/CentrED/UI/Windows/ConnectWindow.cs b/CentrED/UI/Windows/ConnectWindow.cs index e79641c..65c21b7 100644 --- a/CentrED/UI/Windows/ConnectWindow.cs +++ b/CentrED/UI/Windows/ConnectWindow.cs @@ -8,9 +8,10 @@ namespace CentrED.UI.Windows; -public class ConnectWindow : Window { +public class ConnectWindow : Window +{ public override string Name => "Connect"; - + private const int TextInputLength = 255; private int _profileIndex = ProfileManager.Profiles.IndexOf(ProfileManager.ActiveProfile); private string _hostname = ProfileManager.ActiveProfile.Hostname; @@ -25,14 +26,16 @@ public class ConnectWindow : Window { private string _info = ""; private string _profileName = ""; - public override void Draw() { - if (!Show) return; - - ImGui.Begin(Name, ref _show, ImGuiWindowFlags.NoResize); + public override void Draw() + { + if (!Show) + return; + + ImGui.Begin(Name, ref _show, ImGuiWindowFlags.NoResize); ImGui.SetWindowSize(Name, new Vector2(510, 250)); // CenterWindow(); - if (ImGui.Combo("Profile", ref _profileIndex, ProfileManager.ProfileNames, - ProfileManager.Profiles.Count)) { + if (ImGui.Combo("Profile", ref _profileIndex, ProfileManager.ProfileNames, ProfileManager.Profiles.Count)) + { var profile = ProfileManager.Profiles[_profileIndex]; _profileName = profile.Name; _hostname = profile.Hostname; @@ -44,44 +47,66 @@ public override void Draw() { Config.ActiveProfile = profile.Name; } ImGui.SameLine(); - if (ImGui.Button("Save")) { + if (ImGui.Button("Save")) + { ImGui.OpenPopup("SaveProfile"); } - if (ImGui.BeginPopup("SaveProfile")) { + if (ImGui.BeginPopup("SaveProfile")) + { ImGui.InputText("Name", ref _profileName, 128); - if (ImGui.Button("Save")) { - _profileIndex = ProfileManager.Save(new Profile { - Name = _profileName, Hostname = _hostname, Port = _port, - Username = _username, ClientPath = _clientPath, ClientVersion = _clientVersion - }); - + if (ImGui.Button("Save")) + { + _profileIndex = ProfileManager.Save + ( + new Profile + { + Name = _profileName, + Hostname = _hostname, + Port = _port, + Username = _username, + ClientPath = _clientPath, + ClientVersion = _clientVersion + } + ); + ImGui.CloseCurrentPopup(); } ImGui.EndPopup(); } - + ImGui.Text(""); ImGui.InputText("Host", ref _hostname, TextInputLength); ImGui.InputInt("Port", ref _port); ImGui.InputText("Username", ref _username, TextInputLength); - - ImGui.InputText("Password", ref _password, TextInputLength, _showPassword ? ImGuiInputTextFlags.None : ImGuiInputTextFlags.Password); + + ImGui.InputText + ( + "Password", + ref _password, + TextInputLength, + _showPassword ? ImGuiInputTextFlags.None : ImGuiInputTextFlags.Password + ); ImGui.SameLine(); - if (ImGui.Button(_showPassword? "Hide" : "Show")) { + if (ImGui.Button(_showPassword ? "Hide" : "Show")) + { _showPassword = !_showPassword; } ImGui.InputText("ClientPath", ref _clientPath, TextInputLength); ImGui.SameLine(); - if (ImGui.Button("...")) { + if (ImGui.Button("...")) + { ImGui.OpenPopup("open-dir"); } var isOpen = true; - if (ImGui.BeginPopupModal("open-dir", ref isOpen, ImGuiWindowFlags.NoTitleBar)) { - var picker = FilePicker.GetFolderPicker(this, _clientPath.Length == 0 ? Environment.CurrentDirectory : _clientPath); - if (picker.Draw()) { + if (ImGui.BeginPopupModal("open-dir", ref isOpen, ImGuiWindowFlags.NoTitleBar)) + { + var picker = FilePicker.GetFolderPicker + (this, _clientPath.Length == 0 ? Environment.CurrentDirectory : _clientPath); + if (picker.Draw()) + { _clientPath = picker.SelectedFile; FilePicker.RemoveFilePicker(this); } @@ -90,48 +115,62 @@ public override void Draw() { } ImGui.InputText("ClientVersion", ref _clientVersion, TextInputLength); ImGui.SameLine(); - if (ImGui.Button("Discover")) { - if (ClientVersionHelper.TryParseFromFile(Path.Join(_clientPath, "client.exe"), out _clientVersion)) { + if (ImGui.Button("Discover")) + { + if (ClientVersionHelper.TryParseFromFile(Path.Join(_clientPath, "client.exe"), out _clientVersion)) + { _info = "Version discovered!"; _infoColor = UIManager.Green; } - else { + else + { _info = "Unable to discover client version"; _infoColor = UIManager.Red; _clientVersion = ""; } } ImGui.TextColored(_infoColor, _info); - ImGui.BeginDisabled( - _hostname.Length == 0 || _password.Length == 0 || _username.Length == 0 || - _clientPath.Length == 0 || _clientVersion.Length == 0 || _buttonDisabled); - if (CEDGame.MapManager.Client.Running) { - if (ImGui.Button("Disconnect")) { + ImGui.BeginDisabled + ( + _hostname.Length == 0 || _password.Length == 0 || _username.Length == 0 || _clientPath.Length == 0 || + _clientVersion.Length == 0 || _buttonDisabled + ); + if (CEDGame.MapManager.Client.Running) + { + if (ImGui.Button("Disconnect")) + { CEDGame.MapManager.Client.Disconnect(); CEDGame.MapManager.Reset(); _info = "Disconnected"; } } - else { - if (ImGui.Button("Connect")) { + else + { + if (ImGui.Button("Connect")) + { CEDGame.MapManager.Reset(); _buttonDisabled = true; - new Task(() => { - try { + new Task + ( + () => + { + try + { _infoColor = UIManager.Blue; _info = "Loading"; CEDGame.MapManager.Load(_clientPath, _clientVersion); _info = "Connecting"; - CEDClient.Connect(_hostname, _port, _username, - _password); + CEDClient.Connect(_hostname, _port, _username, _password); _info = CEDClient.Status; _infoColor = CEDClient.Running ? UIManager.Blue : UIManager.Red; } - catch (SocketException e) { + catch (SocketException e) + { _info = "Unable to connect"; _infoColor = UIManager.Red; } - finally { + finally + { _buttonDisabled = false; } } diff --git a/CentrED/UI/Windows/DebugWindow.cs b/CentrED/UI/Windows/DebugWindow.cs index 358adda..086d133 100644 --- a/CentrED/UI/Windows/DebugWindow.cs +++ b/CentrED/UI/Windows/DebugWindow.cs @@ -1,17 +1,20 @@ using System.Numerics; using ImGuiNET; -namespace CentrED.UI.Windows; +namespace CentrED.UI.Windows; -public class DebugWindow : Window { +public class DebugWindow : Window +{ public override string Name => "Debug"; - + private int _gotoX; private int _gotoY; private bool _showTestWindow; - - public override void Draw() { - if (!Show) return; + + public override void Draw() + { + if (!Show) + return; // ImGui.SetNextWindowPos(new Vector2( // _graphicsDevice.PresentationParameters.BackBufferWidth / 2, @@ -22,7 +25,10 @@ public override void Draw() { var mapManager = Application.CEDGame.MapManager; ImGui.Begin(Name, ref _show, ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoResize); ImGui.Text($"FPS: {uiManager._framesPerSecond:F1}"); - ImGui.Text($"Resolution: {uiManager._graphicsDevice.PresentationParameters.BackBufferWidth}x{uiManager._graphicsDevice.PresentationParameters.BackBufferHeight}"); + ImGui.Text + ( + $"Resolution: {uiManager._graphicsDevice.PresentationParameters.BackBufferWidth}x{uiManager._graphicsDevice.PresentationParameters.BackBufferHeight}" + ); ImGui.Text($"Land tiles: {mapManager.LandTiles.Count}"); ImGui.Text($"Static tiles: {mapManager.StaticTiles.Count}"); ImGui.Text($"Camera focus tile {mapManager.Camera.LookAt / mapManager.TILE_SIZE}"); @@ -37,15 +43,19 @@ public override void Draw() { ImGui.Separator(); ImGui.InputInt("Camera x", ref _gotoX); ImGui.InputInt("Camera y", ref _gotoY); - if (ImGui.Button("Update pos")) { + if (ImGui.Button("Update pos")) + { mapManager.SetPos((ushort)_gotoX, (ushort)_gotoY); } ImGui.Separator(); - if (ImGui.Button("Server Flush")) mapManager.Client.Flush(); - if (ImGui.Button("Clear cache")) mapManager.Reset(); + if (ImGui.Button("Server Flush")) + mapManager.Client.Flush(); + if (ImGui.Button("Clear cache")) + mapManager.Reset(); // if (ImGui.Button("Render 4K")) _mapManager.DrawHighRes(); - if (ImGui.Button("Test Window")) _showTestWindow = !_showTestWindow; + if (ImGui.Button("Test Window")) + _showTestWindow = !_showTestWindow; if (_showTestWindow) { ImGui.SetNextWindowPos(new Vector2(650, 20), ImGuiCond.FirstUseEver); diff --git a/CentrED/UI/Windows/FilterWindow.cs b/CentrED/UI/Windows/FilterWindow.cs index bb5f5a2..2ec57b5 100644 --- a/CentrED/UI/Windows/FilterWindow.cs +++ b/CentrED/UI/Windows/FilterWindow.cs @@ -1,8 +1,9 @@ using ImGuiNET; -namespace CentrED.UI.Windows; +namespace CentrED.UI.Windows; -public class FilterWindow : Window{ +public class FilterWindow : Window +{ public override string Name => "Filter"; private int minZ = -127; @@ -11,8 +12,10 @@ public class FilterWindow : Window{ public int MinZ => minZ; public int MaxZ => maxZ; - public override void Draw() { - if (!Show) return; + public override void Draw() + { + if (!Show) + return; ImGui.Begin(Name, ref _show); ImGui.SliderInt("Min Z render", ref minZ, -127, 127); ImGui.SliderInt("Max Z render", ref maxZ, -127, 127); diff --git a/CentrED/UI/Windows/HuesWindow.cs b/CentrED/UI/Windows/HuesWindow.cs index 71a9f41..f4d74c7 100644 --- a/CentrED/UI/Windows/HuesWindow.cs +++ b/CentrED/UI/Windows/HuesWindow.cs @@ -3,14 +3,17 @@ using static CentrED.Application; using Vector2 = System.Numerics.Vector2; -namespace CentrED.UI.Windows; +namespace CentrED.UI.Windows; -public class HuesWindow : Window{ - public HuesWindow() { +public class HuesWindow : Window +{ + public HuesWindow() + { CEDClient.Connected += FilterHues; } + public override string Name => "Hues"; - + private bool _updateScroll; private string _filter = ""; private float _tableWidth; @@ -19,52 +22,75 @@ public HuesWindow() { private const int _huesRowHeight = 20; private int[] _matchedHueIds; - - private void FilterHues() { + + private void FilterHues() + { var huesManager = HuesManager.Instance; - if (_filter.Length == 0) { + if (_filter.Length == 0) + { _matchedHueIds = new int[huesManager.HuesCount]; - for (int i = 0; i < huesManager.HuesCount; i++) { + for (int i = 0; i < huesManager.HuesCount; i++) + { _matchedHueIds[i] = i; } } - else { + else + { var matchedIds = new List(); - for (int i = 0; i < huesManager.HuesCount; i++) { + for (int i = 0; i < huesManager.HuesCount; i++) + { var name = huesManager.Names[i]; - if(name.Contains(_filter) || $"{i}".Contains(_filter) || $"0x{i:X4}".Contains(_filter)) + if (name.Contains(_filter) || $"{i}".Contains(_filter) || $"0x{i:X4}".Contains(_filter)) matchedIds.Add(i); } _matchedHueIds = matchedIds.ToArray(); } } - public override void Draw() { - if (!Show) return; - ImGui.SetNextWindowSize(new Vector2(250, CEDGame._gdm.GraphicsDevice.PresentationParameters.BackBufferHeight - CEDGame.UIManager._mainMenuHeight), ImGuiCond.FirstUseEver); + + public override void Draw() + { + if (!Show) + return; + ImGui.SetNextWindowSize + ( + new Vector2 + ( + 250, + CEDGame._gdm.GraphicsDevice.PresentationParameters.BackBufferHeight - CEDGame.UIManager._mainMenuHeight + ), + ImGuiCond.FirstUseEver + ); ImGui.Begin("Hues", ref _show); - if (ImGui.Button("Scroll to selected")) { + if (ImGui.Button("Scroll to selected")) + { _updateScroll = true; } ImGui.Text("Filter"); - if (ImGui.InputText("", ref _filter, 64)) { + if (ImGui.InputText("", ref _filter, 64)) + { FilterHues(); } var huesPosY = ImGui.GetCursorPosY(); ImGui.BeginChild("Hues", new Vector2(), false, ImGuiWindowFlags.Modal); - if (ImGui.BeginTable("TilesTable", 2) && CEDClient.Initialized) { - unsafe { + if (ImGui.BeginTable("TilesTable", 2) && CEDClient.Initialized) + { + unsafe + { ImGuiListClipperPtr clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper()); ImGui.TableSetupColumn("Id", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("0x0000").X); _tableWidth = ImGui.GetContentRegionAvail().X; clipper.Begin(_matchedHueIds.Length, _huesRowHeight); - while (clipper.Step()) { - for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { + while (clipper.Step()) + { + for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) + { HuesDrawElement(_matchedHueIds[i]); } } clipper.End(); - if (_updateScroll) { + if (_updateScroll) + { float itemPosY = clipper.StartPosY + _huesRowHeight * Array.IndexOf(_matchedHueIds, SelectedId); ImGui.SetScrollFromPosY(itemPosY - huesPosY); _updateScroll = false; @@ -77,41 +103,57 @@ public override void Draw() { ImGui.EndChild(); ImGui.End(); } - - private void HuesDrawElement(int index) { + + private void HuesDrawElement(int index) + { var name = HuesManager.Instance.Names[index]; - + ImGui.TableNextRow(ImGuiTableRowFlags.None, _huesRowHeight); - if (ImGui.TableNextColumn()) { + if (ImGui.TableNextColumn()) + { var startPos = ImGui.GetCursorPos(); var selectableSize = new Vector2(_tableWidth, _huesRowHeight); - if (ImGui.Selectable($"##hue{index}", SelectedId == index, - ImGuiSelectableFlags.SpanAllColumns, selectableSize)) { + if (ImGui.Selectable + ($"##hue{index}", SelectedId == index, ImGuiSelectableFlags.SpanAllColumns, selectableSize)) + { SelectedId = index; } - ImGui.SetCursorPos(startPos with { Y = startPos.Y + (_huesRowHeight - ImGui.GetFontSize()) / 2 }); + ImGui.SetCursorPos + ( + startPos with + { + Y = startPos.Y + (_huesRowHeight - ImGui.GetFontSize()) / 2 + } + ); ImGui.Text($"0x{index:X4}"); - } - if (ImGui.TableNextColumn()) { - if (index == 0) - ImGui.TextColored(UIManager.Red , name); - else { - CEDGame.UIManager.DrawImage(HuesManager.Instance.Texture, new Rectangle(0, index - 1, 32, 1), - new Vector2(ImGui.GetContentRegionAvail().X, _huesRowHeight)); + if (ImGui.TableNextColumn()) + { + if (index == 0) + ImGui.TextColored(UIManager.Red, name); + else + { + CEDGame.UIManager.DrawImage + ( + HuesManager.Instance.Texture, + new Rectangle(0, index - 1, 32, 1), + new Vector2(ImGui.GetContentRegionAvail().X, _huesRowHeight) + ); } - if (ImGui.BeginItemTooltip()) { + if (ImGui.BeginItemTooltip()) + { ImGui.Text(name); ImGui.EndTooltip(); } } } - public void UpdateSelectedHue(ushort staticTileHue) { + public void UpdateSelectedHue(ushort staticTileHue) + { SelectedId = staticTileHue; _updateScroll = true; } diff --git a/CentrED/UI/Windows/InfoWindow.cs b/CentrED/UI/Windows/InfoWindow.cs index 2ecac1c..c0b3241 100644 --- a/CentrED/UI/Windows/InfoWindow.cs +++ b/CentrED/UI/Windows/InfoWindow.cs @@ -4,17 +4,21 @@ using Microsoft.Xna.Framework; using static CentrED.Application; -namespace CentrED.UI.Windows; +namespace CentrED.UI.Windows; -public class InfoWindow : Window{ +public class InfoWindow : Window +{ public override string Name => "Info"; public MapObject? Selected; - public override void Draw() { - if (!Show) return; + public override void Draw() + { + if (!Show) + return; ImGui.Begin(Name, ref _show); - if (Selected is LandObject lo) { + if (Selected is LandObject lo) + { var land = lo.Tile; ImGui.Text("Land"); var texture = ArtLoader.Instance.GetLandTexture(land.Id, out var bounds); @@ -22,12 +26,17 @@ public override void Draw() { ImGui.Text($"x:{land.X} y:{land.Y} z:{land.Z}"); ImGui.Text($"id: 0x{land.Id:X4} ({land.Id})"); } - else if (Selected is StaticObject so) { + else if (Selected is StaticObject so) + { var staticTile = so.StaticTile; ImGui.Text("Static"); var texture = ArtLoader.Instance.GetStaticTexture(staticTile.Id, out var bounds); var realBounds = ArtLoader.Instance.GetRealArtBounds(staticTile.Id); - CEDGame.UIManager.DrawImage(texture, new Rectangle(bounds.X + realBounds.X, bounds.Y + realBounds.Y, realBounds.Width, realBounds.Height)); + CEDGame.UIManager.DrawImage + ( + texture, + new Rectangle(bounds.X + realBounds.X, bounds.Y + realBounds.Y, realBounds.Width, realBounds.Height) + ); ImGui.Text($"x:{staticTile.X} y:{staticTile.Y} z:{staticTile.Z}"); ImGui.Text($"id: 0x{staticTile.Id:X4} ({staticTile.Id})"); ImGui.Text($"hue: 0x{staticTile.Hue:X4} ({staticTile.Hue})"); diff --git a/CentrED/UI/Windows/MinimapWindow.cs b/CentrED/UI/Windows/MinimapWindow.cs index b7a2d10..cf22b6a 100644 --- a/CentrED/UI/Windows/MinimapWindow.cs +++ b/CentrED/UI/Windows/MinimapWindow.cs @@ -4,36 +4,44 @@ using static CentrED.Application; using RadarMap = CentrED.Map.RadarMap; -namespace CentrED.UI.Windows; +namespace CentrED.UI.Windows; -public class MinimapWindow : Window{ +public class MinimapWindow : Window +{ public override string Name => "Minimap"; private string _coordsText = ""; - public override void Draw() { - if (!Show) return; + + public override void Draw() + { + if (!Show) + return; ImGui.Begin("Minimap", ref _show, ImGuiWindowFlags.AlwaysAutoResize); - - if (CEDGame.MapManager.Client.Initialized) { + + if (CEDGame.MapManager.Client.Initialized) + { var currentPos = ImGui.GetCursorScreenPos(); var tex = RadarMap.Instance.Texture; CEDGame.UIManager.DrawImage(tex, tex.Bounds); if (ImGui.BeginPopupContextItem()) { - if (ImGui.Button("Reload")) { - CEDClient.Send(new RequestRadarMapPacket()); + if (ImGui.Button("Reload")) + { + CEDClient.Send(new RequestRadarMapPacket()); ImGui.CloseCurrentPopup(); } ImGui.EndPopup(); } - if (ImGui.IsMouseHoveringRect(currentPos, new(currentPos.X + tex.Bounds.Width, currentPos.Y + tex.Bounds.Height), true)) { + if (ImGui.IsMouseHoveringRect + (currentPos, new(currentPos.X + tex.Bounds.Width, currentPos.Y + tex.Bounds.Height), true)) + { var coords = ImGui.GetMousePos() - currentPos; - if (ImGui.IsWindowFocused() && ImGui.IsMouseDown(ImGuiMouseButton.Left)) { + if (ImGui.IsWindowFocused() && ImGui.IsMouseDown(ImGuiMouseButton.Left)) + { CEDGame.MapManager.SetPos((ushort)(coords.X * 8), (ushort)(coords.Y * 8)); } _coordsText = $"x:{coords.X * 8} y:{coords.Y * 8}"; - } CEDGame.MapManager.CalculateViewRange(CEDGame.MapManager.Camera, out var rect); var p1 = currentPos + new Vector2(rect.Left / 8, rect.Top / 8); diff --git a/CentrED/UI/Windows/OptionsWindow.cs b/CentrED/UI/Windows/OptionsWindow.cs index 1c692ff..8c3c535 100644 --- a/CentrED/UI/Windows/OptionsWindow.cs +++ b/CentrED/UI/Windows/OptionsWindow.cs @@ -1,12 +1,16 @@ using ImGuiNET; -namespace CentrED.UI.Windows; +namespace CentrED.UI.Windows; -public class OptionsWindow : Window{ +public class OptionsWindow : Window +{ public override string Name => "Options"; - public override void Draw() { - if (!Show) return; - + + public override void Draw() + { + if (!Show) + return; + ImGui.Begin("Options", ref _show, ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoResize); ImGui.Text("Nothing to see here (yet) :)"); ImGui.End(); diff --git a/CentrED/UI/Windows/ServerWindow.cs b/CentrED/UI/Windows/ServerWindow.cs index 648d648..3f38192 100644 --- a/CentrED/UI/Windows/ServerWindow.cs +++ b/CentrED/UI/Windows/ServerWindow.cs @@ -4,29 +4,35 @@ using ImGuiNET; using static CentrED.Application; -namespace CentrED.UI.Windows; +namespace CentrED.UI.Windows; -public class ServerWindow : Window { +public class ServerWindow : Window +{ public override string Name => "Local Server"; private string _configPath = Config.ServerConfigPath; private Vector4 _statusColor = UIManager.Red; - private string _statusText = "Stopped" -; private StreamReader? _logReader; + private string _statusText = "Stopped"; + private StreamReader? _logReader; private StringBuilder _log = new(); - public override void Draw() { - if (!Show) return; + public override void Draw() + { + if (!Show) + return; - ImGui.Begin(Name, ref _show ); + ImGui.Begin(Name, ref _show); ImGui.InputText("Config File", ref _configPath, 512); ImGui.SameLine(); - if (ImGui.Button("...")) { + if (ImGui.Button("...")) + { ImGui.OpenPopup("open-file"); } var isOpen = true; - if (ImGui.BeginPopupModal("open-file", ref isOpen, ImGuiWindowFlags.NoTitleBar)) { + if (ImGui.BeginPopupModal("open-file", ref isOpen, ImGuiWindowFlags.NoTitleBar)) + { var picker = FilePicker.GetFilePicker(this, Environment.CurrentDirectory, ".xml"); - if (picker.Draw()) { + if (picker.Draw()) + { _configPath = picker.SelectedFile; Config.ServerConfigPath = _configPath; FilePicker.RemoveFilePicker(this); @@ -34,54 +40,71 @@ public override void Draw() { ImGui.EndPopup(); } - if (Application.CEDServer != null && Application.CEDServer.Running) { - if (ImGui.Button("Stop")) { + if (Application.CEDServer != null && Application.CEDServer.Running) + { + if (ImGui.Button("Stop")) + { CEDClient.Disconnect(); Application.CEDServer.Quit = true; } } - else { - if (ImGui.Button("Start")) { - if (Application.CEDServer != null) { + else + { + if (ImGui.Button("Start")) + { + if (Application.CEDServer != null) + { Application.CEDServer.Dispose(); } _log.Clear(); Config.ServerConfigPath = _configPath; - - new Task(() => { - try { - _statusColor = UIManager.Blue; - _statusText = "Starting"; - var logWriter = - new StreamWriter(File.Open("cedserver.log", FileMode.Create, FileAccess.Write, - FileShare.ReadWrite)) { AutoFlush = true }; - _logReader = new StreamReader(File.Open("cedserver.log", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); - Application.CEDServer = new CEDServer(new[] { _configPath }, logWriter); - _statusColor = UIManager.Green; - _statusText = "Running"; - - Application.CEDServer.Run(); - } - catch (Exception e) { - Console.WriteLine("Server stopped"); - Console.WriteLine(e); - _statusColor = UIManager.Red; - _statusText = "Stopped"; + + new Task + ( + () => + { + try + { + _statusColor = UIManager.Blue; + _statusText = "Starting"; + var logWriter = new StreamWriter + (File.Open("cedserver.log", FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) + { + AutoFlush = true + }; + _logReader = new StreamReader + (File.Open("cedserver.log", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); + Application.CEDServer = new CEDServer(new[] { _configPath }, logWriter); + _statusColor = UIManager.Green; + _statusText = "Running"; + + Application.CEDServer.Run(); + } + catch (Exception e) + { + Console.WriteLine("Server stopped"); + Console.WriteLine(e); + _statusColor = UIManager.Red; + _statusText = "Stopped"; + } } - }).Start(); + ).Start(); } } ImGui.SameLine(); ImGui.TextColored(_statusColor, _statusText); - + ImGui.Separator(); ImGui.Text("Server Log:"); ImGui.BeginChild("ServerLogRegion"); - if (_logReader != null) { - do { + if (_logReader != null) + { + do + { var line = _logReader.ReadLine(); - if (line == null) break; + if (line == null) + break; _log.AppendLine(line); } while (true); } diff --git a/CentrED/UI/Windows/TilesWindow.cs b/CentrED/UI/Windows/TilesWindow.cs index 4f81249..a7c0fe5 100644 --- a/CentrED/UI/Windows/TilesWindow.cs +++ b/CentrED/UI/Windows/TilesWindow.cs @@ -6,14 +6,17 @@ using static CentrED.Application; using Vector2 = System.Numerics.Vector2; -namespace CentrED.UI.Windows; +namespace CentrED.UI.Windows; -public class TilesWindow : Window{ - public TilesWindow() { +public class TilesWindow : Window +{ + public TilesWindow() + { CEDClient.Connected += FilterTiles; } + public override string Name => "Tiles"; - + private string _filter = ""; internal int _selectedId; private bool _updateScroll; @@ -22,95 +25,127 @@ public TilesWindow() { private float _tableWidth; public const int MaxLandIndex = ArtLoader.MAX_LAND_DATA_INDEX_COUNT; private static readonly Vector2 _tilesDimensions = new(44, 44); - + private int[] _matchedLandIds; private int[] _matchedStaticIds; - - private void FilterTiles() { - if (_filter.Length == 0) { + + private void FilterTiles() + { + if (_filter.Length == 0) + { _matchedLandIds = new int[CEDGame.MapManager.ValidLandIds.Length]; CEDGame.MapManager.ValidLandIds.CopyTo(_matchedLandIds, 0); - + _matchedStaticIds = new int[CEDGame.MapManager.ValidStaticIds.Length]; CEDGame.MapManager.ValidStaticIds.CopyTo(_matchedStaticIds, 0); } - else { + else + { var filter = _filter.ToLower(); var matchedLandIds = new List(); - foreach (var index in CEDGame.MapManager.ValidLandIds) { + foreach (var index in CEDGame.MapManager.ValidLandIds) + { var name = TileDataLoader.Instance.LandData[index].Name?.ToLower() ?? ""; - if(name.Contains(filter) || $"{index}".Contains(_filter) || $"0x{index:x4}".Contains(filter)) + if (name.Contains(filter) || $"{index}".Contains(_filter) || $"0x{index:x4}".Contains(filter)) matchedLandIds.Add(index); } _matchedLandIds = matchedLandIds.ToArray(); - + var matchedStaticIds = new List(); - foreach (var index in CEDGame.MapManager.ValidStaticIds) { + foreach (var index in CEDGame.MapManager.ValidStaticIds) + { var name = TileDataLoader.Instance.StaticData[index].Name?.ToLower() ?? ""; - if(name.Contains(filter) || $"{index}".Contains(_filter) || $"0x{index:x4}".Contains(filter)) + if (name.Contains(filter) || $"{index}".Contains(_filter) || $"0x{index:x4}".Contains(filter)) matchedStaticIds.Add(index); } _matchedStaticIds = matchedStaticIds.ToArray(); } } - public override void Draw() { - if (!Show) return; - ImGui.SetNextWindowSize(new Vector2(250, CEDGame._gdm.GraphicsDevice.PresentationParameters.BackBufferHeight - CEDGame.UIManager._mainMenuHeight), ImGuiCond.FirstUseEver); + + public override void Draw() + { + if (!Show) + return; + ImGui.SetNextWindowSize + ( + new Vector2 + ( + 250, + CEDGame._gdm.GraphicsDevice.PresentationParameters.BackBufferHeight - CEDGame.UIManager._mainMenuHeight + ), + ImGuiCond.FirstUseEver + ); ImGui.Begin(Name, ref _show); - if (ImGui.Button("Scroll to selected")) { + if (ImGui.Button("Scroll to selected")) + { _updateScroll = true; } - + ImGui.Text("Filter"); - if (ImGui.InputText("", ref _filter, 64)) { + if (ImGui.InputText("", ref _filter, 64)) + { FilterTiles(); } - + ImGui.Checkbox("Land", ref _landVisible); ImGui.SameLine(); ImGui.Checkbox("Static", ref _staticVisible); ImGui.BeginChild("Tiles", new Vector2(), false, ImGuiWindowFlags.Modal); - if (ImGui.IsKeyPressed(ImGuiKey.DownArrow)) { + if (ImGui.IsKeyPressed(ImGuiKey.DownArrow)) + { ImGui.SetScrollY(ImGui.GetScrollY() + 10); } - if (ImGui.IsKeyPressed(ImGuiKey.UpArrow)) { + if (ImGui.IsKeyPressed(ImGuiKey.UpArrow)) + { ImGui.SetScrollY(ImGui.GetScrollY() - 10); } var tilesPosY = ImGui.GetCursorPosY(); - if (ImGui.BeginTable("TilesTable", 3) && CEDClient.Initialized) { - unsafe { + if (ImGui.BeginTable("TilesTable", 3) && CEDClient.Initialized) + { + unsafe + { ImGuiListClipperPtr clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper()); ImGui.TableSetupColumn("Id", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("0x0000").X); ImGui.TableSetupColumn("Graphic", ImGuiTableColumnFlags.WidthFixed, _tilesDimensions.X); _tableWidth = ImGui.GetContentRegionAvail().X; - if (_landVisible) { + if (_landVisible) + { clipper.Begin(_matchedLandIds.Length, _tilesDimensions.Y); - while (clipper.Step()) { - for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) { + while (clipper.Step()) + { + for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) + { TilesDrawLand(_matchedLandIds[row]); } } clipper.End(); } - if (IsLandTile(_selectedId) && _updateScroll) { - float itemPosY = clipper.StartPosY + _tilesDimensions.Y * Array.IndexOf(_matchedLandIds, _selectedId); + if (IsLandTile(_selectedId) && _updateScroll) + { + float itemPosY = clipper.StartPosY + _tilesDimensions.Y * Array.IndexOf + (_matchedLandIds, _selectedId); ImGui.SetScrollFromPosY(itemPosY - tilesPosY); _updateScroll = false; } - if (_staticVisible) { + if (_staticVisible) + { clipper.Begin(_matchedStaticIds.Length, _tilesDimensions.Y); - while (clipper.Step()) { - for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) { + while (clipper.Step()) + { + for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++) + { TilesDrawStatic(_matchedStaticIds[row]); } } clipper.End(); } - if (_updateScroll) { - float itemPosY = clipper.StartPosY + _tilesDimensions.Y * Array.IndexOf(_matchedStaticIds, _selectedId - MaxLandIndex); + if (_updateScroll) + { + float itemPosY = clipper.StartPosY + _tilesDimensions.Y * Array.IndexOf + (_matchedStaticIds, _selectedId - MaxLandIndex); ImGui.SetScrollFromPosY(itemPosY - tilesPosY); _updateScroll = false; } @@ -121,49 +156,74 @@ public override void Draw() { ImGui.EndChild(); ImGui.End(); } - - private void TilesDrawLand(int index) { + + private void TilesDrawLand(int index) + { var texture = ArtLoader.Instance.GetLandTexture((uint)index, out var bounds); var name = TileDataLoader.Instance.LandData[index].Name; TilesDrawRow(index, index, texture, bounds, name); } - - private void TilesDrawStatic(int index) { + + private void TilesDrawStatic(int index) + { var realIndex = index + MaxLandIndex; var texture = ArtLoader.Instance.GetStaticTexture((uint)index, out var bounds); var realBounds = ArtLoader.Instance.GetRealArtBounds(index); var name = TileDataLoader.Instance.StaticData[index].Name; - TilesDrawRow(index, realIndex, texture, new Rectangle(bounds.X + realBounds.X, bounds.Y + realBounds.Y, realBounds.Width, realBounds.Height), name); + TilesDrawRow + ( + index, + realIndex, + texture, + new Rectangle(bounds.X + realBounds.X, bounds.Y + realBounds.Y, realBounds.Width, realBounds.Height), + name + ); } - - private void TilesDrawRow(int index, int realIndex, Texture2D texture, Rectangle bounds, string name) { + + private void TilesDrawRow(int index, int realIndex, Texture2D texture, Rectangle bounds, string name) + { ImGui.TableNextRow(ImGuiTableRowFlags.None, _tilesDimensions.Y); - if (ImGui.TableNextColumn()) { + if (ImGui.TableNextColumn()) + { var startPos = ImGui.GetCursorPos(); var selectableSize = new Vector2(_tableWidth, _tilesDimensions.Y); - if (ImGui.Selectable($"##tile{realIndex}", _selectedId == realIndex, - ImGuiSelectableFlags.SpanAllColumns, selectableSize)) + if (ImGui.Selectable + ( + $"##tile{realIndex}", + _selectedId == realIndex, + ImGuiSelectableFlags.SpanAllColumns, + selectableSize + )) _selectedId = realIndex; - ImGui.SetCursorPos(startPos with { Y = startPos.Y + (_tilesDimensions.Y - ImGui.GetFontSize()) / 2 }); + ImGui.SetCursorPos + ( + startPos with + { + Y = startPos.Y + (_tilesDimensions.Y - ImGui.GetFontSize()) / 2 + } + ); ImGui.Text($"0x{index:X4}"); } - if (ImGui.TableNextColumn()) { + if (ImGui.TableNextColumn()) + { CEDGame.UIManager.DrawImage(texture, bounds, _tilesDimensions); } - if (ImGui.TableNextColumn()) { + if (ImGui.TableNextColumn()) + { ImGui.SetCursorPosY(ImGui.GetCursorPosY() + (_tilesDimensions.Y - ImGui.GetFontSize()) / 2); ImGui.TextUnformatted(name); } } - + public static bool IsLandTile(int id) => id < ArtLoader.MAX_LAND_DATA_INDEX_COUNT; - public void UpdateSelectedId(MapObject mapObject) { + public void UpdateSelectedId(MapObject mapObject) + { _selectedId = mapObject.Tile.Id; if (mapObject is StaticObject) - _selectedId += MaxLandIndex; + _selectedId += MaxLandIndex; _updateScroll = true; } } \ No newline at end of file diff --git a/CentrED/UI/Windows/ToolboxWindow.cs b/CentrED/UI/Windows/ToolboxWindow.cs index b3578eb..172d0d5 100644 --- a/CentrED/UI/Windows/ToolboxWindow.cs +++ b/CentrED/UI/Windows/ToolboxWindow.cs @@ -2,21 +2,27 @@ using ImGuiNET; using static CentrED.Application; -namespace CentrED.UI.Windows; +namespace CentrED.UI.Windows; -public class ToolboxWindow : Window { +public class ToolboxWindow : Window +{ public override string Name => "Toolbox"; - public override void Draw() { - if (!Show) return; + + public override void Draw() + { + if (!Show) + return; ImGui.Begin(Name, ref _show); CEDGame.UIManager.tools.ForEach(ToolButton); ImGui.End(); CEDGame.MapManager.ActiveTool?.DrawWindow(); } - - private void ToolButton(Tool tool) { - if (ImGui.RadioButton(tool.Name, CEDGame.MapManager.ActiveTool == tool)) { + + private void ToolButton(Tool tool) + { + if (ImGui.RadioButton(tool.Name, CEDGame.MapManager.ActiveTool == tool)) + { CEDGame.MapManager.ActiveTool?.OnDeactivated(CEDGame.MapManager.Selected); CEDGame.MapManager.ActiveTool = tool; CEDGame.MapManager.ActiveTool?.OnActivated(CEDGame.MapManager.Selected); diff --git a/CentrED/UI/Windows/Window.cs b/CentrED/UI/Windows/Window.cs index c25bcaa..8c2a35c 100644 --- a/CentrED/UI/Windows/Window.cs +++ b/CentrED/UI/Windows/Window.cs @@ -1,23 +1,25 @@ using ImGuiNET; -namespace CentrED.UI.Windows; +namespace CentrED.UI.Windows; -public abstract class Window { - public abstract string Name { - get; - } +public abstract class Window +{ + public abstract string Name { get; } public virtual string Shortcut => ""; protected bool _show; - public bool Show { + + public bool Show + { get => _show; set => _show = value; } - public virtual void DrawMenuItem() { + public virtual void DrawMenuItem() + { ImGui.MenuItem(Name, Shortcut, ref _show); } - + public abstract void Draw(); } \ No newline at end of file diff --git a/CentrEDSharp.sln.DotSettings b/CentrEDSharp.sln.DotSettings deleted file mode 100644 index 37820e6..0000000 --- a/CentrEDSharp.sln.DotSettings +++ /dev/null @@ -1,16 +0,0 @@ - - END_OF_LINE - END_OF_LINE - True - END_OF_LINE - END_OF_LINE - TOGETHER - END_OF_LINE - END_OF_LINE - END_OF_LINE - END_OF_LINE - True - True - True - True - True \ No newline at end of file diff --git a/CentrEDSharp.sln.DotSettings.user b/CentrEDSharp.sln.DotSettings.user deleted file mode 100644 index 4ffb791..0000000 --- a/CentrEDSharp.sln.DotSettings.user +++ /dev/null @@ -1,7 +0,0 @@ - - True - True - True - True - True - True \ No newline at end of file diff --git a/Client/CentrEDClient.cs b/Client/CentrEDClient.cs index 111aece..deb0189 100644 --- a/Client/CentrEDClient.cs +++ b/Client/CentrEDClient.cs @@ -8,7 +8,9 @@ namespace CentrED.Client; public delegate void Connected(); public delegate void Disconnected(); public delegate void Moved(ushort newX, ushort newY); -public sealed class CentrEDClient : BaseCentrED, IDisposable { + +public sealed class CentrEDClient : BaseCentrED, IDisposable +{ private NetState? NetState { get; set; } private ClientLandscape? Landscape { get; set; } public bool CentrEdPlus { get; internal set; } @@ -22,12 +24,14 @@ public sealed class CentrEDClient : BaseCentrED, IDisposable { public bool Running; private string? _status; - public string Status { + public string Status + { get => _status ?? ""; internal set => _status = value; } - public void Connect(string hostname, int port, string username, string password) { + public void Connect(string hostname, int port, string username, string password) + { Username = username; Password = password; var ipAddress = Dns.GetHostAddresses(hostname)[0]; @@ -38,15 +42,18 @@ public void Connect(string hostname, int port, string username, string password) NetState.Send(new LoginRequestPacket(username, password)); Running = true; - do { + do + { Update(); } while (!Initialized && Running); - if(Initialized) + if (Initialized) Connected?.Invoke(); } - public void Disconnect() { - if (Running) { + public void Disconnect() + { + if (Running) + { Send(new QuitPacket()); while (NetState.FlushPending) NetState.Flush(); @@ -58,17 +65,21 @@ public void Disconnect() { Disconnected?.Invoke(); } - ~CentrEDClient() { + ~CentrEDClient() + { Dispose(false); } - - public void Dispose() { + + public void Dispose() + { Dispose(true); GC.SuppressFinalize(this); } - public void Dispose(bool disposing) { - if (disposing) { + public void Dispose(bool disposing) + { + if (disposing) + { Running = false; while (NetState.FlushPending) NetState.Flush(); @@ -76,22 +87,29 @@ public void Dispose(bool disposing) { } } - public void Update() { - if (Running) { - try { - if (DateTime.Now - TimeSpan.FromMinutes(1) > NetState.LastAction) { + public void Update() + { + if (Running) + { + try + { + if (DateTime.Now - TimeSpan.FromMinutes(1) > NetState.LastAction) + { Send(new NoOpPacket()); } NetState.Receive(); - if (NetState.FlushPending) { - if (!NetState.Flush()) { + if (NetState.FlushPending) + { + if (!NetState.Flush()) + { Disconnect(); } } } - catch { + catch + { Disconnect(); } } @@ -100,23 +118,26 @@ public void Update() { public ushort Width => Landscape?.Width ?? 0; public ushort Height => Landscape?.Height ?? 0; - public void InitLandscape(ushort width, ushort height) { + public void InitLandscape(ushort width, ushort height) + { Landscape = new ClientLandscape(this, width, height); Landscape.BlockCache.Resize(1024); Initialized = true; } - public List LoadBlocks(List blockCoords) { - var filteredBlockCoords = blockCoords.FindAll(b => - !Landscape.BlockCache.Contains(Block.Id(b.X, b.Y)) && - isValidX(b.X) && - isValidY(b.Y)); - if (filteredBlockCoords.Count <= 0) return new List(); + public List LoadBlocks(List blockCoords) + { + var filteredBlockCoords = blockCoords.FindAll + (b => !Landscape.BlockCache.Contains(Block.Id(b.X, b.Y)) && isValidX(b.X) && isValidY(b.Y)); + if (filteredBlockCoords.Count <= 0) + return new List(); Send(new RequestBlocksPacket(filteredBlockCoords)); List result = new List(filteredBlockCoords.Count); - foreach (var block in filteredBlockCoords) { + foreach (var block in filteredBlockCoords) + { var blockId = Block.Id(block.X, block.Y); - while (!Landscape.BlockCache.Contains(blockId)) { + while (!Landscape.BlockCache.Contains(blockId)) + { Thread.Sleep(1); Update(); } @@ -125,65 +146,79 @@ public List LoadBlocks(List blockCoords) { return result; } - public bool isValidX(int x) { + public bool isValidX(int x) + { return x >= 0 && x < Width * 8; } - - public bool isValidY(int y) { + + public bool isValidY(int y) + { return y >= 0 && y < Height * 8; } - public ushort ClampX(int x) { + public ushort ClampX(int x) + { return (ushort)Math.Min(x, Width - 1); } - - public ushort ClampY(int y) { + + public ushort ClampY(int y) + { return (ushort)Math.Min(y, Height - 1); } - public void SetPos(ushort x, ushort y) { - if (x == X && y == Y) return; - + public void SetPos(ushort x, ushort y) + { + if (x == X && y == Y) + return; + X = x; Y = y; Send(new UpdateClientPosPacket(x, y)); - Moved?.Invoke(x,y); + Moved?.Invoke(x, y); } - public void ChatMessage(string sender, ushort message) { + public void ChatMessage(string sender, ushort message) + { _logger.LogInfo($"{sender}: {message}"); } - - public LandTile GetLandTile(int x, int y) { + + public LandTile GetLandTile(int x, int y) + { return Landscape.GetLandTile(Convert.ToUInt16(x), Convert.ToUInt16(y)); } - - public IEnumerable GetStaticTiles(int x, int y) { + + public IEnumerable GetStaticTiles(int x, int y) + { return Landscape.GetStaticTiles(Convert.ToUInt16(x), Convert.ToUInt16(y)); } - public void Add(StaticTile tile) { + public void Add(StaticTile tile) + { NetState.Send(new InsertStaticPacket(tile)); } - public void Remove(StaticTile tile) { + public void Remove(StaticTile tile) + { NetState.Send(new DeleteStaticPacket(tile)); } - - public void Send(Packet p) { + + public void Send(Packet p) + { NetState.Send(p); } - public void ResizeCache(int newSize) { + public void ResizeCache(int newSize) + { Landscape?.BlockCache.Resize(newSize); } - public void Flush() { + public void Flush() + { NetState.Send(new ServerFlushPacket()); } #region events - + /* * Client emits events of changes that came from the server */ @@ -205,73 +240,87 @@ public void Flush() { public event RadarChecksum? RadarChecksum; public event RadarData? RadarData; public event RadarUpdate? RadarUpdate; - - - internal void OnMapChanged() { + + + internal void OnMapChanged() + { MapChanged?.Invoke(); } - internal void OnBlockReleased(Block block) { + internal void OnBlockReleased(Block block) + { BlockUnloaded?.Invoke(block); OnMapChanged(); } - internal void OnBlockLoaded(Block block) { + internal void OnBlockLoaded(Block block) + { BlockLoaded?.Invoke(block); OnMapChanged(); } - internal void OnLandReplaced(LandTile landTile, ushort newId) { + internal void OnLandReplaced(LandTile landTile, ushort newId) + { LandTileReplaced?.Invoke(landTile, newId); OnMapChanged(); } - internal void OnLandElevated(LandTile landTile, sbyte newZ) { + internal void OnLandElevated(LandTile landTile, sbyte newZ) + { LandTileElevated?.Invoke(landTile, newZ); OnMapChanged(); } - internal void OnStaticTileAdded(StaticTile staticTile) { + internal void OnStaticTileAdded(StaticTile staticTile) + { StaticTileAdded?.Invoke(staticTile); OnMapChanged(); } - internal void OnStaticTileRemoved(StaticTile staticTile) { + internal void OnStaticTileRemoved(StaticTile staticTile) + { StaticTileRemoved?.Invoke(staticTile); OnMapChanged(); } - - internal void OnStaticTileReplaced(StaticTile staticTile, ushort newId) { + + internal void OnStaticTileReplaced(StaticTile staticTile, ushort newId) + { StaticTileReplaced?.Invoke(staticTile, newId); OnMapChanged(); } - - internal void OnStaticTileMoved(StaticTile staticTile, ushort newX, ushort newY) { + + internal void OnStaticTileMoved(StaticTile staticTile, ushort newX, ushort newY) + { StaticTileMoved?.Invoke(staticTile, newX, newY); OnMapChanged(); } - internal void OnStaticTileElevated(StaticTile staticTile, sbyte newZ) { + internal void OnStaticTileElevated(StaticTile staticTile, sbyte newZ) + { StaticTileElevated?.Invoke(staticTile, newZ); OnMapChanged(); } - internal void OnStaticTileHued(StaticTile staticTile, ushort newHue) { + internal void OnStaticTileHued(StaticTile staticTile, ushort newHue) + { StaticTileHued?.Invoke(staticTile, newHue); OnMapChanged(); } - - internal void OnRadarChecksum(uint checksum) { + + internal void OnRadarChecksum(uint checksum) + { RadarChecksum?.Invoke(checksum); } - - internal void OnRadarData(ushort[] data) { + + internal void OnRadarData(ushort[] data) + { RadarData?.Invoke(data); } - - internal void OnRadarUpdate(ushort x, ushort y, ushort color) { + + internal void OnRadarUpdate(ushort x, ushort y, ushort color) + { RadarUpdate?.Invoke(x, y, color); } - + #endregion } \ No newline at end of file diff --git a/Client/Client.csproj b/Client/Client.csproj index da99606..4fbff30 100644 --- a/Client/Client.csproj +++ b/Client/Client.csproj @@ -1,14 +1,14 @@ - - net7.0 - enable - enable - CentrED.Client - + + net7.0 + enable + enable + CentrED.Client + - - - + + + diff --git a/Client/ClientHandling.cs b/Client/ClientHandling.cs index 1f9e4fe..bdfd979 100644 --- a/Client/ClientHandling.cs +++ b/Client/ClientHandling.cs @@ -1,12 +1,14 @@ using CentrED.Network; using CentrED.Utility; -namespace CentrED.Client; +namespace CentrED.Client; -public class ClientHandling { +public class ClientHandling +{ private static PacketHandler?[] Handlers { get; } - static ClientHandling() { + static ClientHandling() + { Handlers = new PacketHandler?[0x100]; Handlers[0x01] = new PacketHandler(0, OnClientConnectedPacket); @@ -17,86 +19,104 @@ static ClientHandling() { Handlers[0x07] = new PacketHandler(0, OnAccessChangedPacket); Handlers[0x08] = new PacketHandler(0, OnPasswordChangeStatusPacket); } - - public static void OnClientHandlerPacket(BinaryReader reader, NetState ns) { + + public static void OnClientHandlerPacket(BinaryReader reader, NetState ns) + { var packetHandler = Handlers[reader.ReadByte()]; packetHandler?.OnReceive(reader, ns); } - private static void OnClientConnectedPacket(BinaryReader reader, NetState ns) { + private static void OnClientConnectedPacket(BinaryReader reader, NetState ns) + { var username = reader.ReadStringNull(); - if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) { - reader.ReadByte();//Access level + if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) + { + reader.ReadByte(); //Access level } ns.Parent.Clients.Add(username); - if(username != ns.Username) + if (username != ns.Username) ns.LogInfo($"User {username} has connected."); } - private static void OnClientDisconnectedPacket(BinaryReader reader, NetState ns) { + private static void OnClientDisconnectedPacket(BinaryReader reader, NetState ns) + { var username = reader.ReadStringNull(); ns.Parent.Clients.Remove(username); - if(username != ns.Username) + if (username != ns.Username) ns.LogInfo($"User {username} has disconnected."); } - private static void OnClientListPacket(BinaryReader reader, NetState ns) { + private static void OnClientListPacket(BinaryReader reader, NetState ns) + { ns.Parent.Clients.Clear(); - while (reader.BaseStream.Position < reader.BaseStream.Length) { + while (reader.BaseStream.Position < reader.BaseStream.Length) + { ns.Parent.Clients.Add(reader.ReadStringNull()); - if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) { - reader.ReadByte();//Access level - reader.ReadUInt32();//login time since uptime + if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) + { + reader.ReadByte(); //Access level + reader.ReadUInt32(); //login time since uptime } } } - private static void OnSetPosPacket(BinaryReader reader, NetState ns) { + private static void OnSetPosPacket(BinaryReader reader, NetState ns) + { var x = reader.ReadUInt16(); var y = reader.ReadUInt16(); ns.Parent.SetPos(x, y); } - - private static void OnChatMessagePacket(BinaryReader reader, NetState ns) { + + private static void OnChatMessagePacket(BinaryReader reader, NetState ns) + { var sender = reader.ReadStringNull(); var message = reader.ReadUInt16(); ns.Parent.ChatMessage(sender, message); } - - private static void OnAccessChangedPacket(BinaryReader reader, NetState ns) { + + private static void OnAccessChangedPacket(BinaryReader reader, NetState ns) + { var accessLevel = (AccessLevel)reader.ReadByte(); ReadAccountRestrictions(reader); - if (accessLevel != ns.Parent.AccessLevel) { + if (accessLevel != ns.Parent.AccessLevel) + { ns.Parent.AccessLevel = accessLevel; - if (accessLevel == AccessLevel.None) { //TODO: Maybe move this to client? + if (accessLevel == AccessLevel.None) + { + //TODO: Maybe move this to client? ns.LogInfo("Your account has been locked"); ns.Disconnect(); } } } - - private static void OnPasswordChangeStatusPacket(BinaryReader reader, NetState ns) { + + private static void OnPasswordChangeStatusPacket(BinaryReader reader, NetState ns) + { var status = (PasswordChangeStatus)reader.ReadByte(); - switch(status) { - case PasswordChangeStatus.Success: + switch (status) + { + case PasswordChangeStatus.Success: ns.LogInfo("You password has been changed"); break; case PasswordChangeStatus.OldPwInvalid: - ns.LogInfo("Old password is wrong."); + ns.LogInfo("Old password is wrong."); break; - case PasswordChangeStatus.NewPwInvalid: - ns.LogInfo("New password is not allowed."); + case PasswordChangeStatus.NewPwInvalid: + ns.LogInfo("New password is not allowed."); break; - case PasswordChangeStatus.Identical: - ns.LogInfo("New password matched the old password."); + case PasswordChangeStatus.Identical: + ns.LogInfo("New password matched the old password."); break; - }; + } + ; } - public static List ReadAccountRestrictions(BinaryReader reader) { + public static List ReadAccountRestrictions(BinaryReader reader) + { var rectCount = reader.ReadUInt16(); var result = new List(rectCount); - for (var i = 0; i < rectCount; i++) { + for (var i = 0; i < rectCount; i++) + { result.Add(new Rect(reader)); } return result; diff --git a/Client/ConnectionHandling.cs b/Client/ConnectionHandling.cs index ae055c9..827ad5b 100644 --- a/Client/ConnectionHandling.cs +++ b/Client/ConnectionHandling.cs @@ -2,10 +2,12 @@ namespace CentrED.Client; -public class ConnectionHandling { +public class ConnectionHandling +{ private static PacketHandler?[] Handlers { get; } - static ConnectionHandling() { + static ConnectionHandling() + { Handlers = new PacketHandler?[0x100]; Handlers[0x01] = new PacketHandler(0, OnProtocolVersionPacket); @@ -13,37 +15,44 @@ static ConnectionHandling() { Handlers[0x04] = new PacketHandler(0, OnServerStatePacket); } - public static void OnConnectionHandlerPacket(BinaryReader reader, NetState ns) { + public static void OnConnectionHandlerPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnConnectionHandlerPacket"); var id = reader.ReadByte(); var packetHandler = Handlers[id]; packetHandler?.OnReceive(reader, ns); } - private static void OnProtocolVersionPacket(BinaryReader reader, NetState ns) { + private static void OnProtocolVersionPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnProtocolVersionPacket"); var version = reader.ReadUInt32(); - ns.ProtocolVersion = (ProtocolVersion)version switch { + ns.ProtocolVersion = (ProtocolVersion)version switch + { ProtocolVersion.CentrED => ProtocolVersion.CentrED, ProtocolVersion.CentrEDPlus => ProtocolVersion.CentrEDPlus, _ => throw new ArgumentException($"Unsupported protocol version {version}") }; } - private static void OnLoginResponsePacket(BinaryReader reader, NetState ns) { + private static void OnLoginResponsePacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnLoginResponsePacket"); var loginState = (LoginState)reader.ReadByte(); string logMessage; - switch (loginState) { + switch (loginState) + { case LoginState.Ok: ns.LogInfo("Initializing"); ns.Parent.AccessLevel = (AccessLevel)reader.ReadByte(); - if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) { + if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) + { reader.ReadUInt32(); //server uptime } var width = reader.ReadUInt16(); var height = reader.ReadUInt16(); - if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) { + if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) + { reader.ReadUInt32(); //flags } @@ -67,19 +76,21 @@ private static void OnLoginResponsePacket(BinaryReader reader, NetState ns) { + private static void OnServerStatePacket(BinaryReader reader, NetState ns) + { throw new NotImplementedException(); } } \ No newline at end of file diff --git a/Client/Map/ClientLandscape.cs b/Client/Map/ClientLandscape.cs index d5da751..8334d19 100644 --- a/Client/Map/ClientLandscape.cs +++ b/Client/Map/ClientLandscape.cs @@ -2,10 +2,12 @@ namespace CentrED.Client.Map; -public partial class ClientLandscape : BaseLandscape { +public partial class ClientLandscape : BaseLandscape +{ private CentrEDClient _client; - public ClientLandscape(CentrEDClient client, ushort width, ushort height) : base(width, height) { + public ClientLandscape(CentrEDClient client, ushort width, ushort height) : base(width, height) + { _client = client; PacketHandlers.RegisterPacketHandler(0x04, 0, OnBlockPacket); PacketHandlers.RegisterPacketHandler(0x06, 8, OnDrawMapPacket); @@ -14,16 +16,17 @@ public ClientLandscape(CentrEDClient client, ushort width, ushort height) : base PacketHandlers.RegisterPacketHandler(0x09, 11, OnElevateStaticPacket); PacketHandlers.RegisterPacketHandler(0x0A, 14, OnMoveStaticPacket); PacketHandlers.RegisterPacketHandler(0x0B, 12, OnHueStaticPacket); - + // ClientLandscape events are used to send changes done by the user to the server BlockUnloaded += block => _client.Send(new FreeBlockPacket(block.LandBlock.X, block.LandBlock.Y)); - + LandTileReplaced += (tile, newId) => _client.Send(new DrawMapPacket(tile, newId)); LandTileElevated += (tile, newZ) => _client.Send(new DrawMapPacket(tile, newZ)); - + StaticTileAdded += tile => _client.Send(new InsertStaticPacket(tile)); StaticTileRemoved += tile => _client.Send(new DeleteStaticPacket(tile)); - StaticTileReplaced += (tile, newId) => { + StaticTileReplaced += (tile, newId) => + { _client.Send(new DeleteStaticPacket(tile)); _client.Send(new InsertStaticPacket(tile.X, tile.Y, tile.Z, newId, tile.Hue)); }; @@ -31,13 +34,15 @@ public ClientLandscape(CentrEDClient client, ushort width, ushort height) : base StaticTileElevated += (tile, newZ) => _client.Send(new ElevateStaticPacket(tile, newZ)); StaticTileHued += (tile, newHue) => _client.Send(new HueStaticPacket(tile, newHue)); } - - protected override Block LoadBlock(ushort x, ushort y) { + + protected override Block LoadBlock(ushort x, ushort y) + { AssertBlockCoords(x, y); _client.Send(new RequestBlocksPacket(new BlockCoords(x, y))); var blockId = Block.Id(x, y); var block = BlockCache.Get(blockId); - while (_client.Running && block == null) { + while (_client.Running && block == null) + { Thread.Sleep(1); _client.Update(); block = BlockCache.Get(blockId); diff --git a/Client/Map/ClientLandscapePacketHandlers.cs b/Client/Map/ClientLandscapePacketHandlers.cs index 4cfc68d..da708f9 100644 --- a/Client/Map/ClientLandscapePacketHandlers.cs +++ b/Client/Map/ClientLandscapePacketHandlers.cs @@ -1,19 +1,23 @@ using CentrED.Network; -namespace CentrED.Client.Map; +namespace CentrED.Client.Map; -public partial class ClientLandscape { - private void OnBlockPacket(BinaryReader reader, NetState ns) { +public partial class ClientLandscape +{ + private void OnBlockPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnBlockPacket"); var index = new GenericIndex(); - while (reader.BaseStream.Position < reader.BaseStream.Length) { + while (reader.BaseStream.Position < reader.BaseStream.Length) + { var coords = new BlockCoords(reader); var landBlock = new LandBlock(this, coords.X, coords.Y, reader); var staticsCount = reader.ReadUInt16(); - if(staticsCount > 0 ) + if (staticsCount > 0) index.Lookup = (int)reader.BaseStream.Position; - else { + else + { index.Lookup = -1; } index.Length = StaticTile.Size * staticsCount; @@ -23,8 +27,9 @@ private void OnBlockPacket(BinaryReader reader, NetState ns) { ns.Parent.OnBlockLoaded(block); } } - - private void OnDrawMapPacket(BinaryReader reader, NetState ns) { + + private void OnDrawMapPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnDrawMapPacket"); var x = reader.ReadUInt16(); var y = reader.ReadUInt16(); @@ -32,33 +37,37 @@ private void OnDrawMapPacket(BinaryReader reader, NetState ns) { var tile = GetLandTile(x, y); var newZ = reader.ReadSByte(); - if (tile.Z != newZ) { + if (tile.Z != newZ) + { ns.Parent.OnLandElevated(tile, newZ); InternalSetLandZ(tile, newZ); } var newId = reader.ReadUInt16(); // AssertLandTileId(newId); //Bring me back once we have TileDataProvider in client :) - if (tile.Id != newId) { + if (tile.Id != newId) + { ns.Parent.OnLandReplaced(tile, newId); InternalSetLandId(tile, newId); } } - private void OnInsertStaticPacket(BinaryReader reader, NetState ns) { + private void OnInsertStaticPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnInsertStaticPacket"); var staticInfo = new StaticInfo(reader); - var block = GetStaticBlock((ushort)(staticInfo.X /8), (ushort)(staticInfo.Y / 8)); + var block = GetStaticBlock((ushort)(staticInfo.X / 8), (ushort)(staticInfo.Y / 8)); var newTile = new StaticTile(staticInfo); // AssertStaticTileId(newTile.Id); // AssertHue(newTile.Hue); - + ns.Parent.OnStaticTileAdded(newTile); InternalAddStatic(block, newTile); } - private void OnDeleteStaticPacket(BinaryReader reader, NetState ns) { + private void OnDeleteStaticPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnDeleteStaticPacket"); var staticInfo = new StaticInfo(reader); var x = staticInfo.X; @@ -68,21 +77,24 @@ private void OnDeleteStaticPacket(BinaryReader reader, NetState n var staticTile = new StaticTile(staticInfo); var removed = InternalRemoveStatic(block, staticTile); - if (!removed) { + if (!removed) + { ns.LogError($"OnDeleteStaticPacket static not found {staticInfo}"); return; } - + ns.Parent.OnStaticTileRemoved(staticTile); } - private void OnElevateStaticPacket(BinaryReader reader, NetState ns) { + private void OnElevateStaticPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnElevateStaticPacket"); var staticInfo = new StaticInfo(reader); var newZ = reader.ReadSByte(); var tile = GetStaticTiles(staticInfo.X, staticInfo.Y).FirstOrDefault(s => s.Match(staticInfo)); - if (tile == null) { + if (tile == null) + { ns.LogError($"OnElevateStaticPacket static not found {staticInfo}"); return; } @@ -91,7 +103,8 @@ private void OnElevateStaticPacket(BinaryReader reader, NetState InternalSetStaticZ(tile, newZ); } - private void OnMoveStaticPacket(BinaryReader reader, NetState ns) { + private void OnMoveStaticPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnMoveStaticPacket"); var staticInfo = new StaticInfo(reader); var newX = reader.ReadUInt16(); @@ -100,9 +113,10 @@ private void OnMoveStaticPacket(BinaryReader reader, NetState ns) var sourceBlock = GetStaticBlock((ushort)(staticInfo.X / 8), (ushort)(staticInfo.Y / 8)); var targetBlock = GetStaticBlock((ushort)(newX / 8), (ushort)(newY / 8)); var tile = new StaticTile(staticInfo); - + var removed = InternalRemoveStatic(sourceBlock, tile); - if (!removed) { + if (!removed) + { ns.LogError($"OnMoveStaticPacket static not found {staticInfo}"); return; } @@ -111,14 +125,17 @@ private void OnMoveStaticPacket(BinaryReader reader, NetState ns) InternalSetStaticPos(tile, newX, newY); InternalAddStatic(targetBlock, tile); } - private void OnHueStaticPacket(BinaryReader reader, NetState ns) { + + private void OnHueStaticPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnHueStaticPacket"); var staticInfo = new StaticInfo(reader); var newHue = reader.ReadUInt16(); // AssertHue(newTile.Hue); - + var tile = GetStaticTiles(staticInfo.X, staticInfo.Y).FirstOrDefault(s => s.Match(staticInfo)); - if (tile == null) { + if (tile == null) + { ns.LogError($"OnHueStaticPacket static not found {staticInfo}"); return; } diff --git a/Client/PacketHandlers.cs b/Client/PacketHandlers.cs index c5d6dbf..b1d2a7f 100644 --- a/Client/PacketHandlers.cs +++ b/Client/PacketHandlers.cs @@ -3,10 +3,12 @@ namespace CentrED.Client; -public static class PacketHandlers { +public static class PacketHandlers +{ internal static PacketHandler?[] Handlers { get; } - static PacketHandlers() { + static PacketHandlers() + { Handlers = new PacketHandler?[0x100]; RegisterPacketHandler(0x01, 0, OnCompressedPacket); RegisterPacketHandler(0x02, 0, ConnectionHandling.OnConnectionHandlerPacket); @@ -14,7 +16,9 @@ static PacketHandlers() { RegisterPacketHandler(0x0D, 0, RadarMap.OnRadarHandlerPacket); } - public static void RegisterPacketHandler(int packetId, uint length, PacketHandler.PacketProcessor packetProcessor) { + public static void RegisterPacketHandler + (int packetId, uint length, PacketHandler.PacketProcessor packetProcessor) + { Handlers[packetId] = new PacketHandler(length, packetProcessor); } } \ No newline at end of file diff --git a/Client/Packets.cs b/Client/Packets.cs index bd1bc9f..7dd520f 100644 --- a/Client/Packets.cs +++ b/Client/Packets.cs @@ -1,58 +1,84 @@ using CentrED.Network; using CentrED.Utility; -namespace CentrED.Client; +namespace CentrED.Client; -public class LoginRequestPacket : Packet { - public LoginRequestPacket(string username, string password) : base(0x02, 0) { +public class LoginRequestPacket : Packet +{ + public LoginRequestPacket(string username, string password) : base(0x02, 0) + { Writer.Write((byte)0x03); Writer.WriteStringNull(username); Writer.WriteStringNull(password); } } -public class QuitPacket : Packet { - public QuitPacket() : base(0x02, 0) { +public class QuitPacket : Packet +{ + public QuitPacket() : base(0x02, 0) + { Writer.Write((byte)0x05); } } -public class ServerFlushPacket : Packet { - public ServerFlushPacket() : base(0x03, 0) { +public class ServerFlushPacket : Packet +{ + public ServerFlushPacket() : base(0x03, 0) + { Writer.Write((byte)0x01); } } -public class ServerStopPacket : Packet { - public ServerStopPacket(string reason) : base(0x03, 0) { +public class ServerStopPacket : Packet +{ + public ServerStopPacket(string reason) : base(0x03, 0) + { Writer.Write((byte)0x02); Writer.WriteStringNull(reason); } } -public class RequestBlocksPacket : Packet { - public RequestBlocksPacket(BlockCoords blockCoord) : base(0x04, 0) { +public class RequestBlocksPacket : Packet +{ + public RequestBlocksPacket(BlockCoords blockCoord) : base(0x04, 0) + { blockCoord.Write(Writer); } - public RequestBlocksPacket(List blockCoords) : base(0x04, 0) { - foreach (var blockCoord in blockCoords) { + + public RequestBlocksPacket(List blockCoords) : base(0x04, 0) + { + foreach (var blockCoord in blockCoords) + { blockCoord.Write(Writer); } } } -public class FreeBlockPacket : Packet { - public FreeBlockPacket(ushort x, ushort y) : base(0x05, 5) { +public class FreeBlockPacket : Packet +{ + public FreeBlockPacket(ushort x, ushort y) : base(0x05, 5) + { Writer.Write(x); Writer.Write(y); } } -public class DrawMapPacket : Packet { - public DrawMapPacket(LandTile tile) : this(tile.X, tile.Y, tile.Z, tile.Id){} - public DrawMapPacket(LandTile tile, ushort newId) : this(tile.X, tile.Y, tile.Z, newId){} - public DrawMapPacket(LandTile tile, sbyte newZ) : this(tile.X, tile.Y, newZ, tile.Id){} - public DrawMapPacket(ushort x, ushort y, sbyte z, ushort tileId) : base(0x06, 8) { +public class DrawMapPacket : Packet +{ + public DrawMapPacket(LandTile tile) : this(tile.X, tile.Y, tile.Z, tile.Id) + { + } + + public DrawMapPacket(LandTile tile, ushort newId) : this(tile.X, tile.Y, tile.Z, newId) + { + } + + public DrawMapPacket(LandTile tile, sbyte newZ) : this(tile.X, tile.Y, newZ, tile.Id) + { + } + + public DrawMapPacket(ushort x, ushort y, sbyte z, ushort tileId) : base(0x06, 8) + { Writer.Write(x); Writer.Write(y); Writer.Write(z); @@ -60,9 +86,14 @@ public DrawMapPacket(ushort x, ushort y, sbyte z, ushort tileId) : base(0x06, 8) } } -public class InsertStaticPacket : Packet { - public InsertStaticPacket(StaticTile tile) : this(tile.X, tile.Y, tile.Z, tile.Id, tile.Hue) { } - public InsertStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue) : base(0x07, 10) { +public class InsertStaticPacket : Packet +{ + public InsertStaticPacket(StaticTile tile) : this(tile.X, tile.Y, tile.Z, tile.Id, tile.Hue) + { + } + + public InsertStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue) : base(0x07, 10) + { Writer.Write(x); Writer.Write(y); Writer.Write(z); @@ -71,20 +102,26 @@ public InsertStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue } } -public class DeleteStaticPacket : Packet { - public DeleteStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue) : base(0x08, 10) { +public class DeleteStaticPacket : Packet +{ + public DeleteStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue) : base(0x08, 10) + { Writer.Write(x); Writer.Write(y); Writer.Write(z); Writer.Write(tileId); Writer.Write(hue); } - - public DeleteStaticPacket(StaticTile tile) : this(tile.X, tile.Y, tile.Z, tile.Id, tile.Hue) { } + + public DeleteStaticPacket(StaticTile tile) : this(tile.X, tile.Y, tile.Z, tile.Id, tile.Hue) + { + } } -public class ElevateStaticPacket : Packet { - public ElevateStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue, sbyte newZ) : base(0x09, 11) { +public class ElevateStaticPacket : Packet +{ + public ElevateStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue, sbyte newZ) : base(0x09, 11) + { Writer.Write(x); Writer.Write(y); Writer.Write(z); @@ -92,12 +129,17 @@ public ElevateStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hu Writer.Write(hue); Writer.Write(newZ); } - - public ElevateStaticPacket(StaticTile tile, sbyte newZ) : this(tile.X, tile.Y, tile.Z, tile.Id, tile.Hue, newZ) { } + + public ElevateStaticPacket(StaticTile tile, sbyte newZ) : this(tile.X, tile.Y, tile.Z, tile.Id, tile.Hue, newZ) + { + } } -public class MoveStaticPacket : Packet { - public MoveStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue, ushort newX, ushort newY) : base(0x0A, 14) { +public class MoveStaticPacket : Packet +{ + public MoveStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue, ushort newX, ushort newY) : base + (0x0A, 14) + { Writer.Write(x); Writer.Write(y); Writer.Write(z); @@ -106,12 +148,17 @@ public MoveStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue, Writer.Write(newX); Writer.Write(newY); } - - public MoveStaticPacket(StaticTile tile, ushort newX, ushort newY) : this(tile.X, tile.Y, tile.Z, tile.Id, tile.Hue, newX, newY) { } + + public MoveStaticPacket(StaticTile tile, ushort newX, ushort newY) : this + (tile.X, tile.Y, tile.Z, tile.Id, tile.Hue, newX, newY) + { + } } -public class HueStaticPacket : Packet { - public HueStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue, ushort newHue) : base(0x0B, 12) { +public class HueStaticPacket : Packet +{ + public HueStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue, ushort newHue) : base(0x0B, 12) + { Writer.Write(x); Writer.Write(y); Writer.Write(z); @@ -119,52 +166,69 @@ public HueStaticPacket(ushort x, ushort y, sbyte z, ushort tileId, ushort hue, u Writer.Write(hue); Writer.Write(newHue); } - - public HueStaticPacket(StaticTile tile, ushort newHue) : this(tile.X, tile.Y, tile.Z, tile.Id, tile.Hue, newHue) { } + + public HueStaticPacket(StaticTile tile, ushort newHue) : this(tile.X, tile.Y, tile.Z, tile.Id, tile.Hue, newHue) + { + } } -public class UpdateClientPosPacket : Packet { - public UpdateClientPosPacket(ushort x, ushort y) : base(0x0C, 0) { +public class UpdateClientPosPacket : Packet +{ + public UpdateClientPosPacket(ushort x, ushort y) : base(0x0C, 0) + { Writer.Write((byte)0x04); Writer.Write(x); Writer.Write(y); } } -public class ChatMessagePacket : Packet { - public ChatMessagePacket(string message) : base(0x0C, 0) { +public class ChatMessagePacket : Packet +{ + public ChatMessagePacket(string message) : base(0x0C, 0) + { Writer.Write((byte)0x05); Writer.WriteStringNull(message); } } -public class GotoClientPosPacket : Packet { - public GotoClientPosPacket(string username) : base(0x0C, 0) { +public class GotoClientPosPacket : Packet +{ + public GotoClientPosPacket(string username) : base(0x0C, 0) + { Writer.Write((byte)0x06); Writer.WriteStringNull(username); } } -public class ChangePasswordPacket : Packet { - public ChangePasswordPacket(string oldPassword, string newPassword) : base(0x0C, 0) { +public class ChangePasswordPacket : Packet +{ + public ChangePasswordPacket(string oldPassword, string newPassword) : base(0x0C, 0) + { Writer.Write((byte)0x08); Writer.WriteStringNull(oldPassword); Writer.WriteStringNull(newPassword); } } -public class RequestRadarChecksumPacket : Packet { - public RequestRadarChecksumPacket() : base(0x0D, 2) { +public class RequestRadarChecksumPacket : Packet +{ + public RequestRadarChecksumPacket() : base(0x0D, 2) + { Writer.Write((byte)0x01); } } -public class RequestRadarMapPacket : Packet { - public RequestRadarMapPacket() : base(0x0D, 2) { +public class RequestRadarMapPacket : Packet +{ + public RequestRadarMapPacket() : base(0x0D, 2) + { Writer.Write((byte)0x02); } } -public class NoOpPacket : Packet { - public NoOpPacket() : base(0xFF, 1) {} -} +public class NoOpPacket : Packet +{ + public NoOpPacket() : base(0xFF, 1) + { + } +} \ No newline at end of file diff --git a/Client/RadarMap.cs b/Client/RadarMap.cs index 17ea57e..9076aac 100644 --- a/Client/RadarMap.cs +++ b/Client/RadarMap.cs @@ -1,14 +1,17 @@ using CentrED.Network; -namespace CentrED.Client; +namespace CentrED.Client; public delegate void RadarChecksum(uint checksum); public delegate void RadarData(ushort[] data); public delegate void RadarUpdate(ushort x, ushort y, ushort color); -public class RadarMap { + +public class RadarMap +{ private static PacketHandler?[] Handlers { get; } - static RadarMap() { + static RadarMap() + { Handlers = new PacketHandler?[0x100]; Handlers[0x01] = new PacketHandler(0, OnRadarChecksumPacket); @@ -16,19 +19,22 @@ static RadarMap() { Handlers[0x03] = new PacketHandler(0, OnUpdateRadarPacket); } - public static void OnRadarHandlerPacket(BinaryReader reader, NetState ns) { + public static void OnRadarHandlerPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Client OnRadarHandlerPacket"); var id = reader.ReadByte(); var packetHandler = Handlers[id]; packetHandler?.OnReceive(reader, ns); } - private static void OnRadarChecksumPacket(BinaryReader reader, NetState ns) { + private static void OnRadarChecksumPacket(BinaryReader reader, NetState ns) + { var checksum = reader.ReadUInt32(); ns.Parent.OnRadarChecksum(checksum); } - private static void OnRadarMapPacket(BinaryReader reader, NetState ns) { + private static void OnRadarMapPacket(BinaryReader reader, NetState ns) + { var length = ns.Parent.Width * ns.Parent.Height; var bytes = reader.ReadBytes(length * 2); var data = new ushort[length]; @@ -36,7 +42,8 @@ private static void OnRadarMapPacket(BinaryReader reader, NetState ns) { + private static void OnUpdateRadarPacket(BinaryReader reader, NetState ns) + { var x = reader.ReadUInt16(); var y = reader.ReadUInt16(); var color = reader.ReadUInt16(); diff --git a/Server/AdminHandling.cs b/Server/AdminHandling.cs index 500a89d..e4c55e0 100644 --- a/Server/AdminHandling.cs +++ b/Server/AdminHandling.cs @@ -3,12 +3,14 @@ using CentrED.Utility; using static CentrED.Server.PacketHandlers; -namespace CentrED.Server; +namespace CentrED.Server; -public class AdminHandling { +public class AdminHandling +{ private static PacketHandler?[] Handlers { get; } - static AdminHandling() { + static AdminHandling() + { Handlers = new PacketHandler?[0x100]; Handlers[0x01] = new PacketHandler(0, OnFlushPacket); @@ -20,29 +22,35 @@ static AdminHandling() { Handlers[0x09] = new PacketHandler(0, OnDeleteRegionPacket); Handlers[0x0A] = new PacketHandler(0, OnListRegionsPacket); } - - public static void OnAdminHandlerPacket(BinaryReader reader, NetState ns) { + + public static void OnAdminHandlerPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnAdminHandlerPacket"); - if (!ValidateAccess(ns, AccessLevel.Developer)) return; + if (!ValidateAccess(ns, AccessLevel.Developer)) + return; var id = reader.ReadByte(); - if (id != 0x01 && !ValidateAccess(ns, AccessLevel.Administrator)) return; + if (id != 0x01 && !ValidateAccess(ns, AccessLevel.Administrator)) + return; var packetHandler = Handlers[id]; packetHandler?.OnReceive(reader, ns); } - private static void OnFlushPacket(BinaryReader reader, NetState ns) { + private static void OnFlushPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnFlushPacket"); ns.Parent.Landscape.Flush(); ns.Parent.Config.Flush(); } - private static void OnQuitPacket(BinaryReader reader, NetState ns) { + private static void OnQuitPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnQuitPacket"); ns.Parent.Quit = true; } - - - private static void OnModifyUserPacket(BinaryReader reader, NetState ns) { + + + private static void OnModifyUserPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnModifyUserPacket"); var username = reader.ReadStringNull(); var password = reader.ReadStringNull(); @@ -50,29 +58,36 @@ private static void OnModifyUserPacket(BinaryReader reader, NetState var regionCount = reader.ReadByte(); var account = ns.Parent.GetAccount(username); - if (account != null) { - if (password != "") { + if (account != null) + { + if (password != "") + { account.UpdatePassword(password); } account.AccessLevel = accessLevel; account.Regions.Clear(); - for (int i = 0; i < regionCount; i++) { + for (int i = 0; i < regionCount; i++) + { account.Regions.Add(reader.ReadStringNull()); } - + ns.Parent.Config.Invalidate(); ns.Parent.GetClient(account.Name)?.Send(new AccessChangedPacket(ns)); ns.Send(new ModifyUserResponsePacket(ModifyUserStatus.Modified, account)); } - else { - if (username == "") { + else + { + if (username == "") + { ns.Send(new ModifyUserResponsePacket(ModifyUserStatus.InvalidUsername, account)); } - else { + else + { var regions = new List(); - for (int i = 0; i < regionCount; i++) { + for (int i = 0; i < regionCount; i++) + { regions.Add(reader.ReadStringNull()); } @@ -84,84 +99,101 @@ private static void OnModifyUserPacket(BinaryReader reader, NetState } } - private static void OnDeleteUserPacket(BinaryReader reader, NetState ns) { + private static void OnDeleteUserPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnDeleteUserPacket"); var username = reader.ReadStringNull(); var account = ns.Parent.GetAccount(username); - if (account != null && account.Name != ns.Username) { + if (account != null && account.Name != ns.Username) + { ns.Parent.GetClient(account.Name)?.Disconnect(); ns.Parent.Config.Accounts.Remove(account); ns.Parent.Config.Invalidate(); ns.Send(new DeleteUserResponsePacket(DeleteUserStatus.Deleted, username)); } - else { + else + { ns.Send(new DeleteUserResponsePacket(DeleteUserStatus.NotFound, username)); } } - private static void OnListUsersPacket(BinaryReader reader, NetState ns) { + private static void OnListUsersPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnListUsersPacket"); ns.Send(new CompressedPacket(new UserListPacket(ns))); } - private static void OnModifyRegionPacket(BinaryReader reader, NetState ns) { + private static void OnModifyRegionPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnModifyRegionPacket"); var regionName = reader.ReadStringNull(); var region = ns.Parent.GetRegion(regionName); ModifyRegionStatus status; - if (region == null) { + if (region == null) + { region = new Region(regionName); ns.Parent.Config.Regions.Add(region); status = ModifyRegionStatus.Added; } - else { + else + { region.Area.Clear(); status = ModifyRegionStatus.Modified; } var areaCount = reader.ReadByte(); - for (int i = 0; i < areaCount; i++) { + for (int i = 0; i < areaCount; i++) + { region.Area.Add(new Rect(reader)); } ns.Parent.Config.Invalidate(); AdminBroadcast(ns, AccessLevel.Administrator, new ModifyRegionResponsePacket(status, region)); - if (status == ModifyRegionStatus.Modified) { - foreach (var netState in ns.Parent.Clients) { + if (status == ModifyRegionStatus.Modified) + { + foreach (var netState in ns.Parent.Clients) + { var account = ns.Parent.GetAccount(netState.Username)!; - - if (account.Regions.Contains(regionName)) { + + if (account.Regions.Contains(regionName)) + { netState.Send(new AccessChangedPacket(ns)); } } } } - private static void OnDeleteRegionPacket(BinaryReader reader, NetState ns) { + private static void OnDeleteRegionPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnDeleteRegionPacket"); var regionName = reader.ReadStringNull(); var status = DeleteRegionStatus.NotFound; var region = ns.Parent.GetRegion(regionName); - if (region != null) { + if (region != null) + { ns.Parent.Config.Regions.Remove(region); ns.Parent.Config.Invalidate(); status = DeleteRegionStatus.Deleted; } - + AdminBroadcast(ns, AccessLevel.Administrator, new DeleteRegionResponsePacket(status, regionName)); } - private static void OnListRegionsPacket(BinaryReader reader, NetState ns) { + private static void OnListRegionsPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnListRegionsPacket"); ns.Send(new CompressedPacket(new RegionListPacket(ns))); } - private static void AdminBroadcast(NetState ns, AccessLevel accessLevel, Packet packet) { + private static void AdminBroadcast(NetState ns, AccessLevel accessLevel, Packet packet) + { ns.LogDebug("AdminBroadcast"); - foreach (var netState in ns.Parent.Clients) { - if (ns.Parent.GetAccount(netState.Username)!.AccessLevel >= accessLevel) { + foreach (var netState in ns.Parent.Clients) + { + if (ns.Parent.GetAccount(netState.Username)!.AccessLevel >= accessLevel) + { netState.Send(packet); } } diff --git a/Server/Application.cs b/Server/Application.cs index f1af95d..d06b20f 100644 --- a/Server/Application.cs +++ b/Server/Application.cs @@ -2,26 +2,31 @@ namespace CentrED.Server; -public class Application { - public static void Main(string[] args) { +public class Application +{ + public static void Main(string[] args) + { Console.WriteLine($"CentrED# Server Version {Assembly.GetExecutingAssembly().GetName().Version}"); Console.WriteLine("Copyright " + Constants.Assembly.Copyright); Console.WriteLine("Credits to Andreas Schneider, StaticZ"); - try { + try + { new CEDServer(args).Run(); } - catch(Exception e) + catch (Exception e) { Console.WriteLine(e); Console.Write("Press any key to exit..."); Console.ReadKey(); } - finally { + finally + { Console.WriteLine("Shutting down"); } } - public static string GetCurrentExecutable() { + public static string GetCurrentExecutable() + { return AppDomain.CurrentDomain.FriendlyName; } } \ No newline at end of file diff --git a/Server/CEDServer.cs b/Server/CEDServer.cs index a42c4e4..43bf64c 100644 --- a/Server/CEDServer.cs +++ b/Server/CEDServer.cs @@ -5,31 +5,33 @@ using CentrED.Server.Config; using CentrED.Server.Map; -namespace CentrED.Server; +namespace CentrED.Server; -public class CEDServer : BaseCentrED, IDisposable { +public class CEDServer : BaseCentrED, IDisposable +{ public const int MaxConnections = 1024; private ProtocolVersion ProtocolVersion; private Socket Listener { get; } = null!; public ConfigRoot Config { get; } public ServerLandscape Landscape { get; } public HashSet> Clients { get; } = new(8); - - private readonly ConcurrentQueue> _connectedQueue = new (); - private readonly ConcurrentQueue> _toDispose = new (); - private readonly ConcurrentQueue> _flushPending = new (); + + private readonly ConcurrentQueue> _connectedQueue = new(); + private readonly ConcurrentQueue> _toDispose = new(); + private readonly ConcurrentQueue> _flushPending = new(); public DateTime StartTime = DateTime.Now; private DateTime _lastFlush = DateTime.Now; private DateTime _lastBackup = DateTime.Now; - + public bool Quit { get; set; } private bool _valid; - + public bool Running { get; private set; } - public CEDServer(string[] args, TextWriter? logOutput = default) { + public CEDServer(string[] args, TextWriter? logOutput = default) + { if (logOutput == null) logOutput = Console.Out; _logger.Out = logOutput; @@ -38,8 +40,18 @@ public CEDServer(string[] args, TextWriter? logOutput = default) { ProtocolVersion = Config.CentrEdPlus ? ProtocolVersion.CentrEDPlus : ProtocolVersion.CentrED; _logger.LogInfo("Running as " + (Config.CentrEdPlus ? "CentrED+ 0.7.9" : "CentrED 0.6.3")); Console.CancelKeyPress += ConsoleOnCancelKeyPress; - Landscape = new ServerLandscape(this, Config.Map.MapPath, Config.Map.Statics, Config.Map.StaIdx, Config.Tiledata, - Config.Radarcol, Config.Map.Width, Config.Map.Height, out _valid); + Landscape = new ServerLandscape + ( + this, + Config.Map.MapPath, + Config.Map.Statics, + Config.Map.StaIdx, + Config.Tiledata, + Config.Radarcol, + Config.Map.Width, + Config.Map.Height, + out _valid + ); Listener = Bind(new IPEndPoint(IPAddress.Any, Config.Port)); Quit = false; if (_valid) @@ -47,48 +59,60 @@ public CEDServer(string[] args, TextWriter? logOutput = default) { else throw new Exception("Invalid configuration"); } - - public NetState? GetClient(string name) { + + public NetState? GetClient(string name) + { return Clients.FirstOrDefault(ns => ns.Username == name); } - - public Account? GetAccount(string name) { + + public Account? GetAccount(string name) + { return Config.Accounts.Find(a => a.Name == name); } - - public Account? GetAccount(NetState ns) { + + public Account? GetAccount(NetState ns) + { return Config.Accounts.Find(a => a.Name == ns.Username); } - - public Region? GetRegion(string name) { + + public Region? GetRegion(string name) + { return Config.Regions.Find(a => a.Name == name); } - private Socket Bind(IPEndPoint endPoint) { - var s = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp) { + private Socket Bind(IPEndPoint endPoint) + { + var s = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp) + { LingerState = new LingerOption(false, 0), ExclusiveAddressUse = false, NoDelay = true, SendBufferSize = 64 * 1024, ReceiveBufferSize = 64 * 1024, }; - - try { + + try + { s.Bind(endPoint); s.Listen(32); return s; } - catch (Exception e) { - if (e is SocketException se) { + catch (Exception e) + { + if (e is SocketException se) + { // WSAEADDRINUSE - if (se.ErrorCode == 10048) { + if (se.ErrorCode == 10048) + { _logger.LogError($"Listener Failed: {endPoint.Address}:{endPoint.Port} (In Use)"); } // WSAEADDRNOTAVAIL - else if (se.ErrorCode == 10049) { + else if (se.ErrorCode == 10049) + { _logger.LogError($"Listener Failed: {endPoint.Address}:{endPoint.Port} (Unavailable)"); } - else { + else + { _logger.LogError("Listener Exception:"); Console.WriteLine(e); } @@ -98,141 +122,174 @@ private Socket Bind(IPEndPoint endPoint) { } } - private async void Listen() { - try { - while (Running) { + private async void Listen() + { + try + { + while (Running) + { var socket = await Listener.AcceptAsync(); - if (Clients.Count >= MaxConnections) { + if (Clients.Count >= MaxConnections) + { _logger.LogError("Too many connections"); socket.Shutdown(SocketShutdown.Both); socket.Close(); } - else { - var ns = new NetState(this, socket, PacketHandlers.Handlers) { + else + { + var ns = new NetState(this, socket, PacketHandlers.Handlers) + { ProtocolVersion = ProtocolVersion }; _connectedQueue.Enqueue(ns); } } } - catch (Exception e) { + catch (Exception e) + { _logger.LogError("Server stopped"); _logger.LogError(e.ToString()); } - finally { + finally + { Quit = true; } } - - private void ConsoleOnCancelKeyPress(object? sender, ConsoleCancelEventArgs e) { + + private void ConsoleOnCancelKeyPress(object? sender, ConsoleCancelEventArgs e) + { _logger.LogInfo("Killed"); Quit = true; e.Cancel = true; } - public void Run() { - if (!_valid) return; + public void Run() + { + if (!_valid) + return; new Task(Listen).Start(); Running = true; - try { - do { + try + { + do + { ProcessConnectedQueue(); ProcessNetStates(); AutoSave(); AutoBackup(); - + Thread.Sleep(1); } while (!Quit); } - finally { + finally + { Listener.Close(); - foreach (var ns in Clients) { + foreach (var ns in Clients) + { ns.Dispose(); } Running = false; } } - private void ProcessConnectedQueue() { - while (_connectedQueue.TryDequeue(out var ns)) { + private void ProcessConnectedQueue() + { + while (_connectedQueue.TryDequeue(out var ns)) + { Clients.Add(ns); ns.LogInfo($"Connected. [{Clients.Count} Online]"); ns.Send(new ProtocolVersionPacket((uint)ProtocolVersion)); ns.Flush(); } } - - private void ProcessNetStates() { - foreach (var ns in Clients) { - if (!ns.Receive() || !ns.Active) { + + private void ProcessNetStates() + { + foreach (var ns in Clients) + { + if (!ns.Receive() || !ns.Active) + { _toDispose.Enqueue(ns); } - if(ns.FlushPending) + if (ns.FlushPending) _flushPending.Enqueue(ns); } - while (_flushPending.TryDequeue(out var ns)) { - if (!ns.Flush()) { + while (_flushPending.TryDequeue(out var ns)) + { + if (!ns.Flush()) + { _toDispose.Enqueue(ns); } } - while (_toDispose.TryDequeue(out var ns)) { + while (_toDispose.TryDequeue(out var ns)) + { Clients.Remove(ns); - if (ns.Username != "") { + if (ns.Username != "") + { Send(new ClientDisconnectedPacket(ns)); } ns.Dispose(); } } - private void AutoSave() { - if (DateTime.Now - TimeSpan.FromMinutes(1) > _lastFlush) { + private void AutoSave() + { + if (DateTime.Now - TimeSpan.FromMinutes(1) > _lastFlush) + { Landscape.Flush(); Config.Flush(); _lastFlush = DateTime.Now; } } - private void AutoBackup() { - if (Config.AutoBackup.Enabled && DateTime.Now - Config.AutoBackup.Interval > _lastBackup) { + private void AutoBackup() + { + if (Config.AutoBackup.Enabled && DateTime.Now - Config.AutoBackup.Interval > _lastBackup) + { Backup(); _lastBackup = DateTime.Now; } } - public void Send(Packet packet) { - foreach (var ns in Clients) { + public void Send(Packet packet) + { + foreach (var ns in Clients) + { ns.Send(packet); } } - - private void Backup() { + + private void Backup() + { Landscape.Flush(); var logMsg = "Automatic backup in progress"; _logger.LogInfo(logMsg); Send(new ServerStatePacket(ServerState.Other, logMsg)); String backupDir; - for (var i = Config.AutoBackup.MaxBackups; i > 0; i--) { + for (var i = Config.AutoBackup.MaxBackups; i > 0; i--) + { backupDir = $"{Config.AutoBackup.Directory}/Backup{i}"; - if(Directory.Exists(backupDir)) + if (Directory.Exists(backupDir)) if (i == Config.AutoBackup.MaxBackups) Directory.Delete(backupDir, true); - else + else Directory.Move(backupDir, $"{Config.AutoBackup.Directory}/Backup{i + 1}"); } backupDir = $"{Config.AutoBackup.Directory}/Backup1"; Directory.CreateDirectory(backupDir); - + Landscape.Backup(backupDir); - + Send(new ServerStatePacket(ServerState.Running)); _logger.LogInfo("Automatic backup finished."); } - public void Dispose() { + public void Dispose() + { Listener.Dispose(); Landscape.Dispose(); } -} +} \ No newline at end of file diff --git a/Server/ClientHandling.cs b/Server/ClientHandling.cs index 6a7964a..f0e44cf 100644 --- a/Server/ClientHandling.cs +++ b/Server/ClientHandling.cs @@ -3,12 +3,14 @@ using CentrED.Utility; using static CentrED.Server.PacketHandlers; -namespace CentrED.Server; +namespace CentrED.Server; -public class ClientHandling { +public class ClientHandling +{ private static PacketHandler?[] Handlers { get; } - static ClientHandling() { + static ClientHandling() + { Handlers = new PacketHandler?[0x100]; Handlers[0x04] = new PacketHandler(0, OnUpdateClientPosPacket); @@ -16,15 +18,18 @@ static ClientHandling() { Handlers[0x06] = new PacketHandler(0, OnGotoClientPosPacket); Handlers[0x08] = new PacketHandler(0, OnChangePasswordPacket); } - - public static void OnClientHandlerPacket(BinaryReader reader, NetState ns) { + + public static void OnClientHandlerPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnClientHandlerPacket"); - if (!ValidateAccess(ns, AccessLevel.View)) return; + if (!ValidateAccess(ns, AccessLevel.View)) + return; var packetHandler = Handlers[reader.ReadByte()]; packetHandler?.OnReceive(reader, ns); } - private static void OnUpdateClientPosPacket(BinaryReader reader, NetState ns) { + private static void OnUpdateClientPosPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnUpdateClientPosPacket"); var x = reader.ReadUInt16(); var y = reader.ReadUInt16(); @@ -32,38 +37,47 @@ private static void OnUpdateClientPosPacket(BinaryReader reader, NetState ns) { + private static void OnChatMessagePacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnChatMessagePacket"); ns.Parent.Send(new CompressedPacket(new ChatMessagePacket(ns.Username, reader.ReadStringNull()))); } - private static void OnGotoClientPosPacket(BinaryReader reader, NetState ns) { + private static void OnGotoClientPosPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnGotoClientPosPacket"); var name = reader.ReadStringNull(); var client = ns.Parent.GetClient(name); - if (client != null) { + if (client != null) + { ns.Send(new SetClientPosPacket(client)); } } - private static void OnChangePasswordPacket(BinaryReader reader, NetState ns) { + private static void OnChangePasswordPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnChangePasswordPacket"); var oldPwd = reader.ReadStringNull(); var newPwd = reader.ReadStringNull(); var account = ns.Parent.GetAccount(ns.Username); - if (account == null) return; - + if (account == null) + return; + PasswordChangeStatus status; - if (!account.CheckPassword(oldPwd)) { + if (!account.CheckPassword(oldPwd)) + { status = PasswordChangeStatus.OldPwInvalid; } - else if (oldPwd == newPwd) { + else if (oldPwd == newPwd) + { status = PasswordChangeStatus.Identical; } - else if (newPwd.Length < 4) { + else if (newPwd.Length < 4) + { status = PasswordChangeStatus.NewPwInvalid; } - else { + else + { status = PasswordChangeStatus.Success; account.UpdatePassword(newPwd); } @@ -71,23 +85,28 @@ private static void OnChangePasswordPacket(BinaryReader reader, NetState ns) { + public static void WriteAccountRestrictions(BinaryWriter writer, NetState ns) + { var account = ns.Parent.GetAccount(ns)!; - if (account.AccessLevel >= AccessLevel.Administrator) { + if (account.AccessLevel >= AccessLevel.Administrator) + { writer.Write((ushort)0); //Client expects areaCount all the time return; } var rects = new List(); - foreach (var regionName in account.Regions) { + foreach (var regionName in account.Regions) + { var region = ns.Parent.GetRegion(regionName); - if (region != null) { + if (region != null) + { rects.AddRange(region.Area); } } - + writer.Write((ushort)rects.Count); - foreach (var rect in rects) { + foreach (var rect in rects) + { rect.Write(writer); } } diff --git a/Server/Config/Account.cs b/Server/Config/Account.cs index d760bea..7fb3236 100644 --- a/Server/Config/Account.cs +++ b/Server/Config/Account.cs @@ -1,12 +1,22 @@ using System.Xml.Serialization; using CentrED.Utility; -namespace CentrED.Server.Config; +namespace CentrED.Server.Config; -public class Account { - public Account() : this("") { } - - public Account(string accountName, string password = "", AccessLevel accessLevel = AccessLevel.None, List? regions = null) { +public class Account +{ + public Account() : this("") + { + } + + public Account + ( + string accountName, + string password = "", + AccessLevel accessLevel = AccessLevel.None, + List? regions = null + ) + { Name = accountName; PasswordHash = Crypto.Md5Hash(password); AccessLevel = accessLevel; @@ -15,34 +25,28 @@ public Account(string accountName, string password = "", AccessLevel accessLevel LastLogon = DateTime.MinValue; } - [XmlElement] - public string Name { get; set; } - [XmlElement] - public string PasswordHash { get; set; } - [XmlElement] - public AccessLevel AccessLevel { get; set; } - [XmlElement] - public LastPos LastPos { get; set; } - [XmlArray] - [XmlArrayItem("Region")] - public List Regions { get; set; } - - [XmlElement] - public DateTime LastLogon { get; set; } - - public override string ToString() { - return $"{nameof(Name)}: {Name}, " + - $"{nameof(PasswordHash)}: [redacted], " + - $"{nameof(AccessLevel)}: {AccessLevel}, " + - $"{nameof(LastPos)}: {LastPos}, " + + [XmlElement] public string Name { get; set; } + [XmlElement] public string PasswordHash { get; set; } + [XmlElement] public AccessLevel AccessLevel { get; set; } + [XmlElement] public LastPos LastPos { get; set; } + [XmlArray] [XmlArrayItem("Region")] public List Regions { get; set; } + + [XmlElement] public DateTime LastLogon { get; set; } + + public override string ToString() + { + return $"{nameof(Name)}: {Name}, " + $"{nameof(PasswordHash)}: [redacted], " + + $"{nameof(AccessLevel)}: {AccessLevel}, " + $"{nameof(LastPos)}: {LastPos}, " + $"{nameof(Regions)}: {String.Join(",", Regions)}"; } - public void UpdatePassword(string password) { + public void UpdatePassword(string password) + { PasswordHash = Crypto.Md5Hash(password); } - public bool CheckPassword(string password) { + public bool CheckPassword(string password) + { return PasswordHash.Equals(Crypto.Md5Hash(password), StringComparison.InvariantCultureIgnoreCase); } } \ No newline at end of file diff --git a/Server/Config/Autobackup.cs b/Server/Config/Autobackup.cs index cce2b67..a1f713d 100644 --- a/Server/Config/Autobackup.cs +++ b/Server/Config/Autobackup.cs @@ -2,7 +2,8 @@ namespace CentrED.Server.Config; -public class Autobackup { +public class Autobackup +{ [XmlElement] public bool Enabled { get; set; } = false; [XmlElement] public string Directory { get; set; } = "backups"; [XmlElement] public uint MaxBackups { get; set; } = 7; diff --git a/Server/Config/ConfigRoot.cs b/Server/Config/ConfigRoot.cs index 3daa84d..d0a2f85 100644 --- a/Server/Config/ConfigRoot.cs +++ b/Server/Config/ConfigRoot.cs @@ -1,14 +1,16 @@ using System.Xml; using System.Xml.Serialization; -namespace CentrED.Server.Config; +namespace CentrED.Server.Config; [XmlRoot("CEDConfig")] -public class ConfigRoot { +public class ConfigRoot +{ private static XmlSerializer _xmlSerializer = new(typeof(ConfigRoot)); + private static string DefaultPath => Path.GetFullPath(Path.ChangeExtension(Application.GetCurrentExecutable(), ".xml")); - + [XmlIgnore] public const int CurrentVersion = 4; [XmlAttribute] public int Version { get; set; } = CurrentVersion; [XmlElement] public bool CentrEdPlus { get; set; } @@ -19,15 +21,19 @@ public class ConfigRoot { [XmlArray] public List Accounts { get; set; } = new(); [XmlArray] public List Regions { get; set; } = new(); [XmlElement] public Autobackup AutoBackup { get; set; } = new(); - - public void Invalidate() { + + public void Invalidate() + { Changed = true; } - public void Flush() { - if (Changed) { + public void Flush() + { + if (Changed) + { using var writer = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); - var writerSettings = new XmlWriterSettings { + var writerSettings = new XmlWriterSettings + { Indent = true, }; using var xmlWriter = XmlWriter.Create(writer, writerSettings); @@ -38,33 +44,39 @@ public void Flush() { [XmlIgnore] public bool Changed { get; set; } [XmlIgnore] public string FilePath { get; set; } = DefaultPath; - - public static ConfigRoot Init(string[] args) { + + public static ConfigRoot Init(string[] args) + { var index = Array.IndexOf(args, "-c"); var configPath = DefaultPath; - if (index != -1) { + if (index != -1) + { configPath = args[index + 1]; } - else if (args.Length == 1) { + else if (args.Length == 1) + { configPath = args[0]; } Console.WriteLine($"Config file: {configPath}"); - if (File.Exists(configPath)) { + if (File.Exists(configPath)) + { return Read(configPath); } - else { + else + { return Prompt(configPath); } - } - - public static ConfigRoot Read(string path) { + + public static ConfigRoot Read(string path) + { using var reader = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); var result = (ConfigRoot)_xmlSerializer.Deserialize(reader)!; result.FilePath = path; - if (result.Version != CurrentVersion) { + if (result.Version != CurrentVersion) + { result.Version = CurrentVersion; result.Invalidate(); // fill in missing entries with default values result.Flush(); @@ -73,16 +85,19 @@ public static ConfigRoot Read(string path) { return result; } - private static ConfigRoot Prompt(string path) { + private static ConfigRoot Prompt(string path) + { string? input; - ConfigRoot result = new() { + ConfigRoot result = new() + { FilePath = path }; Console.WriteLine("Configuring Network"); Console.WriteLine("==================="); Console.Write($"Port [{result.Port}]: "); input = Console.ReadLine(); - if (!string.IsNullOrEmpty(input) && Int32.TryParse(input, out int port)) { + if (!string.IsNullOrEmpty(input) && Int32.TryParse(input, out int port)) + { result.Port = port; } @@ -90,31 +105,36 @@ private static ConfigRoot Prompt(string path) { Console.WriteLine("================="); Console.Write($"map [{result.Map.MapPath}]: "); input = Console.ReadLine(); - if (!string.IsNullOrEmpty(input)) { + if (!string.IsNullOrEmpty(input)) + { result.Map.MapPath = input; } Console.Write($"statics [{result.Map.Statics}]: "); input = Console.ReadLine(); - if (!string.IsNullOrEmpty(input)) { + if (!string.IsNullOrEmpty(input)) + { result.Map.Statics = input; } Console.Write($"staidx [{result.Map.StaIdx}]: "); input = Console.ReadLine(); - if (!string.IsNullOrEmpty(input)) { + if (!string.IsNullOrEmpty(input)) + { result.Map.StaIdx = input; } Console.Write($"tiledata [{result.Tiledata}]: "); input = Console.ReadLine(); - if (!string.IsNullOrEmpty(input)) { + if (!string.IsNullOrEmpty(input)) + { result.Tiledata = input; } Console.Write($"radarcol [{result.Radarcol}]: "); input = Console.ReadLine(); - if (!string.IsNullOrEmpty(input)) { + if (!string.IsNullOrEmpty(input)) + { result.Radarcol = input; } @@ -122,13 +142,15 @@ private static ConfigRoot Prompt(string path) { Console.WriteLine("=========="); Console.Write($"Map width [{result.Map.Width}]: "); input = Console.ReadLine(); - if (!string.IsNullOrEmpty(input) && UInt16.TryParse(input, out ushort width)) { + if (!string.IsNullOrEmpty(input) && UInt16.TryParse(input, out ushort width)) + { result.Map.Width = width; } Console.Write($"Map height [{result.Map.Height}]: "); input = Console.ReadLine(); - if (!string.IsNullOrEmpty(input) && UInt16.TryParse(input, out ushort height)) { + if (!string.IsNullOrEmpty(input) && UInt16.TryParse(input, out ushort height)) + { result.Map.Height = height; } @@ -139,15 +161,18 @@ private static ConfigRoot Prompt(string path) { Console.Write("Password [hidden]: "); string password = ""; - while (true) { + while (true) + { var key = Console.ReadKey(true); if (key.Key == ConsoleKey.Enter) break; - if (key.Key == ConsoleKey.Backspace) { + if (key.Key == ConsoleKey.Backspace) + { if (password.Length > 0) password = password.Remove(password.Length - 1); } - else { + else + { password += key.KeyChar; } } @@ -155,7 +180,7 @@ private static ConfigRoot Prompt(string path) { result.Accounts.Add(new Account(accountName, password, AccessLevel.Administrator)); result.Invalidate(); result.Flush(); - + return result; } } \ No newline at end of file diff --git a/Server/Config/LastPos.cs b/Server/Config/LastPos.cs index b2dabba..2539b00 100644 --- a/Server/Config/LastPos.cs +++ b/Server/Config/LastPos.cs @@ -1,13 +1,15 @@ using System.Xml.Serialization; -namespace CentrED.Server.Config; +namespace CentrED.Server.Config; -public class LastPos { - public LastPos() : this(0, 0) { - +public class LastPos +{ + public LastPos() : this(0, 0) + { } - - public LastPos(ushort x, ushort y) { + + public LastPos(ushort x, ushort y) + { X = x; Y = y; } @@ -15,7 +17,8 @@ public LastPos(ushort x, ushort y) { [XmlAttribute("x")] public ushort X { get; set; } [XmlAttribute("y")] public ushort Y { get; set; } - public override string ToString() { + public override string ToString() + { return $"{nameof(X)}: {X}, {nameof(Y)}: {Y}"; } } \ No newline at end of file diff --git a/Server/Config/Map.cs b/Server/Config/Map.cs index 7773a67..77862d2 100644 --- a/Server/Config/Map.cs +++ b/Server/Config/Map.cs @@ -1,15 +1,18 @@ using System.Xml.Serialization; -namespace CentrED.Server.Config; +namespace CentrED.Server.Config; -public class Map { +public class Map +{ [XmlElement("Map")] public string MapPath { get; set; } = "map0.mul"; [XmlElement] public string StaIdx { get; set; } = "staidx0.mul"; [XmlElement] public string Statics { get; set; } = "statics0.mul"; [XmlElement] public ushort Width { get; set; } = 896; [XmlElement] public ushort Height { get; set; } = 512; - public override string ToString() { - return $"{nameof(MapPath)}: {MapPath}, {nameof(StaIdx)}: {StaIdx}, {nameof(Statics)}: {Statics}, {nameof(Width)}: {Width}, {nameof(Height)}: {Height}"; + public override string ToString() + { + return + $"{nameof(MapPath)}: {MapPath}, {nameof(StaIdx)}: {StaIdx}, {nameof(Statics)}: {Statics}, {nameof(Width)}: {Width}, {nameof(Height)}: {Height}"; } } \ No newline at end of file diff --git a/Server/Config/Region.cs b/Server/Config/Region.cs index 1356676..6f77dff 100644 --- a/Server/Config/Region.cs +++ b/Server/Config/Region.cs @@ -1,24 +1,25 @@ using System.Xml.Serialization; using CentrED.Network; -namespace CentrED.Server.Config; +namespace CentrED.Server.Config; -public class Region { - public Region() : this("") { - +public class Region +{ + public Region() : this("") + { } - - public Region(string name, List? area = null) { + + public Region(string name, List? area = null) + { Name = name; Area = area ?? new List(); } - [XmlElement] - public string Name { get; set; } - [XmlArray] - public List Area { get; set; } + [XmlElement] public string Name { get; set; } + [XmlArray] public List Area { get; set; } - public override string ToString() { + public override string ToString() + { return $"{nameof(Name)}: {Name}, {nameof(Area)}: [{String.Join(",", Area)}]"; } } \ No newline at end of file diff --git a/Server/ConnectionHandling.cs b/Server/ConnectionHandling.cs index d576bb0..09ddf8d 100644 --- a/Server/ConnectionHandling.cs +++ b/Server/ConnectionHandling.cs @@ -3,47 +3,57 @@ namespace CentrED.Server; -public class ConnectionHandling { +public class ConnectionHandling +{ private static PacketHandler?[] Handlers { get; } - static ConnectionHandling() { + static ConnectionHandling() + { Handlers = new PacketHandler?[0x100]; Handlers[0x03] = new PacketHandler(0, OnLoginRequestPacket); Handlers[0x05] = new PacketHandler(0, OnQuitPacket); } - public static void OnConnectionHandlerPacket(BinaryReader reader, NetState ns) { + + public static void OnConnectionHandlerPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnConnectionHandlerPacket"); var id = reader.ReadByte(); var packetHandler = Handlers[id]; packetHandler?.OnReceive(reader, ns); } - private static void OnLoginRequestPacket(BinaryReader reader, NetState ns) { + private static void OnLoginRequestPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnLoginRequestPacket"); var username = reader.ReadStringNull(); var password = reader.ReadStringNull(); var account = ns.Parent.GetAccount(username); - if (account == null) { + if (account == null) + { ns.LogDebug($"Invalid account specified: {username}"); ns.Send(new LoginResponsePacket(LoginState.InvalidUser)); ns.Disconnect(); } - else if (account.AccessLevel <= AccessLevel.None) { + else if (account.AccessLevel <= AccessLevel.None) + { ns.LogDebug("Access Denied"); ns.Send(new LoginResponsePacket(LoginState.NoAccess)); ns.Disconnect(); } - else if (!account.CheckPassword(password)) { + else if (!account.CheckPassword(password)) + { ns.LogDebug("Invalid password"); ns.Send(new LoginResponsePacket(LoginState.InvalidPassword)); ns.Disconnect(); } - else if (ns.Parent.Clients.Any(client => client.Username == account.Name)) { + else if (ns.Parent.Clients.Any(client => client.Username == account.Name)) + { ns.Send(new LoginResponsePacket(LoginState.AlreadyLoggedIn)); ns.Disconnect(); } - else { + else + { ns.LogInfo($"Login {username}"); ns.Username = account.Name; ns.Send(new LoginResponsePacket(LoginState.Ok, ns)); @@ -53,7 +63,8 @@ private static void OnLoginRequestPacket(BinaryReader reader, NetState ns) { + private static void OnQuitPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnQuitPacket"); ns.Disconnect(); } diff --git a/Server/Map/LargeScaleOperations.cs b/Server/Map/LargeScaleOperations.cs index 54d4d16..4e43d86 100644 --- a/Server/Map/LargeScaleOperations.cs +++ b/Server/Map/LargeScaleOperations.cs @@ -2,8 +2,10 @@ namespace CentrED.Server.Map; -public abstract class LargeScaleOperation { - public LargeScaleOperation(BinaryReader reader, ServerLandscape landscape) { +public abstract class LargeScaleOperation +{ + public LargeScaleOperation(BinaryReader reader, ServerLandscape landscape) + { _landscape = landscape; } @@ -11,78 +13,89 @@ public LargeScaleOperation(BinaryReader reader, ServerLandscape landscape) { public abstract void Validate(); - public abstract void Apply(LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks); + public abstract void Apply + (LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks); protected static readonly Random random = new(); } -public class LsCopyMove : LargeScaleOperation { - public LsCopyMove(BinaryReader reader, ServerLandscape landscape) : base(reader, landscape) { +public class LsCopyMove : LargeScaleOperation +{ + public LsCopyMove(BinaryReader reader, ServerLandscape landscape) : base(reader, landscape) + { _type = (CopyMove)reader.ReadByte(); OffsetX = reader.ReadInt32(); OffsetY = reader.ReadInt32(); _erase = reader.ReadBoolean(); } - + private CopyMove _type; public int OffsetX { get; } public int OffsetY { get; } private bool _erase; - public override void Validate() { } + public override void Validate() + { + } - public override void Apply(LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks) { + public override void Apply + (LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks) + { ushort x = (ushort)Math.Clamp(landTile.X + OffsetX, 0, _landscape.CellWidth - 1); ushort y = (ushort)Math.Clamp(landTile.Y + OffsetY, 0, _landscape.CellHeight - 1); var targetLandTile = _landscape.GetLandTile(x, y); var targetStaticsBlock = _landscape.GetStaticBlock((ushort)(x / 8), (ushort)(y / 8)); - if (_erase) { - foreach (var targetStatic in _landscape.GetStaticTiles(x, y)) { + if (_erase) + { + foreach (var targetStatic in _landscape.GetStaticTiles(x, y)) + { targetStaticsBlock.RemoveTile(targetStatic); } } targetLandTile.Id = landTile.Id; targetLandTile.Z = landTile.Z; - - switch (_type) { - case CopyMove.Copy: { - foreach (var staticTile in staticTiles) { - targetStaticsBlock.AddTile( - new StaticTile ( - staticTile.Id, - x, - y, - staticTile.Z, - staticTile.Hue - ) - ); + + switch (_type) + { + case CopyMove.Copy: + { + foreach (var staticTile in staticTiles) + { + targetStaticsBlock.AddTile(new StaticTile(staticTile.Id, x, y, staticTile.Z, staticTile.Hue)); } break; } - case CopyMove.Move: { - foreach (var staticTile in staticTiles) { + case CopyMove.Move: + { + foreach (var staticTile in staticTiles) + { staticTile.Block!.RemoveTile(staticTile); targetStaticsBlock.AddTile(staticTile); - staticTile.UpdatePos(x,y, staticTile.Z); + staticTile.UpdatePos(x, y, staticTile.Z); } break; } } - additionalAffectedBlocks[_landscape.GetBlockId(x,y)] = true; + additionalAffectedBlocks[_landscape.GetBlockId(x, y)] = true; } } -public class LsSetAltitude : LargeScaleOperation { - public LsSetAltitude(BinaryReader reader, ServerLandscape landscape) : base(reader, landscape) { +public class LsSetAltitude : LargeScaleOperation +{ + public LsSetAltitude(BinaryReader reader, ServerLandscape landscape) : base(reader, landscape) + { _type = (SetAltitude)reader.ReadByte(); - switch (_type) { - case SetAltitude.Terrain: { + switch (_type) + { + case SetAltitude.Terrain: + { _minZ = reader.ReadSByte(); _maxZ = reader.ReadSByte(); break; } - case SetAltitude.Relative: { + case SetAltitude.Relative: + { _relativeZ = reader.ReadSByte(); break; } @@ -94,137 +107,180 @@ public LsSetAltitude(BinaryReader reader, ServerLandscape landscape) : base(read private sbyte _maxZ; private sbyte _relativeZ; - public override void Validate() { } + public override void Validate() + { + } - public override void Apply(LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks) { + public override void Apply + (LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks) + { sbyte diff = 0; - switch (_type) { - case SetAltitude.Terrain: { + switch (_type) + { + case SetAltitude.Terrain: + { var newZ = (sbyte)(_minZ + random.Next(_maxZ - _minZ + 1)); diff = (sbyte)(newZ - landTile.Z); landTile.Z = newZ; break; } - case SetAltitude.Relative: { + case SetAltitude.Relative: + { diff = _relativeZ; landTile.Z = (sbyte)Math.Clamp(landTile.Z + diff, -128, 127); break; } } - - foreach (var staticTile in staticTiles) { + + foreach (var staticTile in staticTiles) + { staticTile.Z = (sbyte)Math.Clamp(landTile.Z + diff, -128, 127); } } } -public class LsDrawTerrain : LargeScaleOperation { - public LsDrawTerrain(BinaryReader reader, ServerLandscape landscape) : base(reader, landscape) { +public class LsDrawTerrain : LargeScaleOperation +{ + public LsDrawTerrain(BinaryReader reader, ServerLandscape landscape) : base(reader, landscape) + { var count = reader.ReadUInt16(); _tileIds = new ushort[count]; - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { _tileIds[i] = reader.ReadUInt16(); } } private ushort[] _tileIds; - public override void Validate() { - foreach (var tileId in _tileIds) { + public override void Validate() + { + foreach (var tileId in _tileIds) + { _landscape.AssertLandTileId(tileId); } } - public override void Apply(LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks) { - if (_tileIds.Length <= 0) return; + public override void Apply + (LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks) + { + if (_tileIds.Length <= 0) + return; landTile.Id = _tileIds[random.Next(_tileIds.Length)]; } } -public class LsDeleteStatics : LargeScaleOperation { - public LsDeleteStatics(BinaryReader reader, ServerLandscape landscape) : base(reader, landscape) { +public class LsDeleteStatics : LargeScaleOperation +{ + public LsDeleteStatics(BinaryReader reader, ServerLandscape landscape) : base(reader, landscape) + { var count = reader.ReadUInt16(); _tileIds = new ushort[count]; - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { _tileIds[i] = (ushort)(reader.ReadUInt16() - 0x4000); } _minZ = reader.ReadSByte(); _maxZ = reader.ReadSByte(); } - + private ushort[] _tileIds; private sbyte _minZ; private sbyte _maxZ; - public override void Validate() { } + public override void Validate() + { + } - public override void Apply(LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks) { + public override void Apply + (LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks) + { var staticBlock = _landscape.GetStaticBlock((ushort)(landTile.X / 8), (ushort)(landTile.Y / 8)); - foreach (var staticTile in staticTiles) { - if (staticTile.Z < _minZ || staticTile.Z > _maxZ) continue; - - if (_tileIds.Length > 0) { - if (_tileIds.Contains(staticTile.Id)) { + foreach (var staticTile in staticTiles) + { + if (staticTile.Z < _minZ || staticTile.Z > _maxZ) + continue; + + if (_tileIds.Length > 0) + { + if (_tileIds.Contains(staticTile.Id)) + { staticBlock.RemoveTile(staticTile); } } - else { + else + { staticBlock.RemoveTile(staticTile); } } } } -public class LsInsertStatics : LargeScaleOperation { - public LsInsertStatics(BinaryReader reader, ServerLandscape landscape) : base(reader, landscape) { +public class LsInsertStatics : LargeScaleOperation +{ + public LsInsertStatics(BinaryReader reader, ServerLandscape landscape) : base(reader, landscape) + { var count = reader.ReadUInt16(); _tileIds = new ushort[count]; - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { _tileIds[i] = (ushort)(reader.ReadUInt16() - 0x4000); } _probability = reader.ReadByte(); _placementType = (StaticsPlacement)reader.ReadByte(); - if (_placementType == StaticsPlacement.Fix) { + if (_placementType == StaticsPlacement.Fix) + { _fixZ = reader.ReadSByte(); } } - + private ushort[] _tileIds; private byte _probability; private StaticsPlacement _placementType; private sbyte _fixZ; - public override void Validate() { - foreach (var tileId in _tileIds) { + public override void Validate() + { + foreach (var tileId in _tileIds) + { _landscape.AssertStaticTileId(tileId); } } - public override void Apply(LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks) { - if (_tileIds.Length == 0 || random.Next(100) >= _probability) return; + public override void Apply + (LandTile landTile, IEnumerable staticTiles, ref bool[] additionalAffectedBlocks) + { + if (_tileIds.Length == 0 || random.Next(100) >= _probability) + return; - var staticItem = new StaticTile( - _tileIds[random.Next(_tileIds.Length)], - landTile.X, - landTile.Y, - 0, - 0); - switch (_placementType) { - case StaticsPlacement.Terrain: { + var staticItem = new StaticTile(_tileIds[random.Next(_tileIds.Length)], landTile.X, landTile.Y, 0, 0); + switch (_placementType) + { + case StaticsPlacement.Terrain: + { staticItem.Z = landTile.Z; break; } - case StaticsPlacement.Top: { + case StaticsPlacement.Top: + { var topZ = landTile.Z; - foreach (var staticTile in staticTiles) { - sbyte staticTop = Math.Clamp((sbyte)(staticTile.Z + _landscape.TileDataProvider.StaticTiles[staticTile.Id].Height), (sbyte)-128, (sbyte)127); - if (staticTop > topZ) topZ = staticTop; + foreach (var staticTile in staticTiles) + { + sbyte staticTop = Math.Clamp + ( + (sbyte)(staticTile.Z + _landscape.TileDataProvider.StaticTiles[staticTile.Id].Height), + (sbyte)-128, + (sbyte)127 + ); + if (staticTop > topZ) + topZ = staticTop; } staticItem.Z = topZ; break; } - case StaticsPlacement.Fix: { + case StaticsPlacement.Fix: + { staticItem.Z = _fixZ; break; } @@ -232,7 +288,4 @@ public override void Apply(LandTile landTile, IEnumerable staticTile var staticBlock = _landscape.GetStaticBlock((ushort)(staticItem.X / 8), (ushort)(staticItem.Y / 8)); staticBlock.AddTile(staticItem); } -} - - - +} \ No newline at end of file diff --git a/Server/Map/RadarMap.cs b/Server/Map/RadarMap.cs index 45d1de7..41562f7 100644 --- a/Server/Map/RadarMap.cs +++ b/Server/Map/RadarMap.cs @@ -1,23 +1,33 @@ using CentrED.Network; using CentrED.Utility; -namespace CentrED.Server.Map; +namespace CentrED.Server.Map; -public class RadarMap { - - public RadarMap(ServerLandscape landscape, BinaryReader mapReader, BinaryReader staidxReader, BinaryReader staticsReader, string radarcolPath) { +public class RadarMap +{ + public RadarMap + ( + ServerLandscape landscape, + BinaryReader mapReader, + BinaryReader staidxReader, + BinaryReader staticsReader, + string radarcolPath + ) + { using var radarcol = File.Open(radarcolPath, FileMode.Open, FileAccess.Read, FileShare.Read); _radarColors = new ushort[radarcol.Length / sizeof(ushort)]; var buffer = new byte[radarcol.Length]; radarcol.Read(buffer, 0, (int)radarcol.Length); Buffer.BlockCopy(buffer, 0, _radarColors, 0, buffer.Length); - + _width = landscape.Width; _height = landscape.Height; _radarMap = new ushort[_width * _height]; - for (ushort x = 0; x < _width; x++) { - for (ushort y = 0; y < _height; y++) { + for (ushort x = 0; x < _width; x++) + { + for (ushort y = 0; y < _height; y++) + { var block = landscape.GetBlockNumber(x, y); mapReader.BaseStream.Seek(landscape.GetMapOffset(x, y) + 4, SeekOrigin.Begin); var landTile = new LandTile(mapReader); @@ -26,10 +36,12 @@ public RadarMap(ServerLandscape landscape, BinaryReader mapReader, BinaryReader staidxReader.BaseStream.Seek(landscape.GetStaidxOffset(x, y), SeekOrigin.Begin); var index = new GenericIndex(staidxReader); var staticsBlock = new StaticBlock(landscape, staticsReader, index, x, y); - + var highestZ = landTile.Z; - foreach (var staticTile in staticsBlock.GetTiles(0, 0)) { - if (staticTile.Z >= highestZ) { + foreach (var staticTile in staticsBlock.GetTiles(0, 0)) + { + if (staticTile.Z >= highestZ) + { highestZ = staticTile.Z; _radarMap[block] = _radarColors[staticTile.Id + 0x4000]; } @@ -45,50 +57,63 @@ public RadarMap(ServerLandscape landscape, BinaryReader mapReader, BinaryReader private ushort[] _radarMap; private List? _packets; - private void OnRadarHandlingPacket(BinaryReader buffer, NetState ns) { + private void OnRadarHandlingPacket(BinaryReader buffer, NetState ns) + { ns.LogDebug("OnRadarHandlingPacket"); - if (!PacketHandlers.ValidateAccess(ns, AccessLevel.View)) return; - switch(buffer.ReadByte()) { - case 0x01: + if (!PacketHandlers.ValidateAccess(ns, AccessLevel.View)) + return; + switch (buffer.ReadByte()) + { + case 0x01: ns.Send(new RadarChecksumPacket(_radarMap)); break; - case 0x02: + case 0x02: ns.Send(new CompressedPacket(new RadarMapPacket(_radarMap))); break; } } - public void Update(NetState ns, ushort x, ushort y, ushort tileId) { + public void Update(NetState ns, ushort x, ushort y, ushort tileId) + { var block = x * _height + y; var color = _radarColors[tileId]; - if (_radarMap[block] != color) { + if (_radarMap[block] != color) + { _radarMap[block] = color; var packet = new UpdateRadarPacket(x, y, color); - if (_packets != null) { + if (_packets != null) + { _packets.Add(packet); } - else { + else + { ns.Parent.Send(packet); } } } - public void BeginUpdate() { - if (_packets != null) throw new InvalidOperationException("RadarMap update is already in progress"); - + public void BeginUpdate() + { + if (_packets != null) + throw new InvalidOperationException("RadarMap update is already in progress"); + _packets = new List(); } - public void EndUpdate(NetState ns) { - if (_packets == null) throw new InvalidOperationException("RadarMap update isn't in progress"); - + public void EndUpdate(NetState ns) + { + if (_packets == null) + throw new InvalidOperationException("RadarMap update isn't in progress"); + var completePacket = new CompressedPacket(new RadarMapPacket(_radarMap)); - if(completePacket.Writer.BaseStream.Length <= _packets.Count / 4 * 5) + if (completePacket.Writer.BaseStream.Length <= _packets.Count / 4 * 5) { ns.Parent.Send(completePacket); } - else { - foreach (var packet in _packets) { + else + { + foreach (var packet in _packets) + { ns.Parent.Send(packet); } } @@ -96,15 +121,19 @@ public void EndUpdate(NetState ns) { } } -public class RadarChecksumPacket : Packet { - public RadarChecksumPacket(ushort[] radarMap) : base(0x0D, 0) { +public class RadarChecksumPacket : Packet +{ + public RadarChecksumPacket(ushort[] radarMap) : base(0x0D, 0) + { Writer.Write((byte)0x01); Writer.Write(Crypto.Crc32Checksum(radarMap)); } } -public class RadarMapPacket : Packet { - public RadarMapPacket(ushort[] radarMap) : base(0x0D, 0) { +public class RadarMapPacket : Packet +{ + public RadarMapPacket(ushort[] radarMap) : base(0x0D, 0) + { Writer.Write((byte)0x02); byte[] buffer = new byte[Buffer.ByteLength(radarMap)]; Buffer.BlockCopy(radarMap, 0, buffer, 0, buffer.Length); @@ -112,8 +141,10 @@ public RadarMapPacket(ushort[] radarMap) : base(0x0D, 0) { } } -public class UpdateRadarPacket : Packet { - public UpdateRadarPacket(ushort x, ushort y, ushort color) : base(0x0D, 0) { +public class UpdateRadarPacket : Packet +{ + public UpdateRadarPacket(ushort x, ushort y, ushort color) : base(0x0D, 0) + { Writer.Write((byte)0x03); Writer.Write(x); Writer.Write(y); diff --git a/Server/Map/ServerLandscape.cs b/Server/Map/ServerLandscape.cs index fead87a..d9fc606 100644 --- a/Server/Map/ServerLandscape.cs +++ b/Server/Map/ServerLandscape.cs @@ -4,19 +4,33 @@ namespace CentrED.Server.Map; -public sealed partial class ServerLandscape : BaseLandscape, IDisposable { +public sealed partial class ServerLandscape : BaseLandscape, IDisposable +{ private CEDServer _cedServer; private Logger _logger; - - public ServerLandscape(CEDServer cedServer, string mapPath, string staticsPath, string staidxPath, string tileDataPath, string radarcolPath, - ushort width, ushort height, out bool valid) : base(width, height) { + + public ServerLandscape + ( + CEDServer cedServer, + string mapPath, + string staticsPath, + string staidxPath, + string tileDataPath, + string radarcolPath, + ushort width, + ushort height, + out bool valid + ) : base(width, height) + { _cedServer = cedServer; _logger = cedServer._logger; - + _logger.LogInfo("Loading Map"); - if (!File.Exists(mapPath)) { + if (!File.Exists(mapPath)) + { Console.WriteLine("Map file not found, do you want to create it? [y/n]"); - if (Console.ReadLine() == "y") { + if (Console.ReadLine() == "y") + { InitMap(mapPath); } } @@ -25,15 +39,18 @@ public ServerLandscape(CEDServer cedServer, string mapPath, string staticsPath, _mapWriter = new BinaryWriter(_map, Encoding.UTF8); var fi = new FileInfo(mapPath); IsUop = fi.Extension == ".uop"; - if (IsUop) { + if (IsUop) + { string uopPattern = fi.Name.Replace(fi.Extension, "").ToLowerInvariant(); ReadUopFiles(uopPattern); } _logger.LogInfo($"Loaded {fi.Name}"); - if (!File.Exists(staticsPath) || !File.Exists(staidxPath)) { + if (!File.Exists(staticsPath) || !File.Exists(staidxPath)) + { Console.WriteLine("Statics files not found, do you want to create it? [y/n]"); - if (Console.ReadLine() == "y") { + if (Console.ReadLine() == "y") + { InitStatics(staticsPath, staidxPath); } } @@ -45,9 +62,10 @@ public ServerLandscape(CEDServer cedServer, string mapPath, string staticsPath, _staticsWriter = new BinaryWriter(_statics, Encoding.UTF8); _staidxReader = new BinaryReader(_staidx, Encoding.UTF8); _staidxWriter = new BinaryWriter(_staidx, Encoding.UTF8); - + valid = Validate(); - if (valid) { + if (valid) + { _logger.LogInfo("Loading Tiledata"); TileDataProvider = new TileDataProvider(tileDataPath, true); _logger.LogInfo("Creating Cache"); @@ -65,113 +83,130 @@ public ServerLandscape(CEDServer cedServer, string mapPath, string staticsPath, } } - private void InitMap(string mapPath) { + private void InitMap(string mapPath) + { using var mapFile = File.Open(mapPath, FileMode.CreateNew, FileAccess.Write); using var writer = new BinaryWriter(mapFile, Encoding.UTF8); var emptyBLock = LandBlock.Empty(this); writer.Seek(0, SeekOrigin.Begin); - for (var x = 0; x < Width; x++) { - for (var y = 0; y < Height; y++) { + for (var x = 0; x < Width; x++) + { + for (var y = 0; y < Height; y++) + { emptyBLock.Write(writer); } } } - private void InitStatics(string staticsPath, string staidxPath) { + private void InitStatics(string staticsPath, string staidxPath) + { using var staticsFile = File.Open(staticsPath, FileMode.CreateNew, FileAccess.Write); using var staidxFile = File.Open(staidxPath, FileMode.CreateNew, FileAccess.Write); using var writer = new BinaryWriter(staidxFile, Encoding.UTF8); var emptyIndex = GenericIndex.Empty; writer.Seek(0, SeekOrigin.Begin); - for (var x = 0; x < Width; x++) { - for (var y = 0; y < Height; y++) { + for (var x = 0; x < Width; x++) + { + for (var y = 0; y < Height; y++) + { emptyIndex.Write(writer); } } } - ~ServerLandscape() { + ~ServerLandscape() + { Dispose(false); } private readonly FileStream _map; private readonly FileStream _statics; private readonly FileStream _staidx; - + private readonly BinaryReader _mapReader; private readonly BinaryReader _staticsReader; private readonly BinaryReader _staidxReader; - + private readonly BinaryWriter _mapWriter; private readonly BinaryWriter _staticsWriter; private readonly BinaryWriter _staidxWriter; private readonly Dictionary>> _blockSubscriptions = new(); - + public bool IsUop { get; } public bool IsMul => !IsUop; - + private UopFile[] UopFiles { get; set; } = null!; - + public TileDataProvider TileDataProvider { get; } = null!; private RadarMap _radarMap = null!; - private void OnRemovedCachedObject(Block block) { + private void OnRemovedCachedObject(Block block) + { if (block.LandBlock.Changed) SaveBlock(block.LandBlock); if (block.StaticBlock.Changed) SaveBlock(block.StaticBlock); } - - internal void AssertStaticTileId(ushort tileId) { - if(tileId >= TileDataProvider.StaticTiles.Length) + + internal void AssertStaticTileId(ushort tileId) + { + if (tileId >= TileDataProvider.StaticTiles.Length) throw new ArgumentException($"Invalid static tile id {tileId}"); } - internal void AssertLandTileId(ushort tileId) { - if(tileId >= TileDataProvider.LandTiles.Length) + internal void AssertLandTileId(ushort tileId) + { + if (tileId >= TileDataProvider.LandTiles.Length) throw new ArgumentException($"Invalid land tile id {tileId}"); } - internal void AssertHue(ushort hue) { - if(hue > 3000) + internal void AssertHue(ushort hue) + { + if (hue > 3000) throw new ArgumentException($"Invalid hue {hue}"); } - - public HashSet> GetBlockSubscriptions(ushort x, ushort y) { + + public HashSet> GetBlockSubscriptions(ushort x, ushort y) + { AssertBlockCoords(x, y); var key = GetBlockNumber(x, y); - if (_blockSubscriptions.TryGetValue(key, out var subscriptions)) { + if (_blockSubscriptions.TryGetValue(key, out var subscriptions)) + { subscriptions.RemoveWhere(ns => !ns.Running); return subscriptions; } - + var result = new HashSet>(); _blockSubscriptions.Add(key, result); return result; } - - public long GetBlockNumber(ushort x, ushort y) { + + public long GetBlockNumber(ushort x, ushort y) + { return x * Height + y; } - public long GetMapOffset(ushort x, ushort y) { + public long GetMapOffset(ushort x, ushort y) + { long offset = GetBlockNumber(x, y) * 196; if (IsUop) offset = CalculateOffsetFromUop(offset); return offset; } - public long GetStaidxOffset(ushort x, ushort y) { + public long GetStaidxOffset(ushort x, ushort y) + { return GetBlockNumber(x, y) * 12; } - protected override Block LoadBlock(ushort x, ushort y) { + protected override Block LoadBlock(ushort x, ushort y) + { AssertBlockCoords(x, y); _map.Position = GetMapOffset(x, y); var map = new LandBlock(this, x, y, _mapReader); - + _staidx.Position = GetStaidxOffset(x, y); var index = new GenericIndex(_staidxReader); var statics = new StaticBlock(this, _staticsReader, index, x, y); @@ -181,13 +216,15 @@ protected override Block LoadBlock(ushort x, ushort y) { return block; } - public void UpdateRadar(NetState ns, ushort x, ushort y) { - if ((x & 0x7) != 0 || (y & 0x7) != 0) return; + public void UpdateRadar(NetState ns, ushort x, ushort y) + { + if ((x & 0x7) != 0 || (y & 0x7) != 0) + return; var landTile = GetLandTile(x, y); var landPriority = GetEffectiveAltitude(landTile); var radarId = landTile.Id; - + var block = GetStaticBlock((ushort)(x / 8), (ushort)(y / 8)); block.SortTiles(ref TileDataProvider.StaticTiles); var topStaticTile = block.AllTiles().MaxBy(tile => tile.PriorityZ); @@ -198,66 +235,79 @@ public void UpdateRadar(NetState ns, ushort x, ushort y) { _radarMap.Update(ns, (ushort)(x / 8), (ushort)(y / 8), radarId); } - public sbyte GetLandAlt(ushort x, ushort y) { + public sbyte GetLandAlt(ushort x, ushort y) + { return GetLandTile(x, y).Z; } - public sbyte GetEffectiveAltitude(LandTile tile) { + public sbyte GetEffectiveAltitude(LandTile tile) + { var north = tile.Z; var west = GetLandAlt(tile.X, (ushort)(tile.Y + 1)); var south = GetLandAlt((ushort)(tile.X + 1), (ushort)(tile.Y + 1)); var east = GetLandAlt((ushort)(tile.X + 1), tile.Y); - if (Math.Abs(north - south) > Math.Abs(west - east)) { + if (Math.Abs(north - south) > Math.Abs(west - east)) + { return (sbyte)(north + south / 2); } - else { + else + { return (sbyte)((west + east) / 2); } } - - public void Flush() { + + public void Flush() + { BlockCache.Clear(); _map.Flush(); _staidx.Flush(); _statics.Flush(); } - - public void Backup(string backupDir) { - foreach (var fs in new[] { _map, _staidx, _statics }) { + + public void Backup(string backupDir) + { + foreach (var fs in new[] { _map, _staidx, _statics }) + { FileInfo fi = new FileInfo(fs.Name); Backup(fs, $"{backupDir}/{fi.Name}"); } } - private void Backup(FileStream file, String backupPath) { + private void Backup(FileStream file, String backupPath) + { using var backupStream = new FileStream(backupPath, FileMode.CreateNew, FileAccess.Write); file.Position = 0; file.CopyTo(backupStream); } - public void SaveBlock(LandBlock landBlock) { + public void SaveBlock(LandBlock landBlock) + { _logger.LogDebug($"Saving mapBlock {landBlock.X},{landBlock.Y}"); _map.Position = GetMapOffset(landBlock.X, landBlock.Y); landBlock.Write(_mapWriter); landBlock.Changed = false; } - public void SaveBlock(StaticBlock staticBlock) { + public void SaveBlock(StaticBlock staticBlock) + { _logger.LogDebug($"Saving staticBlock {staticBlock.X},{staticBlock.Y}"); _staidx.Position = GetStaidxOffset(staticBlock.X, staticBlock.Y); var index = new GenericIndex(_staidxReader); var size = staticBlock.TotalSize; - if (size > index.Length || index.Lookup <= 0) { + if (size > index.Length || index.Lookup <= 0) + { _statics.Position = _statics.Length; index.Lookup = (int)_statics.Position; } index.Length = size; - if (size == 0) { + if (size == 0) + { index.Lookup = -1; } - else { + else + { _statics.Position = index.Lookup; staticBlock.Write(_staticsWriter); } @@ -267,18 +317,22 @@ public void SaveBlock(StaticBlock staticBlock) { staticBlock.Changed = false; } - public long MapLength { - get { + public long MapLength + { + get + { if (IsUop) return UopFiles.Sum(f => f.Length); - else { + else + { return _map.Length; } } } - private bool Validate() { + private bool Validate() + { var blocks = Width * Height; var mapSize = blocks * LandBlock.SIZE; var staidxSize = blocks * GenericIndex.Size; @@ -286,41 +340,47 @@ private bool Validate() { var staidxFileBlocks = _staidx.Length / GenericIndex.Size; var valid = true; - if ((IsMul && MapLength != mapSize) || - (IsUop && MapLength < mapSize)) { + if ((IsMul && MapLength != mapSize) || (IsUop && MapLength < mapSize)) + { _logger.LogError($"{_map.Name} file doesn't match configured size: {MapLength} != {mapSize}"); _logger.LogInfo($"{_map.Name} seems to be {MapSizeHint()}"); valid = false; } - if (IsUop && MapLength > mapSize) { + if (IsUop && MapLength > mapSize) + { var diff = MapLength - mapSize; var blocksDiff = diff / LandBlock.SIZE; _logger.LogInfo($"{_map.Name} is larger than configured size by {blocksDiff} blocks ({diff} bytes)"); - if (blocksDiff == 1) { + if (blocksDiff == 1) + { _logger.LogInfo("This is normal for newer clients."); } - else { + else + { _logger.LogInfo("Either configuration is wrong or there is something wrong with the uop"); } - } - - if (_staidx.Length != staidxSize) { + + if (_staidx.Length != staidxSize) + { _logger.LogError($"{_staidx.Name} file doesn't match configured size: {_staidx.Length} != {staidxSize}"); _logger.LogInfo($"{_staidx.Name} seems to be {StaidxSizeHint()}"); valid = false; } - if ((IsMul && mapFileBlocks != staidxFileBlocks) || - (IsUop && mapFileBlocks < staidxFileBlocks)) { - _logger.LogError( - $"{_map.Name} file doesn't match {_staidx.Name} file in blocks: {mapFileBlocks} != {staidxFileBlocks} "); + if ((IsMul && mapFileBlocks != staidxFileBlocks) || (IsUop && mapFileBlocks < staidxFileBlocks)) + { + _logger.LogError + ( + $"{_map.Name} file doesn't match {_staidx.Name} file in blocks: {mapFileBlocks} != {staidxFileBlocks} " + ); _logger.LogInfo($"{_map.Name} seems to be {MapSizeHint()}, and staidx seems to be {StaidxSizeHint()}"); valid = false; } - - if (IsMul && MapLength + 1 == mapSize) { + + if (IsMul && MapLength + 1 == mapSize) + { _logger.LogError($"{_map.Name} file is exactly one block larger than configured size"); _logger.LogInfo("If extracted from UOP, then client version is too new for this UOP extractor"); var mapPath = _map.Name + ".extrablock"; @@ -334,8 +394,10 @@ private bool Validate() { return valid; } - private string MapSizeHint() { - return MapLength switch { + private string MapSizeHint() + { + return MapLength switch + { 3_211_264 => "128x128 (map0 Pre-Alpha)", 77_070_336 => "768x512 (map0,map1 Pre-ML)", 89_915_392 => "896x512 (map0,map1 Post-ML)", @@ -346,8 +408,10 @@ private string MapSizeHint() { }; } - private string StaidxSizeHint() { - return _staidx.Length switch { + private string StaidxSizeHint() + { + return _staidx.Length switch + { 196_608 => "128x128 (map0 Pre-Alpha)", 4_718_592 => "768x512 (map0,map1 Pre-ML)", 5_505_024 => "896x512 (map0,map1 Post-ML)", @@ -358,11 +422,12 @@ private string StaidxSizeHint() { }; } - private void ReadUopFiles(string pattern) { - + private void ReadUopFiles(string pattern) + { _map.Seek(0, SeekOrigin.Begin); - if (_mapReader.ReadInt32() != 0x50594D) { + if (_mapReader.ReadInt32() != 0x50594D) + { throw new ArgumentException("Bad UOP file."); } @@ -375,7 +440,8 @@ private void ReadUopFiles(string pattern) { var hashes = new Dictionary(); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { string file = $"build/{pattern}/{i:D8}.dat"; ulong hash = Uop.HashFileName(file); @@ -384,11 +450,13 @@ private void ReadUopFiles(string pattern) { _map.Seek(nextBlock, SeekOrigin.Begin); - do { + do + { int filesCount = _mapReader.ReadInt32(); nextBlock = _mapReader.ReadInt64(); - for (int i = 0; i < filesCount; i++) { + for (int i = 0; i < filesCount; i++) + { long offset = _mapReader.ReadInt64(); int headerLength = _mapReader.ReadInt32(); int compressedLength = _mapReader.ReadInt32(); @@ -399,26 +467,32 @@ private void ReadUopFiles(string pattern) { int length = flag == 1 ? compressedLength : decompressedLength; - if (offset == 0) { + if (offset == 0) + { continue; } - if (hashes.TryGetValue(hash, out int idx)) { - if (idx < 0 || idx > UopFiles.Length) { - throw new IndexOutOfRangeException( - "hashes dictionary and files collection have different count of entries!"); + if (hashes.TryGetValue(hash, out int idx)) + { + if (idx < 0 || idx > UopFiles.Length) + { + throw new IndexOutOfRangeException + ("hashes dictionary and files collection have different count of entries!"); } UopFiles[idx] = new UopFile(offset + headerLength, length); } - else { - throw new ArgumentException( - $"File with hash 0x{hash:X8} was not found in hashes dictionary! EA Mythic changed UOP format!"); + else + { + throw new ArgumentException + ( + $"File with hash 0x{hash:X8} was not found in hashes dictionary! EA Mythic changed UOP format!" + ); } } } while (_map.Seek(nextBlock, SeekOrigin.Begin) != 0); } - + private long CalculateOffsetFromUop(long offset) { long pos = 0; @@ -438,8 +512,10 @@ private long CalculateOffsetFromUop(long offset) return _map.Length; } - private void Dispose(bool disposing) { - if (disposing) { + private void Dispose(bool disposing) + { + if (disposing) + { _map.Dispose(); _statics.Dispose(); _staidx.Dispose(); @@ -452,7 +528,8 @@ private void Dispose(bool disposing) { } } - public void Dispose() { + public void Dispose() + { Dispose(true); GC.SuppressFinalize(this); } diff --git a/Server/Map/ServerLandscapePacketHandlers.cs b/Server/Map/ServerLandscapePacketHandlers.cs index f017350..aaadc3b 100644 --- a/Server/Map/ServerLandscapePacketHandlers.cs +++ b/Server/Map/ServerLandscapePacketHandlers.cs @@ -1,14 +1,17 @@ using System.Diagnostics.CodeAnalysis; using CentrED.Network; -namespace CentrED.Server.Map; +namespace CentrED.Server.Map; -public partial class ServerLandscape { - private void OnDrawMapPacket(BinaryReader reader, NetState ns) { +public partial class ServerLandscape +{ + private void OnDrawMapPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnDrawMapPacket"); var x = reader.ReadUInt16(); var y = reader.ReadUInt16(); - if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, x, y)) return; + if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, x, y)) + return; var tile = GetLandTile(x, y); @@ -20,17 +23,20 @@ private void OnDrawMapPacket(BinaryReader reader, NetState ns) { LandBlock block = tile.Block!; var packet = new DrawMapPacket(tile); - foreach (var netState in GetBlockSubscriptions(block.X, block.Y)) { + foreach (var netState in GetBlockSubscriptions(block.X, block.Y)) + { netState.Send(packet); } UpdateRadar(ns, x, y); } - private void OnInsertStaticPacket(BinaryReader reader, NetState ns) { + private void OnInsertStaticPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnInsertStaticPacket"); var staticInfo = new StaticInfo(reader); - if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, staticInfo.X, staticInfo.Y)) return; + if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, staticInfo.X, staticInfo.Y)) + return; var block = GetStaticBlock((ushort)(staticInfo.X / 8), (ushort)(staticInfo.Y / 8)); @@ -38,87 +44,102 @@ private void OnInsertStaticPacket(BinaryReader reader, NetState ns) { AssertStaticTileId(tile.Id); AssertHue(tile.Hue); InternalAddStatic(block, tile); - + block.SortTiles(ref TileDataProvider.StaticTiles); var packet = new InsertStaticPacket(tile); - foreach (var netState in GetBlockSubscriptions(block.X, block.Y)) { + foreach (var netState in GetBlockSubscriptions(block.X, block.Y)) + { netState.Send(packet); } UpdateRadar(ns, staticInfo.X, staticInfo.Y); } - private void OnDeleteStaticPacket(BinaryReader reader, NetState ns) { + private void OnDeleteStaticPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnDeleteStaticPacket"); var staticInfo = new StaticInfo(reader); var x = staticInfo.X; var y = staticInfo.Y; - if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, x, y)) return; + if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, x, y)) + return; var block = GetStaticBlock((ushort)(x / 8), (ushort)(y / 8)); var statics = block.GetTiles(x, y); var tile = statics.FirstOrDefault(s => s.Match(staticInfo)); - if (tile == null) return; - + if (tile == null) + return; + InternalRemoveStatic(block, tile); - + var packet = new DeleteStaticPacket(tile); - foreach (var netState in GetBlockSubscriptions(block.X, block.Y)) { + foreach (var netState in GetBlockSubscriptions(block.X, block.Y)) + { netState.Send(packet); } UpdateRadar(ns, x, y); } - private void OnElevateStaticPacket(BinaryReader reader, NetState ns) { + private void OnElevateStaticPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnElevateStaticPacket"); var staticInfo = new StaticInfo(reader); var x = staticInfo.X; var y = staticInfo.Y; - if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, x, y)) return; - + if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, x, y)) + return; + var block = GetStaticBlock((ushort)(x / 8), (ushort)(y / 8)); var statics = block.GetTiles(x, y); - + var tile = statics.FirstOrDefault(s => s.Match(staticInfo)); - if (tile == null) return; + if (tile == null) + return; var newZ = reader.ReadSByte(); var packet = new ElevateStaticPacket(tile, newZ); InternalSetStaticZ(tile, newZ); block.SortTiles(ref TileDataProvider.StaticTiles); - foreach (var netState in GetBlockSubscriptions(block.X, block.Y)) { + foreach (var netState in GetBlockSubscriptions(block.X, block.Y)) + { netState.Send(packet); } UpdateRadar(ns, x, y); } - private void OnMoveStaticPacket(BinaryReader reader, NetState ns) { + private void OnMoveStaticPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnMoveStaticPacket"); var staticInfo = new StaticInfo(reader); var newX = (ushort)Math.Clamp(reader.ReadUInt16(), 0, CellWidth - 1); var newY = (ushort)Math.Clamp(reader.ReadUInt16(), 0, CellHeight - 1); - - if (staticInfo.X == newX && staticInfo.Y == newY) return; - if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, staticInfo.X, staticInfo.Y)) return; - if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, newX, newY)) return; - - if((Math.Abs(staticInfo.X - newX) > 8 || Math.Abs(staticInfo.Y - newY) > 8) && - !PacketHandlers.ValidateAccess(ns, AccessLevel.Developer)) return; + if (staticInfo.X == newX && staticInfo.Y == newY) + return; + + if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, staticInfo.X, staticInfo.Y)) + return; + if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, newX, newY)) + return; + + if ((Math.Abs(staticInfo.X - newX) > 8 || Math.Abs(staticInfo.Y - newY) > 8) && + !PacketHandlers.ValidateAccess(ns, AccessLevel.Developer)) + return; var sourceBlock = GetStaticBlock((ushort)(staticInfo.X / 8), (ushort)(staticInfo.Y / 8)); var targetBlock = GetStaticBlock((ushort)(newX / 8), (ushort)(newY / 8)); var statics = GetStaticTiles(staticInfo.X, staticInfo.Y); - + StaticTile? tile = statics.FirstOrDefault(s => s.Match(staticInfo)); - if (tile == null) { + if (tile == null) + { ns.LogError($"Tile not found {staticInfo}"); return; } @@ -142,13 +163,16 @@ private void OnMoveStaticPacket(BinaryReader reader, NetState ns) { var deleteSubscriptions = sourceSubscriptions.Except(targetSubscriptions); var insertSubscriptions = targetSubscriptions.Except(sourceSubscriptions); - foreach (var netState in insertSubscriptions) { + foreach (var netState in insertSubscriptions) + { netState.Send(insertPacket); } - foreach (var netState in deleteSubscriptions) { + foreach (var netState in deleteSubscriptions) + { netState.Send(deletePacket); } - foreach (var netState in moveSubscriptions) { + foreach (var netState in moveSubscriptions) + { netState.Send(movePacket); } @@ -156,51 +180,62 @@ private void OnMoveStaticPacket(BinaryReader reader, NetState ns) { UpdateRadar(ns, newX, newY); } - private void OnHueStaticPacket(BinaryReader reader, NetState ns) { + private void OnHueStaticPacket(BinaryReader reader, NetState ns) + { ns.LogDebug("Server OnHueStaticPacket"); var staticInfo = new StaticInfo(reader); var x = staticInfo.X; var y = staticInfo.Y; - if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, x, y)) return; - + if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Normal, x, y)) + return; + var block = GetStaticBlock((ushort)(x / 8), (ushort)(y / 8)); var statics = block.GetTiles(x, y); var tile = statics.FirstOrDefault(s => s.Match(staticInfo)); var newHue = reader.ReadUInt16(); - if (tile == null) return; + if (tile == null) + return; AssertHue(newHue); var packet = new HueStaticPacket(tile, newHue); InternalSetStaticHue(tile, newHue); - - foreach (var netState in GetBlockSubscriptions(block.X, block.Y)) { + + foreach (var netState in GetBlockSubscriptions(block.X, block.Y)) + { netState.Send(packet); } } [SuppressMessage("ReSharper", "PossibleMultipleEnumeration")] - private void OnLargeScaleCommandPacket(BinaryReader reader, NetState ns) { - if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Developer)) return; + private void OnLargeScaleCommandPacket(BinaryReader reader, NetState ns) + { + if (!PacketHandlers.ValidateAccess(ns, AccessLevel.Developer)) + return; var logMsg = $"{ns.Username} begins large scale operation"; ns.LogInfo(logMsg); ns.Parent.Send(new ServerStatePacket(ServerState.Other, logMsg)); - try { + try + { var affectedBlocks = new bool[Width * Height]; var affectedTiles = new bool[Width * Height, 64]; var extraAffectedBlocks = new bool[Width * Height]; var clients = new Dictionary, HashSet>(); - foreach (var netState in ns.Parent.Clients) { + foreach (var netState in ns.Parent.Clients) + { clients.Add(netState, new HashSet()); } var areaCount = reader.ReadByte(); var areaInfos = new AreaInfo[areaCount]; - for (int i = 0; i < areaCount; i++) { + for (int i = 0; i < areaCount; i++) + { areaInfos[i] = new AreaInfo(reader); - for (ushort x = areaInfos[i].Left; x < areaInfos[i].Right; x++) { - for (ushort y = areaInfos[i].Top; y < areaInfos[i].Bottom; y++) { + for (ushort x = areaInfos[i].Left; x < areaInfos[i].Right; x++) + { + for (ushort y = areaInfos[i].Top; y < areaInfos[i].Bottom; y++) + { var blockId = GetBlockId(x, y); var tileId = GetTileId(x, y); affectedBlocks[blockId] = true; @@ -220,45 +255,60 @@ private void OnLargeScaleCommandPacket(BinaryReader reader, NetState var yBlockRange = Enumerable.Range(minBlockY, maxBlockY - minBlockY); var xTileRange = Enumerable.Range(0, 8); var yTileRange = Enumerable.Range(0, 8); - - if (reader.ReadBoolean()) { + + if (reader.ReadBoolean()) + { var copyMove = new LsCopyMove(reader, this); - if (copyMove.OffsetX > 0) { + if (copyMove.OffsetX > 0) + { xBlockRange = xBlockRange.Reverse(); xTileRange = xTileRange.Reverse(); } - if (copyMove.OffsetY > 0) { + if (copyMove.OffsetY > 0) + { yBlockRange = yBlockRange.Reverse(); yTileRange = yTileRange.Reverse(); } operations.Add(copyMove); } - if (reader.ReadBoolean()) operations.Add(new LsSetAltitude(reader, this)); - if (reader.ReadBoolean()) operations.Add(new LsDrawTerrain(reader, this)); - if (reader.ReadBoolean()) operations.Add(new LsDeleteStatics(reader, this)); - if (reader.ReadBoolean()) operations.Add(new LsInsertStatics(reader, this)); - foreach (var operation in operations) { + if (reader.ReadBoolean()) + operations.Add(new LsSetAltitude(reader, this)); + if (reader.ReadBoolean()) + operations.Add(new LsDrawTerrain(reader, this)); + if (reader.ReadBoolean()) + operations.Add(new LsDeleteStatics(reader, this)); + if (reader.ReadBoolean()) + operations.Add(new LsInsertStatics(reader, this)); + foreach (var operation in operations) + { operation.Validate(); } - + _radarMap.BeginUpdate(); - foreach(ushort blockX in xBlockRange) { - foreach(ushort blockY in yBlockRange) { + foreach (ushort blockX in xBlockRange) + { + foreach (ushort blockY in yBlockRange) + { var blockId = blockX * Height + blockY; - if (!affectedBlocks[blockId]) continue; + if (!affectedBlocks[blockId]) + continue; - foreach (ushort tileY in yTileRange) { - foreach (ushort tileX in xTileRange) { + foreach (ushort tileY in yTileRange) + { + foreach (ushort tileX in xTileRange) + { var tileId = GetTileId(tileX, tileY); - if (!affectedTiles[blockId, tileId]) continue; + if (!affectedTiles[blockId, tileId]) + continue; var x = (ushort)(blockX * 8 + tileX); var y = (ushort)(blockY * 8 + tileY); var mapTile = GetLandTile(x, y); var staticBlock = GetStaticBlock(blockX, blockY); - var statics = staticBlock.GetTiles(x,y); - foreach (var operation in operations) { + var statics = staticBlock.GetTiles(x, y); + foreach (var operation in operations) + { operation.Apply(mapTile, statics.ToArray(), ref extraAffectedBlocks); } @@ -268,19 +318,24 @@ private void OnLargeScaleCommandPacket(BinaryReader reader, NetState } //Notify affected clients - foreach (var netState in GetBlockSubscriptions(blockX, blockY)) { + foreach (var netState in GetBlockSubscriptions(blockX, blockY)) + { clients[netState].Add(new BlockCoords(blockX, blockY)); } } } //aditional blocks - for (ushort blockX = 0; blockX < Width; blockX++) { - for (ushort blockY = 0; blockY < Height; blockY++) { + for (ushort blockX = 0; blockX < Width; blockX++) + { + for (ushort blockY = 0; blockY < Height; blockY++) + { var blockId = (ushort)(blockX * Height + blockY); - if (affectedBlocks[blockId] || !extraAffectedBlocks[blockId]) continue; + if (affectedBlocks[blockId] || !extraAffectedBlocks[blockId]) + continue; - foreach (var netState in GetBlockSubscriptions(blockX, blockY)!) { + foreach (var netState in GetBlockSubscriptions(blockX, blockY)!) + { clients[netState].Add(new BlockCoords(blockX, blockY)); } @@ -290,16 +345,20 @@ private void OnLargeScaleCommandPacket(BinaryReader reader, NetState _radarMap.EndUpdate(ns); - foreach (var (netState, blocks) in clients) { - if (blocks.Count > 0) { + foreach (var (netState, blocks) in clients) + { + if (blocks.Count > 0) + { netState.Send(new CompressedPacket(new BlockPacket(blocks, netState, false))); } } } - catch (Exception e) { + catch (Exception e) + { ns.LogError($"LSO Failed {e}"); } - finally { + finally + { ns.Parent.Send(new ServerStatePacket(ServerState.Running)); } ns.LogInfo("Large scale operation ended."); diff --git a/Server/PacketHandlers.cs b/Server/PacketHandlers.cs index 783e97a..10b7e95 100644 --- a/Server/PacketHandlers.cs +++ b/Server/PacketHandlers.cs @@ -1,14 +1,16 @@ using CentrED.Network; using static CentrED.Network.PacketHandlers; -namespace CentrED.Server; +namespace CentrED.Server; -public static class PacketHandlers { +public static class PacketHandlers +{ public static PacketHandler?[] Handlers { get; } - - static PacketHandlers() { + + static PacketHandlers() + { Handlers = new PacketHandler?[0x100]; - + RegisterPacketHandler(0x01, 0, OnCompressedPacket); RegisterPacketHandler(0x02, 0, ConnectionHandling.OnConnectionHandlerPacket); RegisterPacketHandler(0x03, 0, AdminHandling.OnAdminHandlerPacket); @@ -21,34 +23,43 @@ static PacketHandlers() { RegisterPacketHandler(0xFF, 1, OnNoOpPacket); } - public static void RegisterPacketHandler(int packetId, uint length, PacketHandler.PacketProcessor packetProcessor) + public static void RegisterPacketHandler + (int packetId, uint length, PacketHandler.PacketProcessor packetProcessor) { Handlers[packetId] = new PacketHandler(length, packetProcessor); } - public static bool ValidateAccess(NetState ns, AccessLevel accessLevel) { + public static bool ValidateAccess(NetState ns, AccessLevel accessLevel) + { return ns.AccessLevel() >= accessLevel; } - public static bool ValidateAccess(NetState ns, AccessLevel accessLevel, uint x, uint y) { - if (!ValidateAccess(ns, accessLevel)) return false; + public static bool ValidateAccess(NetState ns, AccessLevel accessLevel, uint x, uint y) + { + if (!ValidateAccess(ns, accessLevel)) + return false; var account = ns.Parent.GetAccount(ns.Username)!; - if (account.Regions.Count == 0 || ns.AccessLevel() >= AccessLevel.Administrator) return true; + if (account.Regions.Count == 0 || ns.AccessLevel() >= AccessLevel.Administrator) + return true; - foreach (var regionName in account.Regions) { + foreach (var regionName in account.Regions) + { var region = ns.Parent.GetRegion(regionName); - if (region != null && region.Area.Any(a => a.Contains(x, y))) + if (region != null && region.Area.Any(a => a.Contains(x, y))) return true; } return false; } - private static void OnRequestBlocksPacket(BinaryReader buffer, NetState ns) { + private static void OnRequestBlocksPacket(BinaryReader buffer, NetState ns) + { ns.LogDebug("Server OnRequestBlocksPacket"); - if (!ValidateAccess(ns, AccessLevel.View)) return; + if (!ValidateAccess(ns, AccessLevel.View)) + return; var blocksCount = (buffer.BaseStream.Length - buffer.BaseStream.Position) / 4; // x and y, both 2 bytes var blocks = new BlockCoords[blocksCount]; - for (var i = 0; i < blocksCount; i++) { + for (var i = 0; i < blocksCount; i++) + { blocks[i] = new BlockCoords(buffer); ns.LogDebug($"Requested x={blocks[i].X} y={blocks[i].Y}"); } @@ -56,16 +67,19 @@ private static void OnRequestBlocksPacket(BinaryReader buffer, NetState(blocks), ns, true))); } - private static void OnFreeBlockPacket(BinaryReader buffer, NetState ns) { + private static void OnFreeBlockPacket(BinaryReader buffer, NetState ns) + { ns.LogDebug("Server OnFreeBlockPacket"); - if (!ValidateAccess(ns, AccessLevel.View)) return; + if (!ValidateAccess(ns, AccessLevel.View)) + return; var x = buffer.ReadUInt16(); var y = buffer.ReadUInt16(); var subscriptions = ns.Parent.Landscape.GetBlockSubscriptions(x, y); subscriptions.Remove(ns); } - private static void OnNoOpPacket(BinaryReader buffer, NetState ns) { + private static void OnNoOpPacket(BinaryReader buffer, NetState ns) + { ns.LogDebug("Server OnNoOpPacket"); } } \ No newline at end of file diff --git a/Server/Packets.cs b/Server/Packets.cs index b617f83..49f6b50 100644 --- a/Server/Packets.cs +++ b/Server/Packets.cs @@ -4,9 +4,12 @@ namespace CentrED.Server; -class BlockPacket : Packet { - public BlockPacket(IEnumerable coords, NetState ns, bool subscribe) : base(0x04, 0) { - foreach (var coord in coords) { +class BlockPacket : Packet +{ + public BlockPacket(IEnumerable coords, NetState ns, bool subscribe) : base(0x04, 0) + { + foreach (var coord in coords) + { var mapBlock = ns.Parent.Landscape.GetLandBlock(coord.X, coord.Y); var staticsBlock = ns.Parent.Landscape.GetStaticBlock(coord.X, coord.Y); @@ -15,15 +18,18 @@ public BlockPacket(IEnumerable coords, NetState ns, bool Writer.Write((ushort)staticsBlock.TotalTilesCount); staticsBlock.SortTiles(ref ns.Parent.Landscape.TileDataProvider.StaticTiles); staticsBlock.Write(Writer); - if (!subscribe) continue; + if (!subscribe) + continue; var subscriptions = ns.Parent.Landscape.GetBlockSubscriptions(coord.X, coord.Y); subscriptions.Add(ns); } } } -class DrawMapPacket : Packet { - public DrawMapPacket(LandTile landTile) : base(0x06, 8) { +class DrawMapPacket : Packet +{ + public DrawMapPacket(LandTile landTile) : base(0x06, 8) + { Writer.Write(landTile.X); Writer.Write(landTile.Y); Writer.Write(landTile.Z); @@ -31,8 +37,10 @@ public DrawMapPacket(LandTile landTile) : base(0x06, 8) { } } -class InsertStaticPacket : Packet { - public InsertStaticPacket(StaticTile staticTile) : base(0x07, 10) { +class InsertStaticPacket : Packet +{ + public InsertStaticPacket(StaticTile staticTile) : base(0x07, 10) + { Writer.Write(staticTile.X); Writer.Write(staticTile.Y); Writer.Write(staticTile.Z); @@ -41,8 +49,10 @@ public InsertStaticPacket(StaticTile staticTile) : base(0x07, 10) { } } -class DeleteStaticPacket : Packet { - public DeleteStaticPacket(StaticTile staticTile) : base(0x08, 10) { +class DeleteStaticPacket : Packet +{ + public DeleteStaticPacket(StaticTile staticTile) : base(0x08, 10) + { Writer.Write(staticTile.X); Writer.Write(staticTile.Y); Writer.Write(staticTile.Z); @@ -51,8 +61,10 @@ public DeleteStaticPacket(StaticTile staticTile) : base(0x08, 10) { } } -class ElevateStaticPacket : Packet { - public ElevateStaticPacket(StaticTile staticTile, sbyte newZ) : base(0x09, 11) { +class ElevateStaticPacket : Packet +{ + public ElevateStaticPacket(StaticTile staticTile, sbyte newZ) : base(0x09, 11) + { Writer.Write(staticTile.X); Writer.Write(staticTile.Y); Writer.Write(staticTile.Z); @@ -62,8 +74,10 @@ public ElevateStaticPacket(StaticTile staticTile, sbyte newZ) : base(0x09, 11) { } } -class MoveStaticPacket : Packet { - public MoveStaticPacket(StaticTile staticTile, ushort newX, ushort newY) : base(0x0A, 14) { +class MoveStaticPacket : Packet +{ + public MoveStaticPacket(StaticTile staticTile, ushort newX, ushort newY) : base(0x0A, 14) + { Writer.Write(staticTile.X); Writer.Write(staticTile.Y); Writer.Write(staticTile.Z); @@ -74,8 +88,10 @@ public MoveStaticPacket(StaticTile staticTile, ushort newX, ushort newY) : base( } } -class HueStaticPacket : Packet { - public HueStaticPacket(StaticTile staticTile, ushort newHue) : base(0x0B, 12) { +class HueStaticPacket : Packet +{ + public HueStaticPacket(StaticTile staticTile, ushort newHue) : base(0x0B, 12) + { Writer.Write(staticTile.X); Writer.Write(staticTile.Y); Writer.Write(staticTile.Z); @@ -85,25 +101,31 @@ public HueStaticPacket(StaticTile staticTile, ushort newHue) : base(0x0B, 12) { } } -public class ProtocolVersionPacket : Packet { - public ProtocolVersionPacket(uint version) : base(0x02, 0) { +public class ProtocolVersionPacket : Packet +{ + public ProtocolVersionPacket(uint version) : base(0x02, 0) + { Writer.Write((byte)0x01); - Writer.Write(version); + Writer.Write(version); } } -public class LoginResponsePacket : Packet { - public LoginResponsePacket(LoginState state, NetState? ns = null) : base(0x02, 0) { +public class LoginResponsePacket : Packet +{ + public LoginResponsePacket(LoginState state, NetState? ns = null) : base(0x02, 0) + { Writer.Write((byte)0x03); Writer.Write((byte)state); - if (state == LoginState.Ok && ns != null) { + if (state == LoginState.Ok && ns != null) + { ns.Account().LastLogon = DateTime.Now; Writer.Write((byte)ns.AccessLevel()); - if(ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) + if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) Writer.Write((uint)Math.Abs((DateTime.Now - ns.Parent.StartTime).TotalSeconds)); Writer.Write(ns.Parent.Landscape.Width); Writer.Write(ns.Parent.Landscape.Height); - if(ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) { + if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) + { uint flags = 0xF0000000; if (ns.Parent.Landscape.TileDataProvider.Version == TileDataVersion.HighSeas) flags |= 0x8; @@ -117,39 +139,52 @@ public LoginResponsePacket(LoginState state, NetState? ns = null) : b } } } - -public class ServerStatePacket : Packet { - public ServerStatePacket(ServerState state, string message = "") : base(0x02, 0) { + +public class ServerStatePacket : Packet +{ + public ServerStatePacket(ServerState state, string message = "") : base(0x02, 0) + { Writer.Write((byte)0x04); Writer.Write((byte)state); - if(state == ServerState.Other) - Writer.WriteStringNull(message); + if (state == ServerState.Other) + Writer.WriteStringNull(message); } } -public class ClientConnectedPacket : Packet { - public ClientConnectedPacket(NetState ns) : base(0x0C, 0) { + +public class ClientConnectedPacket : Packet +{ + public ClientConnectedPacket(NetState ns) : base(0x0C, 0) + { Writer.Write((byte)0x01); Writer.WriteStringNull(ns.Username); - if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) { + if (ns.ProtocolVersion == ProtocolVersion.CentrEDPlus) + { Writer.Write((byte)ns.AccessLevel()); } } } -public class ClientDisconnectedPacket : Packet { - public ClientDisconnectedPacket(NetState ns) : base(0x0C, 0) { +public class ClientDisconnectedPacket : Packet +{ + public ClientDisconnectedPacket(NetState ns) : base(0x0C, 0) + { Writer.Write((byte)0x02); Writer.WriteStringNull(ns.Username); } } -public class ClientListPacket : Packet { - public ClientListPacket(NetState avoid) : base(0x0C, 0) { +public class ClientListPacket : Packet +{ + public ClientListPacket(NetState avoid) : base(0x0C, 0) + { Writer.Write((byte)0x03); - foreach (var ns in avoid.Parent.Clients) { - if (ns.Username != "" && ns != avoid) { + foreach (var ns in avoid.Parent.Clients) + { + if (ns.Username != "" && ns != avoid) + { Writer.WriteStringNull(ns.Username); - if (avoid.Parent.Config.CentrEdPlus) { + if (avoid.Parent.Config.CentrEdPlus) + { Writer.Write((byte)ns.AccessLevel()); Writer.Write((uint)Math.Abs((ns.LastLogon() - avoid.Parent.StartTime).TotalSeconds)); } @@ -158,110 +193,139 @@ public ClientListPacket(NetState avoid) : base(0x0C, 0) { } } -public class SetClientPosPacket : Packet { - public SetClientPosPacket(NetState ns) : base(0x0C, 0) { +public class SetClientPosPacket : Packet +{ + public SetClientPosPacket(NetState ns) : base(0x0C, 0) + { Writer.Write((byte)0x04); Writer.Write((ushort)Math.Clamp(ns.Account().LastPos.X, 0, ns.Parent.Landscape.CellWidth - 1)); Writer.Write((ushort)Math.Clamp(ns.Account().LastPos.Y, 0, ns.Parent.Landscape.CellHeight - 1)); } } -public class ChatMessagePacket : Packet { - public ChatMessagePacket(string sender, string message) : base(0x0C, 0) { +public class ChatMessagePacket : Packet +{ + public ChatMessagePacket(string sender, string message) : base(0x0C, 0) + { Writer.Write((byte)0x05); Writer.WriteStringNull(sender); Writer.WriteStringNull(message); } } -public class AccessChangedPacket : Packet { - public AccessChangedPacket(NetState ns) : base(0x0C, 0) { +public class AccessChangedPacket : Packet +{ + public AccessChangedPacket(NetState ns) : base(0x0C, 0) + { Writer.Write((byte)0x07); Writer.Write((byte)ns.AccessLevel()); ClientHandling.WriteAccountRestrictions(Writer, ns); } } -public class PasswordChangeStatusPacket : Packet { - public PasswordChangeStatusPacket(PasswordChangeStatus status) : base(0x0C, 0) { +public class PasswordChangeStatusPacket : Packet +{ + public PasswordChangeStatusPacket(PasswordChangeStatus status) : base(0x0C, 0) + { Writer.Write((byte)0x08); Writer.Write((byte)status); } } -public class ModifyUserResponsePacket : Packet { - public ModifyUserResponsePacket(ModifyUserStatus status, Account? account) : base(0x03, 0) { +public class ModifyUserResponsePacket : Packet +{ + public ModifyUserResponsePacket(ModifyUserStatus status, Account? account) : base(0x03, 0) + { Writer.Write((byte)0x05); Writer.Write((byte)status); - - if (account == null) return; - + + if (account == null) + return; + Writer.WriteStringNull(account.Name); - if (status == ModifyUserStatus.Added || status == ModifyUserStatus.Modified) { + if (status == ModifyUserStatus.Added || status == ModifyUserStatus.Modified) + { Writer.Write((byte)account.AccessLevel); Writer.Write(account.Regions.Count); - foreach (var regionName in account.Regions) { + foreach (var regionName in account.Regions) + { Writer.WriteStringNull(regionName); } } } } -public class DeleteUserResponsePacket : Packet { - public DeleteUserResponsePacket(DeleteUserStatus status, string username) : base(0x03, 0) { +public class DeleteUserResponsePacket : Packet +{ + public DeleteUserResponsePacket(DeleteUserStatus status, string username) : base(0x03, 0) + { Writer.Write((byte)0x06); Writer.Write((byte)status); Writer.WriteStringNull(username); } } -public class UserListPacket : Packet { - public UserListPacket(NetState ns) : base(0x03, 0) { +public class UserListPacket : Packet +{ + public UserListPacket(NetState ns) : base(0x03, 0) + { var accounts = ns.Parent.Config.Accounts; Writer.Write((byte)0x07); Writer.Write((ushort)accounts.Count); - foreach (var account in accounts) { + foreach (var account in accounts) + { Writer.WriteStringNull(account.Name); Writer.Write((byte)account.AccessLevel); Writer.Write((byte)account.Regions.Count); - foreach (var region in account.Regions) { + foreach (var region in account.Regions) + { Writer.WriteStringNull(region); } } } } -public class ModifyRegionResponsePacket : Packet { - public ModifyRegionResponsePacket(ModifyRegionStatus status, Region region) : base(0x03, 0) { +public class ModifyRegionResponsePacket : Packet +{ + public ModifyRegionResponsePacket(ModifyRegionStatus status, Region region) : base(0x03, 0) + { Writer.Write((byte)0x08); Writer.Write((byte)status); Writer.WriteStringNull(region.Name); - if (status is ModifyRegionStatus.Added or ModifyRegionStatus.Modified) { + if (status is ModifyRegionStatus.Added or ModifyRegionStatus.Modified) + { Writer.Write(region.Area.Count); - foreach (var rect in region.Area) { + foreach (var rect in region.Area) + { rect.Write(Writer); } } } } -public class DeleteRegionResponsePacket : Packet { - public DeleteRegionResponsePacket(DeleteRegionStatus status, string regionName) : base(0x03, 0) { +public class DeleteRegionResponsePacket : Packet +{ + public DeleteRegionResponsePacket(DeleteRegionStatus status, string regionName) : base(0x03, 0) + { Writer.Write((byte)0x09); Writer.Write((byte)status); Writer.WriteStringNull(regionName); } } -public class RegionListPacket : Packet { - public RegionListPacket(NetState ns) : base(0x03, 0) { +public class RegionListPacket : Packet +{ + public RegionListPacket(NetState ns) : base(0x03, 0) + { var regions = ns.Parent.Config.Regions; Writer.Write((byte)0x0A); Writer.Write((byte)regions.Count); - foreach (var region in regions) { + foreach (var region in regions) + { Writer.WriteStringNull(region.Name); Writer.Write((byte)region.Area.Count); - foreach (var rect in region.Area) { + foreach (var rect in region.Area) + { Writer.Write(rect.X1); Writer.Write(rect.Y1); Writer.Write(rect.X2); @@ -269,4 +333,4 @@ public RegionListPacket(NetState ns) : base(0x03, 0) { } } } -} +} \ No newline at end of file diff --git a/Server/Server.csproj b/Server/Server.csproj index 4026d5d..e49131b 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -1,25 +1,25 @@ - - Exe - net7.0 - enable - enable - 11 - false - Cedserver - Cedserver - CentrED.Server - + + Exe + net7.0 + enable + enable + 11 + false + Cedserver + Cedserver + CentrED.Server + - - - + + + - - - ..\lib\x64\ClassicUO.Assets.dll - - + + + ..\lib\x64\ClassicUO.Assets.dll + + diff --git a/Server/ServerNetState.cs b/Server/ServerNetState.cs index b615216..a5a6283 100644 --- a/Server/ServerNetState.cs +++ b/Server/ServerNetState.cs @@ -1,18 +1,22 @@ using CentrED.Network; using CentrED.Server.Config; -namespace CentrED.Server; +namespace CentrED.Server; -public static class ServerNetState { - public static Account Account(this NetState ns) { +public static class ServerNetState +{ + public static Account Account(this NetState ns) + { return ns.Parent.GetAccount(ns)!; } - public static AccessLevel AccessLevel(this NetState ns) { + public static AccessLevel AccessLevel(this NetState ns) + { return ns.Account().AccessLevel; } - - public static DateTime LastLogon(this NetState ns) { + + public static DateTime LastLogon(this NetState ns) + { return ns.Account().LastLogon; } } \ No newline at end of file diff --git a/Shared/BaseCentred.cs b/Shared/BaseCentred.cs index c5d259f..ac07d90 100644 --- a/Shared/BaseCentred.cs +++ b/Shared/BaseCentred.cs @@ -1,7 +1,8 @@ using CentrED.Utility; -namespace CentrED; +namespace CentrED; -public abstract class BaseCentrED { +public abstract class BaseCentrED +{ public Logger _logger = new(); } \ No newline at end of file diff --git a/Shared/BaseLandscape.cs b/Shared/BaseLandscape.cs index 7854544..ed299bf 100644 --- a/Shared/BaseLandscape.cs +++ b/Shared/BaseLandscape.cs @@ -10,89 +10,108 @@ public delegate void StaticElevated(StaticTile staticTile, sbyte newZ); public delegate void StaticHued(StaticTile staticTile, ushort newHue); -public abstract class BaseLandscape { - public uint GetBlockId(ushort x, ushort y) { +public abstract class BaseLandscape +{ + public uint GetBlockId(ushort x, ushort y) + { return (uint)(x / 8 * Height + y / 8); } - public static byte GetTileId(ushort x, ushort y) { + + public static byte GetTileId(ushort x, ushort y) + { return (byte)((y & 0x7) * 8 + (x & 0x7)); } - protected BaseLandscape(ushort width, ushort height) { + protected BaseLandscape(ushort width, ushort height) + { Width = width; Height = height; CellWidth = (ushort)(width * 8); CellHeight = (ushort)(height * 8); - BlockCache = new BlockCache { + BlockCache = new BlockCache + { OnRemovedItem = OnBlockReleased }; } - + public ushort Width { get; } public ushort Height { get; } public ushort CellWidth { get; } public ushort CellHeight { get; } public readonly BlockCache BlockCache; - - protected void AssertBlockCoords(ushort x, ushort y) { - if (x >= Width || y >= Height) + + protected void AssertBlockCoords(ushort x, ushort y) + { + if (x >= Width || y >= Height) throw new ArgumentException($"Coords out of range. Size: {Width}x{Height}, Requested: {x},{y}"); } - - public LandTile GetLandTile(ushort x, ushort y) { + + public LandTile GetLandTile(ushort x, ushort y) + { var block = GetLandBlock((ushort)(x / 8), (ushort)(y / 8)); return block.Tiles[GetTileId(x, y)]; } - - public IEnumerable GetStaticTiles(ushort x, ushort y) { + + public IEnumerable GetStaticTiles(ushort x, ushort y) + { var block = GetStaticBlock((ushort)(x / 8), (ushort)(y / 8)); return block.GetTiles(x, y); } - - public LandBlock GetLandBlock(ushort x, ushort y) { + + public LandBlock GetLandBlock(ushort x, ushort y) + { return GetBlock(x, y).LandBlock; } - public StaticBlock GetStaticBlock(ushort x, ushort y) { + public StaticBlock GetStaticBlock(ushort x, ushort y) + { return GetBlock(x, y).StaticBlock; } - - public Block GetBlock(ushort x, ushort y) { + + public Block GetBlock(ushort x, ushort y) + { AssertBlockCoords(x, y); var result = BlockCache.Get(Block.Id(x, y)); - if (result == null) { + if (result == null) + { result = LoadBlock(x, y); } return result; } - protected void InternalSetLandId(LandTile tile, ushort newId) { + protected void InternalSetLandId(LandTile tile, ushort newId) + { tile._id = newId; tile.Block?.OnChanged(); } - protected void InternalSetLandZ(LandTile tile, sbyte newZ) { + protected void InternalSetLandZ(LandTile tile, sbyte newZ) + { tile._z = newZ; tile.Block?.OnChanged(); } - protected void InternalAddStatic(StaticBlock block, StaticTile tile) { + protected void InternalAddStatic(StaticBlock block, StaticTile tile) + { block.AddTileInternal(tile); block.OnChanged(); - } - - protected bool InternalRemoveStatic(StaticBlock block, StaticTile tile) { + } + + protected bool InternalRemoveStatic(StaticBlock block, StaticTile tile) + { var result = block.RemoveTileInternal(tile); block.OnChanged(); return result; - } - - protected void InternalSetStaticId(StaticTile tile, ushort newId) { + } + + protected void InternalSetStaticId(StaticTile tile, ushort newId) + { tile._id = newId; tile.Block?.OnChanged(); } - protected void InternalSetStaticPos(StaticTile tile, ushort newX, ushort newY) { + protected void InternalSetStaticPos(StaticTile tile, ushort newX, ushort newY) + { tile._x = newX; tile._y = newY; tile.LocalX = (byte)(newX & 0x7); @@ -100,16 +119,18 @@ protected void InternalSetStaticPos(StaticTile tile, ushort newX, ushort newY) { tile.Block?.OnChanged(); } - protected void InternalSetStaticZ(StaticTile tile, sbyte newZ) { + protected void InternalSetStaticZ(StaticTile tile, sbyte newZ) + { tile._z = newZ; tile.Block?.OnChanged(); } - protected void InternalSetStaticHue(StaticTile tile, ushort newHue) { + protected void InternalSetStaticHue(StaticTile tile, ushort newHue) + { tile._hue = newHue; tile.Block?.OnChanged(); } - + public event MapChanged? MapChanged; public event BlockChanged? BlockUnloaded; public event BlockChanged? BlockLoaded; @@ -121,57 +142,68 @@ protected void InternalSetStaticHue(StaticTile tile, ushort newHue) { public event StaticMoved? StaticTileMoved; public event StaticElevated? StaticTileElevated; public event StaticHued? StaticTileHued; - - public void OnMapChanged() { + + public void OnMapChanged() + { MapChanged?.Invoke(); } - public void OnBlockReleased(Block block) { + public void OnBlockReleased(Block block) + { BlockUnloaded?.Invoke(block); OnMapChanged(); } - public void OnBlockLoaded(Block block) { + public void OnBlockLoaded(Block block) + { BlockLoaded?.Invoke(block); OnMapChanged(); } - public void OnLandReplaced(LandTile landTile, ushort newId) { + public void OnLandReplaced(LandTile landTile, ushort newId) + { LandTileReplaced?.Invoke(landTile, newId); OnMapChanged(); } - public void OnLandElevated(LandTile landTile, sbyte newZ) { + public void OnLandElevated(LandTile landTile, sbyte newZ) + { LandTileElevated?.Invoke(landTile, newZ); OnMapChanged(); } - public void OnStaticTileAdded(StaticTile staticTile) { + public void OnStaticTileAdded(StaticTile staticTile) + { StaticTileAdded?.Invoke(staticTile); OnMapChanged(); } - public void OnStaticTileRemoved(StaticTile staticTile) { + public void OnStaticTileRemoved(StaticTile staticTile) + { StaticTileRemoved?.Invoke(staticTile); OnMapChanged(); } - - public void OnStaticTileReplaced(StaticTile staticTile, ushort newId) { + + public void OnStaticTileReplaced(StaticTile staticTile, ushort newId) + { StaticTileReplaced?.Invoke(staticTile, newId); OnMapChanged(); } - - public void OnStaticTileMoved(StaticTile staticTile, ushort newX, ushort newY) { + + public void OnStaticTileMoved(StaticTile staticTile, ushort newX, ushort newY) + { StaticTileMoved?.Invoke(staticTile, newX, newY); OnMapChanged(); } - public void OnStaticTileElevated(StaticTile staticTile, sbyte newZ) { + public void OnStaticTileElevated(StaticTile staticTile, sbyte newZ) + { StaticTileElevated?.Invoke(staticTile, newZ); OnMapChanged(); } - public void OnStaticTileHued(StaticTile staticTile, ushort newHue) { + public void OnStaticTileHued(StaticTile staticTile, ushort newHue) + { StaticTileHued?.Invoke(staticTile, newHue); OnMapChanged(); } diff --git a/Shared/BaseTile.cs b/Shared/BaseTile.cs index aedaff3..818ba72 100644 --- a/Shared/BaseTile.cs +++ b/Shared/BaseTile.cs @@ -1,27 +1,32 @@ -namespace CentrED; +namespace CentrED; -public abstract class BaseTile { +public abstract class BaseTile +{ internal ushort _id; internal ushort _x; internal ushort _y; internal sbyte _z; - public virtual ushort Id { + public virtual ushort Id + { get => _id; set => throw new InvalidOperationException(); } - public virtual ushort X { + public virtual ushort X + { get => _x; set => throw new InvalidOperationException(); } - public virtual ushort Y { + public virtual ushort Y + { get => _y; set => throw new InvalidOperationException(); } - public virtual sbyte Z { + public virtual sbyte Z + { get => _z; set => throw new InvalidOperationException(); } diff --git a/Shared/Block.cs b/Shared/Block.cs index 98cb536..f4753cb 100644 --- a/Shared/Block.cs +++ b/Shared/Block.cs @@ -1,19 +1,23 @@ -namespace CentrED; +namespace CentrED; -public class Block { - public Block(LandBlock land, StaticBlock statics) { +public class Block +{ + public Block(LandBlock land, StaticBlock statics) + { LandBlock = land; StaticBlock = statics; } - + public LandBlock LandBlock { get; } public StaticBlock StaticBlock { get; } - public static int Id(Block block) { + public static int Id(Block block) + { return Id(block.LandBlock.X, block.LandBlock.Y); } - - public static int Id(ushort x, ushort y) { + + public static int Id(ushort x, ushort y) + { return HashCode.Combine(x, y); } } \ No newline at end of file diff --git a/Shared/BlockCache.cs b/Shared/BlockCache.cs index c38a81b..8eaeb31 100644 --- a/Shared/BlockCache.cs +++ b/Shared/BlockCache.cs @@ -1,8 +1,9 @@ using System.Collections.Concurrent; -namespace CentrED; +namespace CentrED; -public class BlockCache { +public class BlockCache +{ public delegate void CacheChanged(Block block); private readonly ConcurrentDictionary blocks; @@ -11,46 +12,58 @@ public class BlockCache { public CacheChanged? OnRemovedItem; public CacheChanged? OnAddedItem; - public BlockCache(int maxSize = 256) { + public BlockCache(int maxSize = 256) + { _maxSize = maxSize; _queue = new ConcurrentQueue(); blocks = new ConcurrentDictionary(); } - public void Add(int id, Block block) { + public void Add(int id, Block block) + { blocks.TryAdd(id, block); _queue.Enqueue(id); - if (blocks.Count > _maxSize) { + if (blocks.Count > _maxSize) + { Dequeue(out _); } } - public void Clear() { - while (!_queue.IsEmpty) { + public void Clear() + { + while (!_queue.IsEmpty) + { Dequeue(out _); } } - public bool Contains(int id) { + public bool Contains(int id) + { return Get(id) != null; } - public Block? Get(int id) { + public Block? Get(int id) + { blocks.TryGetValue(id, out Block? block); return block; } - private bool Dequeue(out Block? block) { + private bool Dequeue(out Block? block) + { block = default; - if (!_queue.TryDequeue(out var id)) return false; - if (!blocks.TryRemove(id, out block)) return false; + if (!_queue.TryDequeue(out var id)) + return false; + if (!blocks.TryRemove(id, out block)) + return false; OnRemovedItem?.Invoke(block); return true; } - public void Resize(int newSize) { + public void Resize(int newSize) + { _maxSize = newSize; - while (blocks.Count > _maxSize) { + while (blocks.Count > _maxSize) + { Dequeue(out _); } } diff --git a/Shared/Enums.cs b/Shared/Enums.cs index deb6603..2cb0407 100644 --- a/Shared/Enums.cs +++ b/Shared/Enums.cs @@ -1,8 +1,9 @@ using System.Xml.Serialization; -namespace CentrED; +namespace CentrED; -public enum LoginState { +public enum LoginState +{ Ok, InvalidUser, InvalidPassword, @@ -10,54 +11,57 @@ public enum LoginState { NoAccess } -public enum ServerState { +public enum ServerState +{ Running, Frozen, Other } -public enum AccessLevel { - [XmlEnum("0")] - None, - [XmlEnum("1")] - View, - [XmlEnum("2")] - Normal, - [XmlEnum("3")] - Developer, - [XmlEnum("255")] - Administrator = 255 +public enum AccessLevel +{ + [XmlEnum("0")] None, + [XmlEnum("1")] View, + [XmlEnum("2")] Normal, + [XmlEnum("3")] Developer, + [XmlEnum("255")] Administrator = 255 } -public enum ModifyUserStatus { +public enum ModifyUserStatus +{ InvalidUsername, Added, Modified } -public enum DeleteUserStatus { +public enum DeleteUserStatus +{ NotFound, Deleted } -public enum ModifyRegionStatus { +public enum ModifyRegionStatus +{ Added, Modified } -public enum DeleteRegionStatus { +public enum DeleteRegionStatus +{ NotFound, Deleted } -public enum PasswordChangeStatus { +public enum PasswordChangeStatus +{ Success, OldPwInvalid, NewPwInvalid, Identical } -public enum ProtocolVersion { +public enum ProtocolVersion +{ CentrED = 6, CentrEDPlus = 0x1008 } \ No newline at end of file diff --git a/Shared/GenericIndex.cs b/Shared/GenericIndex.cs index b1bfb9b..20d480b 100644 --- a/Shared/GenericIndex.cs +++ b/Shared/GenericIndex.cs @@ -1,11 +1,21 @@ namespace CentrED; -public class GenericIndex { +public class GenericIndex +{ public const int Size = 12; - public static GenericIndex Empty => new() { Lookup = 0, Length = -1, Various = 0 }; - public GenericIndex(BinaryReader? reader = null) { - if (reader == null) return; - + + public static GenericIndex Empty => new() + { + Lookup = 0, + Length = -1, + Various = 0 + }; + + public GenericIndex(BinaryReader? reader = null) + { + if (reader == null) + return; + Lookup = reader.ReadInt32(); Length = reader.ReadInt32(); Various = reader.ReadInt32(); @@ -15,7 +25,8 @@ public GenericIndex(BinaryReader? reader = null) { public int Length { get; set; } public int Various { get; init; } - public void Write(BinaryWriter writer) { + public void Write(BinaryWriter writer) + { writer.Write(Lookup); writer.Write(Length); writer.Write(Various); diff --git a/Shared/LandBlock.cs b/Shared/LandBlock.cs index 46bd9b8..5ab2ccd 100644 --- a/Shared/LandBlock.cs +++ b/Shared/LandBlock.cs @@ -1,9 +1,15 @@ namespace CentrED; -public class LandBlock { +public class LandBlock +{ public const int SIZE = 4 + 64 * LandTile.Size; - public static LandBlock Empty(BaseLandscape landscape) => new(landscape) { _header = 0, Tiles = Enumerable.Repeat(LandTile.Empty, 64).ToArray() }; - + + public static LandBlock Empty(BaseLandscape landscape) => new(landscape) + { + _header = 0, + Tiles = Enumerable.Repeat(LandTile.Empty, 64).ToArray() + }; + public BaseLandscape Landscape { get; } public bool Changed { get; set; } public ushort X { get; } @@ -11,27 +17,30 @@ public class LandBlock { public LandTile[] Tiles { get; private init; } = new LandTile[64]; - public LandBlock(BaseLandscape landscape, ushort x = 0, ushort y = 0, BinaryReader? reader = null) { + public LandBlock(BaseLandscape landscape, ushort x = 0, ushort y = 0, BinaryReader? reader = null) + { Landscape = landscape; X = x; Y = y; - if(reader != null) { + if (reader != null) + { _header = reader.ReadInt32(); for (ushort iy = 0; iy < 8; iy++) - for (ushort ix = 0; ix < 8; ix++) - Tiles[iy * 8 + ix] = - new LandTile(reader, this, (ushort)(x * 8 + ix), (ushort)(y * 8 + iy)); + for (ushort ix = 0; ix < 8; ix++) + Tiles[iy * 8 + ix] = new LandTile(reader, this, (ushort)(x * 8 + ix), (ushort)(y * 8 + iy)); } Changed = false; } private int _header; - public void OnChanged() { + public void OnChanged() + { Changed = true; } - public void Write(BinaryWriter writer) { + public void Write(BinaryWriter writer) + { writer.Write(_header); foreach (var tile in Tiles) tile.Write(writer); diff --git a/Shared/LandTile.cs b/Shared/LandTile.cs index 79fdde2..d56d801 100644 --- a/Shared/LandTile.cs +++ b/Shared/LandTile.cs @@ -1,48 +1,58 @@ namespace CentrED; -public class LandTile : BaseTile { +public class LandTile : BaseTile +{ public const int Size = 3; public static LandTile Empty => new(0, 0, 0, 0); - public LandTile(ushort id, ushort x, ushort y, sbyte z) { + public LandTile(ushort id, ushort x, ushort y, sbyte z) + { _id = id; _x = x; _y = y; _z = z; } - public LandTile(BinaryReader reader, LandBlock? block = null, ushort x = 0, ushort y = 0) { + public LandTile(BinaryReader reader, LandBlock? block = null, ushort x = 0, ushort y = 0) + { Block = block; _id = reader.ReadUInt16(); _x = x; _y = y; _z = reader.ReadSByte(); } - + public LandBlock? Block { get; } - public override ushort Id { + public override ushort Id + { get => _id; - set { - if (_id != value) { + set + { + if (_id != value) + { Block?.Landscape.OnLandReplaced(this, value); - Block?.OnChanged(); + Block?.OnChanged(); } } } - public override sbyte Z { + public override sbyte Z + { get => _z; - set { - if (_z != value) { + set + { + if (_z != value) + { Block?.Landscape.OnLandElevated(this, value); - Block?.OnChanged(); + Block?.OnChanged(); } } } - public void Write(BinaryWriter writer) { + public void Write(BinaryWriter writer) + { writer.Write(_id); writer.Write(_z); } diff --git a/Shared/MulEntry.cs b/Shared/MulEntry.cs index 16761e5..1cd0a36 100644 --- a/Shared/MulEntry.cs +++ b/Shared/MulEntry.cs @@ -1,6 +1,7 @@ -namespace CentrED; +namespace CentrED; -public abstract class MulEntry { +public abstract class MulEntry +{ public int Id { get; set; } public abstract void Write(BinaryWriter writer); } \ No newline at end of file diff --git a/Shared/MulProvider.cs b/Shared/MulProvider.cs index 995c52b..0176b17 100644 --- a/Shared/MulProvider.cs +++ b/Shared/MulProvider.cs @@ -1,13 +1,15 @@ using System.Text; -namespace CentrED; +namespace CentrED; -public abstract class MulProvider{ - protected MulProvider(String filePath) { +public abstract class MulProvider +{ + protected MulProvider(String filePath) + { Stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); Reader = new BinaryReader(Stream, Encoding.UTF8); } - + protected FileStream Stream { get; } protected BinaryReader Reader { get; } } \ No newline at end of file diff --git a/Shared/Network/AreaInfo.cs b/Shared/Network/AreaInfo.cs index 8f2172d..40c0264 100644 --- a/Shared/Network/AreaInfo.cs +++ b/Shared/Network/AreaInfo.cs @@ -3,8 +3,10 @@ namespace CentrED.Network; [StructLayout(LayoutKind.Sequential, Pack = 1)] -public struct AreaInfo { - public AreaInfo(BinaryReader reader) { +public struct AreaInfo +{ + public AreaInfo(BinaryReader reader) + { var left = reader.ReadUInt16(); var top = reader.ReadUInt16(); var right = reader.ReadUInt16(); @@ -14,13 +16,14 @@ public AreaInfo(BinaryReader reader) { Right = Math.Max(left, right); Bottom = Math.Max(top, bottom); } - + public ushort Left { get; set; } public ushort Top { get; set; } public ushort Right { get; set; } public ushort Bottom { get; set; } - public void Serialize(BinaryWriter writer) { + public void Serialize(BinaryWriter writer) + { writer.Write(Left); writer.Write(Top); writer.Write(Right); diff --git a/Shared/Network/BlockCoords.cs b/Shared/Network/BlockCoords.cs index 2638a51..b8a5791 100644 --- a/Shared/Network/BlockCoords.cs +++ b/Shared/Network/BlockCoords.cs @@ -1,13 +1,16 @@ -namespace CentrED.Network; +namespace CentrED.Network; -public record BlockCoords(ushort X, ushort Y) { - public BlockCoords(BinaryReader reader) : this(0, 0) { +public record BlockCoords(ushort X, ushort Y) +{ + public BlockCoords(BinaryReader reader) : this(0, 0) + { X = reader.ReadUInt16(); Y = reader.ReadUInt16(); } - public void Write(BinaryWriter writer) { + public void Write(BinaryWriter writer) + { writer.Write(X); writer.Write(Y); } -}; +}; \ No newline at end of file diff --git a/Shared/Network/LargeScaleOperation.cs b/Shared/Network/LargeScaleOperation.cs index 4df6641..e647820 100644 --- a/Shared/Network/LargeScaleOperation.cs +++ b/Shared/Network/LargeScaleOperation.cs @@ -1,15 +1,23 @@ -namespace CentrED.Network; +namespace CentrED.Network; -public class LargeScaleOperation { - public enum CopyMove { - Copy = 0, Move = 1 +public class LargeScaleOperation +{ + public enum CopyMove + { + Copy = 0, + Move = 1 } - public enum SetAltitude { - Terrain = 1, Relative = 2 + public enum SetAltitude + { + Terrain = 1, + Relative = 2 } - public enum StaticsPlacement { - Terrain = 1, Top = 2, Fix = 3 + public enum StaticsPlacement + { + Terrain = 1, + Top = 2, + Fix = 3 } } \ No newline at end of file diff --git a/Shared/Network/NetState.cs b/Shared/Network/NetState.cs index 7d93ae6..b7f21ec 100644 --- a/Shared/Network/NetState.cs +++ b/Shared/Network/NetState.cs @@ -1,9 +1,10 @@ using System.Net.Sockets; using CentrED.Utility; -namespace CentrED.Network; +namespace CentrED.Network; -public class NetState : IDisposable where T : BaseCentrED { +public class NetState : IDisposable where T : BaseCentrED +{ private readonly Socket _socket; internal PacketHandler?[] PacketHandlers { get; } @@ -20,43 +21,52 @@ public class NetState : IDisposable where T : BaseCentrED { public bool FlushPending { get; private set; } = false; public bool Active => LastAction > DateTime.Now - TimeSpan.FromMinutes(2); private const int RECV_BUFFER_CAPACITY = 65536; - - public NetState(T parent, Socket socket, PacketHandler?[] packetHandlers) { + + public NetState(T parent, Socket socket, PacketHandler?[] packetHandlers) + { Parent = parent; _socket = socket; PacketHandlers = packetHandlers; - + _recvStream = new MemoryStream(socket.ReceiveBufferSize); _recvBuffer = new byte[RECV_BUFFER_CAPACITY]; _recvReader = new BinaryReader(_recvStream); - + _sendStream = new MemoryStream(socket.SendBufferSize); - + Username = ""; LastAction = DateTime.Now; } - ~NetState() { + ~NetState() + { Dispose(false); } - - public bool Receive() { - try { - if (PollAndPeek()) { - if (_socket.Available > 0) { + + public bool Receive() + { + try + { + if (PollAndPeek()) + { + if (_socket.Available > 0) + { var bytesRead = _socket.Receive(_recvBuffer, SocketFlags.None); - if (bytesRead > 0) { + if (bytesRead > 0) + { _recvStream.Seek(0, SeekOrigin.End); _recvStream.Write(_recvBuffer, 0, bytesRead); ProcessBuffer(); } } } - else { + else + { Disconnect(); } } - catch (Exception e) { + catch (Exception e) + { LogError("Receive error"); Console.WriteLine(e); Disconnect(); @@ -64,45 +74,56 @@ public bool Receive() { return Running; } - - private void ProcessBuffer() { - try { + + private void ProcessBuffer() + { + try + { _recvStream.Position = 0; - while (_recvStream.Length >= 1) { + while (_recvStream.Length >= 1) + { var packetId = _recvReader.ReadByte(); var packetHandler = PacketHandlers[packetId]; - if (packetHandler != null) { + if (packetHandler != null) + { var size = packetHandler.Length; - if (size == 0) { - if (_recvStream.Length <= 5) { + if (size == 0) + { + if (_recvStream.Length <= 5) + { break; //wait for more data } size = _recvReader.ReadUInt32(); } - if (_recvStream.Length >= size) { + if (_recvStream.Length >= size) + { var buffer = _recvStream.Dequeue((int)_recvStream.Position, (int)(size - _recvStream.Position)); using var packetReader = new BinaryReader(new MemoryStream(buffer)); packetHandler.OnReceive(packetReader, this); } - else { + else + { break; //wait for more data } } - else { + else + { LogError($"Unknown packet: {packetId}"); Disconnect(); } } LastAction = DateTime.Now; } - catch (Exception e) { + catch (Exception e) + { LogError("ProcessBuffer error"); Console.WriteLine(e); Disconnect(); } } - - public void Send(Packet packet) { + + public void Send(Packet packet) + { try { _sendStream.Write(packet.Compile(out _)); @@ -114,20 +135,25 @@ public void Send(Packet packet) { Disconnect(); } - if (!FlushPending) { + if (!FlushPending) + { FlushPending = true; } } - public bool Flush() { - try { + public bool Flush() + { + try + { _sendStream.Position = 0; - if (_sendStream.Length > 0) { + if (_sendStream.Length > 0) + { var buffer = new byte[_sendStream.Length]; var bytesCount = _sendStream.Read(buffer); var bytesSent = _socket.Send(buffer, 0, bytesCount, SocketFlags.None); _sendStream.Dequeue(0, bytesSent); - if (_sendStream.Length == 0) { + if (_sendStream.Length == 0) + { FlushPending = false; } } @@ -143,71 +169,89 @@ public bool Flush() { return Running; } - private bool PollAndPeek() { - try { - if (!_socket.Connected) + private bool PollAndPeek() + { + try + { + if (!_socket.Connected) return false; - if (!_socket.Poll(0, SelectMode.SelectRead)) + if (!_socket.Poll(0, SelectMode.SelectRead)) return true; - + var buff = new byte[1]; return _socket.Receive(buff, SocketFlags.Peek) != 0; } - catch { + catch + { return false; } } - public void Disconnect() { + public void Disconnect() + { Running = false; } - public void Dispose() { + public void Dispose() + { Dispose(true); GC.SuppressFinalize(this); } - - public void Dispose(bool disposing) { + + public void Dispose(bool disposing) + { Disconnect(); - if (disposing) { - if (!_socket.Connected) return; + if (disposing) + { + if (!_socket.Connected) + return; LogInfo("Disconnecting"); Username = ""; - try { + try + { _socket.Shutdown(SocketShutdown.Both); } - catch (SocketException e) { + catch (SocketException e) + { LogError(e.ToString()); } - try { + try + { _socket.Close(); } - catch (SocketException e) { + catch (SocketException e) + { LogError(e.ToString()); } } } - - public void LogInfo(string log) { + + public void LogInfo(string log) + { Parent._logger.LogInfo(LogMessage(log)); } - public void LogError(string log) { + public void LogError(string log) + { Parent._logger.LogError(LogMessage(log)); } - public void LogDebug(string log) { + public void LogDebug(string log) + { Parent._logger.LogDebug(LogMessage(log)); } - private string LogMessage(string log) { + private string LogMessage(string log) + { string endpoint; - try { + try + { endpoint = _socket.RemoteEndPoint!.ToString()!; } - catch (Exception) { + catch (Exception) + { endpoint = ""; } return $"{Username}@{endpoint} {log}"; diff --git a/Shared/Network/Packet.cs b/Shared/Network/Packet.cs index 2860f96..7577f6d 100644 --- a/Shared/Network/Packet.cs +++ b/Shared/Network/Packet.cs @@ -1,23 +1,27 @@ -namespace CentrED.Network; +namespace CentrED.Network; -public class Packet { +public class Packet +{ public Stream Stream { get; } public BinaryWriter Writer { get; } private byte PacketId { get; } private uint Length { get; } - public Packet(byte packetId, uint length) { + public Packet(byte packetId, uint length) + { Stream = new MemoryStream(); Writer = new BinaryWriter(Stream); PacketId = packetId; Length = length; Writer.Write(packetId); - if(Length == 0) + if (Length == 0) Writer.Write(Length); } - public byte[] Compile(out int length) { - if (Length == 0) { + public byte[] Compile(out int length) + { + if (Length == 0) + { Writer.Seek(1, SeekOrigin.Begin); Writer.Write((uint)Stream.Length); } diff --git a/Shared/Network/PacketHandler.cs b/Shared/Network/PacketHandler.cs index 26dfd31..30d9e19 100644 --- a/Shared/Network/PacketHandler.cs +++ b/Shared/Network/PacketHandler.cs @@ -1,13 +1,15 @@ -namespace CentrED.Network; +namespace CentrED.Network; -public class PacketHandler where T : BaseCentrED { +public class PacketHandler where T : BaseCentrED +{ public delegate void PacketProcessor(BinaryReader reader, NetState ns); - + public uint Length { get; } - + public PacketProcessor OnReceive { get; } - public PacketHandler(uint length, PacketProcessor packetProcessor) { + public PacketHandler(uint length, PacketProcessor packetProcessor) + { Length = length; OnReceive = packetProcessor; } diff --git a/Shared/Network/PacketHandlers.cs b/Shared/Network/PacketHandlers.cs index f094f37..9fdf0fd 100644 --- a/Shared/Network/PacketHandlers.cs +++ b/Shared/Network/PacketHandlers.cs @@ -1,9 +1,11 @@ using System.IO.Compression; -namespace CentrED.Network; +namespace CentrED.Network; -public static class PacketHandlers { - public static void OnCompressedPacket(BinaryReader buffer, NetState ns) where T : BaseCentrED { +public static class PacketHandlers +{ + public static void OnCompressedPacket(BinaryReader buffer, NetState ns) where T : BaseCentrED + { ns.LogDebug("OnCompressedPacket"); var targetSize = (int)buffer.ReadUInt32(); var zLibStream = new ZLibStream(buffer.BaseStream, CompressionMode.Decompress); @@ -15,14 +17,17 @@ public static void OnCompressedPacket(BinaryReader buffer, NetState ns) wh using var reader = new BinaryReader(rawData); var packetId = reader.ReadByte(); var handler = ns.PacketHandlers[packetId]; - if (handler != null) { + if (handler != null) + { var size = handler.Length; - if (size == 0) { + if (size == 0) + { size = reader.ReadUInt32(); } handler.OnReceive(reader, ns); } - else { + else + { ns.LogError($"Dropping client due to unknown packet: {packetId}"); ns.Disconnect(); } diff --git a/Shared/Network/Packets.cs b/Shared/Network/Packets.cs index 2db9a76..34aadfe 100644 --- a/Shared/Network/Packets.cs +++ b/Shared/Network/Packets.cs @@ -1,11 +1,14 @@ using System.IO.Compression; -namespace CentrED.Network; +namespace CentrED.Network; -public class CompressedPacket : Packet { - public CompressedPacket(Packet packet) : base(0x01, 0) { +public class CompressedPacket : Packet +{ + public CompressedPacket(Packet packet) : base(0x01, 0) + { var compressedData = new MemoryStream(); - using var zLibStream = new ZLibStream(compressedData, CompressionLevel.Optimal); //SmallestSize level seems to be slow + using var zLibStream = new ZLibStream + (compressedData, CompressionLevel.Optimal); //SmallestSize level seems to be slow var bytes = packet.Compile(out var length); zLibStream.Write(bytes); zLibStream.Flush(); @@ -13,4 +16,4 @@ public CompressedPacket(Packet packet) : base(0x01, 0) { Writer.Write((uint)packet.Stream.Length); Writer.Write(compressedData.GetBuffer()); } -} +} \ No newline at end of file diff --git a/Shared/Network/Rect.cs b/Shared/Network/Rect.cs index 3ab4a17..d6df903 100644 --- a/Shared/Network/Rect.cs +++ b/Shared/Network/Rect.cs @@ -1,20 +1,23 @@ using System.Xml.Serialization; -namespace CentrED.Network; +namespace CentrED.Network; -public class Rect { - public Rect() : this(0,0,0,0) { - +public class Rect +{ + public Rect() : this(0, 0, 0, 0) + { } - public Rect(ushort x1, ushort y1, ushort x2, ushort y2) { + public Rect(ushort x1, ushort y1, ushort x2, ushort y2) + { X1 = Math.Min(x1, x2); X2 = Math.Max(x1, x2); Y1 = Math.Min(y1, y2); Y2 = Math.Max(y1, y2); } - public Rect(BinaryReader reader) { + public Rect(BinaryReader reader) + { X1 = reader.ReadUInt16(); Y1 = reader.ReadUInt16(); X2 = reader.ReadUInt16(); @@ -26,11 +29,13 @@ public Rect(BinaryReader reader) { [XmlAttribute("y1")] public uint Y1 { get; set; } [XmlAttribute("y2")] public uint Y2 { get; set; } - public bool Contains(uint x, uint y) { + public bool Contains(uint x, uint y) + { return x >= X1 && x < X2 && y >= Y1 && y < Y2; } - public void Write(BinaryWriter writer) { + public void Write(BinaryWriter writer) + { writer.Write(X1); writer.Write(Y1); writer.Write(X2); diff --git a/Shared/Network/StaticInfo.cs b/Shared/Network/StaticInfo.cs index 5bba124..f160352 100644 --- a/Shared/Network/StaticInfo.cs +++ b/Shared/Network/StaticInfo.cs @@ -1,23 +1,27 @@ using System.Runtime.InteropServices; -namespace CentrED.Network; +namespace CentrED.Network; [StructLayout(LayoutKind.Sequential, Pack = 1)] -public readonly struct StaticInfo { - public StaticInfo(BinaryReader reader) { +public readonly struct StaticInfo +{ + public StaticInfo(BinaryReader reader) + { X = reader.ReadUInt16(); Y = reader.ReadUInt16(); Z = reader.ReadSByte(); Id = reader.ReadUInt16(); Hue = reader.ReadUInt16(); } + public ushort X { get; } public ushort Y { get; } public sbyte Z { get; } public ushort Id { get; } public ushort Hue { get; } - - public void Serialize(BinaryWriter writer) { + + public void Serialize(BinaryWriter writer) + { writer.Write(X); writer.Write(Y); writer.Write(Z); @@ -25,7 +29,8 @@ public void Serialize(BinaryWriter writer) { writer.Write(Hue); } - public override string ToString() { + public override string ToString() + { return $"{Id}:{X},{Y},{Z} {Hue}"; } } \ No newline at end of file diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj index a42f55a..634d9a4 100644 --- a/Shared/Shared.csproj +++ b/Shared/Shared.csproj @@ -1,18 +1,18 @@ - - net7.0 - enable - enable - 11 - centredlib - CentrED - + + net7.0 + enable + enable + 11 + centredlib + CentrED + - - - ..\lib\x64\ClassicUO.Assets.dll - - + + + ..\lib\x64\ClassicUO.Assets.dll + + diff --git a/Shared/StaticBlock.cs b/Shared/StaticBlock.cs index 66324cb..ce51561 100644 --- a/Shared/StaticBlock.cs +++ b/Shared/StaticBlock.cs @@ -2,25 +2,30 @@ namespace CentrED; -public class StaticBlock { +public class StaticBlock +{ public BaseLandscape Landscape { get; } public bool Changed { get; set; } public ushort X { get; } public ushort Y { get; } - - public StaticBlock(BaseLandscape landscape, BinaryReader? reader = null, GenericIndex? index = null, ushort x = 0, ushort y = 0) { + + public StaticBlock + (BaseLandscape landscape, BinaryReader? reader = null, GenericIndex? index = null, ushort x = 0, ushort y = 0) + { Landscape = landscape; X = x; Y = y; - _tiles = new List[8,8]; - - if (reader != null && index?.Lookup >= 0 && index.Length > 0) { + _tiles = new List[8, 8]; + + if (reader != null && index?.Lookup >= 0 && index.Length > 0) + { reader.BaseStream.Position = index.Lookup; - for (var i = 0; i < index.Length / 7; i++) { + for (var i = 0; i < index.Length / 7; i++) + { AddTileInternal(new StaticTile(reader, this, x, y)); } } - + Changed = false; } @@ -30,11 +35,15 @@ public StaticBlock(BaseLandscape landscape, BinaryReader? reader = null, Generic public int TotalSize => TotalTilesCount * StaticTile.Size; - public IEnumerable AllTiles() { - foreach (var staticTiles in _tiles) { - if (staticTiles == null) continue; - - foreach (var staticTile in staticTiles) { + public IEnumerable AllTiles() + { + foreach (var staticTiles in _tiles) + { + if (staticTiles == null) + continue; + + foreach (var staticTile in staticTiles) + { yield return staticTile; } } @@ -43,28 +52,33 @@ public IEnumerable AllTiles() { public IEnumerable GetTiles(ushort x, ushort y) => EnsureTiles(x, y).AsReadOnly(); - public void AddTile(StaticTile tile) { + public void AddTile(StaticTile tile) + { AddTileInternal(tile); Landscape.OnStaticTileAdded(tile); } - internal void AddTileInternal(StaticTile tile) { + internal void AddTileInternal(StaticTile tile) + { EnsureTiles(tile.LocalX, tile.LocalY).Add(tile); TotalTilesCount++; tile.Block = this; Changed = true; } - - public bool RemoveTile(StaticTile tile) { + + public bool RemoveTile(StaticTile tile) + { var result = RemoveTileInternal(tile); - if(result) + if (result) Landscape.OnStaticTileRemoved(tile); return result; } - internal bool RemoveTileInternal(StaticTile tile) { + internal bool RemoveTileInternal(StaticTile tile) + { var removed = EnsureTiles(tile.LocalX, tile.LocalY).Remove(tile); - if (removed) { + if (removed) + { tile.Block = null; TotalTilesCount--; } @@ -72,31 +86,41 @@ internal bool RemoveTileInternal(StaticTile tile) { return removed; } - public void SortTiles(ref StaticTiles[] tiledata) { - foreach (var staticTiles in _tiles) { - if(staticTiles == null) continue; + public void SortTiles(ref StaticTiles[] tiledata) + { + foreach (var staticTiles in _tiles) + { + if (staticTiles == null) + continue; var i = staticTiles.Count; - foreach (var tile in staticTiles) { + foreach (var tile in staticTiles) + { tile.UpdatePriority(tiledata[tile.Id], i--); } - staticTiles.Sort((tile1, tile2) => tile1.PriorityZ.CompareTo(tile2.PriorityZ) ); + staticTiles.Sort((tile1, tile2) => tile1.PriorityZ.CompareTo(tile2.PriorityZ)); } } - - public void OnChanged() { + + public void OnChanged() + { Changed = true; } - - public void Write(BinaryWriter writer) { - foreach (var staticTiles in _tiles) { - if(staticTiles == null) continue; - foreach (var staticTile in staticTiles) { + + public void Write(BinaryWriter writer) + { + foreach (var staticTiles in _tiles) + { + if (staticTiles == null) + continue; + foreach (var staticTile in staticTiles) + { staticTile.Write(writer); } } } - - private List EnsureTiles(ushort x, ushort y) { + + private List EnsureTiles(ushort x, ushort y) + { var result = _tiles[x & 0x7, y & 0x7] ??= new List(); return result; } diff --git a/Shared/StaticTile.cs b/Shared/StaticTile.cs index fb3253b..7f86486 100644 --- a/Shared/StaticTile.cs +++ b/Shared/StaticTile.cs @@ -3,28 +3,33 @@ namespace CentrED; -public class StaticTile: BaseTile, IEquatable, IEquatable { +public class StaticTile : BaseTile, IEquatable, IEquatable +{ public const int Size = 7; - + private StaticBlock? _block; - + internal ushort _hue; - public StaticTile(StaticInfo si) : this(si.Id, si.X, si.Y, si.Z, si.Hue) { } - - public StaticTile(ushort id, ushort x, ushort y, sbyte z, ushort hue, StaticBlock? block = null) { + public StaticTile(StaticInfo si) : this(si.Id, si.X, si.Y, si.Z, si.Hue) + { + } + + public StaticTile(ushort id, ushort x, ushort y, sbyte z, ushort hue, StaticBlock? block = null) + { _block = block; _id = id; _x = x; _y = y; _z = z; _hue = hue; - + LocalX = (byte)(x & 0x7); LocalY = (byte)(y & 0x7); } - public StaticTile(BinaryReader reader, StaticBlock? block = null, ushort blockX = 0, ushort blockY = 0) { + public StaticTile(BinaryReader reader, StaticBlock? block = null, ushort blockX = 0, ushort blockY = 0) + { _block = block; _id = reader.ReadUInt16(); LocalX = reader.ReadByte(); @@ -35,86 +40,110 @@ public StaticTile(BinaryReader reader, StaticBlock? block = null, ushort blockX _x = (ushort)(blockX * 8 + LocalX); _y = (ushort)(blockY * 8 + LocalY); } - - public StaticBlock? Block { + + public StaticBlock? Block + { get => _block; internal set => _block = value; } - - public override ushort Id { + + public override ushort Id + { get => _id; - set { - if (_id != value) { + set + { + if (_id != value) + { OnTileIdChanged(value); _block?.OnChanged(); } } } - - public override ushort X { + + public override ushort X + { get => _x; - set { - if (_x != value) { + set + { + if (_x != value) + { OnTilePosChanged(value, _y); _block?.OnChanged(); } - } + } } - public override ushort Y { + + public override ushort Y + { get => _y; - set { - if (_y != value) { + set + { + if (_y != value) + { OnTilePosChanged(_x, value); _block?.OnChanged(); } - } + } } - - public override sbyte Z { + + public override sbyte Z + { get => _z; - set { - if (_z != value) { + set + { + if (_z != value) + { OnTileZChanged(value); _block?.OnChanged(); } } } - - public ushort Hue { + + public ushort Hue + { get => _hue; - set { - if (_hue != value) { + set + { + if (_hue != value) + { OnTileHueChanged(value); _block?.OnChanged(); } } } - + public byte LocalX { get; internal set; } public byte LocalY { get; internal set; } - + public int PriorityZ { get; private set; } public int CellIndex { get; private set; } - public void UpdatePos(ushort newX, ushort newY, sbyte newZ) { - if (_x != newX || _y != newY) { + public void UpdatePos(ushort newX, ushort newY, sbyte newZ) + { + if (_x != newX || _y != newY) + { OnTilePosChanged(newX, newY); } - if (_z != newZ) { + if (_z != newZ) + { OnTileZChanged(newZ); } _block?.OnChanged(); } - public void UpdatePriority(StaticTiles tileData, int cellIndex) { + public void UpdatePriority(StaticTiles tileData, int cellIndex) + { CellIndex = cellIndex; PriorityZ = _z; - if (tileData.IsBackground) PriorityZ--; - if (tileData.Height > 0) PriorityZ++; + if (tileData.IsBackground) + PriorityZ--; + if (tileData.Height > 0) + PriorityZ++; } - - public void Write(BinaryWriter writer) { + + public void Write(BinaryWriter writer) + { writer.Write(_id); writer.Write(LocalX); writer.Write(LocalY); @@ -122,39 +151,43 @@ public void Write(BinaryWriter writer) { writer.Write(_hue); } - public bool Equals(BaseTile? other) { + public bool Equals(BaseTile? other) + { if (other is StaticTile staticTile) return Equals(staticTile); return false; } - - public bool Equals(StaticTile? other) { - return other != null && - _id == other._id && - _x == other._x && - _y == other._y && - _z == other._z && + + public bool Equals(StaticTile? other) + { + return other != null && _id == other._id && _x == other._x && _y == other._y && _z == other._z && _hue == other._hue; } - + public bool Match(StaticInfo si) => si.Z == Z && si.Id == Id && si.Hue == Hue; - private void OnTileIdChanged(ushort newId) { + private void OnTileIdChanged(ushort newId) + { _block?.Landscape.OnStaticTileReplaced(this, newId); } - private void OnTilePosChanged(ushort newX, ushort newY) { + + private void OnTilePosChanged(ushort newX, ushort newY) + { _block?.Landscape.OnStaticTileMoved(this, newX, newY); } - private void OnTileZChanged(sbyte newZ) { + private void OnTileZChanged(sbyte newZ) + { _block?.Landscape.OnStaticTileElevated(this, newZ); } - private void OnTileHueChanged(ushort newHue) { + private void OnTileHueChanged(ushort newHue) + { _block?.Landscape.OnStaticTileHued(this, newHue); } - - public override string ToString() { + + public override string ToString() + { return $"{Id}:{X},{Y},{Z} {Hue}"; } } \ No newline at end of file diff --git a/Shared/TileData.cs b/Shared/TileData.cs index bc4746b..2130948 100644 --- a/Shared/TileData.cs +++ b/Shared/TileData.cs @@ -1,22 +1,27 @@ namespace CentrED; -public abstract class TileData : MulEntry{ - protected TileData(TileDataVersion tileDataVersion) { +public abstract class TileData : MulEntry +{ + protected TileData(TileDataVersion tileDataVersion) + { Version = tileDataVersion; } - + protected TileDataVersion Version; public TiledataFlag Flags { get; set; } public string TileName { get; set; } = ""; - - protected void ReadFlags(BinaryReader reader) { - Flags = Version switch { + + protected void ReadFlags(BinaryReader reader) + { + Flags = Version switch + { TileDataVersion.HighSeas => (TiledataFlag)reader.ReadUInt64(), _ => (TiledataFlag)reader.ReadUInt32() }; } - protected void WriteFlags(BinaryWriter writer) { + protected void WriteFlags(BinaryWriter writer) + { writer.Write((ulong)Flags); } } \ No newline at end of file diff --git a/Shared/TileDataFlag.cs b/Shared/TileDataFlag.cs index 0f213e2..4aabc72 100644 --- a/Shared/TileDataFlag.cs +++ b/Shared/TileDataFlag.cs @@ -1,261 +1,262 @@ namespace CentrED; [Flags] -public enum TiledataFlag : ulong { - /// - /// Nothing is flagged. - /// - None = 0x00000000, - /// - /// Not yet documented. - /// - Background = 0x00000001, - /// - /// Not yet documented. - /// - Weapon = 0x00000002, - /// - /// Not yet documented. - /// - Transparent = 0x00000004, - /// - /// The tile is rendered with partial alpha-transparency. - /// - Translucent = 0x00000008, - /// - /// The tile is a wall. - /// - Wall = 0x00000010, - /// - /// The tile can cause damage when moved over. - /// - Damaging = 0x00000020, - /// - /// The tile may not be moved over or through. - /// - Impassable = 0x00000040, - /// - /// Not yet documented. - /// - Wet = 0x00000080, - /// - /// Unknown. - /// - Unknown1 = 0x00000100, - /// - /// The tile is a surface. It may be moved over, but not through. - /// - Surface = 0x00000200, - /// - /// The tile is a stair, ramp, or ladder. - /// - Bridge = 0x00000400, - /// - /// The tile is stackable - /// - Generic = 0x00000800, - /// - /// The tile is a window. Like , tiles with this flag block line of sight. - /// - Window = 0x00001000, - /// - /// The tile blocks line of sight. - /// - NoShoot = 0x00002000, - /// - /// For single-amount tiles, the string "a " should be prepended to the tile name. - /// - ArticleA = 0x00004000, - /// - /// For single-amount tiles, the string "an " should be prepended to the tile name. - /// - ArticleAn = 0x00008000, - /// - /// Probably article The prepended to the tile name. - /// - ArticleThe = 0x00010000, - /// - /// The tile becomes translucent when walked behind. Boat masts also have this flag. - /// - Foliage = 0x00020000, - /// - /// Only gray pixels will be hued - /// - PartialHue = 0x00040000, - /// - /// NoHouse or Unknown. Needs further research. - /// - NoHouse = 0x00080000, - /// - /// The tile is a map--in the cartography sense. Unknown usage. - /// - Map = 0x00100000, - /// - /// The tile is a container. - /// - Container = 0x00200000, - /// - /// The tile may be equipped. - /// - Wearable = 0x00400000, - /// - /// The tile gives off light. - /// - LightSource = 0x00800000, - /// - /// The tile is animated. - /// - Animation = 0x01000000, - /// - /// Gargoyles can fly over or NoDiagonal - /// - HoverOver = 0x02000000, - /// - /// NoDiagonal (Unknown3). - /// - NoDiagonal = 0x04000000, - /// - /// Not yet documented. - /// - Armor = 0x08000000, - /// - /// The tile is a slanted roof. - /// - Roof = 0x10000000, - /// - /// The tile is a door. Tiles with this flag can be moved through by ghosts and GMs. - /// - Door = 0x20000000, - /// - /// Not yet documented. - /// - StairBack = 0x40000000, - /// - /// Not yet documented. - /// - StairRight = 0x80000000, - /// - /// Blend Alphas, tile blending. - /// - AlphaBlend = 0x0100000000, - /// - /// Uses new art style? Something related to the nodraw tile? - /// - UseNewArt = 0x0200000000, - /// - /// Has art being used? - /// - ArtUsed = 0x0400000000, - /// - /// Unused8 ?? - /// - Unused8 = 0x08000000000, - /// - /// Disallow shadow on this tile, lightsource? lava? - /// - NoShadow = 0x1000000000, - /// - /// Let pixels bleed in to other tiles? Is this Disabling Texture Clamp? - /// - PixelBleed = 0x2000000000, - /// - /// Play tile animation once. - /// - PlayAnimOnce = 0x4000000000, - /// - /// Movable multi? Cool ships and vehicles etc? Something related to the masts ??? - /// - MultiMovable = 0x10000000000, - /// - /// Unused10 - /// - Unused10 = 0x20000000000, - /// - /// Unused11 - /// - Unused11 = 0x40000000000, - /// - /// Unused12 - /// - Unused12 = 0x80000000000, - /// - /// Unused13 - /// - Unused13 = 0x100000000000, - /// - /// Unused14 - /// - Unused14 = 0x200000000000, - /// - /// Unused15 - /// - Unused15 = 0x400000000000, - /// - /// Unused16 - /// - Unused16 = 0x800000000000, - /// - /// Unused17 - /// - Unused17 = 0x1000000000000, - /// - /// Unused18 - /// - Unused18 = 0x2000000000000, - /// - /// Unused19 - /// - Unused19 = 0x4000000000000, - /// - /// Unused20 - /// - Unused20 = 0x8000000000000, - /// - /// Unused21 - /// - Unused21 = 0x10000000000000, - /// - /// Unused22 - /// - Unused22 = 0x20000000000000, - /// - /// Unused23 - /// - Unused23 = 0x40000000000000, - /// - /// Unused24 - /// - Unused24 = 0x80000000000000, - /// - /// Unused25 - /// - Unused25 = 0x100000000000000, - /// - /// Unused26 - /// - Unused26 = 0x200000000000000, - /// - /// Unused27 - /// - Unused27 = 0x400000000000000, - /// - /// Unused28 - /// - Unused28 = 0x800000000000000, - /// - /// Unused29 - /// - Unused29 = 0x1000000000000000, - /// - /// Unused30 - /// - Unused30 = 0x2000000000000000, - /// - /// Unused31 - /// - Unused31 = 0x4000000000000000, - /// - /// Unused32 - /// - Unused32 = 0x8000000000000000 +public enum TiledataFlag : ulong +{ + /// + /// Nothing is flagged. + /// + None = 0x00000000, + /// + /// Not yet documented. + /// + Background = 0x00000001, + /// + /// Not yet documented. + /// + Weapon = 0x00000002, + /// + /// Not yet documented. + /// + Transparent = 0x00000004, + /// + /// The tile is rendered with partial alpha-transparency. + /// + Translucent = 0x00000008, + /// + /// The tile is a wall. + /// + Wall = 0x00000010, + /// + /// The tile can cause damage when moved over. + /// + Damaging = 0x00000020, + /// + /// The tile may not be moved over or through. + /// + Impassable = 0x00000040, + /// + /// Not yet documented. + /// + Wet = 0x00000080, + /// + /// Unknown. + /// + Unknown1 = 0x00000100, + /// + /// The tile is a surface. It may be moved over, but not through. + /// + Surface = 0x00000200, + /// + /// The tile is a stair, ramp, or ladder. + /// + Bridge = 0x00000400, + /// + /// The tile is stackable + /// + Generic = 0x00000800, + /// + /// The tile is a window. Like , tiles with this flag block line of sight. + /// + Window = 0x00001000, + /// + /// The tile blocks line of sight. + /// + NoShoot = 0x00002000, + /// + /// For single-amount tiles, the string "a " should be prepended to the tile name. + /// + ArticleA = 0x00004000, + /// + /// For single-amount tiles, the string "an " should be prepended to the tile name. + /// + ArticleAn = 0x00008000, + /// + /// Probably article The prepended to the tile name. + /// + ArticleThe = 0x00010000, + /// + /// The tile becomes translucent when walked behind. Boat masts also have this flag. + /// + Foliage = 0x00020000, + /// + /// Only gray pixels will be hued + /// + PartialHue = 0x00040000, + /// + /// NoHouse or Unknown. Needs further research. + /// + NoHouse = 0x00080000, + /// + /// The tile is a map--in the cartography sense. Unknown usage. + /// + Map = 0x00100000, + /// + /// The tile is a container. + /// + Container = 0x00200000, + /// + /// The tile may be equipped. + /// + Wearable = 0x00400000, + /// + /// The tile gives off light. + /// + LightSource = 0x00800000, + /// + /// The tile is animated. + /// + Animation = 0x01000000, + /// + /// Gargoyles can fly over or NoDiagonal + /// + HoverOver = 0x02000000, + /// + /// NoDiagonal (Unknown3). + /// + NoDiagonal = 0x04000000, + /// + /// Not yet documented. + /// + Armor = 0x08000000, + /// + /// The tile is a slanted roof. + /// + Roof = 0x10000000, + /// + /// The tile is a door. Tiles with this flag can be moved through by ghosts and GMs. + /// + Door = 0x20000000, + /// + /// Not yet documented. + /// + StairBack = 0x40000000, + /// + /// Not yet documented. + /// + StairRight = 0x80000000, + /// + /// Blend Alphas, tile blending. + /// + AlphaBlend = 0x0100000000, + /// + /// Uses new art style? Something related to the nodraw tile? + /// + UseNewArt = 0x0200000000, + /// + /// Has art being used? + /// + ArtUsed = 0x0400000000, + /// + /// Unused8 ?? + /// + Unused8 = 0x08000000000, + /// + /// Disallow shadow on this tile, lightsource? lava? + /// + NoShadow = 0x1000000000, + /// + /// Let pixels bleed in to other tiles? Is this Disabling Texture Clamp? + /// + PixelBleed = 0x2000000000, + /// + /// Play tile animation once. + /// + PlayAnimOnce = 0x4000000000, + /// + /// Movable multi? Cool ships and vehicles etc? Something related to the masts ??? + /// + MultiMovable = 0x10000000000, + /// + /// Unused10 + /// + Unused10 = 0x20000000000, + /// + /// Unused11 + /// + Unused11 = 0x40000000000, + /// + /// Unused12 + /// + Unused12 = 0x80000000000, + /// + /// Unused13 + /// + Unused13 = 0x100000000000, + /// + /// Unused14 + /// + Unused14 = 0x200000000000, + /// + /// Unused15 + /// + Unused15 = 0x400000000000, + /// + /// Unused16 + /// + Unused16 = 0x800000000000, + /// + /// Unused17 + /// + Unused17 = 0x1000000000000, + /// + /// Unused18 + /// + Unused18 = 0x2000000000000, + /// + /// Unused19 + /// + Unused19 = 0x4000000000000, + /// + /// Unused20 + /// + Unused20 = 0x8000000000000, + /// + /// Unused21 + /// + Unused21 = 0x10000000000000, + /// + /// Unused22 + /// + Unused22 = 0x20000000000000, + /// + /// Unused23 + /// + Unused23 = 0x40000000000000, + /// + /// Unused24 + /// + Unused24 = 0x80000000000000, + /// + /// Unused25 + /// + Unused25 = 0x100000000000000, + /// + /// Unused26 + /// + Unused26 = 0x200000000000000, + /// + /// Unused27 + /// + Unused27 = 0x400000000000000, + /// + /// Unused28 + /// + Unused28 = 0x800000000000000, + /// + /// Unused29 + /// + Unused29 = 0x1000000000000000, + /// + /// Unused30 + /// + Unused30 = 0x2000000000000000, + /// + /// Unused31 + /// + Unused31 = 0x4000000000000000, + /// + /// Unused32 + /// + Unused32 = 0x8000000000000000 } \ No newline at end of file diff --git a/Shared/TileDataProvider.cs b/Shared/TileDataProvider.cs index d3e170b..99cc99f 100644 --- a/Shared/TileDataProvider.cs +++ b/Shared/TileDataProvider.cs @@ -1,53 +1,62 @@ using System.Text; using ClassicUO.Assets; -namespace CentrED; +namespace CentrED; -public class TileDataProvider : MulProvider { - - public TileDataProvider(String tileDataPath, bool initOnly) : base(tileDataPath) { +public class TileDataProvider : MulProvider +{ + public TileDataProvider(String tileDataPath, bool initOnly) : base(tileDataPath) + { Version = Stream.Length >= 3188736 ? TileDataVersion.HighSeas : TileDataVersion.Legacy; Stream.Position = 0; - for (var i = 0; i < 0x4000; i++) { + for (var i = 0; i < 0x4000; i++) + { //In High Seas, the first header comes AFTER the unknown tile (for whatever reason). //Therefore special handling is required. if ((Version == TileDataVersion.Legacy && i % 32 == 0) || - Version >= TileDataVersion.HighSeas && (i == 1 || (i > 1 && i % 32 == 0))) { + Version >= TileDataVersion.HighSeas && (i == 1 || (i > 1 && i % 32 == 0))) + { Stream.Seek(4, SeekOrigin.Current); } LandTiles[i] = ReadLandTileData(Version, Reader); } - var tsize = Version switch { + var tsize = Version switch + { TileDataVersion.HighSeas => 41, _ => 37 }; var xsize = 4 + 32 * tsize; - + var staticCount = (uint)((Stream.Length - Stream.Position) / xsize * 32); StaticTiles = new StaticTiles[staticCount]; - for (var i = 0; i < staticCount; i++) { - if (i % 32 == 0) { + for (var i = 0; i < staticCount; i++) + { + if (i % 32 == 0) + { Stream.Seek(4, SeekOrigin.Current); // skip header } StaticTiles[i] = ReadStaticTileData(Version, Reader); } - if (initOnly) { + if (initOnly) + { Reader.Dispose(); Stream.Dispose(); } } - + public TileDataVersion Version { get; } - + public LandTiles[] LandTiles = new LandTiles[0x4000]; public StaticTiles[] StaticTiles; - private LandTiles ReadLandTileData(TileDataVersion version, BinaryReader reader) { - var flags = Version switch { + private LandTiles ReadLandTileData(TileDataVersion version, BinaryReader reader) + { + var flags = Version switch + { TileDataVersion.HighSeas => reader.ReadUInt64(), _ => reader.ReadUInt32() }; @@ -55,9 +64,11 @@ private LandTiles ReadLandTileData(TileDataVersion version, BinaryReader reader) var name = Encoding.ASCII.GetString(reader.ReadBytes(20)).Trim(); return new LandTiles(flags, textureId, name); } - - private StaticTiles ReadStaticTileData(TileDataVersion version, BinaryReader reader) { - var flags = Version switch { + + private StaticTiles ReadStaticTileData(TileDataVersion version, BinaryReader reader) + { + var flags = Version switch + { TileDataVersion.HighSeas => reader.ReadUInt64(), _ => reader.ReadUInt32() }; @@ -69,6 +80,6 @@ private StaticTiles ReadStaticTileData(TileDataVersion version, BinaryReader rea var lightIndex = reader.ReadUInt16(); var height = reader.ReadByte(); var tileName = Encoding.ASCII.GetString(reader.ReadBytes(20)).Trim(); - return new StaticTiles(flags, weight, layer, count, animId, hue, lightIndex, height, tileName); + return new StaticTiles(flags, weight, layer, count, animId, hue, lightIndex, height, tileName); } } \ No newline at end of file diff --git a/Shared/TileDataVersion.cs b/Shared/TileDataVersion.cs index 18f2a31..7c472d6 100644 --- a/Shared/TileDataVersion.cs +++ b/Shared/TileDataVersion.cs @@ -1,6 +1,7 @@ -namespace CentrED; +namespace CentrED; -public enum TileDataVersion { +public enum TileDataVersion +{ Legacy, HighSeas } \ No newline at end of file diff --git a/Shared/Uop.cs b/Shared/Uop.cs index 9f3833a..7b4f262 100644 --- a/Shared/Uop.cs +++ b/Shared/Uop.cs @@ -1,88 +1,89 @@ -namespace CentrED; +namespace CentrED; -public static class Uop { +public static class Uop +{ public static ulong HashFileName(string s) - { - uint eax, ecx, edx, ebx, esi, edi; + { + uint eax, ecx, edx, ebx, esi, edi; - eax = ecx = edx = ebx = esi = edi = 0; - ebx = edi = esi = (uint)s.Length + 0xDEADBEEF; + eax = ecx = edx = ebx = esi = edi = 0; + ebx = edi = esi = (uint)s.Length + 0xDEADBEEF; - int i = 0; + int i = 0; - for (i = 0; i + 12 < s.Length; i += 12) - { - edi = (uint)((s[i + 7] << 24) | (s[i + 6] << 16) | (s[i + 5] << 8) | s[i + 4]) + edi; - esi = (uint)((s[i + 11] << 24) | (s[i + 10] << 16) | (s[i + 9] << 8) | s[i + 8]) + esi; - edx = (uint)((s[i + 3] << 24) | (s[i + 2] << 16) | (s[i + 1] << 8) | s[i]) - esi; + for (i = 0; i + 12 < s.Length; i += 12) + { + edi = (uint)((s[i + 7] << 24) | (s[i + 6] << 16) | (s[i + 5] << 8) | s[i + 4]) + edi; + esi = (uint)((s[i + 11] << 24) | (s[i + 10] << 16) | (s[i + 9] << 8) | s[i + 8]) + esi; + edx = (uint)((s[i + 3] << 24) | (s[i + 2] << 16) | (s[i + 1] << 8) | s[i]) - esi; - edx = (edx + ebx) ^ (esi >> 28) ^ (esi << 4); - esi += edi; - edi = (edi - edx) ^ (edx >> 26) ^ (edx << 6); - edx += esi; - esi = (esi - edi) ^ (edi >> 24) ^ (edi << 8); - edi += edx; - ebx = (edx - esi) ^ (esi >> 16) ^ (esi << 16); - esi += edi; - edi = (edi - ebx) ^ (ebx >> 13) ^ (ebx << 19); - ebx += esi; - esi = (esi - edi) ^ (edi >> 28) ^ (edi << 4); - edi += ebx; - } + edx = (edx + ebx) ^ (esi >> 28) ^ (esi << 4); + esi += edi; + edi = (edi - edx) ^ (edx >> 26) ^ (edx << 6); + edx += esi; + esi = (esi - edi) ^ (edi >> 24) ^ (edi << 8); + edi += edx; + ebx = (edx - esi) ^ (esi >> 16) ^ (esi << 16); + esi += edi; + edi = (edi - ebx) ^ (ebx >> 13) ^ (ebx << 19); + ebx += esi; + esi = (esi - edi) ^ (edi >> 28) ^ (edi << 4); + edi += ebx; + } - if (s.Length - i > 0) + if (s.Length - i > 0) + { + switch (s.Length - i) { - switch (s.Length - i) - { - case 12: - esi += (uint)s[i + 11] << 24; - goto case 11; - case 11: - esi += (uint)s[i + 10] << 16; - goto case 10; - case 10: - esi += (uint)s[i + 9] << 8; - goto case 9; - case 9: - esi += (uint)s[i + 8]; - goto case 8; - case 8: - edi += (uint)s[i + 7] << 24; - goto case 7; - case 7: - edi += (uint)s[i + 6] << 16; - goto case 6; - case 6: - edi += (uint)s[i + 5] << 8; - goto case 5; - case 5: - edi += (uint)s[i + 4]; - goto case 4; - case 4: - ebx += (uint)s[i + 3] << 24; - goto case 3; - case 3: - ebx += (uint)s[i + 2] << 16; - goto case 2; - case 2: - ebx += (uint)s[i + 1] << 8; - goto case 1; - case 1: - ebx += (uint)s[i]; - break; - } - - esi = (esi ^ edi) - ((edi >> 18) ^ (edi << 14)); - ecx = (esi ^ ebx) - ((esi >> 21) ^ (esi << 11)); - edi = (edi ^ ecx) - ((ecx >> 7) ^ (ecx << 25)); - esi = (esi ^ edi) - ((edi >> 16) ^ (edi << 16)); - edx = (esi ^ ecx) - ((esi >> 28) ^ (esi << 4)); - edi = (edi ^ edx) - ((edx >> 18) ^ (edx << 14)); - eax = (esi ^ edi) - ((edi >> 8) ^ (edi << 24)); - - return ((ulong)edi << 32) | eax; + case 12: + esi += (uint)s[i + 11] << 24; + goto case 11; + case 11: + esi += (uint)s[i + 10] << 16; + goto case 10; + case 10: + esi += (uint)s[i + 9] << 8; + goto case 9; + case 9: + esi += (uint)s[i + 8]; + goto case 8; + case 8: + edi += (uint)s[i + 7] << 24; + goto case 7; + case 7: + edi += (uint)s[i + 6] << 16; + goto case 6; + case 6: + edi += (uint)s[i + 5] << 8; + goto case 5; + case 5: + edi += (uint)s[i + 4]; + goto case 4; + case 4: + ebx += (uint)s[i + 3] << 24; + goto case 3; + case 3: + ebx += (uint)s[i + 2] << 16; + goto case 2; + case 2: + ebx += (uint)s[i + 1] << 8; + goto case 1; + case 1: + ebx += (uint)s[i]; + break; } - return ((ulong)esi << 32) | eax; + esi = (esi ^ edi) - ((edi >> 18) ^ (edi << 14)); + ecx = (esi ^ ebx) - ((esi >> 21) ^ (esi << 11)); + edi = (edi ^ ecx) - ((ecx >> 7) ^ (ecx << 25)); + esi = (esi ^ edi) - ((edi >> 16) ^ (edi << 16)); + edx = (esi ^ ecx) - ((esi >> 28) ^ (esi << 4)); + edi = (edi ^ edx) - ((edx >> 18) ^ (edx << 14)); + eax = (esi ^ edi) - ((edi >> 8) ^ (edi << 24)); + + return ((ulong)edi << 32) | eax; } + + return ((ulong)esi << 32) | eax; + } } \ No newline at end of file diff --git a/Shared/UopFile.cs b/Shared/UopFile.cs index ee63d97..b711d70 100644 --- a/Shared/UopFile.cs +++ b/Shared/UopFile.cs @@ -1,3 +1,3 @@ namespace CentrED; -public record UopFile(long Offset, int Length); +public record UopFile(long Offset, int Length); \ No newline at end of file diff --git a/Shared/Utility/Crc32.cs b/Shared/Utility/Crc32.cs index 78225a3..d308237 100644 --- a/Shared/Utility/Crc32.cs +++ b/Shared/Utility/Crc32.cs @@ -1,4 +1,4 @@ -namespace CentrED.Utility; +namespace CentrED.Utility; //https://gist.github.com/sebnilsson/5704028 public static class Crc32 @@ -8,39 +8,37 @@ public static class Crc32 #region CRC Table private static readonly uint[] CrcTable = - { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832 - , 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, - 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0 - , 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, - 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6 - , 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, - 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924 - , 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, - 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB - , 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, - 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49 - , 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, - 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F - , 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, - 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD - , 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344 - , 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, - 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E - , 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, - 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0 - , 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, - 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A - , 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD - , 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, - 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7 - , 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, - 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729 - , 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, - 0x2D02EF8D - }; + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, + 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, + 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, + 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, + 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, + 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, + 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, + 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, + 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, + 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, + 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, + 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; #endregion diff --git a/Shared/Utility/Crypto.cs b/Shared/Utility/Crypto.cs index 8221a55..4b7022f 100644 --- a/Shared/Utility/Crypto.cs +++ b/Shared/Utility/Crypto.cs @@ -1,16 +1,18 @@ using System.Security.Cryptography; using System.Text; -namespace CentrED.Utility; +namespace CentrED.Utility; -public class Crypto { +public class Crypto +{ public static string Md5Hash(String input) { return Hash(MD5.Create(), new MemoryStream(Encoding.ASCII.GetBytes(input))).ToLower(); } - public static uint Crc32Checksum(Array input) { - byte[] output = new byte[Buffer.ByteLength(input)] ; + public static uint Crc32Checksum(Array input) + { + byte[] output = new byte[Buffer.ByteLength(input)]; Buffer.BlockCopy(input, 0, output, 0, output.Length); return Crc32.Compute(output); } diff --git a/Shared/Utility/Logger.cs b/Shared/Utility/Logger.cs index a7b7cda..ff411d1 100644 --- a/Shared/Utility/Logger.cs +++ b/Shared/Utility/Logger.cs @@ -1,26 +1,32 @@ -namespace CentrED.Utility; +namespace CentrED.Utility; -public class Logger { +public class Logger +{ #if DEBUG public static bool DEBUG = true; #else public static bool DEBUG = false; #endif public TextWriter Out = Console.Out; - - public void LogInfo(string log) { + + public void LogInfo(string log) + { Log("INFO", log); } - public void LogError(string log) { + public void LogError(string log) + { Log("ERROR", log); } - public void LogDebug(string log) { - if (DEBUG) Log("DEBUG", log); + public void LogDebug(string log) + { + if (DEBUG) + Log("DEBUG", log); } - internal void Log(string level, string log) { + internal void Log(string level, string log) + { Out.WriteLine($"[{level}] {DateTime.Now} {log}"); } } \ No newline at end of file diff --git a/Shared/Utility/StreamExt.cs b/Shared/Utility/StreamExt.cs index f03d80e..cca102d 100644 --- a/Shared/Utility/StreamExt.cs +++ b/Shared/Utility/StreamExt.cs @@ -1,13 +1,17 @@ using System.Text; -namespace CentrED.Utility; +namespace CentrED.Utility; -public static class StreamExt { - public static string ReadStringNull(this BinaryReader reader) { +public static class StreamExt +{ + public static string ReadStringNull(this BinaryReader reader) + { List bytes = new List(); - while (true) { + while (true) + { var currentVal = reader.ReadByte(); - if (currentVal == '\0') { + if (currentVal == '\0') + { break; } bytes.Add(currentVal); @@ -16,28 +20,31 @@ public static string ReadStringNull(this BinaryReader reader) { return Encoding.ASCII.GetString(bytes.ToArray()); } - public static void WriteStringNull(this BinaryWriter writer, string value) { + public static void WriteStringNull(this BinaryWriter writer, string value) + { writer.Write(Encoding.ASCII.GetBytes(value + char.MinValue)); } - public static int CopyBytesTo(this Stream source, Stream target, int count) { + public static int CopyBytesTo(this Stream source, Stream target, int count) + { var buffer = new byte[count]; var result = source.Read(buffer); target.Write(buffer); return result; } - + /// ///Dequeues count bytes from source.Position. Drops data before current source.Position /// - public static byte[] Dequeue(this MemoryStream source, int offset, int count) { + public static byte[] Dequeue(this MemoryStream source, int offset, int count) + { source.Position = 0; byte[] result = new byte[count]; byte[] remainder = new byte[source.Length - (offset + count)]; - + Buffer.BlockCopy(source.GetBuffer(), offset, result, 0, count); Buffer.BlockCopy(source.GetBuffer(), offset + count, remainder, 0, remainder.Length); - + source.SetLength(0); source.Write(remainder); source.Position = 0;