fix: Moves the rest of the Incoming packets (#1338)

This commit is contained in:
Marcelo Paez Sequeira 2023-02-11 03:59:36 -03:00 committed by GitHub
parent a8d8db8f59
commit b46544d752
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 71 additions and 25 deletions

View file

@ -1,27 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ContainerGridPacketHandler.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 <http://www.gnu.org/licenses/>. *
*************************************************************************/
namespace Server.Network;
public unsafe class ContainerGridPacketHandler : PacketHandler
{
public ContainerGridPacketHandler(int packetID, int length, bool ingame,
delegate*<NetState, CircularBufferReader, int, void> onReceive)
: base(packetID, length, ingame, onReceive)
{
}
public override int GetLength(NetState ns) => base.GetLength(ns) + (ns.ContainerGridLines ? 1 : 0);
}

View file

@ -1,133 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingItemPackets.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 <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System.Collections.Generic;
using System.IO;
using Server.Items;
namespace Server.Network;
public static class IncomingItemPackets
{
public static unsafe void Configure()
{
IncomingPackets.Register(0x07, 7, true, &LiftReq);
IncomingPackets.Register(new ContainerGridPacketHandler(0x08, 14, true, &DropReq));
IncomingPackets.Register(0x13, 10, true, &EquipReq);
IncomingPackets.Register(0xEC, 0, false, &EquipMacro);
IncomingPackets.Register(0xED, 0, false, &UnequipMacro);
}
public static void LiftReq(NetState state, CircularBufferReader reader, int packetLength)
{
var serial = (Serial)reader.ReadUInt32();
int amount = reader.ReadUInt16();
var item = World.FindItem(serial);
state.Mobile.Lift(item, amount, out _, out _);
}
public static void EquipReq(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
var item = from.Holding;
var valid = item != null && item.HeldBy == from && item.Map == Map.Internal;
from.Holding = null;
if (!valid)
{
return;
}
reader.Seek(5, SeekOrigin.Current);
var to = World.FindMobile((Serial)reader.ReadUInt32()) ?? from;
if (!to.AllowEquipFrom(from) || !to.EquipItem(item))
{
item.Bounce(from);
}
item.ClearBounce();
}
public static void DropReq(NetState state, CircularBufferReader reader, int packetLength)
{
reader.ReadInt32(); // serial, ignored
int x = reader.ReadInt16();
int y = reader.ReadInt16();
int z = reader.ReadSByte();
if (state.ContainerGridLines)
{
reader.ReadByte(); // Grid Location?
}
Serial dest = (Serial)reader.ReadUInt32();
var loc = new Point3D(x, y, z);
var from = state.Mobile;
if (dest.IsMobile)
{
from.Drop(World.FindMobile(dest), loc);
}
else if (dest.IsItem)
{
var item = World.FindItem(dest);
if (item is BaseMulti multi && multi.AllowsRelativeDrop)
{
loc.m_X += multi.X;
loc.m_Y += multi.Y;
from.Drop(loc);
}
else
{
from.Drop(item, loc);
}
}
else
{
from.Drop(loc);
}
}
public static void EquipMacro(NetState state, CircularBufferReader reader, int packetLength)
{
int count = reader.ReadByte();
var serialList = new List<Serial>(count);
for (var i = 0; i < count; ++i)
{
serialList.Add((Serial)reader.ReadUInt32());
}
EventSink.InvokeEquipMacro(state.Mobile, serialList);
}
public static void UnequipMacro(NetState state, CircularBufferReader reader, int packetLength)
{
int count = reader.ReadByte();
var layers = new List<Layer>(count);
for (var i = 0; i < count; ++i)
{
layers.Add((Layer)reader.ReadUInt16());
}
EventSink.InvokeUnequipMacro(state.Mobile, layers);
}
}

View file

@ -1,159 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingMessagePackets.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 <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
namespace Server.Network;
[Flags]
public enum MessageType
{
Regular = 0x00,
System = 0x01,
Emote = 0x02,
Label = 0x06,
Focus = 0x07,
Whisper = 0x08,
Yell = 0x09,
Spell = 0x0A,
Guild = 0x0D,
Alliance = 0x0E,
Command = 0x0F,
Encoded = 0xC0
}
public static class IncomingMessagePackets
{
private static readonly KeywordList m_KeywordList = new();
public static unsafe void Configure()
{
IncomingPackets.Register(0x03, 0, true, &AsciiSpeech);
IncomingPackets.Register(0xAD, 0, true, &UnicodeSpeech);
}
public static void AsciiSpeech(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
if (from == null)
{
return;
}
var type = (MessageType)reader.ReadByte();
int hue = reader.ReadInt16();
reader.ReadInt16(); // font
var text = reader.ReadAsciiSafe().Trim();
if (text.Length is <= 0 or > 128)
{
return;
}
if (!Enum.IsDefined(typeof(MessageType), type))
{
type = MessageType.Regular;
}
from.DoSpeech(text, Array.Empty<int>(), type, Utility.ClipDyedHue(hue));
}
public static void UnicodeSpeech(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
if (from == null)
{
return;
}
var type = (MessageType)reader.ReadByte();
int hue = reader.ReadInt16();
reader.ReadInt16(); // font
var lang = reader.ReadAscii(4);
string text;
var isEncoded = (type & MessageType.Encoded) != 0;
int[] keywords;
if (isEncoded)
{
int value = reader.ReadInt16();
var count = (value & 0xFFF0) >> 4;
var hold = value & 0xF;
if (count is < 0 or > 50)
{
return;
}
var keyList = m_KeywordList;
for (var i = 0; i < count; ++i)
{
int speechID;
if ((i & 1) == 0)
{
hold <<= 8;
hold |= reader.ReadByte();
speechID = hold;
hold = 0;
}
else
{
value = reader.ReadInt16();
speechID = (value & 0xFFF0) >> 4;
hold = value & 0xF;
}
if (!keyList.Contains(speechID))
{
keyList.Add(speechID);
}
}
text = reader.ReadUTF8Safe();
keywords = keyList.ToArray();
}
else
{
text = reader.ReadBigUniSafe();
keywords = Array.Empty<int>();
}
text = text.Trim();
if (text.Length is <= 0 or > 128)
{
return;
}
type &= ~MessageType.Encoded;
if (!Enum.IsDefined(typeof(MessageType), type))
{
type = MessageType.Regular;
}
from.Language = lang;
from.DoSpeech(text, keywords, type, Utility.ClipDyedHue(hue));
}
}

View file

@ -1,165 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingMobilePackets.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 <http://www.gnu.org/licenses/>. *
*************************************************************************/
using Server.Items;
namespace Server.Network;
public static class IncomingMobilePackets
{
public static unsafe void Configure()
{
IncomingPackets.Register(0x75, 35, true, &RenameRequest);
IncomingPackets.Register(0x98, 0, true, &MobileNameRequest);
IncomingPackets.Register(0xB8, 0, true, &ProfileReq);
IncomingPackets.Register(0x6F, 0, true, &SecureTrade);
}
public static void RenameRequest(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
var targ = World.FindMobile((Serial)reader.ReadUInt32());
if (targ != null)
{
EventSink.InvokeRenameRequest(from, targ, reader.ReadAsciiSafe());
}
}
public static void MobileNameRequest(NetState state, CircularBufferReader reader, int packetLength)
{
var m = World.FindMobile((Serial)reader.ReadUInt32());
if (m != null && Utility.InUpdateRange(state.Mobile.Location, m.Location) && state.Mobile.CanSee(m))
{
state.SendMobileName(m);
}
}
public static void ProfileReq(NetState state, CircularBufferReader reader, int packetLength)
{
int type = reader.ReadByte();
var serial = (Serial)reader.ReadUInt32();
var beholder = state.Mobile;
var beheld = World.FindMobile(serial);
if (beheld == null)
{
return;
}
switch (type)
{
case 0x00: // display request
{
EventSink.InvokeProfileRequest(beholder, beheld);
break;
}
case 0x01: // edit request
{
reader.ReadInt16(); // Skip
int length = reader.ReadUInt16();
if (length > 511)
{
return;
}
var text = reader.ReadBigUni(length);
EventSink.InvokeChangeProfileRequest(beholder, beheld, text);
break;
}
}
}
public static void SecureTrade(NetState state, CircularBufferReader reader, int packetLength)
{
switch (reader.ReadByte())
{
case 1: // Cancel
{
var serial = (Serial)reader.ReadUInt32();
if (World.FindItem(serial) is SecureTradeContainer cont && cont.Trade != null &&
(cont.Trade.From.Mobile == state.Mobile || cont.Trade.To.Mobile == state.Mobile))
{
cont.Trade.Cancel();
}
break;
}
case 2: // Check
{
var serial = (Serial)reader.ReadUInt32();
if (World.FindItem(serial) is SecureTradeContainer cont)
{
var trade = cont.Trade;
var value = reader.ReadInt32() != 0;
if (trade != null)
{
if (trade.From.Mobile == state.Mobile)
{
trade.From.Accepted = value;
trade.Update();
}
else if (trade.To.Mobile == state.Mobile)
{
trade.To.Accepted = value;
trade.Update();
}
}
}
break;
}
case 3: // Update Gold
{
var serial = (Serial)reader.ReadUInt32();
if (World.FindItem(serial) is SecureTradeContainer cont)
{
var gold = reader.ReadInt32();
var plat = reader.ReadInt32();
var trade = cont.Trade;
if (trade != null)
{
if (trade.From.Mobile == state.Mobile)
{
trade.From.Gold = gold;
trade.From.Plat = plat;
trade.UpdateFromCurrency();
}
else if (trade.To.Mobile == state.Mobile)
{
trade.To.Gold = gold;
trade.To.Plat = plat;
trade.UpdateToCurrency();
}
}
}
}
break;
}
}
}

View file

@ -1,111 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingMovementPackets.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 <http://www.gnu.org/licenses/>. *
*************************************************************************/
namespace Server.Network;
public static class IncomingMovementPackets
{
public static unsafe void Configure()
{
IncomingPackets.Register(0x02, 7, true, &MovementReq);
// Not used by OSI, and interferes with ClassicUO/Razor protocol extensions
// IncomingPackets.Register(0xF0, 0, true, NewMovementReq);
// IncomingPackets.Register(0xF1, 9, true, TimeSyncReq);
}
public static void NewMovementReq(NetState ns, CircularBufferReader reader)
{
var from = ns.Mobile;
if (from == null)
{
return;
}
var steps = reader.ReadByte();
for (int i = 0; i < steps; i++)
{
var t1 = reader.ReadUInt64(); // start time?
var t2 = reader.ReadUInt64(); // end time?
int seq = reader.ReadByte();
var dir = (Direction)reader.ReadByte();
var mode = reader.ReadInt32(); // 1 = walk, 2 = run
if (mode == 2)
{
dir |= Direction.Running;
}
// Location
reader.ReadInt32(); // x
reader.ReadInt32(); // y
reader.ReadInt32(); // z
if (ns.Sequence == 0 && seq != 0 || !from.Move(dir))
{
ns.SendMovementRej(seq, from);
ns.Sequence = 0;
}
else
{
++seq;
if (seq == 256)
{
seq = 1;
}
ns.Sequence = seq;
}
}
}
public static void TimeSyncReq(NetState ns, CircularBufferReader reader)
{
reader.ReadUInt64(); // Client Time?
ns.SendTimeSyncResponse();
}
public static void MovementReq(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
if (from == null)
{
return;
}
var dir = (Direction)reader.ReadByte();
int seq = reader.ReadByte();
var key = reader.ReadUInt32();
if (state.Sequence == 0 && seq != 0 || !from.Move(dir))
{
state.SendMovementRej(seq, from);
state.Sequence = 0;
}
else
{
++seq;
if (seq == 256)
{
seq = 1;
}
state.Sequence = seq;
}
}
}

View file

@ -1,632 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingPlayerPackets.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 <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System.Diagnostics;
using Microsoft.Toolkit.HighPerformance;
using Server.Diagnostics;
using Server.Exceptions;
using Server.Gumps;
namespace Server.Network;
public static class IncomingPlayerPackets
{
public static unsafe void Configure()
{
IncomingPackets.Register(0x01, 5, false, &Disconnect);
IncomingPackets.Register(0x05, 5, true, &AttackReq);
IncomingPackets.Register(0x12, 0, true, &TextCommand);
IncomingPackets.Register(0x22, 3, true, &Resynchronize);
IncomingPackets.Register(0x2C, 2, true, &DeathStatusResponse);
IncomingPackets.Register(0x34, 10, true, &MobileQuery);
IncomingPackets.Register(0x3A, 0, true, &ChangeSkillLock);
IncomingPackets.Register(0x72, 5, true, &SetWarMode);
IncomingPackets.Register(0x73, 2, false, &PingReq);
IncomingPackets.Register(0x7D, 13, true, &MenuResponse);
IncomingPackets.Register(0x95, 9, true, &HuePickerResponse);
IncomingPackets.Register(0x9A, 0, true, &AsciiPromptResponse);
IncomingPackets.Register(0x9B, 258, true, &HelpRequest);
IncomingPackets.Register(0xA4, 149, false, &SystemInfo);
IncomingPackets.Register(0xA7, 4, true, &RequestScrollWindow);
IncomingPackets.Register(0xB1, 0, true, &DisplayGumpResponse);
IncomingPackets.Register(0xC2, 0, true, &UnicodePromptResponse);
IncomingPackets.Register(0xC8, 2, true, &SetUpdateRange);
IncomingPackets.Register(0xD0, 0, true, &ConfigurationFile);
IncomingPackets.Register(0xD1, 2, true, &LogoutReq);
IncomingPackets.Register(0xD7, 0, true, &EncodedCommand);
IncomingPackets.Register(0xF4, 0, false, &CrashReport);
IncomingPackets.RegisterEncoded(0x28, true, &GuildGumpRequest);
IncomingPackets.RegisterEncoded(0x32, true, &QuestGumpRequest);
}
public static void DeathStatusResponse(NetState state, CircularBufferReader reader, int packetLength)
{
// Ignored
}
public static void RequestScrollWindow(NetState state, CircularBufferReader reader, int packetLength)
{
int lastTip = reader.ReadInt16();
int type = reader.ReadByte();
}
public static void AttackReq(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
if (from == null)
{
return;
}
var m = World.FindMobile((Serial)reader.ReadUInt32());
if (m != null)
{
from.Attack(m);
}
}
public static void HuePickerResponse(NetState state, CircularBufferReader reader, int packetLength)
{
var serial = reader.ReadUInt32();
_ = reader.ReadInt16(); // Item ID
var hue = Utility.ClipDyedHue(reader.ReadInt16() & 0x3FFF);
foreach (var huePicker in state.HuePickers)
{
if (huePicker.Serial == serial)
{
state.RemoveHuePicker(huePicker);
huePicker.OnResponse(hue);
break;
}
}
}
public static void SystemInfo(NetState state, CircularBufferReader reader, int packetLength)
{
int v1 = reader.ReadByte();
int v2 = reader.ReadUInt16();
int v3 = reader.ReadByte();
var s1 = reader.ReadAscii(32);
var s2 = reader.ReadAscii(32);
var s3 = reader.ReadAscii(32);
var s4 = reader.ReadAscii(32);
int v4 = reader.ReadUInt16();
int v5 = reader.ReadUInt16();
var v6 = reader.ReadInt32();
var v7 = reader.ReadInt32();
var v8 = reader.ReadInt32();
}
public static void TextCommand(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
if (from == null)
{
return;
}
int type = reader.ReadByte();
var command = reader.ReadAscii();
switch (type)
{
case 0xC7: // Animate
{
EventSink.InvokeAnimateRequest(from, command);
break;
}
case 0x24: // Use skill
{
var tokenizer = command.Tokenize(' ');
if (!tokenizer.MoveNext() || !int.TryParse(tokenizer.Current, out var skillIndex))
{
break;
}
Skills.UseSkill(from, skillIndex);
break;
}
case 0x43: // Open spellbook
{
if (!int.TryParse(command, out var booktype))
{
booktype = 1;
}
EventSink.InvokeOpenSpellbookRequest(from, booktype);
break;
}
case 0x27: // Cast spell from book
{
var tokenizer = command.Tokenize(' ');
var spellID = (tokenizer.MoveNext() ? Utility.ToInt32(tokenizer.Current) : 0) - 1;
var serial = tokenizer.MoveNext() ? (Serial)Utility.ToUInt32(tokenizer.Current) : Serial.MinusOne;
EventSink.InvokeCastSpellRequest(from, spellID, World.FindItem(serial));
break;
}
case 0x58: // Open door
{
EventSink.InvokeOpenDoorMacroUsed(from);
break;
}
case 0x56: // Cast spell from macro
{
var spellID = Utility.ToInt32(command) - 1;
EventSink.InvokeCastSpellRequest(from, spellID, null);
break;
}
case 0xF4: // Invoke virtues from macro
{
var virtueID = Utility.ToInt32(command) - 1;
EventSink.InvokeVirtueMacroRequest(from, virtueID);
break;
}
case 0x2F: // Old scroll double click
{
/*
* This command is still sent for items 0xEF3 - 0xEF9
*
* Command is one of three, depending on the item ID of the scroll:
* - [scroll serial]
* - [scroll serial] [target serial]
* - [scroll serial] [x] [y] [z]
*/
break;
}
default:
{
state.LogInfo($"Unknown text-command type 0x{state:X2}: {type} ({command})");
break;
}
}
}
public static void AsciiPromptResponse(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
if (from == null)
{
return;
}
var serial = reader.ReadUInt32();
var prompt = reader.ReadInt32();
var type = reader.ReadInt32();
var text = reader.ReadAsciiSafe();
if (text.Length > 128)
{
return;
}
var p = from.Prompt;
if (p?.Serial == serial && p.Serial == prompt)
{
from.Prompt = null;
if (type == 0)
{
p.OnCancel(from);
}
else
{
p.OnResponse(from, text);
}
}
}
public static void UnicodePromptResponse(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
if (from == null)
{
return;
}
var serial = reader.ReadUInt32();
var prompt = reader.ReadInt32();
var type = reader.ReadInt32();
var lang = reader.ReadAscii(4);
var text = reader.ReadLittleUniSafe();
if (text.Length > 128)
{
return;
}
var p = from.Prompt;
if (p?.Serial == serial && p.Serial == prompt)
{
from.Prompt = null;
if (type == 0)
{
p.OnCancel(from);
}
else
{
p.OnResponse(from, text);
}
}
}
public static void MenuResponse(NetState state, CircularBufferReader reader, int packetLength)
{
var serial = reader.ReadUInt32();
int menuID = reader.ReadInt16(); // unused in our implementation
int index = reader.ReadInt16();
int itemID = reader.ReadInt16();
int hue = reader.ReadInt16();
index -= 1; // convert from 1-based to 0-based
foreach (var menu in state.Menus)
{
if (menu.Serial == serial)
{
state.RemoveMenu(menu);
if (index >= 0 && index < menu.EntryLength)
{
menu.OnResponse(state, index);
}
else
{
menu.OnCancel(state);
}
break;
}
}
}
public static void Disconnect(NetState state, CircularBufferReader reader, int packetLength)
{
var minusOne = reader.ReadInt32();
}
public static void ConfigurationFile(NetState state, CircularBufferReader reader, int packetLength)
{
}
public static void LogoutReq(NetState state, CircularBufferReader reader, int packetLength)
{
state.SendLogoutAck();
}
public static void ChangeSkillLock(NetState state, CircularBufferReader reader, int packetLength)
{
var s = state.Mobile.Skills[reader.ReadInt16()];
s?.SetLockNoRelay((SkillLock)reader.ReadByte());
}
public static void HelpRequest(NetState state, CircularBufferReader reader, int packetLength)
{
EventSink.InvokeHelpRequest(state.Mobile);
}
public static void DisplayGumpResponse(NetState state, CircularBufferReader reader, int packetLength)
{
var serial = (Serial)reader.ReadUInt32();
var typeID = reader.ReadInt32();
var buttonID = reader.ReadInt32();
foreach (var gump in state.Gumps)
{
if (gump.Serial != serial || gump.TypeID != typeID)
{
continue;
}
var buttonExists = buttonID == 0; // 0 is always 'close'
if (!buttonExists)
{
foreach (var e in gump.Entries)
{
if (e is GumpButton button && button.ButtonID == buttonID)
{
buttonExists = true;
break;
}
if (e is GumpImageTileButton tileButton && tileButton.ButtonID == buttonID)
{
buttonExists = true;
break;
}
}
}
if (!buttonExists)
{
state.LogInfo("Invalid gump response, disconnecting...");
var exception = new InvalidGumpResponseException($"Button {buttonID} doesn't exist");
exception.SetStackTrace(new StackTrace());
NetState.TraceException(exception);
state.Mobile?.SendMessage("Invalid gump response.");
// state.Disconnect("Invalid gump response.");
return;
}
var switchCount = reader.ReadInt32();
if (switchCount < 0 || switchCount > gump.m_Switches)
{
state.LogInfo("Invalid gump response, disconnecting...");
var exception = new InvalidGumpResponseException($"Bad switch count {switchCount}");
exception.SetStackTrace(new StackTrace());
NetState.TraceException(exception);
state.Mobile?.SendMessage("Invalid gump response.");
// state.Disconnect("Invalid gump response.");
return;
}
var switches = new int[switchCount];
for (var i = 0; i < switches.Length; ++i)
{
switches[i] = reader.ReadInt32();
}
var textCount = reader.ReadInt32();
if (textCount < 0 || textCount > gump.m_TextEntries)
{
state.LogInfo("Invalid gump response, disconnecting...");
var exception = new InvalidGumpResponseException($"Bad text entry count {textCount}");
exception.SetStackTrace(new StackTrace());
NetState.TraceException(exception);
state.Mobile?.SendMessage("Invalid gump response.");
// state.Disconnect("Invalid gump response.");
return;
}
var textEntries = new TextRelay[textCount];
for (var i = 0; i < textEntries.Length; ++i)
{
int entryID = reader.ReadUInt16();
int textLength = reader.ReadUInt16();
if (textLength > 239)
{
state.LogInfo("Invalid gump response, disconnecting...");
var exception = new InvalidGumpResponseException($"Text entry {i} is too long ({textLength})");
exception.SetStackTrace(new StackTrace());
NetState.TraceException(exception);
state.Mobile?.SendMessage("Invalid gump response.");
// state.Disconnect("Invalid gump response.");
return;
}
var text = reader.ReadBigUniSafe(textLength);
textEntries[i] = new TextRelay(entryID, text);
}
state.RemoveGump(gump);
var prof = GumpProfile.Acquire(gump.GetType());
prof?.Start();
gump.OnResponse(state, new RelayInfo(buttonID, switches, textEntries));
prof?.Finish();
return;
}
if (typeID == 461)
{
// Virtue gump
var switchCount = reader.Remaining >= 4 ? reader.ReadInt32() : 0;
if (buttonID == 1 && switchCount > 0)
{
var beheld = World.FindMobile((Serial)reader.ReadUInt32());
if (beheld != null)
{
EventSink.InvokeVirtueGumpRequest(state.Mobile, beheld);
}
}
else
{
var beheld = World.FindMobile(serial);
if (beheld != null)
{
EventSink.InvokeVirtueItemRequest(state.Mobile, beheld, buttonID);
}
}
}
}
public static void SetWarMode(NetState state, CircularBufferReader reader, int packetLength)
{
state.Mobile?.DelayChangeWarmode(reader.ReadBoolean());
}
// TODO: Throttle/make this more safe
public static void Resynchronize(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
if (from == null)
{
return;
}
state.SendMobileUpdate(from);
state.SendMobileIncoming(from, from);
from.SendEverything();
state.Sequence = 0;
}
public static void PingReq(NetState state, CircularBufferReader reader, int packetLength)
{
state.SendPingAck(reader.ReadByte());
}
public static void SetUpdateRange(NetState state, CircularBufferReader reader, int packetLength)
{
state.SendChangeUpdateRange(18);
}
public static void MobileQuery(NetState state, CircularBufferReader reader, int packetLength)
{
var from = state.Mobile;
if (from == null)
{
return;
}
reader.ReadInt32(); // 0xEDEDEDED
int type = reader.ReadByte();
var m = World.FindMobile((Serial)reader.ReadUInt32());
if (m == null)
{
return;
}
switch (type)
{
case 0x04: // Stats
{
m.OnStatsQuery(from);
break;
}
case 0x05:
{
m.OnSkillsQuery(from);
break;
}
default:
{
reader.Trace(state);
break;
}
}
}
public static void CrashReport(NetState state, CircularBufferReader reader, int packetLength)
{
var clientMaj = reader.ReadByte();
var clientMin = reader.ReadByte();
var clientRev = reader.ReadByte();
var clientPat = reader.ReadByte();
var x = reader.ReadUInt16();
var y = reader.ReadUInt16();
var z = reader.ReadSByte();
var map = reader.ReadByte();
var account = reader.ReadAscii(32);
var character = reader.ReadAscii(32);
var ip = reader.ReadAscii(15);
var unk1 = reader.ReadInt32();
var exception = reader.ReadInt32();
var process = reader.ReadAscii(100);
var report = reader.ReadAscii(100);
reader.ReadByte(); // 0x00
var offset = reader.ReadInt32();
int count = reader.ReadByte();
for (var i = 0; i < count; i++)
{
var address = reader.ReadInt32();
}
}
public static void GuildGumpRequest(NetState state, IEntity e, EncodedReader reader)
{
EventSink.InvokeGuildGumpRequest(state.Mobile);
}
public static void QuestGumpRequest(NetState state, IEntity e, EncodedReader reader)
{
EventSink.InvokeQuestGumpRequest(state.Mobile);
}
public static unsafe void EncodedCommand(NetState state, CircularBufferReader reader, int packetLength)
{
var e = World.FindEntity((Serial)reader.ReadUInt32());
int packetId = reader.ReadUInt16();
// We will add support if this is ever a real thing.
if (packetId > 0xFF)
{
var reason = $"Sent unsupported encoded packet (0xD7x{packetId:X4}";
state.LogInfo(reason);
state.Disconnect(reason);
}
var ph = IncomingPackets.GetEncodedHandler(packetId);
if (ph == null)
{
reader.Trace(state);
return;
}
if (ph.Ingame && state.Mobile == null)
{
var reason = $"Sent in-game packet (0xD7x{packetId:X4}) before being attached to a mobile.";
state.LogInfo(reason);
state.Disconnect(reason);
}
else if (ph.Ingame && state.Mobile.Deleted)
{
state.Disconnect($"Sent in-game packet(0xD7x{packetId:X4}) but mobile is deleted.");
}
else
{
ph.OnReceive(state, e, new EncodedReader(reader));
}
}
}

View file

@ -1,144 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingTargetingPackets.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 <http://www.gnu.org/licenses/>. *
*************************************************************************/
using Server.Diagnostics;
using Server.Targeting;
namespace Server.Network;
public static class IncomingTargetingPackets
{
public static unsafe void Configure()
{
IncomingPackets.Register(0x6C, 19, true, &TargetResponse);
}
public static void TargetResponse(NetState state, CircularBufferReader reader, int packetLength)
{
int type = reader.ReadByte();
var targetID = reader.ReadInt32();
int flags = reader.ReadByte();
var serial = (Serial)reader.ReadUInt32();
int x = reader.ReadInt16();
int y = reader.ReadInt16();
reader.ReadByte();
int z = reader.ReadSByte();
int graphic = reader.ReadUInt16();
if (targetID == unchecked((int)0xDEADBEEF))
{
return;
}
var from = state.Mobile;
var t = from.Target;
if (t == null)
{
return;
}
var prof = TargetProfile.Acquire(t.GetType());
prof?.Start();
try
{
if (x == -1 && y == -1 && !serial.IsValid)
{
// User pressed escape
t.Cancel(from, TargetCancelType.Canceled);
}
else if (t.TargetID == targetID)
{
object toTarget;
if (type == 1)
{
if (graphic == 0)
{
toTarget = new LandTarget(new Point3D(x, y, z), from.Map);
}
else
{
var map = from.Map;
if (map == null || map == Map.Internal)
{
t.Cancel(from, TargetCancelType.Canceled);
return;
}
else
{
var tiles = map.Tiles.GetStaticTiles(x, y, !t.DisallowMultis);
var valid = false;
if (state.HighSeas)
{
var id = TileData.ItemTable[graphic & TileData.MaxItemValue];
if (id.Surface)
{
z -= id.Height;
}
}
int hue = 0;
for (var i = 0; !valid && i < tiles.Length; ++i)
{
var tile = tiles[i];
if (tile.Z == z && tile.ID == graphic)
{
valid = true;
hue = tile.Hue;
}
}
if (!valid)
{
t.Cancel(from, TargetCancelType.Canceled);
return;
}
else
{
toTarget = new StaticTarget(new Point3D(x, y, z), graphic, hue);
}
}
}
}
else if (serial.IsMobile)
{
toTarget = World.FindMobile(serial);
}
else if (serial.IsItem)
{
toTarget = World.FindItem(serial);
}
else
{
t.Cancel(from, TargetCancelType.Canceled);
return;
}
t.Invoke(from, toTarget);
}
}
finally
{
prof?.Finish();
}
}
}

View file

@ -1,109 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingVendorPackets.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 <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System.Collections.Generic;
namespace Server.Network;
public static class IncomingVendorPackets
{
public static unsafe void Configure()
{
IncomingPackets.Register(0x3B, 0, true, &VendorBuyReply);
IncomingPackets.Register(0x9F, 0, true, &VendorSellReply);
}
public static void VendorBuyReply(NetState state, CircularBufferReader reader, int packetLength)
{
var vendor = World.FindMobile((Serial)reader.ReadUInt32());
if (vendor == null)
{
return;
}
var flag = reader.ReadByte();
if (!vendor.Deleted && Utility.InRange(vendor.Location, state.Mobile.Location, 10) && flag == 0x02)
{
var msgSize = packetLength - 8; // Remaining bytes
if (msgSize / 7 > 100)
{
return;
}
var buyList = new List<BuyItemResponse>(msgSize / 7);
while (msgSize > 0)
{
var layer = reader.ReadByte();
var serial = (Serial)reader.ReadUInt32();
int amount = reader.ReadInt16();
buyList.Add(new BuyItemResponse(serial, amount));
msgSize -= 7;
}
if (buyList.Count <= 0 || (vendor as IVendor)?.OnBuyItems(state.Mobile, buyList) != true)
{
return;
}
}
state.SendEndVendorBuy(vendor.Serial);
}
public static void VendorSellReply(NetState state, CircularBufferReader reader, int packetLength)
{
var serial = (Serial)reader.ReadUInt32();
var vendor = World.FindMobile(serial);
if (vendor == null)
{
return;
}
if (vendor.Deleted || !Utility.InRange(vendor.Location, state.Mobile.Location, 10))
{
state.SendEndVendorSell(vendor.Serial);
return;
}
int count = reader.ReadUInt16();
if (count >= 100 || reader.Remaining != count * 6)
{
return;
}
var sellList = new List<SellItemResponse>(count);
for (var i = 0; i < count; i++)
{
var item = World.FindItem((Serial)reader.ReadUInt32());
int amount = reader.ReadInt16();
if (item != null && amount > 0)
{
sellList.Add(new SellItemResponse(item, amount));
}
}
if (sellList.Count > 0 && vendor is IVendor v && v.OnSellItems(state.Mobile, sellList))
{
state.SendEndVendorSell(vendor.Serial);
}
}
}