Fixes formatting (#200)

This commit is contained in:
Kamron Batman 2020-08-25 18:53:35 -07:00 committed by GitHub
parent 1f651992d7
commit 86b7b3aed1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
209 changed files with 51326 additions and 50397 deletions

View file

@ -1,40 +1,40 @@
/***************************************************************************
* EncodedPacketHandler.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
namespace Server.Network
{
public delegate void OnEncodedPacketReceive(NetState state, IEntity ent, EncodedReader pvSrc);
public class EncodedPacketHandler
{
public EncodedPacketHandler(int packetID, bool ingame, OnEncodedPacketReceive onReceive)
{
PacketID = packetID;
Ingame = ingame;
OnReceive = onReceive;
}
public int PacketID { get; }
public OnEncodedPacketReceive OnReceive { get; }
public bool Ingame { get; }
}
}
/***************************************************************************
* EncodedPacketHandler.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
namespace Server.Network
{
public delegate void OnEncodedPacketReceive(NetState state, IEntity ent, EncodedReader pvSrc);
public class EncodedPacketHandler
{
public EncodedPacketHandler(int packetID, bool ingame, OnEncodedPacketReceive onReceive)
{
PacketID = packetID;
Ingame = ingame;
OnReceive = onReceive;
}
public int PacketID { get; }
public OnEncodedPacketReceive OnReceive { get; }
public bool Ingame { get; }
}
}

View file

@ -1,46 +1,46 @@
/***************************************************************************
* EncodedReader.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
namespace Server.Network
{
public ref struct EncodedReader
{
private PacketReader m_Reader;
public EncodedReader(PacketReader reader) => m_Reader = reader;
public void Trace(NetState state)
{
m_Reader.Trace(state);
}
public int ReadInt32() => m_Reader.ReadByte() != 0 ? 0 : m_Reader.ReadInt32();
public Point3D ReadPoint3D() => m_Reader.ReadByte() != 3
? Point3D.Zero
: new Point3D(m_Reader.ReadInt16(), m_Reader.ReadInt16(), m_Reader.ReadByte());
public string ReadUnicodeStringSafe() =>
m_Reader.ReadByte() != 2 ? string.Empty : m_Reader.ReadUnicodeStringSafe(m_Reader.ReadUInt16());
public string ReadUnicodeString() =>
m_Reader.ReadByte() != 2 ? string.Empty : m_Reader.ReadUnicodeString(m_Reader.ReadUInt16());
}
}
/***************************************************************************
* EncodedReader.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
namespace Server.Network
{
public ref struct EncodedReader
{
private PacketReader m_Reader;
public EncodedReader(PacketReader reader) => m_Reader = reader;
public void Trace(NetState state)
{
m_Reader.Trace(state);
}
public int ReadInt32() => m_Reader.ReadByte() != 0 ? 0 : m_Reader.ReadInt32();
public Point3D ReadPoint3D() => m_Reader.ReadByte() != 3
? Point3D.Zero
: new Point3D(m_Reader.ReadInt16(), m_Reader.ReadInt16(), m_Reader.ReadByte());
public string ReadUnicodeStringSafe() =>
m_Reader.ReadByte() != 2 ? string.Empty : m_Reader.ReadUnicodeStringSafe(m_Reader.ReadUInt16());
public string ReadUnicodeString() =>
m_Reader.ReadByte() != 2 ? string.Empty : m_Reader.ReadUnicodeString(m_Reader.ReadUInt16());
}
}

View file

@ -1,73 +1,73 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MessagePumpService.cs *
* Created: 2020/04/12 - Updated: 2020/04/12 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Buffers;
using System.Collections.Concurrent;
namespace Server.Network
{
public interface IMessagePumpService
{
void QueueWork(NetState ns, IMemoryOwner<byte> memOwner, int length, OnPacketReceive onReceive);
void DoWork();
}
public class MessagePumpService : IMessagePumpService
{
private readonly ConcurrentQueue<Work> m_WorkQueue = new ConcurrentQueue<Work>();
public void QueueWork(NetState ns, IMemoryOwner<byte> memOwner, int length, OnPacketReceive onReceive)
{
m_WorkQueue.Enqueue(new Work(ns, memOwner, length, onReceive));
Core.Set();
}
public void DoWork()
{
var count = 0;
while (!m_WorkQueue.IsEmpty && count++ < 250)
{
if (!m_WorkQueue.TryDequeue(out var work))
break;
var seq = new ReadOnlySequence<byte>(work.MemoryOwner.Memory.Slice(0, work.Length));
work.OnReceive(work.State, new PacketReader(seq));
work.MemoryOwner.Dispose();
}
}
private class Work
{
public readonly NetState State;
public readonly IMemoryOwner<byte> MemoryOwner;
public readonly int Length;
public readonly OnPacketReceive OnReceive;
public Work(NetState ns, IMemoryOwner<byte> memOwner, int length, OnPacketReceive onReceive)
{
State = ns;
MemoryOwner = memOwner;
OnReceive = onReceive;
Length = length;
}
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MessagePumpService.cs *
* Created: 2020/04/12 - Updated: 2020/04/12 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Buffers;
using System.Collections.Concurrent;
namespace Server.Network
{
public interface IMessagePumpService
{
void QueueWork(NetState ns, IMemoryOwner<byte> memOwner, int length, OnPacketReceive onReceive);
void DoWork();
}
public class MessagePumpService : IMessagePumpService
{
private readonly ConcurrentQueue<Work> m_WorkQueue = new ConcurrentQueue<Work>();
public void QueueWork(NetState ns, IMemoryOwner<byte> memOwner, int length, OnPacketReceive onReceive)
{
m_WorkQueue.Enqueue(new Work(ns, memOwner, length, onReceive));
Core.Set();
}
public void DoWork()
{
var count = 0;
while (!m_WorkQueue.IsEmpty && count++ < 250)
{
if (!m_WorkQueue.TryDequeue(out var work))
break;
var seq = new ReadOnlySequence<byte>(work.MemoryOwner.Memory.Slice(0, work.Length));
work.OnReceive(work.State, new PacketReader(seq));
work.MemoryOwner.Dispose();
}
}
private class Work
{
public readonly int Length;
public readonly IMemoryOwner<byte> MemoryOwner;
public readonly OnPacketReceive OnReceive;
public readonly NetState State;
public Work(NetState ns, IMemoryOwner<byte> memOwner, int length, OnPacketReceive onReceive)
{
State = ns;
MemoryOwner = memOwner;
OnReceive = onReceive;
Length = length;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,170 +1,172 @@
/***************************************************************************
* Compression.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
namespace Server.Network
{
/// <summary>
/// Handles outgoing packet compression for the network.
/// </summary>
public static class NetworkCompression
{
private const int CountIndex = 0;
private const int ValueIndex = 1;
// UO packets may not exceed 64kb in length
private const int BufferSize = 0x10000;
// Optimal compression ratio is 2 / 8; worst compression ratio is 11 / 8
private const int MinimalCodeLength = 2;
private const int MaximalCodeLength = 11;
// Fixed overhead, in bits, per compression call
private const int TerminalCodeLength = 4;
// If our input exceeds this length, we cannot possibly compress it within the buffer
private const int DefiniteOverflow = (BufferSize * 8 - TerminalCodeLength) / MinimalCodeLength;
private static readonly int[] _huffmanTable =
{
0x2, 0x000, 0x5, 0x01F, 0x6, 0x022, 0x7, 0x034, 0x7, 0x075, 0x6, 0x028, 0x6, 0x03B, 0x7, 0x032,
0x8, 0x0E0, 0x8, 0x062, 0x7, 0x056, 0x8, 0x079, 0x9, 0x19D, 0x8, 0x097, 0x6, 0x02A, 0x7, 0x057,
0x8, 0x071, 0x8, 0x05B, 0x9, 0x1CC, 0x8, 0x0A7, 0x7, 0x025, 0x7, 0x04F, 0x8, 0x066, 0x8, 0x07D,
0x9, 0x191, 0x9, 0x1CE, 0x7, 0x03F, 0x9, 0x090, 0x8, 0x059, 0x8, 0x07B, 0x8, 0x091, 0x8, 0x0C6,
0x6, 0x02D, 0x9, 0x186, 0x8, 0x06F, 0x9, 0x093, 0xA, 0x1CC, 0x8, 0x05A, 0xA, 0x1AE, 0xA, 0x1C0,
0x9, 0x148, 0x9, 0x14A, 0x9, 0x082, 0xA, 0x19F, 0x9, 0x171, 0x9, 0x120, 0x9, 0x0E7, 0xA, 0x1F3,
0x9, 0x14B, 0x9, 0x100, 0x9, 0x190, 0x6, 0x013, 0x9, 0x161, 0x9, 0x125, 0x9, 0x133, 0x9, 0x195,
0x9, 0x173, 0x9, 0x1CA, 0x9, 0x086, 0x9, 0x1E9, 0x9, 0x0DB, 0x9, 0x1EC, 0x9, 0x08B, 0x9, 0x085,
0x5, 0x00A, 0x8, 0x096, 0x8, 0x09C, 0x9, 0x1C3, 0x9, 0x19C, 0x9, 0x08F, 0x9, 0x18F, 0x9, 0x091,
0x9, 0x087, 0x9, 0x0C6, 0x9, 0x177, 0x9, 0x089, 0x9, 0x0D6, 0x9, 0x08C, 0x9, 0x1EE, 0x9, 0x1EB,
0x9, 0x084, 0x9, 0x164, 0x9, 0x175, 0x9, 0x1CD, 0x8, 0x05E, 0x9, 0x088, 0x9, 0x12B, 0x9, 0x172,
0x9, 0x10A, 0x9, 0x08D, 0x9, 0x13A, 0x9, 0x11C, 0xA, 0x1E1, 0xA, 0x1E0, 0x9, 0x187, 0xA, 0x1DC,
0xA, 0x1DF, 0x7, 0x074, 0x9, 0x19F, 0x8, 0x08D, 0x8, 0x0E4, 0x7, 0x079, 0x9, 0x0EA, 0x9, 0x0E1,
0x8, 0x040, 0x7, 0x041, 0x9, 0x10B, 0x9, 0x0B0, 0x8, 0x06A, 0x8, 0x0C1, 0x7, 0x071, 0x7, 0x078,
0x8, 0x0B1, 0x9, 0x14C, 0x7, 0x043, 0x8, 0x076, 0x7, 0x066, 0x7, 0x04D, 0x9, 0x08A, 0x6, 0x02F,
0x8, 0x0C9, 0x9, 0x0CE, 0x9, 0x149, 0x9, 0x160, 0xA, 0x1BA, 0xA, 0x19E, 0xA, 0x39F, 0x9, 0x0E5,
0x9, 0x194, 0x9, 0x184, 0x9, 0x126, 0x7, 0x030, 0x8, 0x06C, 0x9, 0x121, 0x9, 0x1E8, 0xA, 0x1C1,
0xA, 0x11D, 0xA, 0x163, 0xA, 0x385, 0xA, 0x3DB, 0xA, 0x17D, 0xA, 0x106, 0xA, 0x397, 0xA, 0x24E,
0x7, 0x02E, 0x8, 0x098, 0xA, 0x33C, 0xA, 0x32E, 0xA, 0x1E9, 0x9, 0x0BF, 0xA, 0x3DF, 0xA, 0x1DD,
0xA, 0x32D, 0xA, 0x2ED, 0xA, 0x30B, 0xA, 0x107, 0xA, 0x2E8, 0xA, 0x3DE, 0xA, 0x125, 0xA, 0x1E8,
0x9, 0x0E9, 0xA, 0x1CD, 0xA, 0x1B5, 0x9, 0x165, 0xA, 0x232, 0xA, 0x2E1, 0xB, 0x3AE, 0xB, 0x3C6,
0xB, 0x3E2, 0xA, 0x205, 0xA, 0x29A, 0xA, 0x248, 0xA, 0x2CD, 0xA, 0x23B, 0xB, 0x3C5, 0xA, 0x251,
0xA, 0x2E9, 0xA, 0x252, 0x9, 0x1EA, 0xB, 0x3A0, 0xB, 0x391, 0xA, 0x23C, 0xB, 0x392, 0xB, 0x3D5,
0xA, 0x233, 0xA, 0x2CC, 0xB, 0x390, 0xA, 0x1BB, 0xB, 0x3A1, 0xB, 0x3C4, 0xA, 0x211, 0xA, 0x203,
0x9, 0x12A, 0xA, 0x231, 0xB, 0x3E0, 0xA, 0x29B, 0xB, 0x3D7, 0xA, 0x202, 0xB, 0x3AD, 0xA, 0x213,
0xA, 0x253, 0xA, 0x32C, 0xA, 0x23D, 0xA, 0x23F, 0xA, 0x32F, 0xA, 0x11C, 0xA, 0x384, 0xA, 0x31C,
0xA, 0x17C, 0xA, 0x30A, 0xA, 0x2E0, 0xA, 0x276, 0xA, 0x250, 0xB, 0x3E3, 0xA, 0x396, 0xA, 0x18F,
0xA, 0x204, 0xA, 0x206, 0xA, 0x230, 0xA, 0x265, 0xA, 0x212, 0xA, 0x23E, 0xB, 0x3AC, 0xB, 0x393,
0xB, 0x3E1, 0xA, 0x1DE, 0xB, 0x3D6, 0xA, 0x31D, 0xB, 0x3E5, 0xB, 0x3E4, 0xA, 0x207, 0xB, 0x3C7,
0xA, 0x277, 0xB, 0x3D4, 0x8, 0x0C0, 0xA, 0x162, 0xA, 0x3DA, 0xA, 0x124, 0xA, 0x1B4, 0xA, 0x264,
0xA, 0x33D, 0xA, 0x1D1, 0xA, 0x1AF, 0xA, 0x39E, 0xA, 0x24F, 0xB, 0x373, 0xA, 0x249, 0xB, 0x372,
0x9, 0x167, 0xA, 0x210, 0xA, 0x23A, 0xA, 0x1B8, 0xB, 0x3AF, 0xA, 0x18E, 0xA, 0x2EC, 0x7, 0x062,
0x4, 0x00D
};
public static unsafe void Compress(ReadOnlySpan<byte> input, int offset, int count, Span<byte> output, out int length)
{
if (input == null) throw new ArgumentNullException(nameof(input));
if (offset < 0 || offset >= input.Length) throw new ArgumentOutOfRangeException(nameof(offset));
if (count < 0 || count > input.Length) throw new ArgumentOutOfRangeException(nameof(count));
if (input.Length - offset < count) throw new ArgumentOutOfRangeException(nameof(offset));
length = 0;
if (count > DefiniteOverflow) return;
var bitCount = 0;
var bitValue = 0;
fixed (int* pTable = _huffmanTable)
{
fixed (byte* pInputBuffer = input)
{
byte* pInput = pInputBuffer + offset, pInputEnd = pInput + count;
fixed (byte* pOutputBuffer = output)
{
byte* pOutput = pOutputBuffer, pOutputEnd = pOutput + BufferSize;
int* pEntry;
while (pInput < pInputEnd)
{
pEntry = &pTable[*pInput++ << 1];
bitCount += pEntry[CountIndex];
bitValue <<= pEntry[CountIndex];
bitValue |= pEntry[ValueIndex];
while (bitCount >= 8)
{
bitCount -= 8;
if (pOutput < pOutputEnd)
{
*pOutput++ = (byte)(bitValue >> bitCount);
}
else
{
length = 0;
return;
}
}
}
// terminal code
pEntry = &pTable[0x200];
bitCount += pEntry[CountIndex];
bitValue <<= pEntry[CountIndex];
bitValue |= pEntry[ValueIndex];
// align on byte boundary
if ((bitCount & 7) != 0)
{
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
while (bitCount >= 8)
{
bitCount -= 8;
if (pOutput < pOutputEnd)
{
*pOutput++ = (byte)(bitValue >> bitCount);
}
else
{
length = 0;
return;
}
}
length = (int)(pOutput - pOutputBuffer);
}
}
}
}
}
}
/***************************************************************************
* Compression.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
namespace Server.Network
{
/// <summary>
/// Handles outgoing packet compression for the network.
/// </summary>
public static class NetworkCompression
{
private const int CountIndex = 0;
private const int ValueIndex = 1;
// UO packets may not exceed 64kb in length
private const int BufferSize = 0x10000;
// Optimal compression ratio is 2 / 8; worst compression ratio is 11 / 8
private const int MinimalCodeLength = 2;
private const int MaximalCodeLength = 11;
// Fixed overhead, in bits, per compression call
private const int TerminalCodeLength = 4;
// If our input exceeds this length, we cannot possibly compress it within the buffer
private const int DefiniteOverflow = (BufferSize * 8 - TerminalCodeLength) / MinimalCodeLength;
private static readonly int[] _huffmanTable =
{
0x2, 0x000, 0x5, 0x01F, 0x6, 0x022, 0x7, 0x034, 0x7, 0x075, 0x6, 0x028, 0x6, 0x03B, 0x7, 0x032,
0x8, 0x0E0, 0x8, 0x062, 0x7, 0x056, 0x8, 0x079, 0x9, 0x19D, 0x8, 0x097, 0x6, 0x02A, 0x7, 0x057,
0x8, 0x071, 0x8, 0x05B, 0x9, 0x1CC, 0x8, 0x0A7, 0x7, 0x025, 0x7, 0x04F, 0x8, 0x066, 0x8, 0x07D,
0x9, 0x191, 0x9, 0x1CE, 0x7, 0x03F, 0x9, 0x090, 0x8, 0x059, 0x8, 0x07B, 0x8, 0x091, 0x8, 0x0C6,
0x6, 0x02D, 0x9, 0x186, 0x8, 0x06F, 0x9, 0x093, 0xA, 0x1CC, 0x8, 0x05A, 0xA, 0x1AE, 0xA, 0x1C0,
0x9, 0x148, 0x9, 0x14A, 0x9, 0x082, 0xA, 0x19F, 0x9, 0x171, 0x9, 0x120, 0x9, 0x0E7, 0xA, 0x1F3,
0x9, 0x14B, 0x9, 0x100, 0x9, 0x190, 0x6, 0x013, 0x9, 0x161, 0x9, 0x125, 0x9, 0x133, 0x9, 0x195,
0x9, 0x173, 0x9, 0x1CA, 0x9, 0x086, 0x9, 0x1E9, 0x9, 0x0DB, 0x9, 0x1EC, 0x9, 0x08B, 0x9, 0x085,
0x5, 0x00A, 0x8, 0x096, 0x8, 0x09C, 0x9, 0x1C3, 0x9, 0x19C, 0x9, 0x08F, 0x9, 0x18F, 0x9, 0x091,
0x9, 0x087, 0x9, 0x0C6, 0x9, 0x177, 0x9, 0x089, 0x9, 0x0D6, 0x9, 0x08C, 0x9, 0x1EE, 0x9, 0x1EB,
0x9, 0x084, 0x9, 0x164, 0x9, 0x175, 0x9, 0x1CD, 0x8, 0x05E, 0x9, 0x088, 0x9, 0x12B, 0x9, 0x172,
0x9, 0x10A, 0x9, 0x08D, 0x9, 0x13A, 0x9, 0x11C, 0xA, 0x1E1, 0xA, 0x1E0, 0x9, 0x187, 0xA, 0x1DC,
0xA, 0x1DF, 0x7, 0x074, 0x9, 0x19F, 0x8, 0x08D, 0x8, 0x0E4, 0x7, 0x079, 0x9, 0x0EA, 0x9, 0x0E1,
0x8, 0x040, 0x7, 0x041, 0x9, 0x10B, 0x9, 0x0B0, 0x8, 0x06A, 0x8, 0x0C1, 0x7, 0x071, 0x7, 0x078,
0x8, 0x0B1, 0x9, 0x14C, 0x7, 0x043, 0x8, 0x076, 0x7, 0x066, 0x7, 0x04D, 0x9, 0x08A, 0x6, 0x02F,
0x8, 0x0C9, 0x9, 0x0CE, 0x9, 0x149, 0x9, 0x160, 0xA, 0x1BA, 0xA, 0x19E, 0xA, 0x39F, 0x9, 0x0E5,
0x9, 0x194, 0x9, 0x184, 0x9, 0x126, 0x7, 0x030, 0x8, 0x06C, 0x9, 0x121, 0x9, 0x1E8, 0xA, 0x1C1,
0xA, 0x11D, 0xA, 0x163, 0xA, 0x385, 0xA, 0x3DB, 0xA, 0x17D, 0xA, 0x106, 0xA, 0x397, 0xA, 0x24E,
0x7, 0x02E, 0x8, 0x098, 0xA, 0x33C, 0xA, 0x32E, 0xA, 0x1E9, 0x9, 0x0BF, 0xA, 0x3DF, 0xA, 0x1DD,
0xA, 0x32D, 0xA, 0x2ED, 0xA, 0x30B, 0xA, 0x107, 0xA, 0x2E8, 0xA, 0x3DE, 0xA, 0x125, 0xA, 0x1E8,
0x9, 0x0E9, 0xA, 0x1CD, 0xA, 0x1B5, 0x9, 0x165, 0xA, 0x232, 0xA, 0x2E1, 0xB, 0x3AE, 0xB, 0x3C6,
0xB, 0x3E2, 0xA, 0x205, 0xA, 0x29A, 0xA, 0x248, 0xA, 0x2CD, 0xA, 0x23B, 0xB, 0x3C5, 0xA, 0x251,
0xA, 0x2E9, 0xA, 0x252, 0x9, 0x1EA, 0xB, 0x3A0, 0xB, 0x391, 0xA, 0x23C, 0xB, 0x392, 0xB, 0x3D5,
0xA, 0x233, 0xA, 0x2CC, 0xB, 0x390, 0xA, 0x1BB, 0xB, 0x3A1, 0xB, 0x3C4, 0xA, 0x211, 0xA, 0x203,
0x9, 0x12A, 0xA, 0x231, 0xB, 0x3E0, 0xA, 0x29B, 0xB, 0x3D7, 0xA, 0x202, 0xB, 0x3AD, 0xA, 0x213,
0xA, 0x253, 0xA, 0x32C, 0xA, 0x23D, 0xA, 0x23F, 0xA, 0x32F, 0xA, 0x11C, 0xA, 0x384, 0xA, 0x31C,
0xA, 0x17C, 0xA, 0x30A, 0xA, 0x2E0, 0xA, 0x276, 0xA, 0x250, 0xB, 0x3E3, 0xA, 0x396, 0xA, 0x18F,
0xA, 0x204, 0xA, 0x206, 0xA, 0x230, 0xA, 0x265, 0xA, 0x212, 0xA, 0x23E, 0xB, 0x3AC, 0xB, 0x393,
0xB, 0x3E1, 0xA, 0x1DE, 0xB, 0x3D6, 0xA, 0x31D, 0xB, 0x3E5, 0xB, 0x3E4, 0xA, 0x207, 0xB, 0x3C7,
0xA, 0x277, 0xB, 0x3D4, 0x8, 0x0C0, 0xA, 0x162, 0xA, 0x3DA, 0xA, 0x124, 0xA, 0x1B4, 0xA, 0x264,
0xA, 0x33D, 0xA, 0x1D1, 0xA, 0x1AF, 0xA, 0x39E, 0xA, 0x24F, 0xB, 0x373, 0xA, 0x249, 0xB, 0x372,
0x9, 0x167, 0xA, 0x210, 0xA, 0x23A, 0xA, 0x1B8, 0xB, 0x3AF, 0xA, 0x18E, 0xA, 0x2EC, 0x7, 0x062,
0x4, 0x00D
};
public static unsafe void Compress(
ReadOnlySpan<byte> input, int offset, int count, Span<byte> output, out int length
)
{
if (input == null) throw new ArgumentNullException(nameof(input));
if (offset < 0 || offset >= input.Length) throw new ArgumentOutOfRangeException(nameof(offset));
if (count < 0 || count > input.Length) throw new ArgumentOutOfRangeException(nameof(count));
if (input.Length - offset < count) throw new ArgumentOutOfRangeException(nameof(offset));
length = 0;
if (count > DefiniteOverflow) return;
var bitCount = 0;
var bitValue = 0;
fixed (int* pTable = _huffmanTable)
{
fixed (byte* pInputBuffer = input)
{
byte* pInput = pInputBuffer + offset, pInputEnd = pInput + count;
fixed (byte* pOutputBuffer = output)
{
byte* pOutput = pOutputBuffer, pOutputEnd = pOutput + BufferSize;
int* pEntry;
while (pInput < pInputEnd)
{
pEntry = &pTable[*pInput++ << 1];
bitCount += pEntry[CountIndex];
bitValue <<= pEntry[CountIndex];
bitValue |= pEntry[ValueIndex];
while (bitCount >= 8)
{
bitCount -= 8;
if (pOutput < pOutputEnd)
{
*pOutput++ = (byte)(bitValue >> bitCount);
}
else
{
length = 0;
return;
}
}
}
// terminal code
pEntry = &pTable[0x200];
bitCount += pEntry[CountIndex];
bitValue <<= pEntry[CountIndex];
bitValue |= pEntry[ValueIndex];
// align on byte boundary
if ((bitCount & 7) != 0)
{
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
while (bitCount >= 8)
{
bitCount -= 8;
if (pOutput < pOutputEnd)
{
*pOutput++ = (byte)(bitValue >> bitCount);
}
else
{
length = 0;
return;
}
}
length = (int)(pOutput - pOutputBuffer);
}
}
}
}
}
}

View file

@ -1,267 +1,280 @@
/***************************************************************************
* Packet.cs
* -------------------
* begin : August 2, 2019
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
using System.Buffers;
using System.Diagnostics;
using System.IO;
using Server.Diagnostics;
namespace Server.Network
{
public abstract class Packet
{
private const int CompressorBufferSize = 0x10000;
private const int BufferSize = 4096;
private byte[] m_CompiledBuffer;
private int m_CompiledLength;
private readonly int m_Length;
private State m_State;
protected Packet(int packetID)
{
PacketID = packetID;
if (Core.Profiling)
{
var prof = PacketSendProfile.Acquire(GetType());
prof.Increment();
}
}
protected Packet(int packetID, int length)
{
PacketID = packetID;
m_Length = length;
Stream = PacketWriter.CreateInstance(length); // new PacketWriter( length );
Stream.Write((byte)packetID);
if (Core.Profiling)
{
var prof = PacketSendProfile.Acquire(GetType());
prof.Increment();
}
}
public int PacketID { get; }
public PacketWriter Stream { get; protected set; }
public void EnsureCapacity(int length)
{
Stream = PacketWriter.CreateInstance(length); // new PacketWriter( length );
Stream.Write((byte)PacketID);
Stream.Write((short)0);
}
public static Packet SetStatic(Packet p)
{
p.SetStatic();
return p;
}
public static Packet Acquire(Packet p)
{
p.Acquire();
return p;
}
public static void Release(ref Packet p)
{
p?.Release();
p = null;
}
public static void Release(Packet p)
{
p?.Release();
}
public void SetStatic()
{
m_State |= State.Static | State.Acquired;
}
public void Acquire()
{
m_State |= State.Acquired;
}
public void OnSend()
{
Core.Set(); // Is this still needed if this is done async?
if ((m_State & (State.Acquired | State.Static)) == 0)
Free();
}
private void Free()
{
if (m_CompiledBuffer == null)
return;
if ((m_State & State.Buffered) != 0)
ArrayPool<byte>.Shared.Return(m_CompiledBuffer);
m_State &= ~(State.Static | State.Acquired | State.Buffered);
m_CompiledBuffer = null;
}
public void Release()
{
if ((m_State & State.Acquired) != 0)
Free();
}
public byte[] Compile(bool compress, out int length)
{
lock (this)
{
if (m_CompiledBuffer == null)
{
if ((m_State & State.Accessed) == 0)
{
m_State |= State.Accessed;
}
else
{
if ((m_State & State.Warned) == 0)
{
m_State |= State.Warned;
try
{
using var op = new StreamWriter("net_opt.log", true);
op.WriteLine("Redundant compile for packet {0}, use Acquire() and Release()", GetType());
op.WriteLine(new StackTrace());
}
catch
{
// ignored
}
}
m_CompiledBuffer = Array.Empty<byte>();
m_CompiledLength = 0;
length = m_CompiledLength;
return m_CompiledBuffer;
}
InternalCompile(compress);
}
length = m_CompiledLength;
return m_CompiledBuffer;
}
}
private void InternalCompile(bool compress)
{
if (m_Length == 0)
{
var streamLen = Stream.Length;
Stream.Seek(1, SeekOrigin.Begin);
Stream.Write((ushort)streamLen);
}
else if (Stream.Length != m_Length)
{
var diff = (int)Stream.Length - m_Length;
Console.WriteLine("Packet: 0x{0:X2}: Bad packet length! ({1}{2} bytes)", PacketID, diff >= 0 ? "+" : "",
diff);
}
var ms = Stream.UnderlyingStream;
m_CompiledBuffer = ms.GetBuffer();
var length = (int)ms.Length;
if (compress)
{
var buffer = ArrayPool<byte>.Shared.Rent(CompressorBufferSize);
NetworkCompression.Compress(m_CompiledBuffer, 0, length, buffer, out length);
if (length <= 0)
{
Console.WriteLine("Warning: Compression buffer overflowed on packet 0x{0:X2} ('{1}') (length={2})",
PacketID, GetType().Name, length);
using var op = new StreamWriter("compression_overflow.log", true);
op.WriteLine("{0} Warning: Compression buffer overflowed on packet 0x{1:X2} ('{2}') (length={3})",
DateTime.UtcNow, PacketID, GetType().Name, length);
op.WriteLine(new StackTrace());
}
else
{
m_CompiledLength = length;
if ((m_State & State.Static) != 0)
{
m_CompiledBuffer = new byte[length];
Buffer.BlockCopy(buffer, 0, m_CompiledBuffer, 0, length);
ArrayPool<byte>.Shared.Return(buffer);
}
else
{
m_CompiledBuffer = buffer;
m_State |= State.Buffered;
}
}
}
else if (length > 0)
{
var old = m_CompiledBuffer;
m_CompiledLength = length;
if ((m_State & State.Static) != 0)
{
m_CompiledBuffer = new byte[length];
}
else
{
m_CompiledBuffer = ArrayPool<byte>.Shared.Rent(length);
m_State |= State.Buffered;
}
Buffer.BlockCopy(old, 0, m_CompiledBuffer, 0, length);
}
PacketWriter.ReleaseInstance(Stream);
Stream = null;
}
[Flags]
private enum State
{
Inactive = 0x00,
Static = 0x01,
Acquired = 0x02,
Accessed = 0x04,
Buffered = 0x08,
Warned = 0x10
}
}
}
/***************************************************************************
* Packet.cs
* -------------------
* begin : August 2, 2019
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
using System.Buffers;
using System.Diagnostics;
using System.IO;
using Server.Diagnostics;
namespace Server.Network
{
public abstract class Packet
{
private const int CompressorBufferSize = 0x10000;
private const int BufferSize = 4096;
private readonly int m_Length;
private byte[] m_CompiledBuffer;
private int m_CompiledLength;
private State m_State;
protected Packet(int packetID)
{
PacketID = packetID;
if (Core.Profiling)
{
var prof = PacketSendProfile.Acquire(GetType());
prof.Increment();
}
}
protected Packet(int packetID, int length)
{
PacketID = packetID;
m_Length = length;
Stream = PacketWriter.CreateInstance(length); // new PacketWriter( length );
Stream.Write((byte)packetID);
if (Core.Profiling)
{
var prof = PacketSendProfile.Acquire(GetType());
prof.Increment();
}
}
public int PacketID { get; }
public PacketWriter Stream { get; protected set; }
public void EnsureCapacity(int length)
{
Stream = PacketWriter.CreateInstance(length); // new PacketWriter( length );
Stream.Write((byte)PacketID);
Stream.Write((short)0);
}
public static Packet SetStatic(Packet p)
{
p.SetStatic();
return p;
}
public static Packet Acquire(Packet p)
{
p.Acquire();
return p;
}
public static void Release(ref Packet p)
{
p?.Release();
p = null;
}
public static void Release(Packet p)
{
p?.Release();
}
public void SetStatic()
{
m_State |= State.Static | State.Acquired;
}
public void Acquire()
{
m_State |= State.Acquired;
}
public void OnSend()
{
Core.Set(); // Is this still needed if this is done async?
if ((m_State & (State.Acquired | State.Static)) == 0)
Free();
}
private void Free()
{
if (m_CompiledBuffer == null)
return;
if ((m_State & State.Buffered) != 0)
ArrayPool<byte>.Shared.Return(m_CompiledBuffer);
m_State &= ~(State.Static | State.Acquired | State.Buffered);
m_CompiledBuffer = null;
}
public void Release()
{
if ((m_State & State.Acquired) != 0)
Free();
}
public byte[] Compile(bool compress, out int length)
{
lock (this)
{
if (m_CompiledBuffer == null)
{
if ((m_State & State.Accessed) == 0)
{
m_State |= State.Accessed;
}
else
{
if ((m_State & State.Warned) == 0)
{
m_State |= State.Warned;
try
{
using var op = new StreamWriter("net_opt.log", true);
op.WriteLine("Redundant compile for packet {0}, use Acquire() and Release()", GetType());
op.WriteLine(new StackTrace());
}
catch
{
// ignored
}
}
m_CompiledBuffer = Array.Empty<byte>();
m_CompiledLength = 0;
length = m_CompiledLength;
return m_CompiledBuffer;
}
InternalCompile(compress);
}
length = m_CompiledLength;
return m_CompiledBuffer;
}
}
private void InternalCompile(bool compress)
{
if (m_Length == 0)
{
var streamLen = Stream.Length;
Stream.Seek(1, SeekOrigin.Begin);
Stream.Write((ushort)streamLen);
}
else if (Stream.Length != m_Length)
{
var diff = (int)Stream.Length - m_Length;
Console.WriteLine(
"Packet: 0x{0:X2}: Bad packet length! ({1}{2} bytes)",
PacketID,
diff >= 0 ? "+" : "",
diff
);
}
var ms = Stream.UnderlyingStream;
m_CompiledBuffer = ms.GetBuffer();
var length = (int)ms.Length;
if (compress)
{
var buffer = ArrayPool<byte>.Shared.Rent(CompressorBufferSize);
NetworkCompression.Compress(m_CompiledBuffer, 0, length, buffer, out length);
if (length <= 0)
{
Console.WriteLine(
"Warning: Compression buffer overflowed on packet 0x{0:X2} ('{1}') (length={2})",
PacketID,
GetType().Name,
length
);
using var op = new StreamWriter("compression_overflow.log", true);
op.WriteLine(
"{0} Warning: Compression buffer overflowed on packet 0x{1:X2} ('{2}') (length={3})",
DateTime.UtcNow,
PacketID,
GetType().Name,
length
);
op.WriteLine(new StackTrace());
}
else
{
m_CompiledLength = length;
if ((m_State & State.Static) != 0)
{
m_CompiledBuffer = new byte[length];
Buffer.BlockCopy(buffer, 0, m_CompiledBuffer, 0, length);
ArrayPool<byte>.Shared.Return(buffer);
}
else
{
m_CompiledBuffer = buffer;
m_State |= State.Buffered;
}
}
}
else if (length > 0)
{
var old = m_CompiledBuffer;
m_CompiledLength = length;
if ((m_State & State.Static) != 0)
{
m_CompiledBuffer = new byte[length];
}
else
{
m_CompiledBuffer = ArrayPool<byte>.Shared.Rent(length);
m_State |= State.Buffered;
}
Buffer.BlockCopy(old, 0, m_CompiledBuffer, 0, length);
}
PacketWriter.ReleaseInstance(Stream);
Stream = null;
}
[Flags]
private enum State
{
Inactive = 0x00,
Static = 0x01,
Acquired = 0x02,
Accessed = 0x04,
Buffered = 0x08,
Warned = 0x10
}
}
}

View file

@ -1,49 +1,49 @@
/***************************************************************************
* PacketHandler.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
namespace Server.Network
{
public delegate void OnPacketReceive(NetState state, PacketReader pvSrc);
public delegate TimeSpan ThrottlePacketCallback(NetState state);
public class PacketHandler
{
public PacketHandler(int packetID, int length, bool ingame, OnPacketReceive onReceive)
{
PacketID = packetID;
Length = length;
Ingame = ingame;
OnReceive = onReceive;
}
public int PacketID { get; }
public int Length { get; }
public OnPacketReceive OnReceive { get; }
public ThrottlePacketCallback ThrottleCallback { get; set; }
public bool Ingame { get; }
}
}
/***************************************************************************
* PacketHandler.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
namespace Server.Network
{
public delegate void OnPacketReceive(NetState state, PacketReader pvSrc);
public delegate TimeSpan ThrottlePacketCallback(NetState state);
public class PacketHandler
{
public PacketHandler(int packetID, int length, bool ingame, OnPacketReceive onReceive)
{
PacketID = packetID;
Length = length;
Ingame = ingame;
OnReceive = onReceive;
}
public int PacketID { get; }
public int Length { get; }
public OnPacketReceive OnReceive { get; }
public ThrottlePacketCallback ThrottleCallback { get; set; }
public bool Ingame { get; }
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,308 +1,309 @@
/***************************************************************************
* PacketReader.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
using System.Buffers;
using System.IO;
using System.Text;
namespace Server.Network
{
public ref struct PacketReader
{
private SequenceReader<byte> m_Reader;
public SequencePosition Position => m_Reader.Position;
public long Length => m_Reader.Length;
public long Consumed => m_Reader.Consumed;
public long Remaining => m_Reader.Remaining;
public PacketReader(ReadOnlySequence<byte> seq) => m_Reader = new SequenceReader<byte>(seq);
public byte Peek() => m_Reader.TryPeek(out var value) ? value : (byte)0;
public void Trace(NetState state)
{
try
{
using var sw = new StreamWriter("Packets.log", true);
var buffer = m_Reader.Sequence.ToArray();
if (buffer.Length > 0)
sw.WriteLine("Client: {0}: Unhandled packet 0x{1:X2}", state, buffer[0]);
using (var ms = new MemoryStream(buffer))
{
Utility.FormatBuffer(sw, ms, buffer.Length);
}
sw.WriteLine();
sw.WriteLine();
}
catch
{
// ignored
}
}
public SequencePosition Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
if (offset < m_Reader.Consumed)
m_Reader.Rewind(m_Reader.Consumed - Math.Max(offset, 0L));
else
m_Reader.Advance(offset - m_Reader.Consumed);
break;
case SeekOrigin.Current:
if (offset < 0)
m_Reader.Rewind(Math.Min(m_Reader.Consumed, offset * -1));
else
m_Reader.Advance(Math.Min(m_Reader.Remaining, offset));
break;
case SeekOrigin.End:
var count = m_Reader.Remaining - offset;
if (count < 0)
m_Reader.Rewind(count * -1);
else if (count > 0)
m_Reader.Advance(count);
break;
}
return m_Reader.Position;
}
public bool TryReadByte(out byte value) => m_Reader.TryRead(out value);
public int ReadInt32() => m_Reader.TryReadBigEndian(out int value) ? value : 0;
public short ReadInt16() => m_Reader.TryReadBigEndian(out short value) ? value : (short)0;
public byte ReadByte() => m_Reader.TryRead(out var value) ? value : (byte)0;
public uint ReadUInt32() => (uint)ReadInt32();
public ushort ReadUInt16() => (ushort)ReadInt16();
public sbyte ReadSByte() => (sbyte)ReadByte();
public bool ReadBoolean() => ReadByte() > 0;
public string ReadUnicodeStringLE()
{
var sb = new StringBuilder();
while (m_Reader.TryReadLittleEndian(out short c) && c != 0)
sb.Append((char)c);
return sb.ToString();
}
public string ReadUnicodeStringLE(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryReadLittleEndian(out short c) && c != 0)
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength);
return sb.ToString();
}
public string ReadUnicodeStringLESafe(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryReadLittleEndian(out short c) && c != 0)
if (IsSafeChar(c))
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength * 2);
return sb.ToString();
}
public string ReadUnicodeStringLESafe()
{
var sb = new StringBuilder();
while (m_Reader.TryReadLittleEndian(out short c) && c != 0)
if (IsSafeChar(c))
sb.Append((char)c);
return sb.ToString();
}
public string ReadUnicodeStringSafe()
{
var sb = new StringBuilder();
while (m_Reader.TryReadBigEndian(out short c) && c != 0)
if (IsSafeChar(c))
sb.Append((char)c);
return sb.ToString();
}
public string ReadUnicodeString()
{
var sb = new StringBuilder();
while (m_Reader.TryReadBigEndian(out short c) && c != 0)
sb.Append((char)c);
return sb.ToString();
}
private static bool IsSafeChar(int c) => c >= 0x20 && c < 0xFFFE;
public string ReadUTF8StringSafe(int fixedLength)
{
string s;
if (m_Reader.TryReadTo(out ReadOnlySpan<byte> span, (byte)'\0'))
{
s = Utility.UTF8.GetString(span.Length > fixedLength ? span.Slice(0, fixedLength) : span);
}
else
{
var size = Math.Min(m_Reader.Remaining, fixedLength);
s = Utility.UTF8.GetString(m_Reader.Sequence.Slice(m_Reader.Position, size).ToArray());
m_Reader.Advance(size);
}
var sb = new StringBuilder(s.Length);
for (var i = 0; i < s.Length; ++i)
if (IsSafeChar(s[i]))
sb.Append(s[i]);
return sb.ToString();
}
public string ReadUTF8StringSafe()
{
string s;
if (m_Reader.TryReadTo(out ReadOnlySpan<byte> span, (byte)'\0'))
{
s = Utility.UTF8.GetString(span);
}
else
{
s = Utility.UTF8.GetString(m_Reader.Sequence.Slice(m_Reader.Position, m_Reader.Remaining).ToArray());
m_Reader.Advance(m_Reader.Remaining);
}
var sb = new StringBuilder(s.Length);
for (var i = 0; i < s.Length; ++i)
if (IsSafeChar(s[i]))
sb.Append(s[i]);
return sb.ToString();
}
public string ReadUTF8String() =>
Utility.UTF8.GetString(
m_Reader.TryReadTo(out ReadOnlySpan<byte> span, (byte)'\0')
? span
: m_Reader.Sequence.Slice(m_Reader.Position, m_Reader.Remaining).ToArray());
public string ReadString()
{
var sb = new StringBuilder();
while (m_Reader.TryRead(out var c))
sb.Append((char)c);
return sb.ToString();
}
public string ReadStringSafe()
{
var sb = new StringBuilder();
while (m_Reader.TryRead(out var c))
if (IsSafeChar(c))
sb.Append((char)c);
return sb.ToString();
}
public string ReadUnicodeStringSafe(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryReadBigEndian(out short c) && c != 0)
if (IsSafeChar(c))
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength * 2);
return sb.ToString();
}
public string ReadUnicodeString(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryReadBigEndian(out short c) && c != 0)
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength * 2);
return sb.ToString();
}
public string ReadStringSafe(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryRead(out var c) && c != 0)
if (IsSafeChar(c))
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength);
return sb.ToString();
}
public string ReadString(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryRead(out var c) && c != 0)
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength);
return sb.ToString();
}
}
}
/***************************************************************************
* PacketReader.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
using System.Buffers;
using System.IO;
using System.Text;
namespace Server.Network
{
public ref struct PacketReader
{
private SequenceReader<byte> m_Reader;
public SequencePosition Position => m_Reader.Position;
public long Length => m_Reader.Length;
public long Consumed => m_Reader.Consumed;
public long Remaining => m_Reader.Remaining;
public PacketReader(ReadOnlySequence<byte> seq) => m_Reader = new SequenceReader<byte>(seq);
public byte Peek() => m_Reader.TryPeek(out var value) ? value : (byte)0;
public void Trace(NetState state)
{
try
{
using var sw = new StreamWriter("Packets.log", true);
var buffer = m_Reader.Sequence.ToArray();
if (buffer.Length > 0)
sw.WriteLine("Client: {0}: Unhandled packet 0x{1:X2}", state, buffer[0]);
using (var ms = new MemoryStream(buffer))
{
Utility.FormatBuffer(sw, ms, buffer.Length);
}
sw.WriteLine();
sw.WriteLine();
}
catch
{
// ignored
}
}
public SequencePosition Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
if (offset < m_Reader.Consumed)
m_Reader.Rewind(m_Reader.Consumed - Math.Max(offset, 0L));
else
m_Reader.Advance(offset - m_Reader.Consumed);
break;
case SeekOrigin.Current:
if (offset < 0)
m_Reader.Rewind(Math.Min(m_Reader.Consumed, offset * -1));
else
m_Reader.Advance(Math.Min(m_Reader.Remaining, offset));
break;
case SeekOrigin.End:
var count = m_Reader.Remaining - offset;
if (count < 0)
m_Reader.Rewind(count * -1);
else if (count > 0)
m_Reader.Advance(count);
break;
}
return m_Reader.Position;
}
public bool TryReadByte(out byte value) => m_Reader.TryRead(out value);
public int ReadInt32() => m_Reader.TryReadBigEndian(out int value) ? value : 0;
public short ReadInt16() => m_Reader.TryReadBigEndian(out short value) ? value : (short)0;
public byte ReadByte() => m_Reader.TryRead(out var value) ? value : (byte)0;
public uint ReadUInt32() => (uint)ReadInt32();
public ushort ReadUInt16() => (ushort)ReadInt16();
public sbyte ReadSByte() => (sbyte)ReadByte();
public bool ReadBoolean() => ReadByte() > 0;
public string ReadUnicodeStringLE()
{
var sb = new StringBuilder();
while (m_Reader.TryReadLittleEndian(out short c) && c != 0)
sb.Append((char)c);
return sb.ToString();
}
public string ReadUnicodeStringLE(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryReadLittleEndian(out short c) && c != 0)
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength);
return sb.ToString();
}
public string ReadUnicodeStringLESafe(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryReadLittleEndian(out short c) && c != 0)
if (IsSafeChar(c))
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength * 2);
return sb.ToString();
}
public string ReadUnicodeStringLESafe()
{
var sb = new StringBuilder();
while (m_Reader.TryReadLittleEndian(out short c) && c != 0)
if (IsSafeChar(c))
sb.Append((char)c);
return sb.ToString();
}
public string ReadUnicodeStringSafe()
{
var sb = new StringBuilder();
while (m_Reader.TryReadBigEndian(out short c) && c != 0)
if (IsSafeChar(c))
sb.Append((char)c);
return sb.ToString();
}
public string ReadUnicodeString()
{
var sb = new StringBuilder();
while (m_Reader.TryReadBigEndian(out short c) && c != 0)
sb.Append((char)c);
return sb.ToString();
}
private static bool IsSafeChar(int c) => c >= 0x20 && c < 0xFFFE;
public string ReadUTF8StringSafe(int fixedLength)
{
string s;
if (m_Reader.TryReadTo(out ReadOnlySpan<byte> span, (byte)'\0'))
{
s = Utility.UTF8.GetString(span.Length > fixedLength ? span.Slice(0, fixedLength) : span);
}
else
{
var size = Math.Min(m_Reader.Remaining, fixedLength);
s = Utility.UTF8.GetString(m_Reader.Sequence.Slice(m_Reader.Position, size).ToArray());
m_Reader.Advance(size);
}
var sb = new StringBuilder(s.Length);
for (var i = 0; i < s.Length; ++i)
if (IsSafeChar(s[i]))
sb.Append(s[i]);
return sb.ToString();
}
public string ReadUTF8StringSafe()
{
string s;
if (m_Reader.TryReadTo(out ReadOnlySpan<byte> span, (byte)'\0'))
{
s = Utility.UTF8.GetString(span);
}
else
{
s = Utility.UTF8.GetString(m_Reader.Sequence.Slice(m_Reader.Position, m_Reader.Remaining).ToArray());
m_Reader.Advance(m_Reader.Remaining);
}
var sb = new StringBuilder(s.Length);
for (var i = 0; i < s.Length; ++i)
if (IsSafeChar(s[i]))
sb.Append(s[i]);
return sb.ToString();
}
public string ReadUTF8String() =>
Utility.UTF8.GetString(
m_Reader.TryReadTo(out ReadOnlySpan<byte> span, (byte)'\0')
? span
: m_Reader.Sequence.Slice(m_Reader.Position, m_Reader.Remaining).ToArray()
);
public string ReadString()
{
var sb = new StringBuilder();
while (m_Reader.TryRead(out var c))
sb.Append((char)c);
return sb.ToString();
}
public string ReadStringSafe()
{
var sb = new StringBuilder();
while (m_Reader.TryRead(out var c))
if (IsSafeChar(c))
sb.Append((char)c);
return sb.ToString();
}
public string ReadUnicodeStringSafe(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryReadBigEndian(out short c) && c != 0)
if (IsSafeChar(c))
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength * 2);
return sb.ToString();
}
public string ReadUnicodeString(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryReadBigEndian(out short c) && c != 0)
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength * 2);
return sb.ToString();
}
public string ReadStringSafe(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryRead(out var c) && c != 0)
if (IsSafeChar(c))
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength);
return sb.ToString();
}
public string ReadString(int fixedLength)
{
var sb = new StringBuilder();
while (fixedLength-- > 0 && m_Reader.TryRead(out var c) && c != 0)
sb.Append((char)c);
if (fixedLength > 0)
m_Reader.Advance(fixedLength);
return sb.ToString();
}
}
}

View file

@ -1,348 +1,372 @@
/***************************************************************************
* PacketWriter.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Text;
namespace Server.Network
{
/// <summary>
/// Provides functionality for writing primitive binary data.
/// </summary>
public class PacketWriter
{
private static readonly ConcurrentQueue<PacketWriter> m_Pool = new ConcurrentQueue<PacketWriter>();
/// <summary>
/// Internal format buffer.
/// </summary>
private readonly byte[] m_Buffer = new byte[4];
private int m_Capacity;
/// <summary>
/// Instantiates a new PacketWriter instance with a given capacity.
/// </summary>
/// <param name="capacity">Initial capacity for the internal stream.</param>
public PacketWriter(int capacity = 32)
{
UnderlyingStream = new MemoryStream(capacity);
m_Capacity = capacity;
}
/// <summary>
/// Gets the total stream length.
/// </summary>
public long Length => UnderlyingStream.Length;
/// <summary>
/// Gets or sets the current stream position.
/// </summary>
public long Position
{
get => UnderlyingStream.Position;
set => UnderlyingStream.Position = value;
}
/// <summary>
/// The internal stream used by this PacketWriter instance.
/// </summary>
public MemoryStream UnderlyingStream { get; private set; }
public static PacketWriter CreateInstance(int capacity = 32)
{
if (m_Pool.TryDequeue(out var pw))
{
pw.m_Capacity = capacity;
pw.UnderlyingStream.SetLength(0);
return pw;
}
return new PacketWriter(capacity);
}
public static void ReleaseInstance(PacketWriter pw)
{
m_Pool.Enqueue(pw);
}
/// <summary>
/// Writes a 1-byte boolean value to the underlying stream. False is represented by 0, true by 1.
/// </summary>
public void Write(bool value)
{
UnderlyingStream.WriteByte((byte)(value ? 1 : 0));
}
/// <summary>
/// Writes a 1-byte unsigned integer value to the underlying stream.
/// </summary>
public void Write(byte value)
{
UnderlyingStream.WriteByte(value);
}
/// <summary>
/// Writes a 1-byte signed integer value to the underlying stream.
/// </summary>
public void Write(sbyte value)
{
UnderlyingStream.WriteByte((byte)value);
}
/// <summary>
/// Writes a 2-byte signed integer value to the underlying stream.
/// </summary>
public void Write(short value)
{
m_Buffer[0] = (byte)(value >> 8);
m_Buffer[1] = (byte)value;
UnderlyingStream.Write(m_Buffer, 0, 2);
}
/// <summary>
/// Writes a 2-byte unsigned integer value to the underlying stream.
/// </summary>
public void Write(ushort value)
{
m_Buffer[0] = (byte)(value >> 8);
m_Buffer[1] = (byte)value;
UnderlyingStream.Write(m_Buffer, 0, 2);
}
/// <summary>
/// Writes a 4-byte signed integer value to the underlying stream.
/// </summary>
public void Write(int value)
{
m_Buffer[0] = (byte)(value >> 24);
m_Buffer[1] = (byte)(value >> 16);
m_Buffer[2] = (byte)(value >> 8);
m_Buffer[3] = (byte)value;
UnderlyingStream.Write(m_Buffer, 0, 4);
}
/// <summary>
/// Writes a 4-byte unsigned integer value to the underlying stream.
/// </summary>
public void Write(uint value)
{
m_Buffer[0] = (byte)(value >> 24);
m_Buffer[1] = (byte)(value >> 16);
m_Buffer[2] = (byte)(value >> 8);
m_Buffer[3] = (byte)value;
UnderlyingStream.Write(m_Buffer, 0, 4);
}
/// <summary>
/// Writes a sequence of bytes to the underlying stream
/// </summary>
public void Write(byte[] buffer, int offset, int size)
{
UnderlyingStream.Write(buffer, offset, size);
}
/// <summary>
/// Writes a fixed-length ASCII-encoded string value to the underlying stream. To fit (size), the string content is either
/// truncated or padded with null characters.
/// </summary>
public void WriteAsciiFixed(string value, int size)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteAsciiFixed() with null value");
value = string.Empty;
}
var length = value.Length;
UnderlyingStream.SetLength(UnderlyingStream.Length + size);
if (length >= size)
{
UnderlyingStream.Position +=
Encoding.ASCII.GetBytes(value, 0, size, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
}
else
{
Encoding.ASCII.GetBytes(value, 0, length, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
UnderlyingStream.Position += size;
}
}
/// <summary>
/// Writes a dynamic-length ASCII-encoded string value to the underlying stream, followed by a 1-byte null character.
/// </summary>
public void WriteAsciiNull(string value)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteAsciiNull() with null value");
value = string.Empty;
}
var length = value.Length;
UnderlyingStream.SetLength(UnderlyingStream.Length + length + 1);
Encoding.ASCII.GetBytes(value, 0, length, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
UnderlyingStream.Position += length + 1;
}
/// <summary>
/// Writes a dynamic-length little-endian unicode string value to the underlying stream, followed by a 2-byte null character.
/// </summary>
public void WriteLittleUniNull(string value)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteLittleUniNull() with null value");
value = string.Empty;
}
var length = value.Length;
UnderlyingStream.SetLength(UnderlyingStream.Length + (length + 1) * 2);
UnderlyingStream.Position +=
Encoding.Unicode.GetBytes(value, 0, length, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
UnderlyingStream.Position += 2;
}
/// <summary>
/// Writes a fixed-length little-endian unicode string value to the underlying stream. To fit (size), the string content is
/// either truncated or padded with null characters.
/// </summary>
public void WriteLittleUniFixed(string value, int size)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteLittleUniFixed() with null value");
value = string.Empty;
}
var length = value.Length;
size *= 2;
UnderlyingStream.SetLength(UnderlyingStream.Length + size);
if (length * 2 >= size)
{
UnderlyingStream.Position +=
Encoding.Unicode.GetBytes(value, 0, size / 2, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
}
else
{
Encoding.Unicode.GetBytes(value, 0, length, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
UnderlyingStream.Position += size;
}
}
/// <summary>
/// Writes a dynamic-length big-endian unicode string value to the underlying stream, followed by a 2-byte null character.
/// </summary>
public void WriteBigUniNull(string value)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteBigUniNull() with null value");
value = string.Empty;
}
var length = value.Length;
UnderlyingStream.SetLength(UnderlyingStream.Length + (length + 1) * 2);
UnderlyingStream.Position +=
Encoding.BigEndianUnicode.GetBytes(value, 0, length, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
UnderlyingStream.Position += 2;
}
/// <summary>
/// Writes a fixed-length big-endian unicode string value to the underlying stream. To fit (size), the string content is
/// either truncated or padded with null characters.
/// </summary>
public void WriteBigUniFixed(string value, int size)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteBigUniFixed() with null value");
value = string.Empty;
}
var length = value.Length;
size *= 2;
UnderlyingStream.SetLength(UnderlyingStream.Length + size);
if (length * 2 >= size)
{
UnderlyingStream.Position +=
Encoding.BigEndianUnicode.GetBytes(value, 0, size / 2, UnderlyingStream.GetBuffer(),
(int)UnderlyingStream.Position);
}
else
{
Encoding.BigEndianUnicode.GetBytes(value, 0, length, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
UnderlyingStream.Position += size;
}
}
/// <summary>
/// Fills the stream from the current position up to (capacity) with 0x00's
/// </summary>
public void Fill()
{
Fill(m_Capacity - UnderlyingStream.Length);
}
/// <summary>
/// Writes a number of 0x00 byte values to the underlying stream.
/// </summary>
public void Fill(long length)
{
if (UnderlyingStream.Position == UnderlyingStream.Length)
{
UnderlyingStream.SetLength(UnderlyingStream.Length + length);
UnderlyingStream.Seek(0, SeekOrigin.End);
}
else
{
UnderlyingStream.Write(new byte[length], 0, (int)length);
}
}
/// <summary>
/// Offsets the current position from an origin.
/// </summary>
public long Seek(long offset, SeekOrigin origin) => UnderlyingStream.Seek(offset, origin);
/// <summary>
/// Gets the entire stream content as a byte array.
/// </summary>
public byte[] ToArray() => UnderlyingStream.ToArray();
}
}
/***************************************************************************
* PacketWriter.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* 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 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Text;
namespace Server.Network
{
/// <summary>
/// Provides functionality for writing primitive binary data.
/// </summary>
public class PacketWriter
{
private static readonly ConcurrentQueue<PacketWriter> m_Pool = new ConcurrentQueue<PacketWriter>();
/// <summary>
/// Internal format buffer.
/// </summary>
private readonly byte[] m_Buffer = new byte[4];
private int m_Capacity;
/// <summary>
/// Instantiates a new PacketWriter instance with a given capacity.
/// </summary>
/// <param name="capacity">Initial capacity for the internal stream.</param>
public PacketWriter(int capacity = 32)
{
UnderlyingStream = new MemoryStream(capacity);
m_Capacity = capacity;
}
/// <summary>
/// Gets the total stream length.
/// </summary>
public long Length => UnderlyingStream.Length;
/// <summary>
/// Gets or sets the current stream position.
/// </summary>
public long Position
{
get => UnderlyingStream.Position;
set => UnderlyingStream.Position = value;
}
/// <summary>
/// The internal stream used by this PacketWriter instance.
/// </summary>
public MemoryStream UnderlyingStream { get; }
public static PacketWriter CreateInstance(int capacity = 32)
{
if (m_Pool.TryDequeue(out var pw))
{
pw.m_Capacity = capacity;
pw.UnderlyingStream.SetLength(0);
return pw;
}
return new PacketWriter(capacity);
}
public static void ReleaseInstance(PacketWriter pw)
{
m_Pool.Enqueue(pw);
}
/// <summary>
/// Writes a 1-byte boolean value to the underlying stream. False is represented by 0, true by 1.
/// </summary>
public void Write(bool value)
{
UnderlyingStream.WriteByte((byte)(value ? 1 : 0));
}
/// <summary>
/// Writes a 1-byte unsigned integer value to the underlying stream.
/// </summary>
public void Write(byte value)
{
UnderlyingStream.WriteByte(value);
}
/// <summary>
/// Writes a 1-byte signed integer value to the underlying stream.
/// </summary>
public void Write(sbyte value)
{
UnderlyingStream.WriteByte((byte)value);
}
/// <summary>
/// Writes a 2-byte signed integer value to the underlying stream.
/// </summary>
public void Write(short value)
{
m_Buffer[0] = (byte)(value >> 8);
m_Buffer[1] = (byte)value;
UnderlyingStream.Write(m_Buffer, 0, 2);
}
/// <summary>
/// Writes a 2-byte unsigned integer value to the underlying stream.
/// </summary>
public void Write(ushort value)
{
m_Buffer[0] = (byte)(value >> 8);
m_Buffer[1] = (byte)value;
UnderlyingStream.Write(m_Buffer, 0, 2);
}
/// <summary>
/// Writes a 4-byte signed integer value to the underlying stream.
/// </summary>
public void Write(int value)
{
m_Buffer[0] = (byte)(value >> 24);
m_Buffer[1] = (byte)(value >> 16);
m_Buffer[2] = (byte)(value >> 8);
m_Buffer[3] = (byte)value;
UnderlyingStream.Write(m_Buffer, 0, 4);
}
/// <summary>
/// Writes a 4-byte unsigned integer value to the underlying stream.
/// </summary>
public void Write(uint value)
{
m_Buffer[0] = (byte)(value >> 24);
m_Buffer[1] = (byte)(value >> 16);
m_Buffer[2] = (byte)(value >> 8);
m_Buffer[3] = (byte)value;
UnderlyingStream.Write(m_Buffer, 0, 4);
}
/// <summary>
/// Writes a sequence of bytes to the underlying stream
/// </summary>
public void Write(byte[] buffer, int offset, int size)
{
UnderlyingStream.Write(buffer, offset, size);
}
/// <summary>
/// Writes a fixed-length ASCII-encoded string value to the underlying stream. To fit (size), the string content is either
/// truncated or padded with null characters.
/// </summary>
public void WriteAsciiFixed(string value, int size)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteAsciiFixed() with null value");
value = string.Empty;
}
var length = value.Length;
UnderlyingStream.SetLength(UnderlyingStream.Length + size);
if (length >= size)
{
UnderlyingStream.Position +=
Encoding.ASCII.GetBytes(value, 0, size, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
}
else
{
Encoding.ASCII.GetBytes(value, 0, length, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
UnderlyingStream.Position += size;
}
}
/// <summary>
/// Writes a dynamic-length ASCII-encoded string value to the underlying stream, followed by a 1-byte null character.
/// </summary>
public void WriteAsciiNull(string value)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteAsciiNull() with null value");
value = string.Empty;
}
var length = value.Length;
UnderlyingStream.SetLength(UnderlyingStream.Length + length + 1);
Encoding.ASCII.GetBytes(value, 0, length, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
UnderlyingStream.Position += length + 1;
}
/// <summary>
/// Writes a dynamic-length little-endian unicode string value to the underlying stream, followed by a 2-byte null
/// character.
/// </summary>
public void WriteLittleUniNull(string value)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteLittleUniNull() with null value");
value = string.Empty;
}
var length = value.Length;
UnderlyingStream.SetLength(UnderlyingStream.Length + (length + 1) * 2);
UnderlyingStream.Position +=
Encoding.Unicode.GetBytes(value, 0, length, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
UnderlyingStream.Position += 2;
}
/// <summary>
/// Writes a fixed-length little-endian unicode string value to the underlying stream. To fit (size), the string content is
/// either truncated or padded with null characters.
/// </summary>
public void WriteLittleUniFixed(string value, int size)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteLittleUniFixed() with null value");
value = string.Empty;
}
var length = value.Length;
size *= 2;
UnderlyingStream.SetLength(UnderlyingStream.Length + size);
if (length * 2 >= size)
{
UnderlyingStream.Position +=
Encoding.Unicode.GetBytes(
value,
0,
size / 2,
UnderlyingStream.GetBuffer(),
(int)UnderlyingStream.Position
);
}
else
{
Encoding.Unicode.GetBytes(value, 0, length, UnderlyingStream.GetBuffer(), (int)UnderlyingStream.Position);
UnderlyingStream.Position += size;
}
}
/// <summary>
/// Writes a dynamic-length big-endian unicode string value to the underlying stream, followed by a 2-byte null character.
/// </summary>
public void WriteBigUniNull(string value)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteBigUniNull() with null value");
value = string.Empty;
}
var length = value.Length;
UnderlyingStream.SetLength(UnderlyingStream.Length + (length + 1) * 2);
UnderlyingStream.Position +=
Encoding.BigEndianUnicode.GetBytes(
value,
0,
length,
UnderlyingStream.GetBuffer(),
(int)UnderlyingStream.Position
);
UnderlyingStream.Position += 2;
}
/// <summary>
/// Writes a fixed-length big-endian unicode string value to the underlying stream. To fit (size), the string content is
/// either truncated or padded with null characters.
/// </summary>
public void WriteBigUniFixed(string value, int size)
{
if (value == null)
{
Console.WriteLine("Network: Attempted to WriteBigUniFixed() with null value");
value = string.Empty;
}
var length = value.Length;
size *= 2;
UnderlyingStream.SetLength(UnderlyingStream.Length + size);
if (length * 2 >= size)
{
UnderlyingStream.Position +=
Encoding.BigEndianUnicode.GetBytes(
value,
0,
size / 2,
UnderlyingStream.GetBuffer(),
(int)UnderlyingStream.Position
);
}
else
{
Encoding.BigEndianUnicode.GetBytes(
value,
0,
length,
UnderlyingStream.GetBuffer(),
(int)UnderlyingStream.Position
);
UnderlyingStream.Position += size;
}
}
/// <summary>
/// Fills the stream from the current position up to (capacity) with 0x00's
/// </summary>
public void Fill()
{
Fill(m_Capacity - UnderlyingStream.Length);
}
/// <summary>
/// Writes a number of 0x00 byte values to the underlying stream.
/// </summary>
public void Fill(long length)
{
if (UnderlyingStream.Position == UnderlyingStream.Length)
{
UnderlyingStream.SetLength(UnderlyingStream.Length + length);
UnderlyingStream.Seek(0, SeekOrigin.End);
}
else
{
UnderlyingStream.Write(new byte[length], 0, (int)length);
}
}
/// <summary>
/// Offsets the current position from an origin.
/// </summary>
public long Seek(long offset, SeekOrigin origin) => UnderlyingStream.Seek(offset, origin);
/// <summary>
/// Gets the entire stream content as a byte array.
/// </summary>
public byte[] ToArray() => UnderlyingStream.ToArray();
}
}

View file

@ -1,381 +1,381 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: AccountPackets.cs - Created: 2020/05/08 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using Server.Accounting;
namespace Server.Network
{
public enum ALRReason : byte
{
Invalid = 0x00,
InUse = 0x01,
Blocked = 0x02,
BadPass = 0x03,
Idle = 0xFE,
BadComm = 0xFF
}
public enum PMMessage : byte
{
CharNoExist = 1,
CharExists = 2,
CharInWorld = 5,
LoginSyncError = 6,
IdleWarning = 7
}
public enum DeleteResultType
{
PasswordInvalid,
CharNotExist,
CharBeingPlayed,
CharTooYoung,
CharQueued,
BadRequest
}
public sealed class ChangeCharacter : Packet
{
public ChangeCharacter(IAccount a) : base(0x81)
{
EnsureCapacity(305);
var count = 0;
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
++count;
Stream.Write((byte)count);
Stream.Write((byte)0);
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
{
var name = a[i].Name;
if (name == null)
name = "-null-";
else if ((name = name.Trim()).Length == 0)
name = "-empty-";
Stream.WriteAsciiFixed(name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
}
}
/// <summary>
/// Asks the client for it's version
/// </summary>
public sealed class ClientVersionReq : Packet
{
public ClientVersionReq() : base(0xBD)
{
EnsureCapacity(3);
}
}
public sealed class DeleteResult : Packet
{
public DeleteResult(DeleteResultType res) : base(0x85, 2)
{
Stream.Write((byte)res);
}
}
public sealed class PopupMessage : Packet
{
public PopupMessage(PMMessage msg) : base(0x53, 2)
{
Stream.Write((byte)msg);
}
}
public sealed class SupportedFeatures : Packet
{
public SupportedFeatures(NetState ns) : base(0xB9, ns.ExtendedSupportedFeatures ? 5 : 3)
{
var flags = ExpansionInfo.CoreExpansion.SupportedFeatures;
flags |= Value;
if (ns.Account.Limit >= 6)
{
flags |= FeatureFlags.LiveAccount;
flags &= ~FeatureFlags.UOTD;
if (ns.Account.Limit > 6)
flags |= FeatureFlags.SeventhCharacterSlot;
else
flags |= FeatureFlags.SixthCharacterSlot;
}
if (ns.ExtendedSupportedFeatures)
Stream.Write((uint)flags);
else
Stream.Write((ushort)flags);
}
public static FeatureFlags Value { get; set; }
public static SupportedFeatures Instantiate(NetState ns) => new SupportedFeatures(ns);
}
public sealed class LoginConfirm : Packet
{
public LoginConfirm(Mobile m) : base(0x1B, 37)
{
Stream.Write(m.Serial);
Stream.Write(0);
Stream.Write((short)m.Body);
Stream.Write((short)m.X);
Stream.Write((short)m.Y);
Stream.Write((short)m.Z);
Stream.Write((byte)m.Direction);
Stream.Write((byte)0);
Stream.Write(-1);
var map = m.Map;
if (map == null || map == Map.Internal)
map = m.LogoutMap;
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((short)(map?.Width ?? Map.Felucca.Width));
Stream.Write((short)(map?.Height ?? Map.Felucca.Height));
Stream.Fill();
}
}
public sealed class LoginComplete : Packet
{
public static readonly Packet Instance = SetStatic(new LoginComplete());
public LoginComplete() : base(0x55, 1)
{
}
}
public sealed class CharacterListUpdate : Packet
{
public CharacterListUpdate(IAccount a) : base(0x86)
{
EnsureCapacity(4 + a.Length * 60);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
highSlot = i;
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
{
var m = a[i];
if (m != null)
{
Stream.WriteAsciiFixed(m.Name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
}
}
}
public sealed class CharacterList : Packet
{
public CharacterList(IAccount a, CityInfo[] info) : base(0xA9)
{
EnsureCapacity(11 + a.Length * 60 + info.Length * 89);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
highSlot = i;
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
if (a[i] != null)
{
Stream.WriteAsciiFixed(a[i].Name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
Stream.Write((byte)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var ci = info[i];
Stream.Write((byte)i);
Stream.WriteAsciiFixed(ci.City, 32);
Stream.WriteAsciiFixed(ci.Building, 32);
Stream.Write(ci.X);
Stream.Write(ci.Y);
Stream.Write(ci.Z);
Stream.Write(ci.Map.MapID);
Stream.Write(ci.Description);
Stream.Write(0);
}
var flags = ExpansionInfo.CoreExpansion.CharacterListFlags;
if (count > 6)
flags |= CharacterListFlags.SeventhCharacterSlot |
CharacterListFlags.SixthCharacterSlot; // 7th Character Slot - TODO: Is SixthCharacterSlot Required?
else if (count == 6)
flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot
else if (a.Limit == 1)
flags |= CharacterListFlags.SlotLimit &
CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character
Stream.Write((int)(flags | AdditionalFlags)); // Additional Flags
Stream.Write((short)-1);
}
public static CharacterListFlags AdditionalFlags { get; set; }
}
public sealed class CharacterListOld : Packet
{
public CharacterListOld(IAccount a, CityInfo[] info) : base(0xA9)
{
EnsureCapacity(9 + a.Length * 60 + info.Length * 63);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
highSlot = i;
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
if (a[i] != null)
{
Stream.WriteAsciiFixed(a[i].Name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
Stream.Write((byte)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var ci = info[i];
Stream.Write((byte)i);
Stream.WriteAsciiFixed(ci.City, 31);
Stream.WriteAsciiFixed(ci.Building, 31);
}
var flags = ExpansionInfo.CoreExpansion.CharacterListFlags;
if (count > 6)
flags |= CharacterListFlags.SeventhCharacterSlot |
CharacterListFlags.SixthCharacterSlot; // 7th Character Slot - TODO: Is SixthCharacterSlot Required?
else if (count == 6)
flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot
else if (a.Limit == 1)
flags |= CharacterListFlags.SlotLimit &
CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character
Stream.Write((int)(flags | CharacterList.AdditionalFlags)); // Additional Flags
}
}
public sealed class AccountLoginRej : Packet
{
public AccountLoginRej(ALRReason reason) : base(0x82, 2)
{
Stream.Write((byte)reason);
}
}
public sealed class AccountLoginAck : Packet
{
public AccountLoginAck(ServerInfo[] info) : base(0xA8)
{
EnsureCapacity(6 + info.Length * 40);
Stream.Write((byte)0x5D); // Unknown
Stream.Write((ushort)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var si = info[i];
Stream.Write((ushort)i);
Stream.WriteAsciiFixed(si.Name, 32);
Stream.Write((byte)si.FullPercent);
Stream.Write((sbyte)si.TimeZone);
Stream.Write(Utility.GetAddressValue(si.Address.Address));
}
}
}
public sealed class PlayServerAck : Packet
{
internal static int m_AuthID = -1;
public PlayServerAck(ServerInfo si) : base(0x8C, 11)
{
var addr = Utility.GetAddressValue(si.Address.Address);
Stream.Write((byte)addr);
Stream.Write((byte)(addr >> 8));
Stream.Write((byte)(addr >> 16));
Stream.Write((byte)(addr >> 24));
Stream.Write((short)si.Address.Port);
Stream.Write(m_AuthID);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: AccountPackets.cs - Created: 2020/05/08 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using Server.Accounting;
namespace Server.Network
{
public enum ALRReason : byte
{
Invalid = 0x00,
InUse = 0x01,
Blocked = 0x02,
BadPass = 0x03,
Idle = 0xFE,
BadComm = 0xFF
}
public enum PMMessage : byte
{
CharNoExist = 1,
CharExists = 2,
CharInWorld = 5,
LoginSyncError = 6,
IdleWarning = 7
}
public enum DeleteResultType
{
PasswordInvalid,
CharNotExist,
CharBeingPlayed,
CharTooYoung,
CharQueued,
BadRequest
}
public sealed class ChangeCharacter : Packet
{
public ChangeCharacter(IAccount a) : base(0x81)
{
EnsureCapacity(305);
var count = 0;
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
++count;
Stream.Write((byte)count);
Stream.Write((byte)0);
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
{
var name = a[i].Name;
if (name == null)
name = "-null-";
else if ((name = name.Trim()).Length == 0)
name = "-empty-";
Stream.WriteAsciiFixed(name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
}
}
/// <summary>
/// Asks the client for it's version
/// </summary>
public sealed class ClientVersionReq : Packet
{
public ClientVersionReq() : base(0xBD)
{
EnsureCapacity(3);
}
}
public sealed class DeleteResult : Packet
{
public DeleteResult(DeleteResultType res) : base(0x85, 2)
{
Stream.Write((byte)res);
}
}
public sealed class PopupMessage : Packet
{
public PopupMessage(PMMessage msg) : base(0x53, 2)
{
Stream.Write((byte)msg);
}
}
public sealed class SupportedFeatures : Packet
{
public SupportedFeatures(NetState ns) : base(0xB9, ns.ExtendedSupportedFeatures ? 5 : 3)
{
var flags = ExpansionInfo.CoreExpansion.SupportedFeatures;
flags |= Value;
if (ns.Account.Limit >= 6)
{
flags |= FeatureFlags.LiveAccount;
flags &= ~FeatureFlags.UOTD;
if (ns.Account.Limit > 6)
flags |= FeatureFlags.SeventhCharacterSlot;
else
flags |= FeatureFlags.SixthCharacterSlot;
}
if (ns.ExtendedSupportedFeatures)
Stream.Write((uint)flags);
else
Stream.Write((ushort)flags);
}
public static FeatureFlags Value { get; set; }
public static SupportedFeatures Instantiate(NetState ns) => new SupportedFeatures(ns);
}
public sealed class LoginConfirm : Packet
{
public LoginConfirm(Mobile m) : base(0x1B, 37)
{
Stream.Write(m.Serial);
Stream.Write(0);
Stream.Write((short)m.Body);
Stream.Write((short)m.X);
Stream.Write((short)m.Y);
Stream.Write((short)m.Z);
Stream.Write((byte)m.Direction);
Stream.Write((byte)0);
Stream.Write(-1);
var map = m.Map;
if (map == null || map == Map.Internal)
map = m.LogoutMap;
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((short)(map?.Width ?? Map.Felucca.Width));
Stream.Write((short)(map?.Height ?? Map.Felucca.Height));
Stream.Fill();
}
}
public sealed class LoginComplete : Packet
{
public static readonly Packet Instance = SetStatic(new LoginComplete());
public LoginComplete() : base(0x55, 1)
{
}
}
public sealed class CharacterListUpdate : Packet
{
public CharacterListUpdate(IAccount a) : base(0x86)
{
EnsureCapacity(4 + a.Length * 60);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
highSlot = i;
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
{
var m = a[i];
if (m != null)
{
Stream.WriteAsciiFixed(m.Name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
}
}
}
public sealed class CharacterList : Packet
{
public CharacterList(IAccount a, CityInfo[] info) : base(0xA9)
{
EnsureCapacity(11 + a.Length * 60 + info.Length * 89);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
highSlot = i;
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
if (a[i] != null)
{
Stream.WriteAsciiFixed(a[i].Name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
Stream.Write((byte)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var ci = info[i];
Stream.Write((byte)i);
Stream.WriteAsciiFixed(ci.City, 32);
Stream.WriteAsciiFixed(ci.Building, 32);
Stream.Write(ci.X);
Stream.Write(ci.Y);
Stream.Write(ci.Z);
Stream.Write(ci.Map.MapID);
Stream.Write(ci.Description);
Stream.Write(0);
}
var flags = ExpansionInfo.CoreExpansion.CharacterListFlags;
if (count > 6)
flags |= CharacterListFlags.SeventhCharacterSlot |
CharacterListFlags.SixthCharacterSlot; // 7th Character Slot - TODO: Is SixthCharacterSlot Required?
else if (count == 6)
flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot
else if (a.Limit == 1)
flags |= CharacterListFlags.SlotLimit &
CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character
Stream.Write((int)(flags | AdditionalFlags)); // Additional Flags
Stream.Write((short)-1);
}
public static CharacterListFlags AdditionalFlags { get; set; }
}
public sealed class CharacterListOld : Packet
{
public CharacterListOld(IAccount a, CityInfo[] info) : base(0xA9)
{
EnsureCapacity(9 + a.Length * 60 + info.Length * 63);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
highSlot = i;
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
if (a[i] != null)
{
Stream.WriteAsciiFixed(a[i].Name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
Stream.Write((byte)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var ci = info[i];
Stream.Write((byte)i);
Stream.WriteAsciiFixed(ci.City, 31);
Stream.WriteAsciiFixed(ci.Building, 31);
}
var flags = ExpansionInfo.CoreExpansion.CharacterListFlags;
if (count > 6)
flags |= CharacterListFlags.SeventhCharacterSlot |
CharacterListFlags.SixthCharacterSlot; // 7th Character Slot - TODO: Is SixthCharacterSlot Required?
else if (count == 6)
flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot
else if (a.Limit == 1)
flags |= CharacterListFlags.SlotLimit &
CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character
Stream.Write((int)(flags | CharacterList.AdditionalFlags)); // Additional Flags
}
}
public sealed class AccountLoginRej : Packet
{
public AccountLoginRej(ALRReason reason) : base(0x82, 2)
{
Stream.Write((byte)reason);
}
}
public sealed class AccountLoginAck : Packet
{
public AccountLoginAck(ServerInfo[] info) : base(0xA8)
{
EnsureCapacity(6 + info.Length * 40);
Stream.Write((byte)0x5D); // Unknown
Stream.Write((ushort)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var si = info[i];
Stream.Write((ushort)i);
Stream.WriteAsciiFixed(si.Name, 32);
Stream.Write((byte)si.FullPercent);
Stream.Write((sbyte)si.TimeZone);
Stream.Write(Utility.GetAddressValue(si.Address.Address));
}
}
}
public sealed class PlayServerAck : Packet
{
internal static int m_AuthID = -1;
public PlayServerAck(ServerInfo si) : base(0x8C, 11)
{
var addr = Utility.GetAddressValue(si.Address.Address);
Stream.Write((byte)addr);
Stream.Write((byte)(addr >> 8));
Stream.Write((byte)(addr >> 16));
Stream.Write((byte)(addr >> 24));
Stream.Write((short)si.Address.Port);
Stream.Write(m_AuthID);
}
}
}

View file

@ -1,64 +1,64 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ArrowPackets.cs - Created: 2020/05/03 - Updated: 2020/05/03 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class CancelArrow : Packet
{
public CancelArrow() : base(0xBA, 6)
{
Stream.Write((byte)0);
Stream.Write((short)-1);
Stream.Write((short)-1);
}
}
public sealed class SetArrow : Packet
{
public SetArrow(int x, int y) : base(0xBA, 6)
{
Stream.Write((byte)1);
Stream.Write((short)x);
Stream.Write((short)y);
}
}
public sealed class CancelArrowHS : Packet
{
public CancelArrowHS(int x, int y, Serial s) : base(0xBA, 10)
{
Stream.Write((byte)0);
Stream.Write((short)x);
Stream.Write((short)y);
Stream.Write(s);
}
}
public sealed class SetArrowHS : Packet
{
public SetArrowHS(int x, int y, Serial s) : base(0xBA, 10)
{
Stream.Write((byte)1);
Stream.Write((short)x);
Stream.Write((short)y);
Stream.Write(s);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ArrowPackets.cs - Created: 2020/05/03 - Updated: 2020/05/03 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class CancelArrow : Packet
{
public CancelArrow() : base(0xBA, 6)
{
Stream.Write((byte)0);
Stream.Write((short)-1);
Stream.Write((short)-1);
}
}
public sealed class SetArrow : Packet
{
public SetArrow(int x, int y) : base(0xBA, 6)
{
Stream.Write((byte)1);
Stream.Write((short)x);
Stream.Write((short)y);
}
}
public sealed class CancelArrowHS : Packet
{
public CancelArrowHS(int x, int y, Serial s) : base(0xBA, 10)
{
Stream.Write((byte)0);
Stream.Write((short)x);
Stream.Write((short)y);
Stream.Write(s);
}
}
public sealed class SetArrowHS : Packet
{
public SetArrowHS(int x, int y, Serial s) : base(0xBA, 10)
{
Stream.Write((byte)1);
Stream.Write((short)x);
Stream.Write((short)y);
Stream.Write(s);
}
}
}

View file

@ -1,58 +1,58 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: AttributeNormalizer.cs *
* Created: 2020/06/24 - Updated: 2020/06/24 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 AttributeNormalizer
{
public static int Maximum { get; set; } = 25;
public static bool Enabled { get; set; } = true;
public static void Write(PacketWriter stream, int cur, int max)
{
if (Enabled && max != 0)
{
stream.Write((short)Maximum);
stream.Write((short)(cur * Maximum / max));
}
else
{
stream.Write((short)max);
stream.Write((short)cur);
}
}
public static void WriteReverse(PacketWriter stream, int cur, int max)
{
if (Enabled && max != 0)
{
stream.Write((short)(cur * Maximum / max));
stream.Write((short)Maximum);
}
else
{
stream.Write((short)cur);
stream.Write((short)max);
}
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: AttributeNormalizer.cs *
* Created: 2020/06/24 - Updated: 2020/06/24 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 AttributeNormalizer
{
public static int Maximum { get; set; } = 25;
public static bool Enabled { get; set; } = true;
public static void Write(PacketWriter stream, int cur, int max)
{
if (Enabled && max != 0)
{
stream.Write((short)Maximum);
stream.Write((short)(cur * Maximum / max));
}
else
{
stream.Write((short)max);
stream.Write((short)cur);
}
}
public static void WriteReverse(PacketWriter stream, int cur, int max)
{
if (Enabled && max != 0)
{
stream.Write((short)(cur * Maximum / max));
stream.Write((short)Maximum);
}
else
{
stream.Write((short)cur);
stream.Write((short)max);
}
}
}
}

View file

@ -1,56 +1,56 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: CombatPackets.cs - Created: 2020/06/25 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class Swing : Packet
{
public Swing(Serial attacker, Serial defender) : base(0x2F, 10)
{
Stream.Write((byte)0);
Stream.Write(attacker);
Stream.Write(defender);
}
}
public sealed class SetWarMode : Packet
{
public static readonly Packet InWarMode = SetStatic(new SetWarMode(true));
public static readonly Packet InPeaceMode = SetStatic(new SetWarMode(false));
public SetWarMode(bool mode) : base(0x72, 5)
{
Stream.Write(mode);
Stream.Write((byte)0x00);
Stream.Write((byte)0x32);
Stream.Write((byte)0x00);
}
public static Packet Instantiate(bool mode) => mode ? InWarMode : InPeaceMode;
}
public sealed class ChangeCombatant : Packet
{
public ChangeCombatant(Serial combatant) : base(0xAA, 5)
{
Stream.Write(combatant);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: CombatPackets.cs - Created: 2020/06/25 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class Swing : Packet
{
public Swing(Serial attacker, Serial defender) : base(0x2F, 10)
{
Stream.Write((byte)0);
Stream.Write(attacker);
Stream.Write(defender);
}
}
public sealed class SetWarMode : Packet
{
public static readonly Packet InWarMode = SetStatic(new SetWarMode(true));
public static readonly Packet InPeaceMode = SetStatic(new SetWarMode(false));
public SetWarMode(bool mode) : base(0x72, 5)
{
Stream.Write(mode);
Stream.Write((byte)0x00);
Stream.Write((byte)0x32);
Stream.Write((byte)0x00);
}
public static Packet Instantiate(bool mode) => mode ? InWarMode : InPeaceMode;
}
public sealed class ChangeCombatant : Packet
{
public ChangeCombatant(Serial combatant) : base(0xAA, 5)
{
Stream.Write(combatant);
}
}
}

View file

@ -1,48 +1,48 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: DamagePackets.cs - Created: 2020/05/03 - Updated: 2020/05/03 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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
{
public sealed class DamagePacketOld : Packet
{
public DamagePacketOld(Serial mobile, int amount) : base(0xBF)
{
EnsureCapacity(11);
Stream.Write((short)0x22);
Stream.Write((byte)1);
Stream.Write(mobile);
Stream.Write((byte)Math.Clamp(amount, 0, 255));
}
}
public sealed class DamagePacket : Packet
{
public DamagePacket(Serial mobile, int amount) : base(0x0B, 7)
{
Stream.Write(mobile);
Stream.Write((ushort)Math.Clamp(amount, 0, 0xFFFF));
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: DamagePackets.cs - Created: 2020/05/03 - Updated: 2020/05/03 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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
{
public sealed class DamagePacketOld : Packet
{
public DamagePacketOld(Serial mobile, int amount) : base(0xBF)
{
EnsureCapacity(11);
Stream.Write((short)0x22);
Stream.Write((byte)1);
Stream.Write(mobile);
Stream.Write((byte)Math.Clamp(amount, 0, 255));
}
}
public sealed class DamagePacket : Packet
{
public DamagePacket(Serial mobile, int amount) : base(0x0B, 7)
{
Stream.Write(mobile);
Stream.Write((ushort)Math.Clamp(amount, 0, 0xFFFF));
}
}
}

View file

@ -1,35 +1,35 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: DisplayHuePicker.cs *
* Created: 2020/05/08 - Updated: 2020/05/08 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.HuePickers;
namespace Server.Network
{
public sealed class DisplayHuePicker : Packet
{
public DisplayHuePicker(HuePicker huePicker) : base(0x95, 9)
{
Stream.Write(huePicker.Serial);
Stream.Write((short)0);
Stream.Write((short)huePicker.ItemID);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: DisplayHuePicker.cs *
* Created: 2020/05/08 - Updated: 2020/05/08 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.HuePickers;
namespace Server.Network
{
public sealed class DisplayHuePicker : Packet
{
public DisplayHuePicker(HuePicker huePicker) : base(0x95, 9)
{
Stream.Write(huePicker.Serial);
Stream.Write((short)0);
Stream.Write((short)huePicker.ItemID);
}
}
}

View file

@ -1,292 +1,396 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: EffectPackets.cs - Created: 2020/05/26 - Updated: 2020/05/26 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 enum EffectType
{
Moving,
Lightning,
FixedXYZ,
FixedFrom
}
public class ParticleEffect : Packet
{
public ParticleEffect(EffectType type, Serial from, Serial to, int itemID, Point3D fromPoint, Point3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect,
int explodeEffect, int explodeSound, Serial serial, int layer, int unknown) : base(0xC7, 49)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.m_X);
Stream.Write((short)fromPoint.m_Y);
Stream.Write((sbyte)fromPoint.m_Z);
Stream.Write((short)toPoint.m_X);
Stream.Write((short)toPoint.m_Y);
Stream.Write((sbyte)toPoint.m_Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
Stream.Write((short)effect);
Stream.Write((short)explodeEffect);
Stream.Write((short)explodeSound);
Stream.Write(serial);
Stream.Write((byte)layer);
Stream.Write((short)unknown);
}
public ParticleEffect(EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect,
int explodeEffect, int explodeSound, Serial serial, int layer, int unknown) : base(0xC7, 49)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.X);
Stream.Write((short)fromPoint.Y);
Stream.Write((sbyte)fromPoint.Z);
Stream.Write((short)toPoint.X);
Stream.Write((short)toPoint.Y);
Stream.Write((sbyte)toPoint.Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
Stream.Write((short)effect);
Stream.Write((short)explodeEffect);
Stream.Write((short)explodeSound);
Stream.Write(serial);
Stream.Write((byte)layer);
Stream.Write((short)unknown);
}
}
public class HuedEffect : Packet
{
public HuedEffect(EffectType type, Serial from, Serial to, int itemID, Point3D fromPoint, Point3D toPoint, int speed,
int duration, bool fixedDirection, bool explode, int hue, int renderMode) : base(0xC0, 36)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.m_X);
Stream.Write((short)fromPoint.m_Y);
Stream.Write((sbyte)fromPoint.m_Z);
Stream.Write((short)toPoint.m_X);
Stream.Write((short)toPoint.m_Y);
Stream.Write((sbyte)toPoint.m_Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
}
public HuedEffect(EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode) : base(0xC0, 36)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.X);
Stream.Write((short)fromPoint.Y);
Stream.Write((sbyte)fromPoint.Z);
Stream.Write((short)toPoint.X);
Stream.Write((short)toPoint.Y);
Stream.Write((sbyte)toPoint.Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
}
}
public sealed class TargetParticleEffect : ParticleEffect
{
public TargetParticleEffect(IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect,
int layer, int unknown) : base(EffectType.FixedFrom, e.Serial, Serial.Zero, itemID, e.Location, e.Location,
speed, duration, true, false, hue, renderMode, effect, 1, 0, e.Serial, layer, unknown)
{
}
}
public sealed class TargetEffect : HuedEffect
{
public TargetEffect(IEntity e, int itemID, int speed, int duration, int hue, int renderMode) : base(
EffectType.FixedFrom, e.Serial, Serial.Zero, itemID, e.Location, e.Location, speed, duration, true, false, hue,
renderMode)
{
}
}
public sealed class LocationParticleEffect : ParticleEffect
{
public LocationParticleEffect(IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect,
int unknown) : base(EffectType.FixedXYZ, e.Serial, Serial.Zero, itemID, e.Location, e.Location, speed, duration,
true, false, hue, renderMode, effect, 1, 0, e.Serial, 255, unknown)
{
}
}
public sealed class LocationEffect : HuedEffect
{
public LocationEffect(IPoint3D p, int itemID, int speed, int duration, int hue, int renderMode) : base(
EffectType.FixedXYZ, Serial.Zero, Serial.Zero, itemID, p, p, speed, duration, true, false, hue, renderMode)
{
}
}
public sealed class MovingParticleEffect : ParticleEffect
{
public MovingParticleEffect(IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound, EffectLayer layer,
int unknown) : base(EffectType.Moving, from.Serial, to.Serial, itemID, from.Location, to.Location, speed,
duration, fixedDirection, explodes, hue, renderMode, effect, explodeEffect, explodeSound, Serial.Zero,
(int)layer, unknown)
{
}
}
public sealed class MovingEffect : HuedEffect
{
public MovingEffect(IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode) : base(EffectType.Moving, from.Serial, to.Serial, itemID, from.Location,
to.Location, speed, duration, fixedDirection, explodes, hue, renderMode)
{
}
}
public enum ScreenEffectType
{
FadeOut = 0x00,
FadeIn = 0x01,
LightFlash = 0x02,
FadeInOut = 0x03,
DarkFlash = 0x04
}
public class ScreenEffect : Packet
{
public ScreenEffect(ScreenEffectType type)
: base(0x70, 28)
{
Stream.Write((byte)0x04);
Stream.Fill(8);
Stream.Write((short)type);
Stream.Fill(16);
}
}
public sealed class ScreenFadeOut : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenFadeOut());
public ScreenFadeOut()
: base(ScreenEffectType.FadeOut)
{
}
}
public sealed class ScreenFadeIn : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenFadeIn());
public ScreenFadeIn()
: base(ScreenEffectType.FadeIn)
{
}
}
public sealed class ScreenFadeInOut : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenFadeInOut());
public ScreenFadeInOut()
: base(ScreenEffectType.FadeInOut)
{
}
}
public sealed class ScreenLightFlash : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenLightFlash());
public ScreenLightFlash()
: base(ScreenEffectType.LightFlash)
{
}
}
public sealed class ScreenDarkFlash : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenDarkFlash());
public ScreenDarkFlash()
: base(ScreenEffectType.DarkFlash)
{
}
}
public sealed class BoltEffect : Packet
{
public BoltEffect(IEntity target, int hue) : base(0xC0, 36)
{
Stream.Write((byte)0x01); // type
Stream.Write(target.Serial);
Stream.Write(Serial.Zero);
Stream.Write((short)0); // itemID
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((sbyte)target.Z);
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((sbyte)target.Z);
Stream.Write((byte)0); // speed
Stream.Write((byte)0); // duration
Stream.Write((short)0); // unk
Stream.Write(false); // fixed direction
Stream.Write(false); // explode
Stream.Write(hue);
Stream.Write(0); // render mode
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: EffectPackets.cs - Created: 2020/05/26 - Updated: 2020/05/26 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 enum EffectType
{
Moving,
Lightning,
FixedXYZ,
FixedFrom
}
public class ParticleEffect : Packet
{
public ParticleEffect(
EffectType type, Serial from, Serial to, int itemID, Point3D fromPoint, Point3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect,
int explodeEffect, int explodeSound, Serial serial, int layer, int unknown
) : base(0xC7, 49)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.m_X);
Stream.Write((short)fromPoint.m_Y);
Stream.Write((sbyte)fromPoint.m_Z);
Stream.Write((short)toPoint.m_X);
Stream.Write((short)toPoint.m_Y);
Stream.Write((sbyte)toPoint.m_Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
Stream.Write((short)effect);
Stream.Write((short)explodeEffect);
Stream.Write((short)explodeSound);
Stream.Write(serial);
Stream.Write((byte)layer);
Stream.Write((short)unknown);
}
public ParticleEffect(
EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect,
int explodeEffect, int explodeSound, Serial serial, int layer, int unknown
) : base(0xC7, 49)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.X);
Stream.Write((short)fromPoint.Y);
Stream.Write((sbyte)fromPoint.Z);
Stream.Write((short)toPoint.X);
Stream.Write((short)toPoint.Y);
Stream.Write((sbyte)toPoint.Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
Stream.Write((short)effect);
Stream.Write((short)explodeEffect);
Stream.Write((short)explodeSound);
Stream.Write(serial);
Stream.Write((byte)layer);
Stream.Write((short)unknown);
}
}
public class HuedEffect : Packet
{
public HuedEffect(
EffectType type, Serial from, Serial to, int itemID, Point3D fromPoint, Point3D toPoint, int speed,
int duration, bool fixedDirection, bool explode, int hue, int renderMode
) : base(0xC0, 36)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.m_X);
Stream.Write((short)fromPoint.m_Y);
Stream.Write((sbyte)fromPoint.m_Z);
Stream.Write((short)toPoint.m_X);
Stream.Write((short)toPoint.m_Y);
Stream.Write((sbyte)toPoint.m_Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
}
public HuedEffect(
EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode
) : base(0xC0, 36)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.X);
Stream.Write((short)fromPoint.Y);
Stream.Write((sbyte)fromPoint.Z);
Stream.Write((short)toPoint.X);
Stream.Write((short)toPoint.Y);
Stream.Write((sbyte)toPoint.Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
}
}
public sealed class TargetParticleEffect : ParticleEffect
{
public TargetParticleEffect(
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect,
int layer, int unknown
) : base(
EffectType.FixedFrom,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode,
effect,
1,
0,
e.Serial,
layer,
unknown
)
{
}
}
public sealed class TargetEffect : HuedEffect
{
public TargetEffect(IEntity e, int itemID, int speed, int duration, int hue, int renderMode) : base(
EffectType.FixedFrom,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode
)
{
}
}
public sealed class LocationParticleEffect : ParticleEffect
{
public LocationParticleEffect(
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect,
int unknown
) : base(
EffectType.FixedXYZ,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode,
effect,
1,
0,
e.Serial,
255,
unknown
)
{
}
}
public sealed class LocationEffect : HuedEffect
{
public LocationEffect(IPoint3D p, int itemID, int speed, int duration, int hue, int renderMode) : base(
EffectType.FixedXYZ,
Serial.Zero,
Serial.Zero,
itemID,
p,
p,
speed,
duration,
true,
false,
hue,
renderMode
)
{
}
}
public sealed class MovingParticleEffect : ParticleEffect
{
public MovingParticleEffect(
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound, EffectLayer layer,
int unknown
) : base(
EffectType.Moving,
from.Serial,
to.Serial,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode,
effect,
explodeEffect,
explodeSound,
Serial.Zero,
(int)layer,
unknown
)
{
}
}
public sealed class MovingEffect : HuedEffect
{
public MovingEffect(
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode
) : base(
EffectType.Moving,
from.Serial,
to.Serial,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
)
{
}
}
public enum ScreenEffectType
{
FadeOut = 0x00,
FadeIn = 0x01,
LightFlash = 0x02,
FadeInOut = 0x03,
DarkFlash = 0x04
}
public class ScreenEffect : Packet
{
public ScreenEffect(ScreenEffectType type)
: base(0x70, 28)
{
Stream.Write((byte)0x04);
Stream.Fill(8);
Stream.Write((short)type);
Stream.Fill(16);
}
}
public sealed class ScreenFadeOut : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenFadeOut());
public ScreenFadeOut()
: base(ScreenEffectType.FadeOut)
{
}
}
public sealed class ScreenFadeIn : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenFadeIn());
public ScreenFadeIn()
: base(ScreenEffectType.FadeIn)
{
}
}
public sealed class ScreenFadeInOut : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenFadeInOut());
public ScreenFadeInOut()
: base(ScreenEffectType.FadeInOut)
{
}
}
public sealed class ScreenLightFlash : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenLightFlash());
public ScreenLightFlash()
: base(ScreenEffectType.LightFlash)
{
}
}
public sealed class ScreenDarkFlash : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenDarkFlash());
public ScreenDarkFlash()
: base(ScreenEffectType.DarkFlash)
{
}
}
public sealed class BoltEffect : Packet
{
public BoltEffect(IEntity target, int hue) : base(0xC0, 36)
{
Stream.Write((byte)0x01); // type
Stream.Write(target.Serial);
Stream.Write(Serial.Zero);
Stream.Write((short)0); // itemID
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((sbyte)target.Z);
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((sbyte)target.Z);
Stream.Write((byte)0); // speed
Stream.Write((byte)0); // duration
Stream.Write((short)0); // unk
Stream.Write(false); // fixed direction
Stream.Write(false); // explode
Stream.Write(hue);
Stream.Write(0); // render mode
}
}
}

View file

@ -1,131 +1,133 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: EquipmentPackets.cs - Created: 2020/05/07 - Updated: 2020/05/07 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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
{
public class EquipInfoAttribute
{
public EquipInfoAttribute(int number, int charges = -1)
{
Number = number;
Charges = charges;
}
public int Number { get; }
public int Charges { get; }
}
public class EquipmentInfo
{
public EquipmentInfo(int number, Mobile crafter, bool unidentified, EquipInfoAttribute[] attributes)
{
Number = number;
Crafter = crafter;
Unidentified = unidentified;
Attributes = attributes;
}
public int Number { get; }
public Mobile Crafter { get; }
public bool Unidentified { get; }
public EquipInfoAttribute[] Attributes { get; }
}
public sealed class DisplayEquipmentInfo : Packet
{
public DisplayEquipmentInfo(Item item, EquipmentInfo info) : base(0xBF)
{
var attrs = info.Attributes;
EnsureCapacity(17 + (info.Crafter?.Name?.Length ?? 0) +
(info.Unidentified ? 4 : 0) + attrs.Length * 6);
Stream.Write((short)0x10);
Stream.Write(item.Serial);
Stream.Write(info.Number);
if (info.Crafter != null)
{
var name = info.Crafter.Name;
Stream.Write(-3);
if (name == null)
{
Stream.Write((ushort)0);
}
else
{
var length = name.Length;
Stream.Write((ushort)length);
Stream.WriteAsciiFixed(name, length);
}
}
if (info.Unidentified) Stream.Write(-4);
for (var i = 0; i < attrs.Length; ++i)
{
Stream.Write(attrs[i].Number);
Stream.Write((short)attrs[i].Charges);
}
Stream.Write(-1);
}
}
public sealed class EquipUpdate : Packet
{
public EquipUpdate(Item item) : base(0x2E, 15)
{
Serial parentSerial;
var parent = item.Parent as Mobile;
var hue = item.Hue;
if (parent != null)
{
parentSerial = parent.Serial;
if (parent.SolidHueOverride >= 0)
hue = parent.SolidHueOverride;
}
else
{
Console.WriteLine("Warning: EquipUpdate on item with !(parent is Mobile)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((byte)item.Layer);
Stream.Write(parentSerial);
Stream.Write((short)hue);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: EquipmentPackets.cs - Created: 2020/05/07 - Updated: 2020/05/07 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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
{
public class EquipInfoAttribute
{
public EquipInfoAttribute(int number, int charges = -1)
{
Number = number;
Charges = charges;
}
public int Number { get; }
public int Charges { get; }
}
public class EquipmentInfo
{
public EquipmentInfo(int number, Mobile crafter, bool unidentified, EquipInfoAttribute[] attributes)
{
Number = number;
Crafter = crafter;
Unidentified = unidentified;
Attributes = attributes;
}
public int Number { get; }
public Mobile Crafter { get; }
public bool Unidentified { get; }
public EquipInfoAttribute[] Attributes { get; }
}
public sealed class DisplayEquipmentInfo : Packet
{
public DisplayEquipmentInfo(Item item, EquipmentInfo info) : base(0xBF)
{
var attrs = info.Attributes;
EnsureCapacity(
17 + (info.Crafter?.Name?.Length ?? 0) +
(info.Unidentified ? 4 : 0) + attrs.Length * 6
);
Stream.Write((short)0x10);
Stream.Write(item.Serial);
Stream.Write(info.Number);
if (info.Crafter != null)
{
var name = info.Crafter.Name;
Stream.Write(-3);
if (name == null)
{
Stream.Write((ushort)0);
}
else
{
var length = name.Length;
Stream.Write((ushort)length);
Stream.WriteAsciiFixed(name, length);
}
}
if (info.Unidentified) Stream.Write(-4);
for (var i = 0; i < attrs.Length; ++i)
{
Stream.Write(attrs[i].Number);
Stream.Write((short)attrs[i].Charges);
}
Stream.Write(-1);
}
}
public sealed class EquipUpdate : Packet
{
public EquipUpdate(Item item) : base(0x2E, 15)
{
Serial parentSerial;
var parent = item.Parent as Mobile;
var hue = item.Hue;
if (parent != null)
{
parentSerial = parent.Serial;
if (parent.SolidHueOverride >= 0)
hue = parent.SolidHueOverride;
}
else
{
Console.WriteLine("Warning: EquipUpdate on item with !(parent is Mobile)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((byte)item.Layer);
Stream.Write(parentSerial);
Stream.Write((short)hue);
}
}
}

View file

@ -1,344 +1,344 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: GumpPackets.cs - Created: 2020/05/26 - Updated: 2020/05/26 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Buffers;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using Server.Gumps;
namespace Server.Network
{
public sealed class CloseGump : Packet
{
public CloseGump(int typeID, int buttonID) : base(0xBF)
{
EnsureCapacity(13);
Stream.Write((short)0x04);
Stream.Write(typeID);
Stream.Write(buttonID);
}
}
public interface IGumpWriter
{
int TextEntries { get; set; }
int Switches { get; set; }
void AppendLayout(bool val);
void AppendLayout(int val);
void AppendLayout(uint val);
void AppendLayoutNS(int val);
void AppendLayout(string text);
void AppendLayout(byte[] buffer);
void WriteStrings(List<string> strings);
void Flush();
}
public sealed class DisplayGumpPacked : Packet, IGumpWriter
{
private static readonly byte[] m_True = Gump.StringToBuffer(" 1");
private static readonly byte[] m_False = Gump.StringToBuffer(" 0");
private static readonly byte[] m_BeginTextSeparator = Gump.StringToBuffer(" @");
private static readonly byte[] m_EndTextSeparator = Gump.StringToBuffer("@");
private static readonly byte[] m_Buffer = new byte[48];
private readonly Gump m_Gump;
private readonly PacketWriter m_Layout;
private int m_StringCount;
private readonly PacketWriter m_Strings;
static DisplayGumpPacked() => m_Buffer[0] = (byte)' ';
public DisplayGumpPacked(Gump gump)
: base(0xDD)
{
m_Gump = gump;
m_Layout = PacketWriter.CreateInstance(8192);
m_Strings = PacketWriter.CreateInstance(8192);
}
public int TextEntries { get; set; }
public int Switches { get; set; }
public void AppendLayout(bool val)
{
AppendLayout(val ? m_True : m_False);
}
public void AppendLayout(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
m_Layout.Write(m_Buffer, 0, bytes);
}
public void AppendLayout(uint val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
m_Layout.Write(m_Buffer, 0, bytes);
}
public void AppendLayoutNS(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1);
m_Layout.Write(m_Buffer, 1, bytes);
}
public void AppendLayout(string text)
{
AppendLayout(m_BeginTextSeparator);
m_Layout.WriteAsciiFixed(text, text.Length);
AppendLayout(m_EndTextSeparator);
}
public void AppendLayout(byte[] buffer)
{
m_Layout.Write(buffer, 0, buffer.Length);
}
public void WriteStrings(List<string> strings)
{
m_StringCount = strings.Count;
for (var i = 0; i < strings.Count; ++i)
{
var v = strings[i] ?? "";
m_Strings.Write((ushort)v.Length);
m_Strings.WriteBigUniFixed(v, v.Length);
}
}
public void Flush()
{
EnsureCapacity(28 + (int)m_Layout.Length + (int)m_Strings.Length);
Stream.Write(m_Gump.Serial);
Stream.Write(m_Gump.TypeID);
Stream.Write(m_Gump.X);
Stream.Write(m_Gump.Y);
// Note: layout MUST be null terminated (don't listen to krrios)
m_Layout.Write((byte)0);
WritePacked(m_Layout);
Stream.Write(m_StringCount);
WritePacked(m_Strings);
PacketWriter.ReleaseInstance(m_Layout);
PacketWriter.ReleaseInstance(m_Strings);
}
private void WritePacked(PacketWriter src)
{
var buffer = src.UnderlyingStream.GetBuffer();
var length = (int)src.Length;
if (length == 0)
{
Stream.Write(0);
return;
}
var wantLength = 1 + buffer.Length * 1024 / 1000;
wantLength += 4095;
wantLength &= ~4095;
var packBuffer = ArrayPool<byte>.Shared.Rent(wantLength);
var packLength = wantLength;
Zlib.Pack(packBuffer, ref packLength, buffer, length, ZlibQuality.Default);
Stream.Write(4 + packLength);
Stream.Write(length);
Stream.Write(packBuffer, 0, packLength);
ArrayPool<byte>.Shared.Return(packBuffer);
}
}
public sealed class DisplayGumpFast : Packet, IGumpWriter
{
private static readonly byte[] m_True = Gump.StringToBuffer(" 1");
private static readonly byte[] m_False = Gump.StringToBuffer(" 0");
private static readonly byte[] m_BeginTextSeparator = Gump.StringToBuffer(" @");
private static readonly byte[] m_EndTextSeparator = Gump.StringToBuffer("@");
private readonly byte[] m_Buffer = new byte[48];
private int m_LayoutLength;
public DisplayGumpFast(Gump g) : base(0xB0)
{
m_Buffer[0] = (byte)' ';
EnsureCapacity(4096);
Stream.Write(g.Serial);
Stream.Write(g.TypeID);
Stream.Write(g.X);
Stream.Write(g.Y);
Stream.Write((ushort)0xFFFF);
}
public int TextEntries { get; set; }
public int Switches { get; set; }
public void AppendLayout(bool val)
{
AppendLayout(val ? m_True : m_False);
}
public void AppendLayout(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
Stream.Write(m_Buffer, 0, bytes);
m_LayoutLength += bytes;
}
public void AppendLayout(uint val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
Stream.Write(m_Buffer, 0, bytes);
m_LayoutLength += bytes;
}
public void AppendLayoutNS(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1);
Stream.Write(m_Buffer, 1, bytes);
m_LayoutLength += bytes;
}
public void AppendLayout(string text)
{
AppendLayout(m_BeginTextSeparator);
var length = text.Length;
Stream.WriteAsciiFixed(text, length);
m_LayoutLength += length;
AppendLayout(m_EndTextSeparator);
}
public void AppendLayout(byte[] buffer)
{
var length = buffer.Length;
Stream.Write(buffer, 0, length);
m_LayoutLength += length;
}
public void WriteStrings(List<string> text)
{
Stream.Seek(19, SeekOrigin.Begin);
Stream.Write((ushort)m_LayoutLength);
Stream.Seek(0, SeekOrigin.End);
Stream.Write((ushort)text.Count);
for (var i = 0; i < text.Count; ++i)
{
var v = text[i] ?? "";
int length = (ushort)v.Length;
Stream.Write((ushort)length);
Stream.WriteBigUniFixed(v, length);
}
}
public void Flush()
{
}
}
public sealed class DisplayGump : Packet
{
public DisplayGump(Gump g, string layout, string[] text) : base(0xB0)
{
layout ??= "";
EnsureCapacity(256);
Stream.Write(g.Serial);
Stream.Write(g.TypeID);
Stream.Write(g.X);
Stream.Write(g.Y);
Stream.Write((ushort)(layout.Length + 1));
Stream.WriteAsciiNull(layout);
Stream.Write((ushort)text.Length);
for (var i = 0; i < text.Length; ++i)
{
var v = text[i] ?? "";
var length = (ushort)v.Length;
Stream.Write(length);
Stream.WriteBigUniFixed(v, length);
}
}
}
public sealed class DisplaySignGump : Packet
{
public DisplaySignGump(Serial serial, int gumpID, string unknown, string caption) : base(0x8B)
{
unknown ??= "";
caption ??= "";
EnsureCapacity(15 + unknown.Length + caption.Length);
Stream.Write(serial);
Stream.Write((short)gumpID);
Stream.Write((short)(unknown.Length + 1));
Stream.WriteAsciiNull(unknown);
Stream.Write((short)(caption.Length + 1));
Stream.WriteAsciiNull(caption);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: GumpPackets.cs - Created: 2020/05/26 - Updated: 2020/05/26 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Buffers;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using Server.Gumps;
namespace Server.Network
{
public sealed class CloseGump : Packet
{
public CloseGump(int typeID, int buttonID) : base(0xBF)
{
EnsureCapacity(13);
Stream.Write((short)0x04);
Stream.Write(typeID);
Stream.Write(buttonID);
}
}
public interface IGumpWriter
{
int TextEntries { get; set; }
int Switches { get; set; }
void AppendLayout(bool val);
void AppendLayout(int val);
void AppendLayout(uint val);
void AppendLayoutNS(int val);
void AppendLayout(string text);
void AppendLayout(byte[] buffer);
void WriteStrings(List<string> strings);
void Flush();
}
public sealed class DisplayGumpPacked : Packet, IGumpWriter
{
private static readonly byte[] m_True = Gump.StringToBuffer(" 1");
private static readonly byte[] m_False = Gump.StringToBuffer(" 0");
private static readonly byte[] m_BeginTextSeparator = Gump.StringToBuffer(" @");
private static readonly byte[] m_EndTextSeparator = Gump.StringToBuffer("@");
private static readonly byte[] m_Buffer = new byte[48];
private readonly Gump m_Gump;
private readonly PacketWriter m_Layout;
private readonly PacketWriter m_Strings;
private int m_StringCount;
static DisplayGumpPacked() => m_Buffer[0] = (byte)' ';
public DisplayGumpPacked(Gump gump)
: base(0xDD)
{
m_Gump = gump;
m_Layout = PacketWriter.CreateInstance(8192);
m_Strings = PacketWriter.CreateInstance(8192);
}
public int TextEntries { get; set; }
public int Switches { get; set; }
public void AppendLayout(bool val)
{
AppendLayout(val ? m_True : m_False);
}
public void AppendLayout(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
m_Layout.Write(m_Buffer, 0, bytes);
}
public void AppendLayout(uint val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
m_Layout.Write(m_Buffer, 0, bytes);
}
public void AppendLayoutNS(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1);
m_Layout.Write(m_Buffer, 1, bytes);
}
public void AppendLayout(string text)
{
AppendLayout(m_BeginTextSeparator);
m_Layout.WriteAsciiFixed(text, text.Length);
AppendLayout(m_EndTextSeparator);
}
public void AppendLayout(byte[] buffer)
{
m_Layout.Write(buffer, 0, buffer.Length);
}
public void WriteStrings(List<string> strings)
{
m_StringCount = strings.Count;
for (var i = 0; i < strings.Count; ++i)
{
var v = strings[i] ?? "";
m_Strings.Write((ushort)v.Length);
m_Strings.WriteBigUniFixed(v, v.Length);
}
}
public void Flush()
{
EnsureCapacity(28 + (int)m_Layout.Length + (int)m_Strings.Length);
Stream.Write(m_Gump.Serial);
Stream.Write(m_Gump.TypeID);
Stream.Write(m_Gump.X);
Stream.Write(m_Gump.Y);
// Note: layout MUST be null terminated (don't listen to krrios)
m_Layout.Write((byte)0);
WritePacked(m_Layout);
Stream.Write(m_StringCount);
WritePacked(m_Strings);
PacketWriter.ReleaseInstance(m_Layout);
PacketWriter.ReleaseInstance(m_Strings);
}
private void WritePacked(PacketWriter src)
{
var buffer = src.UnderlyingStream.GetBuffer();
var length = (int)src.Length;
if (length == 0)
{
Stream.Write(0);
return;
}
var wantLength = 1 + buffer.Length * 1024 / 1000;
wantLength += 4095;
wantLength &= ~4095;
var packBuffer = ArrayPool<byte>.Shared.Rent(wantLength);
var packLength = wantLength;
Zlib.Pack(packBuffer, ref packLength, buffer, length, ZlibQuality.Default);
Stream.Write(4 + packLength);
Stream.Write(length);
Stream.Write(packBuffer, 0, packLength);
ArrayPool<byte>.Shared.Return(packBuffer);
}
}
public sealed class DisplayGumpFast : Packet, IGumpWriter
{
private static readonly byte[] m_True = Gump.StringToBuffer(" 1");
private static readonly byte[] m_False = Gump.StringToBuffer(" 0");
private static readonly byte[] m_BeginTextSeparator = Gump.StringToBuffer(" @");
private static readonly byte[] m_EndTextSeparator = Gump.StringToBuffer("@");
private readonly byte[] m_Buffer = new byte[48];
private int m_LayoutLength;
public DisplayGumpFast(Gump g) : base(0xB0)
{
m_Buffer[0] = (byte)' ';
EnsureCapacity(4096);
Stream.Write(g.Serial);
Stream.Write(g.TypeID);
Stream.Write(g.X);
Stream.Write(g.Y);
Stream.Write((ushort)0xFFFF);
}
public int TextEntries { get; set; }
public int Switches { get; set; }
public void AppendLayout(bool val)
{
AppendLayout(val ? m_True : m_False);
}
public void AppendLayout(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
Stream.Write(m_Buffer, 0, bytes);
m_LayoutLength += bytes;
}
public void AppendLayout(uint val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
Stream.Write(m_Buffer, 0, bytes);
m_LayoutLength += bytes;
}
public void AppendLayoutNS(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1);
Stream.Write(m_Buffer, 1, bytes);
m_LayoutLength += bytes;
}
public void AppendLayout(string text)
{
AppendLayout(m_BeginTextSeparator);
var length = text.Length;
Stream.WriteAsciiFixed(text, length);
m_LayoutLength += length;
AppendLayout(m_EndTextSeparator);
}
public void AppendLayout(byte[] buffer)
{
var length = buffer.Length;
Stream.Write(buffer, 0, length);
m_LayoutLength += length;
}
public void WriteStrings(List<string> text)
{
Stream.Seek(19, SeekOrigin.Begin);
Stream.Write((ushort)m_LayoutLength);
Stream.Seek(0, SeekOrigin.End);
Stream.Write((ushort)text.Count);
for (var i = 0; i < text.Count; ++i)
{
var v = text[i] ?? "";
int length = (ushort)v.Length;
Stream.Write((ushort)length);
Stream.WriteBigUniFixed(v, length);
}
}
public void Flush()
{
}
}
public sealed class DisplayGump : Packet
{
public DisplayGump(Gump g, string layout, string[] text) : base(0xB0)
{
layout ??= "";
EnsureCapacity(256);
Stream.Write(g.Serial);
Stream.Write(g.TypeID);
Stream.Write(g.X);
Stream.Write(g.Y);
Stream.Write((ushort)(layout.Length + 1));
Stream.WriteAsciiNull(layout);
Stream.Write((ushort)text.Length);
for (var i = 0; i < text.Length; ++i)
{
var v = text[i] ?? "";
var length = (ushort)v.Length;
Stream.Write(length);
Stream.WriteBigUniFixed(v, length);
}
}
}
public sealed class DisplaySignGump : Packet
{
public DisplaySignGump(Serial serial, int gumpID, string unknown, string caption) : base(0x8B)
{
unknown ??= "";
caption ??= "";
EnsureCapacity(15 + unknown.Length + caption.Length);
Stream.Write(serial);
Stream.Write((short)gumpID);
Stream.Write((short)(unknown.Length + 1));
Stream.WriteAsciiNull(unknown);
Stream.Write((short)(caption.Length + 1));
Stream.WriteAsciiNull(caption);
}
}
}

View file

@ -1,445 +1,445 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ItemPackets.cs - Created: 2020/05/26 - Updated: 2020/05/26 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using System.IO;
using Server.Items;
namespace Server.Network
{
public sealed class WorldItem : Packet
{
public WorldItem(Item item) : base(0x1A)
{
EnsureCapacity(20);
// 14 base length
// +2 - Amount
// +2 - Hue
// +1 - Flags
var serial = item.Serial.Value;
var itemID = item.ItemID & 0x3FFF;
var amount = item.Amount;
var loc = item.Location;
var x = loc.m_X;
var y = loc.m_Y;
var hue = item.Hue;
var flags = item.GetPacketFlags();
var direction = (int)item.Direction;
if (amount != 0)
serial |= 0x80000000;
else
serial &= 0x7FFFFFFF;
Stream.Write(serial);
if (item is BaseMulti)
Stream.Write((short)(itemID | 0x4000));
else
Stream.Write((short)itemID);
if (amount != 0) Stream.Write((short)amount);
x &= 0x7FFF;
if (direction != 0) x |= 0x8000;
Stream.Write((short)x);
y &= 0x3FFF;
if (hue != 0) y |= 0x8000;
if (flags != 0) y |= 0x4000;
Stream.Write((short)y);
if (direction != 0)
Stream.Write((byte)direction);
Stream.Write((sbyte)loc.m_Z);
if (hue != 0)
Stream.Write((ushort)hue);
if (flags != 0)
Stream.Write((byte)flags);
}
}
public sealed class WorldItemSA : Packet
{
public WorldItemSA(Item item) : base(0xF3, 24)
{
Stream.Write((short)0x1);
var itemID = item.ItemID;
if (item is BaseMulti)
{
Stream.Write((byte)0x02);
Stream.Write(item.Serial);
itemID &= 0x3FFF;
Stream.Write((short)itemID);
Stream.Write((byte)0);
}
else
{
Stream.Write((byte)0x00);
Stream.Write(item.Serial);
itemID &= 0x7FFF;
Stream.Write((short)itemID);
Stream.Write((byte)0);
}
var amount = item.Amount;
Stream.Write((short)amount);
Stream.Write((short)amount);
var loc = item.Location;
Stream.Write((short)loc.m_X);
Stream.Write((short)loc.m_Y);
Stream.Write((sbyte)loc.m_Z);
Stream.Write((byte)item.Light);
Stream.Write((short)item.Hue);
Stream.Write((byte)item.GetPacketFlags());
}
}
public sealed class WorldItemHS : Packet
{
public WorldItemHS(Item item) : base(0xF3, 26)
{
Stream.Write((short)0x1);
var itemID = item.ItemID;
if (item is BaseMulti)
{
Stream.Write((byte)0x02);
Stream.Write(item.Serial);
itemID &= 0x3FFF;
Stream.Write((ushort)itemID);
Stream.Write((byte)0);
}
else
{
Stream.Write((byte)0x00);
Stream.Write(item.Serial);
itemID &= 0xFFFF;
Stream.Write((ushort)itemID);
Stream.Write((byte)0);
}
var amount = item.Amount;
Stream.Write((short)amount);
Stream.Write((short)amount);
var loc = item.Location;
Stream.Write((short)loc.m_X);
Stream.Write((short)loc.m_Y);
Stream.Write((sbyte)loc.m_Z);
Stream.Write((byte)item.Light);
Stream.Write((short)item.Hue);
Stream.Write((byte)item.GetPacketFlags());
Stream.Write((short)0x00); // ??
}
}
public sealed class DisplaySpellbook : Packet
{
public DisplaySpellbook(Serial book) : base(0x24, 7)
{
Stream.Write(book);
Stream.Write((short)-1);
}
}
public sealed class DisplaySpellbookHS : Packet
{
public DisplaySpellbookHS(Serial book) : base(0x24, 9)
{
Stream.Write(book);
Stream.Write((short)-1);
Stream.Write((short)0x7D);
}
}
public sealed class NewSpellbookContent : Packet
{
public NewSpellbookContent(Serial spellbook, int graphic, int offset, ulong content) : base(0xBF)
{
EnsureCapacity(23);
Stream.Write((short)0x1B);
Stream.Write((short)0x01);
Stream.Write(spellbook);
Stream.Write((short)graphic);
Stream.Write((short)offset);
for (var i = 0; i < 8; ++i)
Stream.Write((byte)(content >> (i * 8)));
}
}
public sealed class SpellbookContent : Packet
{
public SpellbookContent(Serial spellbook, int offset, ulong content) : base(0x3C)
{
EnsureCapacity(5 + 64 * 19);
var written = 0;
Stream.Write((ushort)0);
ulong mask = 1;
for (var i = 0; i < 64; ++i, mask <<= 1)
if ((content & mask) != 0)
{
Stream.Write(0x7FFFFFFF - i);
Stream.Write((ushort)0);
Stream.Write((byte)0);
Stream.Write((ushort)(i + offset));
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write(spellbook);
Stream.Write((short)0);
++written;
}
Stream.Seek(3, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class SpellbookContent6017 : Packet
{
public SpellbookContent6017(Serial spellbook, int offset, ulong content) : base(0x3C)
{
EnsureCapacity(5 + 64 * 20);
var written = 0;
Stream.Write((ushort)0);
ulong mask = 1;
for (var i = 0; i < 64; ++i, mask <<= 1)
if ((content & mask) != 0)
{
Stream.Write(0x7FFFFFFF - i);
Stream.Write((ushort)0);
Stream.Write((byte)0);
Stream.Write((ushort)(i + offset));
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((byte)0); // Grid Location?
Stream.Write(spellbook);
Stream.Write((short)0);
++written;
}
Stream.Seek(3, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class ContainerDisplay : Packet
{
public ContainerDisplay(Serial cont, int gumpId) : base(0x24, 7)
{
Stream.Write(cont);
Stream.Write((short)gumpId);
}
}
public sealed class ContainerDisplayHS : Packet
{
public ContainerDisplayHS(Serial cont, int gumpId) : base(0x24, 9)
{
Stream.Write(cont);
Stream.Write((short)gumpId);
Stream.Write((short)0x7D);
}
}
public sealed class ContainerContentUpdate : Packet
{
public ContainerContentUpdate(Item item) : base(0x25, 20)
{
Serial parentSerial;
if (item.Parent is Item parentItem)
{
parentSerial = parentItem.Serial;
}
else
{
Console.WriteLine("Warning: ContainerContentUpdate on item with !(parent is Item)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((ushort)item.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(item.Amount, ushort.MaxValue));
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write(parentSerial);
Stream.Write((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue));
}
}
public sealed class ContainerContentUpdate6017 : Packet
{
public ContainerContentUpdate6017(Item item) : base(0x25, 21)
{
Serial parentSerial;
if (item.Parent is Item parentItem)
{
parentSerial = parentItem.Serial;
}
else
{
Console.WriteLine("Warning: ContainerContentUpdate on item with !(parent is Item)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((ushort)item.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(item.Amount, ushort.MaxValue));
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(parentSerial);
Stream.Write((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue));
}
}
public sealed class ContainerContent : Packet
{
public ContainerContent(Mobile beholder, Item beheld) : base(0x3C)
{
var items = beheld.Items;
var count = items.Count;
EnsureCapacity(5 + count * 19);
var pos = Stream.Position;
var written = 0;
Stream.Write((ushort)0);
for (var i = 0; i < count; ++i)
{
var child = items[i];
if (!child.Deleted && beholder.CanSee(child))
{
var loc = child.Location;
Stream.Write(child.Serial);
Stream.Write((ushort)child.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(child.Amount, ushort.MaxValue));
Stream.Write((short)loc.m_X);
Stream.Write((short)loc.m_Y);
Stream.Write(beheld.Serial);
Stream.Write((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue));
++written;
}
}
Stream.Seek(pos, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class ContainerContent6017 : Packet
{
public ContainerContent6017(Mobile beholder, Item beheld) : base(0x3C)
{
var items = beheld.Items;
var count = items.Count;
EnsureCapacity(5 + count * 20);
var pos = Stream.Position;
var written = 0;
Stream.Write((ushort)0);
for (var i = 0; i < count; ++i)
{
var child = items[i];
if (!child.Deleted && beholder.CanSee(child))
{
var loc = child.Location;
Stream.Write(child.Serial);
Stream.Write((ushort)child.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(child.Amount, ushort.MaxValue));
Stream.Write((short)loc.m_X);
Stream.Write((short)loc.m_Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(beheld.Serial);
Stream.Write((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue));
++written;
}
}
Stream.Seek(pos, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ItemPackets.cs - Created: 2020/05/26 - Updated: 2020/05/26 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using System.IO;
using Server.Items;
namespace Server.Network
{
public sealed class WorldItem : Packet
{
public WorldItem(Item item) : base(0x1A)
{
EnsureCapacity(20);
// 14 base length
// +2 - Amount
// +2 - Hue
// +1 - Flags
var serial = item.Serial.Value;
var itemID = item.ItemID & 0x3FFF;
var amount = item.Amount;
var loc = item.Location;
var x = loc.m_X;
var y = loc.m_Y;
var hue = item.Hue;
var flags = item.GetPacketFlags();
var direction = (int)item.Direction;
if (amount != 0)
serial |= 0x80000000;
else
serial &= 0x7FFFFFFF;
Stream.Write(serial);
if (item is BaseMulti)
Stream.Write((short)(itemID | 0x4000));
else
Stream.Write((short)itemID);
if (amount != 0) Stream.Write((short)amount);
x &= 0x7FFF;
if (direction != 0) x |= 0x8000;
Stream.Write((short)x);
y &= 0x3FFF;
if (hue != 0) y |= 0x8000;
if (flags != 0) y |= 0x4000;
Stream.Write((short)y);
if (direction != 0)
Stream.Write((byte)direction);
Stream.Write((sbyte)loc.m_Z);
if (hue != 0)
Stream.Write((ushort)hue);
if (flags != 0)
Stream.Write((byte)flags);
}
}
public sealed class WorldItemSA : Packet
{
public WorldItemSA(Item item) : base(0xF3, 24)
{
Stream.Write((short)0x1);
var itemID = item.ItemID;
if (item is BaseMulti)
{
Stream.Write((byte)0x02);
Stream.Write(item.Serial);
itemID &= 0x3FFF;
Stream.Write((short)itemID);
Stream.Write((byte)0);
}
else
{
Stream.Write((byte)0x00);
Stream.Write(item.Serial);
itemID &= 0x7FFF;
Stream.Write((short)itemID);
Stream.Write((byte)0);
}
var amount = item.Amount;
Stream.Write((short)amount);
Stream.Write((short)amount);
var loc = item.Location;
Stream.Write((short)loc.m_X);
Stream.Write((short)loc.m_Y);
Stream.Write((sbyte)loc.m_Z);
Stream.Write((byte)item.Light);
Stream.Write((short)item.Hue);
Stream.Write((byte)item.GetPacketFlags());
}
}
public sealed class WorldItemHS : Packet
{
public WorldItemHS(Item item) : base(0xF3, 26)
{
Stream.Write((short)0x1);
var itemID = item.ItemID;
if (item is BaseMulti)
{
Stream.Write((byte)0x02);
Stream.Write(item.Serial);
itemID &= 0x3FFF;
Stream.Write((ushort)itemID);
Stream.Write((byte)0);
}
else
{
Stream.Write((byte)0x00);
Stream.Write(item.Serial);
itemID &= 0xFFFF;
Stream.Write((ushort)itemID);
Stream.Write((byte)0);
}
var amount = item.Amount;
Stream.Write((short)amount);
Stream.Write((short)amount);
var loc = item.Location;
Stream.Write((short)loc.m_X);
Stream.Write((short)loc.m_Y);
Stream.Write((sbyte)loc.m_Z);
Stream.Write((byte)item.Light);
Stream.Write((short)item.Hue);
Stream.Write((byte)item.GetPacketFlags());
Stream.Write((short)0x00); // ??
}
}
public sealed class DisplaySpellbook : Packet
{
public DisplaySpellbook(Serial book) : base(0x24, 7)
{
Stream.Write(book);
Stream.Write((short)-1);
}
}
public sealed class DisplaySpellbookHS : Packet
{
public DisplaySpellbookHS(Serial book) : base(0x24, 9)
{
Stream.Write(book);
Stream.Write((short)-1);
Stream.Write((short)0x7D);
}
}
public sealed class NewSpellbookContent : Packet
{
public NewSpellbookContent(Serial spellbook, int graphic, int offset, ulong content) : base(0xBF)
{
EnsureCapacity(23);
Stream.Write((short)0x1B);
Stream.Write((short)0x01);
Stream.Write(spellbook);
Stream.Write((short)graphic);
Stream.Write((short)offset);
for (var i = 0; i < 8; ++i)
Stream.Write((byte)(content >> (i * 8)));
}
}
public sealed class SpellbookContent : Packet
{
public SpellbookContent(Serial spellbook, int offset, ulong content) : base(0x3C)
{
EnsureCapacity(5 + 64 * 19);
var written = 0;
Stream.Write((ushort)0);
ulong mask = 1;
for (var i = 0; i < 64; ++i, mask <<= 1)
if ((content & mask) != 0)
{
Stream.Write(0x7FFFFFFF - i);
Stream.Write((ushort)0);
Stream.Write((byte)0);
Stream.Write((ushort)(i + offset));
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write(spellbook);
Stream.Write((short)0);
++written;
}
Stream.Seek(3, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class SpellbookContent6017 : Packet
{
public SpellbookContent6017(Serial spellbook, int offset, ulong content) : base(0x3C)
{
EnsureCapacity(5 + 64 * 20);
var written = 0;
Stream.Write((ushort)0);
ulong mask = 1;
for (var i = 0; i < 64; ++i, mask <<= 1)
if ((content & mask) != 0)
{
Stream.Write(0x7FFFFFFF - i);
Stream.Write((ushort)0);
Stream.Write((byte)0);
Stream.Write((ushort)(i + offset));
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((byte)0); // Grid Location?
Stream.Write(spellbook);
Stream.Write((short)0);
++written;
}
Stream.Seek(3, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class ContainerDisplay : Packet
{
public ContainerDisplay(Serial cont, int gumpId) : base(0x24, 7)
{
Stream.Write(cont);
Stream.Write((short)gumpId);
}
}
public sealed class ContainerDisplayHS : Packet
{
public ContainerDisplayHS(Serial cont, int gumpId) : base(0x24, 9)
{
Stream.Write(cont);
Stream.Write((short)gumpId);
Stream.Write((short)0x7D);
}
}
public sealed class ContainerContentUpdate : Packet
{
public ContainerContentUpdate(Item item) : base(0x25, 20)
{
Serial parentSerial;
if (item.Parent is Item parentItem)
{
parentSerial = parentItem.Serial;
}
else
{
Console.WriteLine("Warning: ContainerContentUpdate on item with !(parent is Item)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((ushort)item.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(item.Amount, ushort.MaxValue));
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write(parentSerial);
Stream.Write((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue));
}
}
public sealed class ContainerContentUpdate6017 : Packet
{
public ContainerContentUpdate6017(Item item) : base(0x25, 21)
{
Serial parentSerial;
if (item.Parent is Item parentItem)
{
parentSerial = parentItem.Serial;
}
else
{
Console.WriteLine("Warning: ContainerContentUpdate on item with !(parent is Item)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((ushort)item.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(item.Amount, ushort.MaxValue));
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(parentSerial);
Stream.Write((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue));
}
}
public sealed class ContainerContent : Packet
{
public ContainerContent(Mobile beholder, Item beheld) : base(0x3C)
{
var items = beheld.Items;
var count = items.Count;
EnsureCapacity(5 + count * 19);
var pos = Stream.Position;
var written = 0;
Stream.Write((ushort)0);
for (var i = 0; i < count; ++i)
{
var child = items[i];
if (!child.Deleted && beholder.CanSee(child))
{
var loc = child.Location;
Stream.Write(child.Serial);
Stream.Write((ushort)child.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(child.Amount, ushort.MaxValue));
Stream.Write((short)loc.m_X);
Stream.Write((short)loc.m_Y);
Stream.Write(beheld.Serial);
Stream.Write((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue));
++written;
}
}
Stream.Seek(pos, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class ContainerContent6017 : Packet
{
public ContainerContent6017(Mobile beholder, Item beheld) : base(0x3C)
{
var items = beheld.Items;
var count = items.Count;
EnsureCapacity(5 + count * 20);
var pos = Stream.Position;
var written = 0;
Stream.Write((ushort)0);
for (var i = 0; i < count; ++i)
{
var child = items[i];
if (!child.Deleted && beholder.CanSee(child))
{
var loc = child.Location;
Stream.Write(child.Serial);
Stream.Write((ushort)child.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(child.Amount, ushort.MaxValue));
Stream.Write((short)loc.m_X);
Stream.Write((short)loc.m_Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(beheld.Serial);
Stream.Write((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue));
++written;
}
}
Stream.Seek(pos, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
}

View file

@ -1,55 +1,55 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: LightPackets.cs - Created: 2020/06/25 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 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);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: LightPackets.cs - Created: 2020/06/25 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 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);
}
}
}

View file

@ -1,65 +1,65 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MapPackets.cs - Created: 2020/05/03 - Updated: 2020/06/24 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class MapPatches : Packet
{
// TODO: Base this on the client version and expansion
public MapPatches() : base(0xBF)
{
EnsureCapacity(9 + 4 * 8);
Stream.Write((short)0x18);
Stream.Write(4);
Stream.Write(Map.Felucca.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Felucca.Tiles.Patch.LandBlocks);
Stream.Write(Map.Trammel.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Trammel.Tiles.Patch.LandBlocks);
Stream.Write(Map.Ilshenar.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Ilshenar.Tiles.Patch.LandBlocks);
Stream.Write(Map.Malas.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Malas.Tiles.Patch.LandBlocks);
}
}
public sealed class InvalidMapEnable : Packet
{
public InvalidMapEnable() : base(0xC6, 1)
{
}
}
public sealed class MapChange : Packet
{
public MapChange(Map map) : base(0xBF)
{
EnsureCapacity(6);
Stream.Write((short)0x08);
Stream.Write((byte)map.MapID);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MapPackets.cs - Created: 2020/05/03 - Updated: 2020/06/24 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class MapPatches : Packet
{
// TODO: Base this on the client version and expansion
public MapPatches() : base(0xBF)
{
EnsureCapacity(9 + 4 * 8);
Stream.Write((short)0x18);
Stream.Write(4);
Stream.Write(Map.Felucca.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Felucca.Tiles.Patch.LandBlocks);
Stream.Write(Map.Trammel.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Trammel.Tiles.Patch.LandBlocks);
Stream.Write(Map.Ilshenar.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Ilshenar.Tiles.Patch.LandBlocks);
Stream.Write(Map.Malas.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Malas.Tiles.Patch.LandBlocks);
}
}
public sealed class InvalidMapEnable : Packet
{
public InvalidMapEnable() : base(0xC6, 1)
{
}
}
public sealed class MapChange : Packet
{
public MapChange(Map map) : base(0xBF)
{
EnsureCapacity(6);
Stream.Write((short)0x08);
Stream.Write((byte)map.MapID);
}
}
}

View file

@ -1,239 +1,239 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MenuPackets.cs - Created: 2020/05/08 - Updated: 2020/05/26 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using Server.ContextMenus;
using Server.Menus;
using Server.Menus.ItemLists;
using Server.Menus.Questions;
namespace Server.Network
{
[Flags]
public enum CMEFlags
{
None = 0x00,
Disabled = 0x01,
Arrow = 0x02,
Highlighted = 0x04,
Colored = 0x20
}
public sealed class DisplayItemListMenu : Packet
{
public DisplayItemListMenu(ItemListMenu menu) : base(0x7C)
{
EnsureCapacity(256);
Stream.Write(((IMenu)menu).Serial);
Stream.Write((short)0);
var question = menu.Question;
if (question == null)
{
Stream.Write((byte)0);
}
else
{
var questionLength = question.Length;
Stream.Write((byte)questionLength);
Stream.WriteAsciiFixed(question, questionLength);
}
var entries = menu.Entries;
int entriesLength = (byte)entries.Length;
Stream.Write((byte)entriesLength);
for (var i = 0; i < entriesLength; ++i)
{
var e = entries[i];
Stream.Write((ushort)e.ItemID);
Stream.Write((short)e.Hue);
var name = e.Name;
if (name == null)
{
Stream.Write((byte)0);
}
else
{
var nameLength = name.Length;
Stream.Write((byte)nameLength);
Stream.WriteAsciiFixed(name, nameLength);
}
}
}
}
public sealed class DisplayQuestionMenu : Packet
{
public DisplayQuestionMenu(QuestionMenu menu) : base(0x7C)
{
EnsureCapacity(256);
Stream.Write(((IMenu)menu).Serial);
Stream.Write((short)0);
var question = menu.Question;
if (question == null)
{
Stream.Write((byte)0);
}
else
{
var questionLength = question.Length;
Stream.Write((byte)questionLength);
Stream.WriteAsciiFixed(question, questionLength);
}
var answers = menu.Answers;
int answersLength = (byte)answers.Length;
Stream.Write((byte)answersLength);
for (var i = 0; i < answersLength; ++i)
{
Stream.Write(0);
var answer = answers[i];
if (answer == null)
{
Stream.Write((byte)0);
}
else
{
var answerLength = answer.Length;
Stream.Write((byte)answerLength);
Stream.WriteAsciiFixed(answer, answerLength);
}
}
}
}
public sealed class DisplayContextMenu : Packet
{
public DisplayContextMenu(ContextMenu menu) : base(0xBF)
{
var entries = menu.Entries;
int length = (byte)entries.Length;
EnsureCapacity(12 + length * 8);
Stream.Write((short)0x14);
Stream.Write((short)0x02);
var target = menu.Target;
Stream.Write(target.Serial);
Stream.Write((byte)length);
Point3D p = target switch
{
Mobile _ => target.Location,
Item item => item.GetWorldLocation(),
_ => Point3D.Zero
};
for (var i = 0; i < length; ++i)
{
var e = entries[i];
Stream.Write(e.Number);
Stream.Write((short)i);
var range = e.Range;
if (range == -1)
range = 18;
var flags = e.Flags;
if (!(e.Enabled && menu.From.InRange(p, range)))
flags |= CMEFlags.Disabled;
Stream.Write((short)flags);
}
}
}
public sealed class DisplayContextMenuOld : Packet
{
public DisplayContextMenuOld(ContextMenu menu) : base(0xBF)
{
var entries = menu.Entries;
int length = (byte)entries.Length;
EnsureCapacity(12 + length * 8);
Stream.Write((short)0x14);
Stream.Write((short)0x01);
var target = menu.Target;
Stream.Write(target.Serial);
Stream.Write((byte)length);
Point3D p = target switch
{
Mobile _ => target.Location,
Item item => item.GetWorldLocation(),
_ => Point3D.Zero
};
for (var i = 0; i < length; ++i)
{
var e = entries[i];
Stream.Write((short)i);
Stream.Write((ushort)(e.Number - 3000000));
var range = e.Range;
if (range == -1)
range = 18;
var flags = e.Flags;
if (!(e.Enabled && menu.From.InRange(p, range)))
flags |= CMEFlags.Disabled;
var color = e.Color & 0xFFFF;
if (color != 0xFFFF)
flags |= CMEFlags.Colored;
Stream.Write((short)flags);
if ((flags & CMEFlags.Colored) != 0)
Stream.Write((short)color);
}
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MenuPackets.cs - Created: 2020/05/08 - Updated: 2020/05/26 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using Server.ContextMenus;
using Server.Menus;
using Server.Menus.ItemLists;
using Server.Menus.Questions;
namespace Server.Network
{
[Flags]
public enum CMEFlags
{
None = 0x00,
Disabled = 0x01,
Arrow = 0x02,
Highlighted = 0x04,
Colored = 0x20
}
public sealed class DisplayItemListMenu : Packet
{
public DisplayItemListMenu(ItemListMenu menu) : base(0x7C)
{
EnsureCapacity(256);
Stream.Write(((IMenu)menu).Serial);
Stream.Write((short)0);
var question = menu.Question;
if (question == null)
{
Stream.Write((byte)0);
}
else
{
var questionLength = question.Length;
Stream.Write((byte)questionLength);
Stream.WriteAsciiFixed(question, questionLength);
}
var entries = menu.Entries;
int entriesLength = (byte)entries.Length;
Stream.Write((byte)entriesLength);
for (var i = 0; i < entriesLength; ++i)
{
var e = entries[i];
Stream.Write((ushort)e.ItemID);
Stream.Write((short)e.Hue);
var name = e.Name;
if (name == null)
{
Stream.Write((byte)0);
}
else
{
var nameLength = name.Length;
Stream.Write((byte)nameLength);
Stream.WriteAsciiFixed(name, nameLength);
}
}
}
}
public sealed class DisplayQuestionMenu : Packet
{
public DisplayQuestionMenu(QuestionMenu menu) : base(0x7C)
{
EnsureCapacity(256);
Stream.Write(((IMenu)menu).Serial);
Stream.Write((short)0);
var question = menu.Question;
if (question == null)
{
Stream.Write((byte)0);
}
else
{
var questionLength = question.Length;
Stream.Write((byte)questionLength);
Stream.WriteAsciiFixed(question, questionLength);
}
var answers = menu.Answers;
int answersLength = (byte)answers.Length;
Stream.Write((byte)answersLength);
for (var i = 0; i < answersLength; ++i)
{
Stream.Write(0);
var answer = answers[i];
if (answer == null)
{
Stream.Write((byte)0);
}
else
{
var answerLength = answer.Length;
Stream.Write((byte)answerLength);
Stream.WriteAsciiFixed(answer, answerLength);
}
}
}
}
public sealed class DisplayContextMenu : Packet
{
public DisplayContextMenu(ContextMenu menu) : base(0xBF)
{
var entries = menu.Entries;
int length = (byte)entries.Length;
EnsureCapacity(12 + length * 8);
Stream.Write((short)0x14);
Stream.Write((short)0x02);
var target = menu.Target;
Stream.Write(target.Serial);
Stream.Write((byte)length);
var p = target switch
{
Mobile _ => target.Location,
Item item => item.GetWorldLocation(),
_ => Point3D.Zero
};
for (var i = 0; i < length; ++i)
{
var e = entries[i];
Stream.Write(e.Number);
Stream.Write((short)i);
var range = e.Range;
if (range == -1)
range = 18;
var flags = e.Flags;
if (!(e.Enabled && menu.From.InRange(p, range)))
flags |= CMEFlags.Disabled;
Stream.Write((short)flags);
}
}
}
public sealed class DisplayContextMenuOld : Packet
{
public DisplayContextMenuOld(ContextMenu menu) : base(0xBF)
{
var entries = menu.Entries;
int length = (byte)entries.Length;
EnsureCapacity(12 + length * 8);
Stream.Write((short)0x14);
Stream.Write((short)0x01);
var target = menu.Target;
Stream.Write(target.Serial);
Stream.Write((byte)length);
var p = target switch
{
Mobile _ => target.Location,
Item item => item.GetWorldLocation(),
_ => Point3D.Zero
};
for (var i = 0; i < length; ++i)
{
var e = entries[i];
Stream.Write((short)i);
Stream.Write((ushort)(e.Number - 3000000));
var range = e.Range;
if (range == -1)
range = 18;
var flags = e.Flags;
if (!(e.Enabled && menu.From.InRange(p, range)))
flags |= CMEFlags.Disabled;
var color = e.Color & 0xFFFF;
if (color != 0xFFFF)
flags |= CMEFlags.Colored;
Stream.Write((short)flags);
if ((flags & CMEFlags.Colored) != 0)
Stream.Write((short)color);
}
}
}
}

View file

@ -1,185 +1,201 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MessagePackets.cs - Created: 2020/05/26 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 AffixType : byte
{
Append = 0x00,
Prepend = 0x01,
System = 0x02
}
public sealed class MessageLocalized : Packet
{
private static readonly MessageLocalized[] m_Cache_IntLoc = new MessageLocalized[15000];
private static readonly MessageLocalized[] m_Cache_CliLoc = new MessageLocalized[100000];
private static readonly MessageLocalized[] m_Cache_CliLocCmp = new MessageLocalized[5000];
public MessageLocalized(Serial serial, int graphic, MessageType type, int hue, int font, int number, string name,
string args) : base(0xC1)
{
name ??= "";
args ??= "";
if (hue == 0)
hue = 0x3B2;
EnsureCapacity(50 + args.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.Write(number);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteLittleUniNull(args);
}
public static MessageLocalized InstantiateGeneric(int number)
{
MessageLocalized[] cache = null;
var index = 0;
if (number >= 3000000)
{
cache = m_Cache_IntLoc;
index = number - 3000000;
}
else if (number >= 1000000)
{
cache = m_Cache_CliLoc;
index = number - 1000000;
}
else if (number >= 500000)
{
cache = m_Cache_CliLocCmp;
index = number - 500000;
}
MessageLocalized p;
if (cache != null && index < cache.Length)
{
p = cache[index];
if (p == null)
{
cache[index] = p = new MessageLocalized(Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, number,
"System", "");
p.SetStatic();
}
}
else
{
p = new MessageLocalized(Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, number, "System", "");
}
return p;
}
}
public sealed class MessageLocalizedAffix : Packet
{
public MessageLocalizedAffix(Serial serial, int graphic, MessageType messageType, int hue, int font, int number,
string name, AffixType affixType, string affix, string args) : base(0xCC)
{
name ??= "";
affix ??= "";
args ??= "";
if (hue == 0)
hue = 0x3B2;
EnsureCapacity(52 + affix.Length + args.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)messageType);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.Write(number);
Stream.Write((byte)affixType);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteAsciiNull(affix);
Stream.WriteBigUniNull(args);
}
}
public sealed class AsciiMessage : Packet
{
public AsciiMessage(Serial serial, int graphic, MessageType type, int hue, int font, string name, string text) : base(0x1C)
{
name ??= "";
text ??= "";
if (hue == 0)
hue = 0x3B2;
EnsureCapacity(45 + text.Length);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteAsciiNull(text);
}
}
public sealed class UnicodeMessage : Packet
{
public UnicodeMessage(Serial serial, int graphic, MessageType type, int hue, int font, string lang, string name,
string text) : base(0xAE)
{
if (string.IsNullOrEmpty(lang)) lang = "ENU";
name ??= "";
text ??= "";
if (hue == 0)
hue = 0x3B2;
EnsureCapacity(50 + text.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.WriteAsciiFixed(lang, 4);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteBigUniNull(text);
}
}
public sealed class FollowMessage : Packet
{
public FollowMessage(Serial serial1, Serial serial2) : base(0x15, 9)
{
Stream.Write(serial1);
Stream.Write(serial2);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MessagePackets.cs - Created: 2020/05/26 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 AffixType : byte
{
Append = 0x00,
Prepend = 0x01,
System = 0x02
}
public sealed class MessageLocalized : Packet
{
private static readonly MessageLocalized[] m_Cache_IntLoc = new MessageLocalized[15000];
private static readonly MessageLocalized[] m_Cache_CliLoc = new MessageLocalized[100000];
private static readonly MessageLocalized[] m_Cache_CliLocCmp = new MessageLocalized[5000];
public MessageLocalized(
Serial serial, int graphic, MessageType type, int hue, int font, int number, string name,
string args
) : base(0xC1)
{
name ??= "";
args ??= "";
if (hue == 0)
hue = 0x3B2;
EnsureCapacity(50 + args.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.Write(number);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteLittleUniNull(args);
}
public static MessageLocalized InstantiateGeneric(int number)
{
MessageLocalized[] cache = null;
var index = 0;
if (number >= 3000000)
{
cache = m_Cache_IntLoc;
index = number - 3000000;
}
else if (number >= 1000000)
{
cache = m_Cache_CliLoc;
index = number - 1000000;
}
else if (number >= 500000)
{
cache = m_Cache_CliLocCmp;
index = number - 500000;
}
MessageLocalized p;
if (cache != null && index < cache.Length)
{
p = cache[index];
if (p == null)
{
cache[index] = p = new MessageLocalized(
Serial.MinusOne,
-1,
MessageType.Regular,
0x3B2,
3,
number,
"System",
""
);
p.SetStatic();
}
}
else
{
p = new MessageLocalized(Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, number, "System", "");
}
return p;
}
}
public sealed class MessageLocalizedAffix : Packet
{
public MessageLocalizedAffix(
Serial serial, int graphic, MessageType messageType, int hue, int font, int number,
string name, AffixType affixType, string affix, string args
) : base(0xCC)
{
name ??= "";
affix ??= "";
args ??= "";
if (hue == 0)
hue = 0x3B2;
EnsureCapacity(52 + affix.Length + args.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)messageType);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.Write(number);
Stream.Write((byte)affixType);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteAsciiNull(affix);
Stream.WriteBigUniNull(args);
}
}
public sealed class AsciiMessage : Packet
{
public AsciiMessage(
Serial serial, int graphic, MessageType type, int hue, int font, string name, string text
) : base(0x1C)
{
name ??= "";
text ??= "";
if (hue == 0)
hue = 0x3B2;
EnsureCapacity(45 + text.Length);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteAsciiNull(text);
}
}
public sealed class UnicodeMessage : Packet
{
public UnicodeMessage(
Serial serial, int graphic, MessageType type, int hue, int font, string lang, string name,
string text
) : base(0xAE)
{
if (string.IsNullOrEmpty(lang)) lang = "ENU";
name ??= "";
text ??= "";
if (hue == 0)
hue = 0x3B2;
EnsureCapacity(50 + text.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.WriteAsciiFixed(lang, 4);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteBigUniNull(text);
}
}
public sealed class FollowMessage : Packet
{
public FollowMessage(Serial serial1, Serial serial2) : base(0x15, 9)
{
Stream.Write(serial1);
Stream.Write(serial2);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,103 +1,103 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MovementPackets.cs - Created: 2020/06/25 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class SpeedControl : Packet
{
public static readonly Packet WalkSpeed = SetStatic(new SpeedControl(2));
public static readonly Packet MountSpeed = SetStatic(new SpeedControl(1));
public static readonly Packet Disable = SetStatic(new SpeedControl(0));
public SpeedControl(int speedControl) : base(0xBF)
{
EnsureCapacity(3);
Stream.Write((short)0x26);
Stream.Write((byte)speedControl);
}
}
/// <summary>
/// Causes the client to walk in a given direction. It does not send a movement request.
/// </summary>
public sealed class MovePlayer : Packet
{
public MovePlayer(Direction d) : base(0x97, 2)
{
Stream.Write((byte)d);
// @4C63B0
}
}
public sealed class MovementRej : Packet
{
public MovementRej(int seq, Mobile m) : base(0x21, 8)
{
Stream.Write((byte)seq);
Stream.Write((short)m.X);
Stream.Write((short)m.Y);
Stream.Write((byte)m.Direction);
Stream.Write((sbyte)m.Z);
}
}
public sealed class MovementAck : Packet
{
private static readonly MovementAck[] m_Cache = new MovementAck[8 * 256];
private MovementAck(int seq, int noto) : base(0x22, 3)
{
Stream.Write((byte)seq);
Stream.Write((byte)noto);
}
public static MovementAck Instantiate(int seq, Mobile m)
{
var noto = Notoriety.Compute(m, m);
var p = m_Cache[noto * seq];
if (p == null)
{
m_Cache[noto * seq] = p = new MovementAck(seq, noto);
p.SetStatic();
}
return p;
}
}
public sealed class NullFastwalkStack : Packet
{
public NullFastwalkStack() : base(0xBF)
{
EnsureCapacity(256);
Stream.Write((short)0x1);
Stream.Write(0x0);
Stream.Write(0x0);
Stream.Write(0x0);
Stream.Write(0x0);
Stream.Write(0x0);
Stream.Write(0x0);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MovementPackets.cs - Created: 2020/06/25 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class SpeedControl : Packet
{
public static readonly Packet WalkSpeed = SetStatic(new SpeedControl(2));
public static readonly Packet MountSpeed = SetStatic(new SpeedControl(1));
public static readonly Packet Disable = SetStatic(new SpeedControl(0));
public SpeedControl(int speedControl) : base(0xBF)
{
EnsureCapacity(3);
Stream.Write((short)0x26);
Stream.Write((byte)speedControl);
}
}
/// <summary>
/// Causes the client to walk in a given direction. It does not send a movement request.
/// </summary>
public sealed class MovePlayer : Packet
{
public MovePlayer(Direction d) : base(0x97, 2)
{
Stream.Write((byte)d);
// @4C63B0
}
}
public sealed class MovementRej : Packet
{
public MovementRej(int seq, Mobile m) : base(0x21, 8)
{
Stream.Write((byte)seq);
Stream.Write((short)m.X);
Stream.Write((short)m.Y);
Stream.Write((byte)m.Direction);
Stream.Write((sbyte)m.Z);
}
}
public sealed class MovementAck : Packet
{
private static readonly MovementAck[] m_Cache = new MovementAck[8 * 256];
private MovementAck(int seq, int noto) : base(0x22, 3)
{
Stream.Write((byte)seq);
Stream.Write((byte)noto);
}
public static MovementAck Instantiate(int seq, Mobile m)
{
var noto = Notoriety.Compute(m, m);
var p = m_Cache[noto * seq];
if (p == null)
{
m_Cache[noto * seq] = p = new MovementAck(seq, noto);
p.SetStatic();
}
return p;
}
}
public sealed class NullFastwalkStack : Packet
{
public NullFastwalkStack() : base(0xBF)
{
EnsureCapacity(256);
Stream.Write((short)0x1);
Stream.Write(0x0);
Stream.Write(0x0);
Stream.Write(0x0);
Stream.Write(0x0);
Stream.Write(0x0);
Stream.Write(0x0);
}
}
}

View file

@ -1,34 +1,34 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ObjectHelpResponse.cs *
* Created: 2020/05/03 - Updated: 2020/05/03 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class ObjectHelpResponse : Packet
{
public ObjectHelpResponse(Serial e, string text) : base(0xB7)
{
EnsureCapacity(9 + text.Length * 2);
Stream.Write(e);
Stream.WriteBigUniNull(text);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ObjectHelpResponse.cs *
* Created: 2020/05/03 - Updated: 2020/05/03 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class ObjectHelpResponse : Packet
{
public ObjectHelpResponse(Serial e, string text) : base(0xB7)
{
EnsureCapacity(9 + text.Length * 2);
Stream.Write(e);
Stream.WriteBigUniNull(text);
}
}
}

View file

@ -1,429 +1,430 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: PlayerPackets.cs - Created: 2020/05/07 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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
{
public enum LRReason : byte
{
CannotLift = 0,
OutOfRange = 1,
OutOfSight = 2,
TryToSteal = 3,
AreHolding = 4,
Inspecific = 5
}
public sealed class StatLockInfo : Packet
{
public StatLockInfo(Mobile m) : base(0xBF)
{
EnsureCapacity(12);
Stream.Write((short)0x19);
Stream.Write((byte)2);
Stream.Write(m.Serial);
Stream.Write((byte)0);
var lockBits = ((int)m.StrLock << 4) | ((int)m.DexLock << 2) | (int)m.IntLock;
Stream.Write((byte)lockBits);
}
}
public sealed class ChangeUpdateRange : Packet
{
private static readonly ChangeUpdateRange[] m_Cache = new ChangeUpdateRange[0x100];
public ChangeUpdateRange(int range) : base(0xC8, 2)
{
Stream.Write((byte)range);
}
public static ChangeUpdateRange Instantiate(int range)
{
var idx = (byte)range;
var p = m_Cache[idx];
if (p == null)
{
m_Cache[idx] = p = new ChangeUpdateRange(range);
p.SetStatic();
}
return p;
}
}
public sealed class DeathStatus : Packet
{
public static readonly Packet Dead = SetStatic(new DeathStatus(true));
public static readonly Packet Alive = SetStatic(new DeathStatus(false));
public DeathStatus(bool dead) : base(0x2C, 2)
{
Stream.Write((byte)(dead ? 0 : 2));
}
public static Packet Instantiate(bool dead) => dead ? Dead : Alive;
}
public sealed class ToggleSpecialAbility : Packet
{
public ToggleSpecialAbility(int abilityID, bool active) : base(0xBF)
{
EnsureCapacity(7);
Stream.Write((short)0x25);
Stream.Write((short)abilityID);
Stream.Write(active);
}
}
public sealed class DisplayProfile : Packet
{
public DisplayProfile(Serial m, string header, string body, string footer) : base(0xB8)
{
header ??= "";
body ??= "";
footer ??= "";
EnsureCapacity(12 + header.Length + footer.Length * 2 + body.Length * 2);
Stream.Write(m);
Stream.WriteAsciiNull(header);
Stream.WriteBigUniNull(footer);
Stream.WriteBigUniNull(body);
}
}
public sealed class LiftRej : Packet
{
public LiftRej(LRReason reason) : base(0x27, 2)
{
Stream.Write((byte)reason);
}
}
public sealed class LogoutAck : Packet
{
public LogoutAck() : base(0xD1, 2)
{
Stream.Write((byte)0x01);
}
}
public sealed class Weather : Packet
{
public Weather(int type, int density, int temp) : base(0x65, 4)
{
Stream.Write((byte)type);
Stream.Write((byte)density);
Stream.Write((byte)temp);
}
}
public sealed class RemoveEntity : Packet
{
public RemoveEntity(Serial entity) : base(0x1D, 5)
{
Stream.Write(entity);
}
}
public sealed class ServerChange : Packet
{
public ServerChange(Point3D p, Map map) : base(0x76, 16)
{
Stream.Write((short)p.X);
Stream.Write((short)p.Y);
Stream.Write((short)p.Z);
Stream.Write((byte)0);
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((short)map.Width);
Stream.Write((short)map.Height);
}
}
public sealed class SkillUpdate : Packet
{
public SkillUpdate(Skills skills) : base(0x3A)
{
EnsureCapacity(6 + skills.Length * 9);
Stream.Write((byte)0x02); // type: absolute, capped
for (var i = 0; i < skills.Length; ++i)
{
var s = skills[i];
var v = s.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
Stream.Write((ushort)(s.Info.SkillID + 1));
Stream.Write((ushort)uv);
Stream.Write((ushort)s.BaseFixedPoint);
Stream.Write((byte)s.Lock);
Stream.Write((ushort)s.CapFixedPoint);
}
Stream.Write((short)0); // terminate
}
}
public sealed class Sequence : Packet
{
public Sequence(int num) : base(0x7B, 2)
{
Stream.Write((byte)num);
}
}
public sealed class SkillChange : Packet
{
public SkillChange(Skill skill) : base(0x3A)
{
EnsureCapacity(13);
var v = skill.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
Stream.Write((byte)0xDF); // type: delta, capped
Stream.Write((ushort)skill.Info.SkillID);
Stream.Write((ushort)uv);
Stream.Write((ushort)skill.BaseFixedPoint);
Stream.Write((byte)skill.Lock);
Stream.Write((ushort)skill.CapFixedPoint);
}
}
public sealed class LaunchBrowser : Packet
{
public LaunchBrowser(string url) : base(0xA5)
{
url ??= "";
EnsureCapacity(4 + url.Length);
Stream.WriteAsciiNull(url);
}
}
public sealed class DragEffect : Packet
{
public DragEffect(IEntity src, IEntity trg, int itemID, int hue, int amount) : base(0x23, 26)
{
Stream.Write((short)itemID);
Stream.Write((byte)0);
Stream.Write((short)hue);
Stream.Write((short)amount);
Stream.Write(src.Serial);
Stream.Write((short)src.X);
Stream.Write((short)src.Y);
Stream.Write((sbyte)src.Z);
Stream.Write(trg.Serial);
Stream.Write((short)trg.X);
Stream.Write((short)trg.Y);
Stream.Write((sbyte)trg.Z);
}
}
public sealed class SeasonChange : Packet
{
private static readonly SeasonChange[][] m_Cache = {
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2]
};
public SeasonChange(int season, bool playSound = true) : base(0xBC, 3)
{
Stream.Write((byte)season);
Stream.Write(playSound);
}
public static SeasonChange Instantiate(int season) => Instantiate(season, true);
public static SeasonChange Instantiate(int season, bool playSound)
{
if (season >= 0 && season < m_Cache.Length)
{
var idx = playSound ? 1 : 0;
var p = m_Cache[season][idx];
if (p == null)
{
m_Cache[season][idx] = p = new SeasonChange(season, playSound);
p.SetStatic();
}
return p;
}
return new SeasonChange(season, playSound);
}
}
public sealed class DisplayPaperdoll : Packet
{
public DisplayPaperdoll(Serial m, string title, bool warmode, bool canLift) : base(0x88, 66)
{
byte flags = 0x00;
if (warmode)
flags |= 0x01;
if (canLift)
flags |= 0x02;
Stream.Write(m);
Stream.WriteAsciiFixed(title, 60);
Stream.Write(flags);
}
}
public sealed class PlaySound : Packet
{
public PlaySound(int soundID, IPoint3D target) : base(0x54, 12)
{
Stream.Write((byte)1); // flags
Stream.Write((short)soundID);
Stream.Write((short)0); // volume
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((short)target.Z);
}
}
public sealed class PlayMusic : Packet
{
public static readonly Packet InvalidInstance = SetStatic(new PlayMusic(MusicName.Invalid));
private static readonly Packet[] m_Instances = new Packet[60];
public PlayMusic(MusicName name) : base(0x6D, 3)
{
Stream.Write((short)name);
}
public static Packet GetInstance(MusicName name)
{
if (name == MusicName.Invalid)
return InvalidInstance;
var v = (int)name;
Packet p;
if (v >= 0 && v < m_Instances.Length)
{
p = m_Instances[v];
if (p == null)
m_Instances[v] = p = SetStatic(new PlayMusic(name));
}
else
{
p = new PlayMusic(name);
}
return p;
}
}
public sealed class ScrollMessage : Packet
{
public ScrollMessage(int type, int tip, string text) : base(0xA6)
{
text ??= "";
EnsureCapacity(10 + text.Length);
Stream.Write((byte)type);
Stream.Write(tip);
Stream.Write((ushort)text.Length);
Stream.WriteAsciiFixed(text, text.Length);
}
}
public sealed class CurrentTime : Packet
{
public CurrentTime() : this(DateTime.Now)
{
}
public CurrentTime(DateTime date) : base(0x5B, 4)
{
Stream.Write((byte)date.Hour);
Stream.Write((byte)date.Minute);
Stream.Write((byte)date.Second);
}
}
public sealed class PathfindMessage : Packet
{
public PathfindMessage(Point3D p) : base(0x38, 7)
{
Stream.Write((short)p.X);
Stream.Write((short)p.Y);
Stream.Write((short)p.Z);
}
}
public sealed class PingAck : Packet
{
private static readonly PingAck[] m_Cache = new PingAck[0x100];
public PingAck(byte ping) : base(0x73, 2)
{
Stream.Write(ping);
}
public static PingAck Instantiate(byte ping)
{
var p = m_Cache[ping];
if (p == null)
{
m_Cache[ping] = p = new PingAck(ping);
p.SetStatic();
}
return p;
}
}
public sealed class ClearWeaponAbility : Packet
{
public static readonly Packet Instance = SetStatic(new ClearWeaponAbility());
public ClearWeaponAbility() : base(0xBF)
{
EnsureCapacity(5);
Stream.Write((short)0x21);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: PlayerPackets.cs - Created: 2020/05/07 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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
{
public enum LRReason : byte
{
CannotLift = 0,
OutOfRange = 1,
OutOfSight = 2,
TryToSteal = 3,
AreHolding = 4,
Inspecific = 5
}
public sealed class StatLockInfo : Packet
{
public StatLockInfo(Mobile m) : base(0xBF)
{
EnsureCapacity(12);
Stream.Write((short)0x19);
Stream.Write((byte)2);
Stream.Write(m.Serial);
Stream.Write((byte)0);
var lockBits = ((int)m.StrLock << 4) | ((int)m.DexLock << 2) | (int)m.IntLock;
Stream.Write((byte)lockBits);
}
}
public sealed class ChangeUpdateRange : Packet
{
private static readonly ChangeUpdateRange[] m_Cache = new ChangeUpdateRange[0x100];
public ChangeUpdateRange(int range) : base(0xC8, 2)
{
Stream.Write((byte)range);
}
public static ChangeUpdateRange Instantiate(int range)
{
var idx = (byte)range;
var p = m_Cache[idx];
if (p == null)
{
m_Cache[idx] = p = new ChangeUpdateRange(range);
p.SetStatic();
}
return p;
}
}
public sealed class DeathStatus : Packet
{
public static readonly Packet Dead = SetStatic(new DeathStatus(true));
public static readonly Packet Alive = SetStatic(new DeathStatus(false));
public DeathStatus(bool dead) : base(0x2C, 2)
{
Stream.Write((byte)(dead ? 0 : 2));
}
public static Packet Instantiate(bool dead) => dead ? Dead : Alive;
}
public sealed class ToggleSpecialAbility : Packet
{
public ToggleSpecialAbility(int abilityID, bool active) : base(0xBF)
{
EnsureCapacity(7);
Stream.Write((short)0x25);
Stream.Write((short)abilityID);
Stream.Write(active);
}
}
public sealed class DisplayProfile : Packet
{
public DisplayProfile(Serial m, string header, string body, string footer) : base(0xB8)
{
header ??= "";
body ??= "";
footer ??= "";
EnsureCapacity(12 + header.Length + footer.Length * 2 + body.Length * 2);
Stream.Write(m);
Stream.WriteAsciiNull(header);
Stream.WriteBigUniNull(footer);
Stream.WriteBigUniNull(body);
}
}
public sealed class LiftRej : Packet
{
public LiftRej(LRReason reason) : base(0x27, 2)
{
Stream.Write((byte)reason);
}
}
public sealed class LogoutAck : Packet
{
public LogoutAck() : base(0xD1, 2)
{
Stream.Write((byte)0x01);
}
}
public sealed class Weather : Packet
{
public Weather(int type, int density, int temp) : base(0x65, 4)
{
Stream.Write((byte)type);
Stream.Write((byte)density);
Stream.Write((byte)temp);
}
}
public sealed class RemoveEntity : Packet
{
public RemoveEntity(Serial entity) : base(0x1D, 5)
{
Stream.Write(entity);
}
}
public sealed class ServerChange : Packet
{
public ServerChange(Point3D p, Map map) : base(0x76, 16)
{
Stream.Write((short)p.X);
Stream.Write((short)p.Y);
Stream.Write((short)p.Z);
Stream.Write((byte)0);
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((short)map.Width);
Stream.Write((short)map.Height);
}
}
public sealed class SkillUpdate : Packet
{
public SkillUpdate(Skills skills) : base(0x3A)
{
EnsureCapacity(6 + skills.Length * 9);
Stream.Write((byte)0x02); // type: absolute, capped
for (var i = 0; i < skills.Length; ++i)
{
var s = skills[i];
var v = s.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
Stream.Write((ushort)(s.Info.SkillID + 1));
Stream.Write((ushort)uv);
Stream.Write((ushort)s.BaseFixedPoint);
Stream.Write((byte)s.Lock);
Stream.Write((ushort)s.CapFixedPoint);
}
Stream.Write((short)0); // terminate
}
}
public sealed class Sequence : Packet
{
public Sequence(int num) : base(0x7B, 2)
{
Stream.Write((byte)num);
}
}
public sealed class SkillChange : Packet
{
public SkillChange(Skill skill) : base(0x3A)
{
EnsureCapacity(13);
var v = skill.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
Stream.Write((byte)0xDF); // type: delta, capped
Stream.Write((ushort)skill.Info.SkillID);
Stream.Write((ushort)uv);
Stream.Write((ushort)skill.BaseFixedPoint);
Stream.Write((byte)skill.Lock);
Stream.Write((ushort)skill.CapFixedPoint);
}
}
public sealed class LaunchBrowser : Packet
{
public LaunchBrowser(string url) : base(0xA5)
{
url ??= "";
EnsureCapacity(4 + url.Length);
Stream.WriteAsciiNull(url);
}
}
public sealed class DragEffect : Packet
{
public DragEffect(IEntity src, IEntity trg, int itemID, int hue, int amount) : base(0x23, 26)
{
Stream.Write((short)itemID);
Stream.Write((byte)0);
Stream.Write((short)hue);
Stream.Write((short)amount);
Stream.Write(src.Serial);
Stream.Write((short)src.X);
Stream.Write((short)src.Y);
Stream.Write((sbyte)src.Z);
Stream.Write(trg.Serial);
Stream.Write((short)trg.X);
Stream.Write((short)trg.Y);
Stream.Write((sbyte)trg.Z);
}
}
public sealed class SeasonChange : Packet
{
private static readonly SeasonChange[][] m_Cache =
{
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2]
};
public SeasonChange(int season, bool playSound = true) : base(0xBC, 3)
{
Stream.Write((byte)season);
Stream.Write(playSound);
}
public static SeasonChange Instantiate(int season) => Instantiate(season, true);
public static SeasonChange Instantiate(int season, bool playSound)
{
if (season >= 0 && season < m_Cache.Length)
{
var idx = playSound ? 1 : 0;
var p = m_Cache[season][idx];
if (p == null)
{
m_Cache[season][idx] = p = new SeasonChange(season, playSound);
p.SetStatic();
}
return p;
}
return new SeasonChange(season, playSound);
}
}
public sealed class DisplayPaperdoll : Packet
{
public DisplayPaperdoll(Serial m, string title, bool warmode, bool canLift) : base(0x88, 66)
{
byte flags = 0x00;
if (warmode)
flags |= 0x01;
if (canLift)
flags |= 0x02;
Stream.Write(m);
Stream.WriteAsciiFixed(title, 60);
Stream.Write(flags);
}
}
public sealed class PlaySound : Packet
{
public PlaySound(int soundID, IPoint3D target) : base(0x54, 12)
{
Stream.Write((byte)1); // flags
Stream.Write((short)soundID);
Stream.Write((short)0); // volume
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((short)target.Z);
}
}
public sealed class PlayMusic : Packet
{
public static readonly Packet InvalidInstance = SetStatic(new PlayMusic(MusicName.Invalid));
private static readonly Packet[] m_Instances = new Packet[60];
public PlayMusic(MusicName name) : base(0x6D, 3)
{
Stream.Write((short)name);
}
public static Packet GetInstance(MusicName name)
{
if (name == MusicName.Invalid)
return InvalidInstance;
var v = (int)name;
Packet p;
if (v >= 0 && v < m_Instances.Length)
{
p = m_Instances[v];
if (p == null)
m_Instances[v] = p = SetStatic(new PlayMusic(name));
}
else
{
p = new PlayMusic(name);
}
return p;
}
}
public sealed class ScrollMessage : Packet
{
public ScrollMessage(int type, int tip, string text) : base(0xA6)
{
text ??= "";
EnsureCapacity(10 + text.Length);
Stream.Write((byte)type);
Stream.Write(tip);
Stream.Write((ushort)text.Length);
Stream.WriteAsciiFixed(text, text.Length);
}
}
public sealed class CurrentTime : Packet
{
public CurrentTime() : this(DateTime.Now)
{
}
public CurrentTime(DateTime date) : base(0x5B, 4)
{
Stream.Write((byte)date.Hour);
Stream.Write((byte)date.Minute);
Stream.Write((byte)date.Second);
}
}
public sealed class PathfindMessage : Packet
{
public PathfindMessage(Point3D p) : base(0x38, 7)
{
Stream.Write((short)p.X);
Stream.Write((short)p.Y);
Stream.Write((short)p.Z);
}
}
public sealed class PingAck : Packet
{
private static readonly PingAck[] m_Cache = new PingAck[0x100];
public PingAck(byte ping) : base(0x73, 2)
{
Stream.Write(ping);
}
public static PingAck Instantiate(byte ping)
{
var p = m_Cache[ping];
if (p == null)
{
m_Cache[ping] = p = new PingAck(ping);
p.SetStatic();
}
return p;
}
}
public sealed class ClearWeaponAbility : Packet
{
public static readonly Packet Instance = SetStatic(new ClearWeaponAbility());
public ClearWeaponAbility() : base(0xBF)
{
EnsureCapacity(5);
Stream.Write((short)0x21);
}
}
}

View file

@ -1,115 +1,115 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: SecureTradePackets.cs *
* Created: 2020/05/03 - Updated: 2020/05/03 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class DisplaySecureTrade : Packet
{
public DisplaySecureTrade(Mobile them, Container first, Container second, string name)
: base(0x6F)
{
name ??= "";
EnsureCapacity(18 + name.Length);
Stream.Write((byte)0); // Display
Stream.Write(them.Serial);
Stream.Write(first.Serial);
Stream.Write(second.Serial);
Stream.Write(true);
Stream.WriteAsciiFixed(name, 30);
}
}
public sealed class CloseSecureTrade : Packet
{
public CloseSecureTrade(Container cont)
: base(0x6F)
{
EnsureCapacity(8);
Stream.Write((byte)1); // Close
Stream.Write(cont.Serial);
}
}
public enum TradeFlag : byte
{
Display = 0x0,
Close = 0x1,
Update = 0x2,
UpdateGold = 0x3,
UpdateLedger = 0x4
}
public sealed class UpdateSecureTrade : Packet
{
public UpdateSecureTrade(Container cont, bool first, bool second)
: this(cont, TradeFlag.Update, first ? 1 : 0, second ? 1 : 0)
{
}
public UpdateSecureTrade(Container cont, TradeFlag flag, int first, int second)
: base(0x6F)
{
EnsureCapacity(17);
Stream.Write((byte)flag);
Stream.Write(cont.Serial);
Stream.Write(first);
Stream.Write(second);
}
}
public sealed class SecureTradeEquip : Packet
{
public SecureTradeEquip(Item item, Mobile m) : base(0x25, 20)
{
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((short)item.Amount);
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write(m.Serial);
Stream.Write((short)item.Hue);
}
}
public sealed class SecureTradeEquip6017 : Packet
{
public SecureTradeEquip6017(Item item, Mobile m) : base(0x25, 21)
{
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((short)item.Amount);
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(m.Serial);
Stream.Write((short)item.Hue);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: SecureTradePackets.cs *
* Created: 2020/05/03 - Updated: 2020/05/03 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class DisplaySecureTrade : Packet
{
public DisplaySecureTrade(Mobile them, Container first, Container second, string name)
: base(0x6F)
{
name ??= "";
EnsureCapacity(18 + name.Length);
Stream.Write((byte)0); // Display
Stream.Write(them.Serial);
Stream.Write(first.Serial);
Stream.Write(second.Serial);
Stream.Write(true);
Stream.WriteAsciiFixed(name, 30);
}
}
public sealed class CloseSecureTrade : Packet
{
public CloseSecureTrade(Container cont)
: base(0x6F)
{
EnsureCapacity(8);
Stream.Write((byte)1); // Close
Stream.Write(cont.Serial);
}
}
public enum TradeFlag : byte
{
Display = 0x0,
Close = 0x1,
Update = 0x2,
UpdateGold = 0x3,
UpdateLedger = 0x4
}
public sealed class UpdateSecureTrade : Packet
{
public UpdateSecureTrade(Container cont, bool first, bool second)
: this(cont, TradeFlag.Update, first ? 1 : 0, second ? 1 : 0)
{
}
public UpdateSecureTrade(Container cont, TradeFlag flag, int first, int second)
: base(0x6F)
{
EnsureCapacity(17);
Stream.Write((byte)flag);
Stream.Write(cont.Serial);
Stream.Write(first);
Stream.Write(second);
}
}
public sealed class SecureTradeEquip : Packet
{
public SecureTradeEquip(Item item, Mobile m) : base(0x25, 20)
{
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((short)item.Amount);
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write(m.Serial);
Stream.Write((short)item.Hue);
}
}
public sealed class SecureTradeEquip6017 : Packet
{
public SecureTradeEquip6017(Item item, Mobile m) : base(0x25, 21)
{
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((short)item.Amount);
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(m.Serial);
Stream.Write((short)item.Hue);
}
}
}

View file

@ -1,87 +1,87 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TargetPackets.cs - Created: 2020/05/26 - Updated: 2020/05/26 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.IO;
using Server.Targeting;
namespace Server.Network
{
public sealed class MultiTargetReqHS : Packet
{
public MultiTargetReqHS(MultiTarget t) : base(0x99, 30)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
Stream.Seek(18, SeekOrigin.Begin);
Stream.Write((short)t.MultiID);
Stream.Write((short)t.Offset.X);
Stream.Write((short)t.Offset.Y);
Stream.Write((short)t.Offset.Z);
// DWORD Hue
}
}
public sealed class MultiTargetReq : Packet
{
public MultiTargetReq(MultiTarget t) : base(0x99, 26)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
Stream.Seek(18, SeekOrigin.Begin);
Stream.Write((short)t.MultiID);
Stream.Write((short)t.Offset.X);
Stream.Write((short)t.Offset.Y);
Stream.Write((short)t.Offset.Z);
}
}
public sealed class CancelTarget : Packet
{
public static readonly Packet Instance = SetStatic(new CancelTarget());
public CancelTarget() : base(0x6C, 19)
{
Stream.Write((byte)0);
Stream.Write(0);
Stream.Write((byte)3);
Stream.Fill();
}
}
public sealed class TargetReq : Packet
{
public TargetReq(Target t) : base(0x6C, 19)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TargetPackets.cs - Created: 2020/05/26 - Updated: 2020/05/26 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.IO;
using Server.Targeting;
namespace Server.Network
{
public sealed class MultiTargetReqHS : Packet
{
public MultiTargetReqHS(MultiTarget t) : base(0x99, 30)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
Stream.Seek(18, SeekOrigin.Begin);
Stream.Write((short)t.MultiID);
Stream.Write((short)t.Offset.X);
Stream.Write((short)t.Offset.Y);
Stream.Write((short)t.Offset.Z);
// DWORD Hue
}
}
public sealed class MultiTargetReq : Packet
{
public MultiTargetReq(MultiTarget t) : base(0x99, 26)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
Stream.Seek(18, SeekOrigin.Begin);
Stream.Write((short)t.MultiID);
Stream.Write((short)t.Offset.X);
Stream.Write((short)t.Offset.Y);
Stream.Write((short)t.Offset.Z);
}
}
public sealed class CancelTarget : Packet
{
public static readonly Packet Instance = SetStatic(new CancelTarget());
public CancelTarget() : base(0x6C, 19)
{
Stream.Write((byte)0);
Stream.Write(0);
Stream.Write((byte)3);
Stream.Fill();
}
}
public sealed class TargetReq : Packet
{
public TargetReq(Target t) : base(0x6C, 19)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
}
}
}

View file

@ -1,38 +1,38 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: UnicodePrompt.cs - Created: 2020/05/08 - Updated: 2020/05/08 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Prompts;
namespace Server.Network
{
public sealed class UnicodePrompt : Packet
{
public UnicodePrompt(Prompt prompt) : base(0xC2)
{
EnsureCapacity(21);
Stream.Write(prompt.Serial); // TODO: Does this value even matter?
Stream.Write(prompt.Serial);
Stream.Write(0);
Stream.Write(0);
Stream.Write((short)0);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: UnicodePrompt.cs - Created: 2020/05/08 - Updated: 2020/05/08 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Prompts;
namespace Server.Network
{
public sealed class UnicodePrompt : Packet
{
public UnicodePrompt(Prompt prompt) : base(0xC2)
{
EnsureCapacity(21);
Stream.Write(prompt.Serial); // TODO: Does this value even matter?
Stream.Write(prompt.Serial);
Stream.Write(0);
Stream.Write(0);
Stream.Write((short)0);
}
}
}

View file

@ -1,128 +1,128 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: VendorBuyPackets.cs - Created: 2020/05/03 - Updated: 2020/05/03 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 Server.Items;
namespace Server.Network
{
public sealed class VendorBuyContent : Packet
{
public VendorBuyContent(List<BuyItemState> list) : base(0x3C)
{
EnsureCapacity(list.Count * 19 + 5);
Stream.Write((short)list.Count);
for (var i = list.Count - 1; i >= 0; --i)
{
var bis = list[i];
Stream.Write(bis.MySerial);
Stream.Write((ushort)bis.ItemID);
Stream.Write((byte)0); // itemID offset
Stream.Write((ushort)bis.Amount);
Stream.Write((short)(i + 1)); // x
Stream.Write((short)1); // y
Stream.Write(bis.ContainerSerial);
Stream.Write((ushort)bis.Hue);
}
}
}
public sealed class VendorBuyContent6017 : Packet
{
public VendorBuyContent6017(List<BuyItemState> list) : base(0x3C)
{
EnsureCapacity(list.Count * 20 + 5);
Stream.Write((short)list.Count);
for (var i = list.Count - 1; i >= 0; --i)
{
var bis = list[i];
Stream.Write(bis.MySerial);
Stream.Write((ushort)bis.ItemID);
Stream.Write((byte)0); // itemID offset
Stream.Write((ushort)bis.Amount);
Stream.Write((short)(i + 1)); // x
Stream.Write((short)1); // y
Stream.Write((byte)0); // Grid Location?
Stream.Write(bis.ContainerSerial);
Stream.Write((ushort)bis.Hue);
}
}
}
public sealed class DisplayBuyList : Packet
{
public DisplayBuyList(Mobile vendor) : base(0x24, 7)
{
Stream.Write(vendor.Serial);
Stream.Write((short)0x30); // buy window id?
}
}
public sealed class DisplayBuyListHS : Packet
{
public DisplayBuyListHS(Mobile vendor) : base(0x24, 9)
{
Stream.Write(vendor.Serial);
Stream.Write((short)0x30); // buy window id?
Stream.Write((short)0x00);
}
}
public sealed class VendorBuyList : Packet
{
public VendorBuyList(Mobile vendor, List<BuyItemState> list) : base(0x74)
{
EnsureCapacity(256);
Stream.Write(!(vendor.FindItemOnLayer(Layer.ShopBuy) is Container buyPack) ? Serial.MinusOne : buyPack.Serial);
Stream.Write((byte)list.Count);
for (var i = 0; i < list.Count; ++i)
{
var bis = list[i];
Stream.Write(bis.Price);
var desc = bis.Description ?? "";
// TODO: Test if this is actually WriteAsciiFixed and the extra null doesn't matter.
Stream.Write((byte)(desc.Length + 1));
Stream.WriteAsciiNull(desc);
}
}
}
public sealed class EndVendorBuy : Packet
{
public EndVendorBuy(Mobile vendor) : base(0x3B, 8)
{
Stream.Write((ushort)8); // length
Stream.Write(vendor.Serial);
Stream.Write((byte)0);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: VendorBuyPackets.cs - Created: 2020/05/03 - Updated: 2020/05/03 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 Server.Items;
namespace Server.Network
{
public sealed class VendorBuyContent : Packet
{
public VendorBuyContent(List<BuyItemState> list) : base(0x3C)
{
EnsureCapacity(list.Count * 19 + 5);
Stream.Write((short)list.Count);
for (var i = list.Count - 1; i >= 0; --i)
{
var bis = list[i];
Stream.Write(bis.MySerial);
Stream.Write((ushort)bis.ItemID);
Stream.Write((byte)0); // itemID offset
Stream.Write((ushort)bis.Amount);
Stream.Write((short)(i + 1)); // x
Stream.Write((short)1); // y
Stream.Write(bis.ContainerSerial);
Stream.Write((ushort)bis.Hue);
}
}
}
public sealed class VendorBuyContent6017 : Packet
{
public VendorBuyContent6017(List<BuyItemState> list) : base(0x3C)
{
EnsureCapacity(list.Count * 20 + 5);
Stream.Write((short)list.Count);
for (var i = list.Count - 1; i >= 0; --i)
{
var bis = list[i];
Stream.Write(bis.MySerial);
Stream.Write((ushort)bis.ItemID);
Stream.Write((byte)0); // itemID offset
Stream.Write((ushort)bis.Amount);
Stream.Write((short)(i + 1)); // x
Stream.Write((short)1); // y
Stream.Write((byte)0); // Grid Location?
Stream.Write(bis.ContainerSerial);
Stream.Write((ushort)bis.Hue);
}
}
}
public sealed class DisplayBuyList : Packet
{
public DisplayBuyList(Mobile vendor) : base(0x24, 7)
{
Stream.Write(vendor.Serial);
Stream.Write((short)0x30); // buy window id?
}
}
public sealed class DisplayBuyListHS : Packet
{
public DisplayBuyListHS(Mobile vendor) : base(0x24, 9)
{
Stream.Write(vendor.Serial);
Stream.Write((short)0x30); // buy window id?
Stream.Write((short)0x00);
}
}
public sealed class VendorBuyList : Packet
{
public VendorBuyList(Mobile vendor, List<BuyItemState> list) : base(0x74)
{
EnsureCapacity(256);
Stream.Write(!(vendor.FindItemOnLayer(Layer.ShopBuy) is Container buyPack) ? Serial.MinusOne : buyPack.Serial);
Stream.Write((byte)list.Count);
for (var i = 0; i < list.Count; ++i)
{
var bis = list[i];
Stream.Write(bis.Price);
var desc = bis.Description ?? "";
// TODO: Test if this is actually WriteAsciiFixed and the extra null doesn't matter.
Stream.Write((byte)(desc.Length + 1));
Stream.WriteAsciiNull(desc);
}
}
}
public sealed class EndVendorBuy : Packet
{
public EndVendorBuy(Mobile vendor) : base(0x3B, 8)
{
Stream.Write((ushort)8); // length
Stream.Write(vendor.Serial);
Stream.Write((byte)0);
}
}
}

View file

@ -1,61 +1,61 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: VendorSellPackets.cs *
* Created: 2020/05/07 - Updated: 2020/05/07 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class VendorSellList : Packet
{
public VendorSellList(Mobile shopkeeper, List<SellItemState> sis) : base(0x9E)
{
EnsureCapacity(256);
Stream.Write(shopkeeper.Serial);
Stream.Write((ushort)sis.Count);
foreach (var state in sis)
{
Stream.Write(state.Item.Serial);
Stream.Write((ushort)state.Item.ItemID);
Stream.Write((ushort)state.Item.Hue);
Stream.Write((ushort)state.Item.Amount);
Stream.Write((ushort)state.Price);
var name = string.IsNullOrWhiteSpace(state.Item.Name) ? state.Name ?? "" : state.Item.Name.Trim();
Stream.Write((ushort)name.Length);
Stream.WriteAsciiFixed(name, (ushort)name.Length);
}
}
}
public sealed class EndVendorSell : Packet
{
public EndVendorSell(Mobile vendor) : base(0x3B, 8)
{
Stream.Write((ushort)8); // length
Stream.Write(vendor.Serial);
Stream.Write((byte)0);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: VendorSellPackets.cs *
* Created: 2020/05/07 - Updated: 2020/05/07 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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 sealed class VendorSellList : Packet
{
public VendorSellList(Mobile shopkeeper, List<SellItemState> sis) : base(0x9E)
{
EnsureCapacity(256);
Stream.Write(shopkeeper.Serial);
Stream.Write((ushort)sis.Count);
foreach (var state in sis)
{
Stream.Write(state.Item.Serial);
Stream.Write((ushort)state.Item.ItemID);
Stream.Write((ushort)state.Item.Hue);
Stream.Write((ushort)state.Item.Amount);
Stream.Write((ushort)state.Price);
var name = string.IsNullOrWhiteSpace(state.Item.Name) ? state.Name ?? "" : state.Item.Name.Trim();
Stream.Write((ushort)name.Length);
Stream.WriteAsciiFixed(name, (ushort)name.Length);
}
}
}
public sealed class EndVendorSell : Packet
{
public EndVendorSell(Mobile vendor) : base(0x3B, 8)
{
Stream.Write((ushort)8); // length
Stream.Write(vendor.Serial);
Stream.Write((byte)0);
}
}
}

View file

@ -1,96 +1,97 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerConnectionHandler.cs *
* Created: 2020/04/12 - Updated: 2020/04/12 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections;
using Microsoft.Extensions.Logging;
namespace Server.Network
{
public class ServerConnectionHandler : ConnectionHandler
{
private readonly IMessagePumpService _messagePumpService;
private readonly ILogger<ServerConnectionHandler> _logger;
public ServerConnectionHandler(
IMessagePumpService messagePumpService,
ILogger<ServerConnectionHandler> logger)
{
_messagePumpService = messagePumpService;
_logger = logger;
}
public override async Task OnConnectedAsync(ConnectionContext connection)
{
if (!VerifySocket(connection))
{
Release(connection);
return;
}
var ns = new NetState(connection);
TcpServer.Instances.Add(ns);
Console.WriteLine($"Client: {ns}: Connected. [{TcpServer.Instances.Count} Online]");
await ns.ProcessIncoming(_messagePumpService).ConfigureAwait(false);
}
private static bool VerifySocket(ConnectionContext connection)
{
try
{
var args = new SocketConnectEventArgs(connection);
EventSink.InvokeSocketConnect(args);
return args.AllowConnection;
}
catch (Exception ex)
{
NetState.TraceException(ex);
return false;
}
}
private static void Release(ConnectionContext connection)
{
try
{
connection.Abort(new ConnectionAbortedException("Failed socket verification."));
}
catch (Exception ex)
{
NetState.TraceException(ex);
}
try
{
// TODO: Is this needed?
connection.DisposeAsync();
}
catch (Exception ex)
{
NetState.TraceException(ex);
}
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerConnectionHandler.cs *
* Created: 2020/04/12 - Updated: 2020/04/12 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections;
using Microsoft.Extensions.Logging;
namespace Server.Network
{
public class ServerConnectionHandler : ConnectionHandler
{
private readonly ILogger<ServerConnectionHandler> _logger;
private readonly IMessagePumpService _messagePumpService;
public ServerConnectionHandler(
IMessagePumpService messagePumpService,
ILogger<ServerConnectionHandler> logger
)
{
_messagePumpService = messagePumpService;
_logger = logger;
}
public override async Task OnConnectedAsync(ConnectionContext connection)
{
if (!VerifySocket(connection))
{
Release(connection);
return;
}
var ns = new NetState(connection);
TcpServer.Instances.Add(ns);
Console.WriteLine($"Client: {ns}: Connected. [{TcpServer.Instances.Count} Online]");
await ns.ProcessIncoming(_messagePumpService).ConfigureAwait(false);
}
private static bool VerifySocket(ConnectionContext connection)
{
try
{
var args = new SocketConnectEventArgs(connection);
EventSink.InvokeSocketConnect(args);
return args.AllowConnection;
}
catch (Exception ex)
{
NetState.TraceException(ex);
return false;
}
}
private static void Release(ConnectionContext connection)
{
try
{
connection.Abort(new ConnectionAbortedException("Failed socket verification."));
}
catch (Exception ex)
{
NetState.TraceException(ex);
}
try
{
// TODO: Is this needed?
connection.DisposeAsync();
}
catch (Exception ex)
{
NetState.TraceException(ex);
}
}
}
}

View file

@ -1,44 +1,44 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerInfo.cs - Created: 2020/06/25 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using System.Net;
namespace Server.Network
{
public sealed class ServerInfo
{
public ServerInfo(string name, int fullPercent, TimeZoneInfo tz, IPEndPoint address)
{
Name = name;
FullPercent = fullPercent;
TimeZone = tz.GetUtcOffset(DateTime.Now).Hours;
Address = address;
}
public string Name { get; set; }
public int FullPercent { get; set; }
public int TimeZone { get; set; }
public IPEndPoint Address { get; set; }
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerInfo.cs - Created: 2020/06/25 - Updated: 2020/06/25 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using System.Net;
namespace Server.Network
{
public sealed class ServerInfo
{
public ServerInfo(string name, int fullPercent, TimeZoneInfo tz, IPEndPoint address)
{
Name = name;
FullPercent = fullPercent;
TimeZone = tz.GetUtcOffset(DateTime.Now).Hours;
Address = address;
}
public string Name { get; set; }
public int FullPercent { get; set; }
public int TimeZone { get; set; }
public IPEndPoint Address { get; set; }
}
}

View file

@ -1,43 +1,43 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerStartup.cs *
* Created: 2020/04/12 - Updated: 2020/04/12 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace Server.Network
{
public class ServerStartup
{
private readonly IMessagePumpService _messagePumpService;
public ServerStartup(IMessagePumpService messagePumpService) => _messagePumpService = messagePumpService;
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app)
{
// Run async?
Task.Run(() => Core.RunEventLoop(_messagePumpService));
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerStartup.cs *
* Created: 2020/04/12 - Updated: 2020/04/12 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace Server.Network
{
public class ServerStartup
{
private readonly IMessagePumpService _messagePumpService;
public ServerStartup(IMessagePumpService messagePumpService) => _messagePumpService = messagePumpService;
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app)
{
// Run async?
Task.Run(() => Core.RunEventLoop(_messagePumpService));
}
}
}

View file

@ -1,119 +1,134 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: StaticPacketHandlers.cs *
* Created: 2019/03/15 - Updated: 2019/12/24 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Concurrent;
namespace Server.Network
{
public static class StaticPacketHandlers
{
private static readonly ConcurrentDictionary<IPropertyListObject, OPLInfo> OPLInfoPackets =
new ConcurrentDictionary<IPropertyListObject, OPLInfo>();
private static readonly ConcurrentDictionary<IEntity, RemoveEntity> RemoveEntityPackets =
new ConcurrentDictionary<IEntity, RemoveEntity>();
private static readonly ConcurrentDictionary<Item, WorldItem> WorldItemPackets =
new ConcurrentDictionary<Item, WorldItem>();
private static readonly ConcurrentDictionary<Item, WorldItemSA> WorldItemSAPackets =
new ConcurrentDictionary<Item, WorldItemSA>();
private static readonly ConcurrentDictionary<Item, WorldItemHS> WorldItemHSPackets =
new ConcurrentDictionary<Item, WorldItemHS>();
public static OPLInfo GetOPLInfoPacket(IPropertyListObject obj)
{
return OPLInfoPackets.GetOrAdd(obj, value =>
{
var packet = new OPLInfo(value.PropertyList.Entity.Serial, value.PropertyList.Hash);
packet.SetStatic();
return packet;
});
}
public static OPLInfo FreeOPLInfoPacket(IPropertyListObject obj)
{
if (OPLInfoPackets.TryRemove(obj, out var p))
Packet.Release(p);
return p;
}
public static RemoveEntity GetRemoveEntityPacket(IEntity entity)
{
return RemoveEntityPackets.GetOrAdd(entity, value =>
{
var packet = new RemoveEntity(value.Serial);
packet.SetStatic();
return packet;
});
}
public static void FreeRemoveItemPacket(IEntity entity)
{
if (RemoveEntityPackets.TryRemove(entity, out var p))
Packet.Release(p);
}
public static WorldItem GetWorldItemPacket(Item item)
{
return WorldItemPackets.GetOrAdd(item, value =>
{
var packet = new WorldItem(value);
packet.SetStatic();
return packet;
});
}
public static WorldItemSA GetWorldItemSAPacket(Item item)
{
return WorldItemSAPackets.GetOrAdd(item, value =>
{
var packet = new WorldItemSA(value);
packet.SetStatic();
return packet;
});
}
public static WorldItemHS GetWorldItemHSPacket(Item item)
{
return WorldItemHSPackets.GetOrAdd(item, value =>
{
var packet = new WorldItemHS(value);
packet.SetStatic();
return packet;
});
}
public static void FreeWorldItemPackets(Item item)
{
if (WorldItemPackets.TryRemove(item, out var wi))
Packet.Release(wi);
if (WorldItemSAPackets.TryRemove(item, out var wisa))
Packet.Release(wisa);
if (WorldItemHSPackets.TryRemove(item, out var wihs))
Packet.Release(wihs);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: StaticPacketHandlers.cs *
* Created: 2019/03/15 - Updated: 2019/12/24 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Concurrent;
namespace Server.Network
{
public static class StaticPacketHandlers
{
private static readonly ConcurrentDictionary<IPropertyListObject, OPLInfo> OPLInfoPackets =
new ConcurrentDictionary<IPropertyListObject, OPLInfo>();
private static readonly ConcurrentDictionary<IEntity, RemoveEntity> RemoveEntityPackets =
new ConcurrentDictionary<IEntity, RemoveEntity>();
private static readonly ConcurrentDictionary<Item, WorldItem> WorldItemPackets =
new ConcurrentDictionary<Item, WorldItem>();
private static readonly ConcurrentDictionary<Item, WorldItemSA> WorldItemSAPackets =
new ConcurrentDictionary<Item, WorldItemSA>();
private static readonly ConcurrentDictionary<Item, WorldItemHS> WorldItemHSPackets =
new ConcurrentDictionary<Item, WorldItemHS>();
public static OPLInfo GetOPLInfoPacket(IPropertyListObject obj)
{
return OPLInfoPackets.GetOrAdd(
obj,
value =>
{
var packet = new OPLInfo(value.PropertyList.Entity.Serial, value.PropertyList.Hash);
packet.SetStatic();
return packet;
}
);
}
public static OPLInfo FreeOPLInfoPacket(IPropertyListObject obj)
{
if (OPLInfoPackets.TryRemove(obj, out var p))
Packet.Release(p);
return p;
}
public static RemoveEntity GetRemoveEntityPacket(IEntity entity)
{
return RemoveEntityPackets.GetOrAdd(
entity,
value =>
{
var packet = new RemoveEntity(value.Serial);
packet.SetStatic();
return packet;
}
);
}
public static void FreeRemoveItemPacket(IEntity entity)
{
if (RemoveEntityPackets.TryRemove(entity, out var p))
Packet.Release(p);
}
public static WorldItem GetWorldItemPacket(Item item)
{
return WorldItemPackets.GetOrAdd(
item,
value =>
{
var packet = new WorldItem(value);
packet.SetStatic();
return packet;
}
);
}
public static WorldItemSA GetWorldItemSAPacket(Item item)
{
return WorldItemSAPackets.GetOrAdd(
item,
value =>
{
var packet = new WorldItemSA(value);
packet.SetStatic();
return packet;
}
);
}
public static WorldItemHS GetWorldItemHSPacket(Item item)
{
return WorldItemHSPackets.GetOrAdd(
item,
value =>
{
var packet = new WorldItemHS(value);
packet.SetStatic();
return packet;
}
);
}
public static void FreeWorldItemPackets(Item item)
{
if (WorldItemPackets.TryRemove(item, out var wi))
Packet.Release(wi);
if (WorldItemSAPackets.TryRemove(item, out var wisa))
Packet.Release(wisa);
if (WorldItemHSPackets.TryRemove(item, out var wihs))
Packet.Release(wihs);
}
}
}

View file

@ -1,84 +1,86 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TcpServer.cs *
* Created: 2020/04/12 - Updated: 2020/04/12 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Server.Network
{
public static class TcpServer
{
// Make this thread safe
public static List<NetState> Instances { get; } = new List<NetState>();
private static IPAddress[] m_ListeningAddresses;
public static IWebHostBuilder CreateWebHostBuilder(string[] args = null) =>
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.SuppressStatusMessagesKey, "True")
.ConfigureServices(services => { services.AddSingleton<IMessagePumpService>(new MessagePumpService()); })
.UseKestrel(options =>
{
foreach (var ipep in ServerConfiguration.Listeners)
{
options.Listen(ipep, builder => { builder.UseConnectionHandler<ServerConnectionHandler>(); });
m_ListeningAddresses = GetListeningAddresses(ipep);
DisplayListener(ipep);
}
// Webservices here
})
.UseLibuv()
.UseStartup<ServerStartup>();
public static IPAddress[] GetListeningAddresses(IPEndPoint ipep)
{
if (m_ListeningAddresses != null)
return m_ListeningAddresses;
var list = new List<IPAddress>();
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
{
var properties = adapter.GetIPProperties();
foreach (var unicast in properties.UnicastAddresses)
if (ipep.AddressFamily == unicast.Address.AddressFamily)
list.Add(unicast.Address);
}
return list.ToArray();
}
private static void DisplayListener(IPEndPoint ipep)
{
if (ipep.Address.Equals(IPAddress.Any) || ipep.Address.Equals(IPAddress.IPv6Any))
foreach (var ip in m_ListeningAddresses)
Console.WriteLine("Listening: {0}:{1}", ip, ipep.Port);
else
Console.WriteLine("Listening: {0}:{1}", ipep.Address, ipep.Port);
}
}
}
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TcpServer.cs *
* Created: 2020/04/12 - Updated: 2020/04/12 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Server.Network
{
public static class TcpServer
{
private static IPAddress[] m_ListeningAddresses;
// Make this thread safe
public static List<NetState> Instances { get; } = new List<NetState>();
public static IWebHostBuilder CreateWebHostBuilder(string[] args = null) =>
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.SuppressStatusMessagesKey, "True")
.ConfigureServices(services => { services.AddSingleton<IMessagePumpService>(new MessagePumpService()); })
.UseKestrel(
options =>
{
foreach (var ipep in ServerConfiguration.Listeners)
{
options.Listen(ipep, builder => { builder.UseConnectionHandler<ServerConnectionHandler>(); });
m_ListeningAddresses = GetListeningAddresses(ipep);
DisplayListener(ipep);
}
// Webservices here
}
)
.UseLibuv()
.UseStartup<ServerStartup>();
public static IPAddress[] GetListeningAddresses(IPEndPoint ipep)
{
if (m_ListeningAddresses != null)
return m_ListeningAddresses;
var list = new List<IPAddress>();
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
{
var properties = adapter.GetIPProperties();
foreach (var unicast in properties.UnicastAddresses)
if (ipep.AddressFamily == unicast.Address.AddressFamily)
list.Add(unicast.Address);
}
return list.ToArray();
}
private static void DisplayListener(IPEndPoint ipep)
{
if (ipep.Address.Equals(IPAddress.Any) || ipep.Address.Equals(IPAddress.IPv6Any))
foreach (var ip in m_ListeningAddresses)
Console.WriteLine("Listening: {0}:{1}", ip, ipep.Port);
else
Console.WriteLine("Listening: {0}:{1}", ipep.Address, ipep.Port);
}
}
}