From d2cfeb06ab341fb1c170eb2951fc0aa77ab17efe Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Tue, 17 Nov 2020 00:46:06 -0800 Subject: [PATCH] Updates Light Packets & World Loading (#316) - [X] Changes light packets - [X] Updates world loading Bumps release version --- .../Network/Packets/Outgoing/EffectPackets.cs | 15 ------ .../Packets/Outgoing/EquipmentPackets.cs | 15 ------ .../Packets/Outgoing/LightPacketTests.cs | 27 +++++------ .../Network/Packets/Outgoing/LightPackets.cs | 35 ++++++++++++++ .../Network/Packets/Outgoing/MobilePackets.cs | 15 ------ ...ightPackets.cs => OutgoingLightPackets.cs} | 48 +++++++++---------- Projects/Server/Serialization/BufferReader.cs | 46 +++++++++++------- Projects/Server/World/World.cs | 22 ++++----- Projects/UOContent/Mobiles/PlayerMobile.cs | 4 +- 9 files changed, 112 insertions(+), 115 deletions(-) create mode 100644 Projects/Server.Tests/Tests/Network/Packets/Outgoing/LightPackets.cs rename Projects/Server/Network/Packets/{LightPackets.cs => OutgoingLightPackets.cs} (56%) diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/EffectPackets.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/EffectPackets.cs index efc18d915..c176c2d61 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/EffectPackets.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/EffectPackets.cs @@ -1,18 +1,3 @@ -/************************************************************************* - * ModernUO * - * Copyright 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: EffectPackets.cs * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - *************************************************************************/ - namespace Server.Network { public sealed class PlaySound : Packet diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/EquipmentPackets.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/EquipmentPackets.cs index 8d81f694d..b00bf2c04 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/EquipmentPackets.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/EquipmentPackets.cs @@ -1,18 +1,3 @@ -/************************************************************************* - * ModernUO * - * Copyright 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: EquipmentPackets.cs * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - *************************************************************************/ - using System; namespace Server.Network diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/LightPacketTests.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/LightPacketTests.cs index 18b14296a..f050a77ee 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/LightPacketTests.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/LightPacketTests.cs @@ -11,32 +11,27 @@ namespace Server.Tests.Network public void TestGlobalLightLevel() { byte lightLevel = 5; - var data = new GlobalLightLevel(lightLevel).Compile(); + var expected = new GlobalLightLevel(lightLevel).Compile(); - Span expectedData = stackalloc byte[2]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendGlobalLightLevel(lightLevel); - expectedData.Write(ref pos, (byte)0x4F); // Packet ID - expectedData.Write(ref pos, lightLevel); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] public void TestPersonalLightLevel() { - Serial serial = 0x1; + Serial serial = 0x1024; byte lightLevel = 5; - var data = new PersonalLightLevel(serial, lightLevel).Compile(); + var expected = new PersonalLightLevel(serial, lightLevel).Compile(); - Span expectedData = stackalloc byte[6]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendPersonalLightLevel(serial, lightLevel); - expectedData.Write(ref pos, (byte)0x4E); // Packet ID - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, lightLevel); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } } } diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/LightPackets.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/LightPackets.cs new file mode 100644 index 000000000..5da20a6d5 --- /dev/null +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/LightPackets.cs @@ -0,0 +1,35 @@ +namespace Server.Network +{ + public sealed class GlobalLightLevel : Packet + { + private static readonly GlobalLightLevel[] m_Cache = new GlobalLightLevel[0x100]; + + public GlobalLightLevel(int level) : base(0x4F, 2) + { + Stream.Write((sbyte)level); + } + + public static GlobalLightLevel Instantiate(int level) + { + var lvl = (byte)level; + var p = m_Cache[lvl]; + + if (p == null) + { + m_Cache[lvl] = p = new GlobalLightLevel(level); + p.SetStatic(); + } + + return p; + } + } + + public sealed class PersonalLightLevel : Packet + { + public PersonalLightLevel(Serial mobile, int level = 0) : base(0x4E, 6) + { + Stream.Write(mobile); + Stream.Write((sbyte)level); + } + } +} diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs index 3e5a432a9..a2802dd83 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs @@ -1,18 +1,3 @@ -/************************************************************************* - * ModernUO * - * Copyright 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: MobilePackets.cs * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - *************************************************************************/ - using Server.Network; namespace Server.Tests.Network diff --git a/Projects/Server/Network/Packets/LightPackets.cs b/Projects/Server/Network/Packets/OutgoingLightPackets.cs similarity index 56% rename from Projects/Server/Network/Packets/LightPackets.cs rename to Projects/Server/Network/Packets/OutgoingLightPackets.cs index 6fd482b94..1eb7e37db 100644 --- a/Projects/Server/Network/Packets/LightPackets.cs +++ b/Projects/Server/Network/Packets/OutgoingLightPackets.cs @@ -2,7 +2,7 @@ * ModernUO * * Copyright 2019-2020 - ModernUO Development Team * * Email: hi@modernuo.com * - * File: LightPackets.cs * + * File: OutgoingLightPackets.cs * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -13,38 +13,38 @@ * along with this program. If not, see . * *************************************************************************/ +using System.Buffers; + namespace Server.Network { - public sealed class GlobalLightLevel : Packet + public static class OutgoingLightPackets { - private static readonly GlobalLightLevel[] m_Cache = new GlobalLightLevel[0x100]; - - public GlobalLightLevel(int level) : base(0x4F, 2) + public static void SendPersonalLightLevel(this NetState ns, Serial serial, int level) { - Stream.Write((sbyte)level); - } - - public static GlobalLightLevel Instantiate(int level) - { - var lvl = (byte)level; - var p = m_Cache[lvl]; - - if (p == null) + if (ns == null || !ns.GetSendBuffer(out var buffer)) { - m_Cache[lvl] = p = new GlobalLightLevel(level); - p.SetStatic(); + return; } - return p; - } - } + var writer = new CircularBufferWriter(buffer); + writer.Write((byte)0x4E); // Packet ID + writer.Write(serial); + writer.Write((byte)level); - public sealed class PersonalLightLevel : Packet - { - public PersonalLightLevel(Serial mobile, int level = 0) : base(0x4E, 6) + ns.Send(ref buffer, 6); + } + + public static void SendGlobalLightLevel(this NetState ns, int level = 0) { - Stream.Write(mobile); - Stream.Write((sbyte)level); + if (ns == null || !ns.GetSendBuffer(out var buffer)) + { + return; + } + + buffer[0] = 0x4F; // Packet ID + buffer[1] = (byte)level; + + ns.Send(ref buffer, 2); } } } diff --git a/Projects/Server/Serialization/BufferReader.cs b/Projects/Server/Serialization/BufferReader.cs index 593d51ab5..e4b35756b 100644 --- a/Projects/Server/Serialization/BufferReader.cs +++ b/Projects/Server/Serialization/BufferReader.cs @@ -16,6 +16,7 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; +using System.IO; using System.Net; using System.Text; using Server.Guilds; @@ -25,12 +26,12 @@ namespace Server public class BufferReader : IGenericReader { private readonly Encoding _encoding; - private ArraySegment _segment; + private byte[] _buffer; public int Position { get; private set; } - public BufferReader(ArraySegment segment) + public BufferReader(byte[] buffer) { - _segment = segment; + _buffer = buffer; _encoding = Utility.UTF8; } @@ -42,7 +43,7 @@ namespace Server } var length = ReadEncodedInt(); - var s = length == 0 ? "" : _encoding.GetString(_segment.AsSpan(Position, length)); + var s = length == 0 ? "" : _encoding.GetString(_buffer.AsSpan(Position, length)); Position += length; return s; } @@ -82,65 +83,65 @@ namespace Server public long ReadLong() { - var v = BinaryPrimitives.ReadInt64LittleEndian(_segment.AsSpan(Position, 8)); + var v = BinaryPrimitives.ReadInt64LittleEndian(_buffer.AsSpan(Position, 8)); Position += 8; return v; } public ulong ReadULong() { - var v = BinaryPrimitives.ReadUInt64LittleEndian(_segment.AsSpan(Position, 8)); + var v = BinaryPrimitives.ReadUInt64LittleEndian(_buffer.AsSpan(Position, 8)); Position += 8; return v; } public int ReadInt() { - var v = BinaryPrimitives.ReadInt32LittleEndian(_segment.AsSpan(Position, 4)); + var v = BinaryPrimitives.ReadInt32LittleEndian(_buffer.AsSpan(Position, 4)); Position += 4; return v; } public uint ReadUInt() { - var v = BinaryPrimitives.ReadUInt32LittleEndian(_segment.AsSpan(Position, 4)); + var v = BinaryPrimitives.ReadUInt32LittleEndian(_buffer.AsSpan(Position, 4)); Position += 4; return v; } public short ReadShort() { - var v = BinaryPrimitives.ReadInt16LittleEndian(_segment.AsSpan(Position, 2)); + var v = BinaryPrimitives.ReadInt16LittleEndian(_buffer.AsSpan(Position, 2)); Position += 2; return v; } public ushort ReadUShort() { - var v = BinaryPrimitives.ReadUInt16LittleEndian(_segment.AsSpan(Position, 2)); + var v = BinaryPrimitives.ReadUInt16LittleEndian(_buffer.AsSpan(Position, 2)); Position += 2; return v; } public double ReadDouble() { - var v = BinaryPrimitives.ReadDoubleLittleEndian(_segment.AsSpan(Position, 8)); + var v = BinaryPrimitives.ReadDoubleLittleEndian(_buffer.AsSpan(Position, 8)); Position += 8; return v; } public float ReadFloat() { - var v = BinaryPrimitives.ReadSingleLittleEndian(_segment.AsSpan(Position, 4)); + var v = BinaryPrimitives.ReadSingleLittleEndian(_buffer.AsSpan(Position, 4)); Position += 4; return v; } - public byte ReadByte() => _segment[Position++]; + public byte ReadByte() => _buffer[Position++]; - public sbyte ReadSByte() => (sbyte)_segment[Position++]; + public sbyte ReadSByte() => (sbyte)_buffer[Position++]; - public bool ReadBool() => _segment[Position++] != 0; + public bool ReadBool() => _buffer[Position++] != 0; public int ReadEncodedInt() { @@ -310,14 +311,25 @@ namespace Server public int Read(Span buffer) { var length = buffer.Length; - if (length > _segment.Count - Position) + if (length > _buffer.Length - Position) { throw new OutOfMemoryException(); } - _segment.AsSpan(Position, length).CopyTo(buffer); + _buffer.AsSpan(Position, length).CopyTo(buffer); Position += length; return length; } + + public virtual int Seek(int offset, SeekOrigin origin) + { + return origin switch + { + SeekOrigin.Begin => Position = offset, + SeekOrigin.Current => Position += offset, + SeekOrigin.End => Position = _buffer.Length - offset, + _ => Position + }; + } } } diff --git a/Projects/Server/World/World.cs b/Projects/Server/World/World.cs index 87e67db37..f7b3012ed 100644 --- a/Projects/Server/World/World.cs +++ b/Projects/Server/World/World.cs @@ -337,30 +337,31 @@ namespace Server } using FileStream bin = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read); - var fileBuffer = new byte[bin.Length]; - bin.Read(fileBuffer); + var buffer = new byte[bin.Length]; + bin.Read(buffer); bin.Close(); - int position = 0; + var br = new BufferReader(buffer); foreach (var entry in entities) { T t = entry.Entity; + // Skip this entry if (t == null) { + br.Seek(entry.Length, SeekOrigin.Current); continue; } - var segment = new ArraySegment(fileBuffer, position, entry.Length); - var bufferReader = new BufferReader(segment); - t.Deserialize(bufferReader); + t.Deserialize(br); + var end = entry.Position + entry.Length; - if (bufferReader.Position != entry.Length) + if (br.Position != end) { Console.WriteLine($"***** Bad deserialize on {t.GetType()} *****"); Console.WriteLine( - $"Serialized object was {entry.Length} bytes, but {bufferReader.Position - entry.Position} bytes deserialized" + $"Serialized object was {entry.Length} bytes, but {br.Position - entry.Position} bytes deserialized" ); Console.WriteLine("Delete the object and continue? (y/n)"); @@ -370,10 +371,9 @@ namespace Server throw new Exception("Deserialization failed."); } t.Delete(); + + br.Seek((int)end, SeekOrigin.Begin); } - - - position += entry.Length; } } diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs index 85619000c..931f9a57c 100644 --- a/Projects/UOContent/Mobiles/PlayerMobile.cs +++ b/Projects/UOContent/Mobiles/PlayerMobile.cs @@ -1253,8 +1253,8 @@ namespace Server.Mobiles m_LastGlobalLight = global; m_LastPersonalLight = personal; - ns.Send(GlobalLightLevel.Instantiate(global)); - ns.Send(new PersonalLightLevel(Serial, personal)); + ns.SendGlobalLightLevel(global); + ns.SendPersonalLightLevel(Serial, personal); } public override int GetMinResistance(ResistanceType type)