From a85c8304f20b2bb0842ddefec475d54ce11d6fd2 Mon Sep 17 00:00:00 2001 From: Ethan Moffat Date: Thu, 24 Feb 2022 21:36:13 -0800 Subject: [PATCH 1/3] Login path compatibility with GameServer.exe. Support for official server software. - Send player ID and file ID in WELCOME_AGREE packets during login - Handle WELCOME_MSG reply of '3', which means the character login was rejected --- EOLib.IO/Services/NumberEncoderService.cs | 2 +- .../FileTransfer/FileRequestServiceTest.cs | 50 ++++++++++++++----- EOLib/Domain/Login/CharacterLoginReply.cs | 5 +- .../Login/ILoginRequestCompletedData.cs | 4 ++ EOLib/Domain/Login/LoginActions.cs | 13 +++-- .../Domain/Login/LoginRequestCompletedData.cs | 15 +++++- EOLib/Domain/Login/PlayerInfoRepository.cs | 6 +-- EOLib/Net/Communication/AsyncSocket.cs | 4 +- EOLib/Net/FileTransfer/FileRequestActions.cs | 16 +++--- EOLib/Net/FileTransfer/FileRequestService.cs | 16 +++--- .../LoginRequestCompletedPacketTranslator.cs | 12 ++++- EndlessClient/Controllers/LoginController.cs | 18 +++++-- .../UIControls/CharacterInfoPanel.cs | 2 +- 13 files changed, 117 insertions(+), 46 deletions(-) diff --git a/EOLib.IO/Services/NumberEncoderService.cs b/EOLib.IO/Services/NumberEncoderService.cs index ec07ee9b6..424ecc1a8 100644 --- a/EOLib.IO/Services/NumberEncoderService.cs +++ b/EOLib.IO/Services/NumberEncoderService.cs @@ -32,7 +32,7 @@ public byte[] EncodeNumber(int number, int size) numArray[0] = unsigned + 1; - return numArray.Select(x => (byte)x) + return numArray.Cast() .Take(size) .ToArray(); } diff --git a/EOLib.Test/Net/FileTransfer/FileRequestServiceTest.cs b/EOLib.Test/Net/FileTransfer/FileRequestServiceTest.cs index 49e3352b6..5a9fcec91 100644 --- a/EOLib.Test/Net/FileTransfer/FileRequestServiceTest.cs +++ b/EOLib.Test/Net/FileTransfer/FileRequestServiceTest.cs @@ -42,7 +42,7 @@ public void SetUp() public void RequestFile_ResponsePacketHasInvalidHeader_ThrowsEmptyPacketReceivedException() { Mock.Get(_packetSendService).SetupReceivedPacketHasHeader(PacketFamily.Account, PacketAction.Accept); - Assert.ThrowsAsync(async () => await _fileRequestService.RequestFile(InitFileType.Item)); + Assert.ThrowsAsync(async () => await _fileRequestService.RequestFile(InitFileType.Item, 1)); } [Test] @@ -50,7 +50,7 @@ public void RequestFile_ResponsePacketInvalidExtraByte_ThrowsMalformedPacketExce { Mock.Get(_packetSendService).SetupReceivedPacketHasHeader(PacketFamily.Init, PacketAction.Init, (byte)InitReply.ItemFile, 33); - Assert.ThrowsAsync(async () => await _fileRequestService.RequestFile(InitFileType.Item)); + Assert.ThrowsAsync(async () => await _fileRequestService.RequestFile(InitFileType.Item, 1)); } [Test] @@ -64,7 +64,7 @@ public void RequestFile_SendsPacket_BasedOnSpecifiedType() Mock.Get(_packetSendService).Setup(x => x.SendEncodedPacketAndWaitAsync(It.IsAny())) .Callback((IPacket packet) => packetIsCorrect = IsCorrectFileRequestPacket(packet, localType)); - _fileRequestService.RequestFile(type); + _fileRequestService.RequestFile(type, 1); Assert.IsTrue(packetIsCorrect, "Incorrect packet for {0}", type); } @@ -81,10 +81,10 @@ public void RequestFile_CorrectResponse_ExecutesWithoutFault() AggregateException aggEx = null; switch (type) { - case InitFileType.Item: aggEx = _fileRequestService.RequestFile(type).Exception; break; - case InitFileType.Npc: aggEx = _fileRequestService.RequestFile(type).Exception; break; - case InitFileType.Spell: aggEx = _fileRequestService.RequestFile(type).Exception; break; - case InitFileType.Class: aggEx = _fileRequestService.RequestFile(type).Exception; break; + case InitFileType.Item: aggEx = _fileRequestService.RequestFile(type, 1).Exception; break; + case InitFileType.Npc: aggEx = _fileRequestService.RequestFile(type, 1).Exception; break; + case InitFileType.Spell: aggEx = _fileRequestService.RequestFile(type, 1).Exception; break; + case InitFileType.Class: aggEx = _fileRequestService.RequestFile(type, 1).Exception; break; } if (aggEx != null) @@ -100,14 +100,14 @@ public void RequestFile_CorrectResponse_ExecutesWithoutFault() public void RequestMapFile_ResponsePacketHasInvalidHeader_ThrowsEmptyPacketReceivedException() { Mock.Get(_packetSendService).SetupReceivedPacketHasHeader(PacketFamily.Account, PacketAction.Accept); - Assert.ThrowsAsync(async () => await _fileRequestService.RequestMapFile(1)); + Assert.ThrowsAsync(async () => await _fileRequestService.RequestMapFile(1, 1)); } [Test] public void RequestMapFile_ResponsePacketHasIncorrectFileType_ThrowsMalformedPacketException() { Mock.Get(_packetSendService).SetupReceivedPacketHasHeader(PacketFamily.Init, PacketAction.Init, (byte) InitReply.SpellFile, 33); - Assert.ThrowsAsync(async () => await _fileRequestService.RequestMapFile(1)); + Assert.ThrowsAsync(async () => await _fileRequestService.RequestMapFile(1, 1)); } [Test] @@ -116,18 +116,42 @@ public void RequestMapFile_SendsPacket_BasedOnSpecifiedMap() var packetIsCorrect = false; Mock.Get(_packetSendService).Setup(x => x.SendEncodedPacketAndWaitAsync(It.IsAny())).Callback((IPacket packet) => packetIsCorrect = IsCorrectFileRequestPacket(packet, InitFileType.Map)); - _fileRequestService.RequestMapFile(1); + _fileRequestService.RequestMapFile(1, 1); - Assert.IsTrue(packetIsCorrect, "Incorrect packet for Map"); + Assert.That(packetIsCorrect, Is.True); + } + + [Test] + public void RequestMapFile_HasPlayerAndMapID() + { + const short PlayerID = 1234; + const short MapID = 333; + + var packetIsCorrect = false; + Mock.Get(_packetSendService) + .Setup(x => x.SendEncodedPacketAndWaitAsync(It.IsAny())) + .Callback((IPacket p) => packetIsCorrect = IsCorrectFileRequestPacket(p, InitFileType.Map, PlayerID, MapID)); + + _fileRequestService.RequestMapFile(MapID, PlayerID); + + Assert.That(packetIsCorrect, Is.True); } #endregion #region Helper Methods - private static bool IsCorrectFileRequestPacket(IPacket packet, InitFileType type) + private static bool IsCorrectFileRequestPacket(IPacket packet, InitFileType type, short playerId = 0, short mapId = 0) { - return packet.Family == PacketFamily.Welcome && packet.Action == PacketAction.Agree && packet.ReadChar() == (byte) type; + var correctTyping = packet.Family == PacketFamily.Welcome && packet.Action == PacketAction.Agree && packet.ReadChar() == (byte) type; + + var correctData = true; + if (mapId > 0 && playerId > 0) + { + correctData = packet.ReadShort() == playerId && packet.ReadShort() == mapId; + } + + return correctTyping && correctData; } private static byte[] CreateFilePacket(InitFileType type) diff --git a/EOLib/Domain/Login/CharacterLoginReply.cs b/EOLib/Domain/Login/CharacterLoginReply.cs index 93f6dac62..0e1f48e7f 100644 --- a/EOLib/Domain/Login/CharacterLoginReply.cs +++ b/EOLib/Domain/Login/CharacterLoginReply.cs @@ -2,7 +2,8 @@ namespace EOLib.Domain.Login { public enum CharacterLoginReply : short { - RequestGranted = 1, //response from welcome_request - RequestCompleted = 2, //response from welcome_message + RequestGranted = 1, // response from welcome_request + RequestCompleted = 2, // response from welcome_message + RequestDenied = 3, // response from welcome_message if the client sends invalid player ID } } \ No newline at end of file diff --git a/EOLib/Domain/Login/ILoginRequestCompletedData.cs b/EOLib/Domain/Login/ILoginRequestCompletedData.cs index f1e8dfb9f..14c24d271 100644 --- a/EOLib/Domain/Login/ILoginRequestCompletedData.cs +++ b/EOLib/Domain/Login/ILoginRequestCompletedData.cs @@ -24,6 +24,8 @@ public interface ILoginRequestCompletedData : ITranslatedData IReadOnlyList MapItems { get; } + CharacterLoginReply Error { get; } + ILoginRequestCompletedData WithNews(IEnumerable newsStrings); ILoginRequestCompletedData WithWeight(byte weight); @@ -39,5 +41,7 @@ public interface ILoginRequestCompletedData : ITranslatedData ILoginRequestCompletedData WithNPCs(IEnumerable npcs); ILoginRequestCompletedData WithItems(IEnumerable items); + + ILoginRequestCompletedData WithError(CharacterLoginReply error); } } diff --git a/EOLib/Domain/Login/LoginActions.cs b/EOLib/Domain/Login/LoginActions.cs index 8ad209617..f22d6ea09 100644 --- a/EOLib/Domain/Login/LoginActions.cs +++ b/EOLib/Domain/Login/LoginActions.cs @@ -131,10 +131,10 @@ public async Task RequestCharacterLogin(ICharacter character) _loginFileChecksumRepository.ECFLength = data.EcfLen; } - public async Task CompleteCharacterLogin() + public async Task CompleteCharacterLogin() { var packet = new PacketBuilder(PacketFamily.Welcome, PacketAction.Message) - .AddThree(0x00123456) //? + .AddThree(_playerInfoRepository.PlayerID) .AddInt(_characterRepository.MainCharacter.ID) .Build(); @@ -144,6 +144,11 @@ public async Task CompleteCharacterLogin() var data = _loginRequestCompletedPacketTranslator.TranslatePacket(response); + if (data.Error == CharacterLoginReply.RequestDenied) + { + return data.Error; + } + _newsRepository.NewsHeader = data.News.First(); _newsRepository.NewsText = data.News.Except(new[] { data.News.First() }).ToList(); @@ -175,6 +180,8 @@ public async Task CompleteCharacterLogin() _currentMapStateRepository.MapItems = new HashSet(data.MapItems); _playerInfoRepository.PlayerIsInGame = true; + + return CharacterLoginReply.RequestCompleted; } private bool IsInvalidResponse(IPacket response) @@ -197,6 +204,6 @@ public interface ILoginActions Task RequestCharacterLogin(ICharacter character); - Task CompleteCharacterLogin(); + Task CompleteCharacterLogin(); } } \ No newline at end of file diff --git a/EOLib/Domain/Login/LoginRequestCompletedData.cs b/EOLib/Domain/Login/LoginRequestCompletedData.cs index a77d78971..96490674c 100644 --- a/EOLib/Domain/Login/LoginRequestCompletedData.cs +++ b/EOLib/Domain/Login/LoginRequestCompletedData.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using EOLib.Domain.Character; using EOLib.Domain.Map; @@ -24,6 +25,8 @@ public class LoginRequestCompletedData : ILoginRequestCompletedData public IReadOnlyList MapItems { get; private set; } + public CharacterLoginReply Error { get; private set; } + public ILoginRequestCompletedData WithNews(IEnumerable newsStrings) { var copy = MakeCopy(this); @@ -80,6 +83,13 @@ public ILoginRequestCompletedData WithItems(IEnumerable items) return copy; } + public ILoginRequestCompletedData WithError(CharacterLoginReply error) + { + var copy = MakeCopy(this); + copy.Error = error; + return copy; + } + private static LoginRequestCompletedData MakeCopy(ILoginRequestCompletedData source) { return new LoginRequestCompletedData @@ -91,7 +101,8 @@ private static LoginRequestCompletedData MakeCopy(ILoginRequestCompletedData sou CharacterSpellInventory = source.CharacterSpellInventory, MapCharacters = source.MapCharacters, MapNPCs = source.MapNPCs, - MapItems = source.MapItems + MapItems = source.MapItems, + Error = source.Error, }; } } diff --git a/EOLib/Domain/Login/PlayerInfoRepository.cs b/EOLib/Domain/Login/PlayerInfoRepository.cs index 4e7ce55a2..a3aba345d 100644 --- a/EOLib/Domain/Login/PlayerInfoRepository.cs +++ b/EOLib/Domain/Login/PlayerInfoRepository.cs @@ -8,7 +8,7 @@ public interface IPlayerInfoRepository string PlayerPassword { get; set; } - int PlayerID { get; set; } + short PlayerID { get; set; } bool IsFirstTimePlayer { get; set; } @@ -21,7 +21,7 @@ public interface IPlayerInfoProvider string PlayerPassword { get; } - int PlayerID { get; } + short PlayerID { get; } bool IsFirstTimePlayer { get; } @@ -35,7 +35,7 @@ public sealed class PlayerInfoRepository : IPlayerInfoRepository, IPlayerInfoPro public string PlayerPassword { get; set; } - public int PlayerID { get; set; } + public short PlayerID { get; set; } public bool IsFirstTimePlayer { get; set; } diff --git a/EOLib/Net/Communication/AsyncSocket.cs b/EOLib/Net/Communication/AsyncSocket.cs index b8e8aa433..a5fa860d0 100644 --- a/EOLib/Net/Communication/AsyncSocket.cs +++ b/EOLib/Net/Communication/AsyncSocket.cs @@ -117,9 +117,7 @@ private bool BlockingIsConnected() { try { - var pollResult = !_socket.Poll(1000, SelectMode.SelectRead); - var dataAvailable = _socket.Available != 0; - return _connected && (pollResult || dataAvailable); + return _connected && _socket.Connected; } catch (ObjectDisposedException) { diff --git a/EOLib/Net/FileTransfer/FileRequestActions.cs b/EOLib/Net/FileTransfer/FileRequestActions.cs index 749656dde..ba716d9ed 100644 --- a/EOLib/Net/FileTransfer/FileRequestActions.cs +++ b/EOLib/Net/FileTransfer/FileRequestActions.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using AutomaticTypeMapper; +using EOLib.Domain.Login; using EOLib.Domain.Protocol; using EOLib.IO; using EOLib.IO.Map; @@ -20,6 +21,7 @@ public class FileRequestActions : IFileRequestActions private readonly ILoginFileChecksumProvider _loginFileChecksumProvider; private readonly IPubFileRepository _pubFileRepository; private readonly IMapFileRepository _mapFileRepository; + private readonly IPlayerInfoProvider _playerInfoProvider; public FileRequestActions(INumberEncoderService numberEncoderService, IFileRequestService fileRequestService, @@ -27,7 +29,8 @@ public class FileRequestActions : IFileRequestActions IMapFileSaveService mapFileSaveService, ILoginFileChecksumProvider loginFileChecksumProvider, IPubFileRepository pubFileRepository, - IMapFileRepository mapFileRepository) + IMapFileRepository mapFileRepository, + IPlayerInfoProvider playerInfoProvider) { _numberEncoderService = numberEncoderService; _fileRequestService = fileRequestService; @@ -36,6 +39,7 @@ public class FileRequestActions : IFileRequestActions _loginFileChecksumProvider = loginFileChecksumProvider; _pubFileRepository = pubFileRepository; _mapFileRepository = mapFileRepository; + _playerInfoProvider = playerInfoProvider; } public bool NeedsFileForLogin(InitFileType fileType, short optionalID = 0) @@ -56,7 +60,7 @@ public bool NeedsMapForWarp(short mapID, byte[] mapRid, int fileSize) public async Task GetMapFromServer(short mapID) { - var mapFile = await _fileRequestService.RequestMapFile(mapID); + var mapFile = await _fileRequestService.RequestMapFile(mapID, _playerInfoProvider.PlayerID); SaveAndCacheMapFile(mapID, mapFile); } @@ -68,28 +72,28 @@ public async Task GetMapForWarp(short mapID) public async Task GetItemFileFromServer() { - var itemFile = await _fileRequestService.RequestFile(InitFileType.Item); + var itemFile = await _fileRequestService.RequestFile(InitFileType.Item, _playerInfoProvider.PlayerID); _pubFileSaveService.SaveFile(PubFileNameConstants.PathToEIFFile, itemFile); _pubFileRepository.EIFFile = (EIFFile)itemFile; } public async Task GetNPCFileFromServer() { - var npcFile = await _fileRequestService.RequestFile(InitFileType.Npc); + var npcFile = await _fileRequestService.RequestFile(InitFileType.Npc, _playerInfoProvider.PlayerID); _pubFileSaveService.SaveFile(PubFileNameConstants.PathToENFFile, npcFile); _pubFileRepository.ENFFile = (ENFFile)npcFile; } public async Task GetSpellFileFromServer() { - var spellFile = await _fileRequestService.RequestFile(InitFileType.Spell); + var spellFile = await _fileRequestService.RequestFile(InitFileType.Spell, _playerInfoProvider.PlayerID); _pubFileSaveService.SaveFile(PubFileNameConstants.PathToESFFile, spellFile); _pubFileRepository.ESFFile = (ESFFile)spellFile; } public async Task GetClassFileFromServer() { - var classFile = await _fileRequestService.RequestFile(InitFileType.Class); + var classFile = await _fileRequestService.RequestFile(InitFileType.Class, _playerInfoProvider.PlayerID); _pubFileSaveService.SaveFile(PubFileNameConstants.PathToECFFile, classFile); _pubFileRepository.ECFFile = (ECFFile)classFile; } diff --git a/EOLib/Net/FileTransfer/FileRequestService.cs b/EOLib/Net/FileTransfer/FileRequestService.cs index 824836d87..5ded6df1f 100644 --- a/EOLib/Net/FileTransfer/FileRequestService.cs +++ b/EOLib/Net/FileTransfer/FileRequestService.cs @@ -26,10 +26,12 @@ public class FileRequestService : IFileRequestService _mapFileSerializer = mapFileSerializer; } - public async Task RequestMapFile(short mapID) + public async Task RequestMapFile(short mapID, short playerID) { var request = new PacketBuilder(PacketFamily.Welcome, PacketAction.Agree) - .AddChar((byte) InitFileType.Map) + .AddChar((byte)InitFileType.Map) + .AddShort(playerID) + .AddShort(mapID) .Build(); return await GetMapFile(request, mapID, false); @@ -41,10 +43,12 @@ public async Task RequestMapFileForWarp(short mapID) return await GetMapFile(request, mapID, true); } - public async Task RequestFile(InitFileType fileType) + public async Task RequestFile(InitFileType fileType, short playerID) { var request = new PacketBuilder(PacketFamily.Welcome, PacketAction.Agree) - .AddChar((byte) fileType) + .AddChar((byte)fileType) + .AddShort(playerID) + .AddChar(1) // file id (for chunking oversize pub files) .Build(); var response = await _packetSendService.SendEncodedPacketAndWaitAsync(request); @@ -101,10 +105,10 @@ private static bool PacketIsValid(IPacket packet) public interface IFileRequestService { - Task RequestMapFile(short mapID); + Task RequestMapFile(short mapID, short playerID); Task RequestMapFileForWarp(short mapID); - Task RequestFile(InitFileType fileType); + Task RequestFile(InitFileType fileType, short playerID); } } \ No newline at end of file diff --git a/EOLib/Net/Translators/LoginRequestCompletedPacketTranslator.cs b/EOLib/Net/Translators/LoginRequestCompletedPacketTranslator.cs index 2a63c2e0b..332d9171e 100644 --- a/EOLib/Net/Translators/LoginRequestCompletedPacketTranslator.cs +++ b/EOLib/Net/Translators/LoginRequestCompletedPacketTranslator.cs @@ -17,8 +17,18 @@ public LoginRequestCompletedPacketTranslator(ICharacterFromPacketFactory charact public override ILoginRequestCompletedData TranslatePacket(IPacket packet) { var reply = (CharacterLoginReply)packet.ReadShort(); - if (reply != CharacterLoginReply.RequestCompleted) + + if (reply == CharacterLoginReply.RequestDenied) + { + if (packet.ReadEndString() != "NO") + throw new MalformedPacketException("Expected NO bytes in CharacterLoginReply login", packet); + + return new LoginRequestCompletedData().WithError(reply); + } + else if (reply != CharacterLoginReply.RequestCompleted) + { throw new MalformedPacketException("Unexpected welcome response in packet: " + reply, packet); + } if (packet.ReadByte() != 255) throw new MalformedPacketException("Missing 255 byte separator after CharacterLoginReply type", packet); diff --git a/EndlessClient/Controllers/LoginController.cs b/EndlessClient/Controllers/LoginController.cs index af7cb7e20..13d713aff 100644 --- a/EndlessClient/Controllers/LoginController.cs +++ b/EndlessClient/Controllers/LoginController.cs @@ -173,14 +173,22 @@ public async Task LoginToCharacter(ICharacter character) if (!await completeCharacterLoginOperation.Invoke()) return; + if (completeCharacterLoginOperation.Result == CharacterLoginReply.RequestDenied) + { + // https://discord.com/channels/723989119503696013/787685796055482368/946634672295784509 + // Sausage: 'I have WELCOME_REPLY 3 as returning a "server is busy" message if you send it and then disconnect the client' + _errorDisplayAction.ShowLoginError(LoginReply.Busy); + _gameStateActions.ChangeToState(GameStates.Initial); + return; + } + AddDefaultTextToChat(); await Task.Delay(1000); //always wait 1 second } finally { - if (gameLoadingDialog != null) - gameLoadingDialog.CloseDialog(); + gameLoadingDialog?.CloseDialog(); } _gameStateActions.ChangeToState(GameStates.PlayingTheGame); @@ -203,12 +211,12 @@ private void SetInitialStateAndShowError(EmptyPacketReceivedException ex) _errorDisplayAction.ShowException(ex); } - private async Task InitialDelayInReleaseMode() + private Task InitialDelayInReleaseMode() { #if DEBUG - await Task.FromResult(false); //no-op in debug + return Task.Delay(2000); #else - await Task.Delay(5000); + return Task.Delay(5000); #endif } diff --git a/EndlessClient/UIControls/CharacterInfoPanel.cs b/EndlessClient/UIControls/CharacterInfoPanel.cs index d15f47bf8..f309baa6d 100644 --- a/EndlessClient/UIControls/CharacterInfoPanel.cs +++ b/EndlessClient/UIControls/CharacterInfoPanel.cs @@ -174,7 +174,7 @@ protected virtual void DoDrawLogic(GameTime gameTime) { _characterControl.Draw(gameTime); - if (_adminGraphic.HasTexture) + if (_adminGraphic.HasTexture && !_spriteBatch.IsDisposed) { _spriteBatch.Begin(); _spriteBatch.Draw(_adminGraphic.SheetTexture, GetAdminGraphicLocation(), _adminGraphic.SourceRectangle, Color.White); From 078ebb40e7b83f0eed39a610242696d552bf4608 Mon Sep 17 00:00:00 2001 From: Ethan Moffat Date: Thu, 24 Feb 2022 22:15:26 -0800 Subject: [PATCH 2/3] Minor fixes to PacketDecoder - Remove messagebox call when using invalid value for send/recv multiples - Show decoded data in packet view --- PacketDecoder/MainForm.cs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/PacketDecoder/MainForm.cs b/PacketDecoder/MainForm.cs index e63f97d3e..ea96754af 100644 --- a/PacketDecoder/MainForm.cs +++ b/PacketDecoder/MainForm.cs @@ -1,4 +1,5 @@ using System; +using System.Drawing; using System.IO; using System.Windows.Forms; using EOLib.Config; @@ -110,13 +111,25 @@ private void intTextValidate(object sender, EventArgs e) { _packetProcessActions.SetEncodeMultiples((byte)param, _packetEncoderRepository.SendMultiplier); if (param < 6 || param > 12) - MessageBox.Show("This should be between 6 and 12...", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning); + { + txtDMulti.BackColor = Color.FromArgb(255, 255, 128, 128); + } + else + { + txtDMulti.BackColor = Color.White; + } } else if (txt == txtEMulti) { _packetProcessActions.SetEncodeMultiples(_packetEncoderRepository.ReceiveMultiplier, (byte)param); if (param < 6 || param > 12) - MessageBox.Show("This should be between 6 and 12...", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning); + { + txtEMulti.BackColor = Color.FromArgb(255, 255, 128, 128); + } + else + { + txtEMulti.BackColor = Color.White; + } } else if (txt == txtOffset) { @@ -169,9 +182,9 @@ private void _checkRequiredInputs() lblAction.Text = pkt.Action.ToString(); string decoded = ""; - for (int i = 0; i < data.Length; i++) + for (int i = 0; i < pkt.Length; i++) { - decoded += $"{data[i].ToString("D3")} "; + decoded += $"{pkt.RawData[i].ToString("D3")} "; } txtDecoded.Text = decoded; From 9498d6e4ca2431b49d72d2ceb78c87080e5cc3f9 Mon Sep 17 00:00:00 2001 From: Ethan Moffat Date: Thu, 24 Feb 2022 22:25:25 -0800 Subject: [PATCH 3/3] Fix tests (use Select to cast to byte instead of Cast()) --- EOLib.IO/Services/NumberEncoderService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EOLib.IO/Services/NumberEncoderService.cs b/EOLib.IO/Services/NumberEncoderService.cs index 424ecc1a8..ec07ee9b6 100644 --- a/EOLib.IO/Services/NumberEncoderService.cs +++ b/EOLib.IO/Services/NumberEncoderService.cs @@ -32,7 +32,7 @@ public byte[] EncodeNumber(int number, int size) numArray[0] = unsigned + 1; - return numArray.Cast() + return numArray.Select(x => (byte)x) .Take(size) .ToArray(); }