Readd mapgenerator

This commit is contained in:
Cinder Biscuits
2019-10-04 08:04:59 -05:00
parent 08fb0051c8
commit 39d221782f
6 changed files with 2294 additions and 0 deletions

View File

@@ -0,0 +1,694 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace mapgenerator
{
/// <summary>
///
/// </summary>
public enum PacketFrequency
{
/// <summary></summary>
Low,
/// <summary></summary>
Medium,
/// <summary></summary>
High
}
/// <summary>
///
/// </summary>
public enum FieldType
{
/// <summary></summary>
U8,
/// <summary></summary>
U16,
/// <summary></summary>
U32,
/// <summary></summary>
U64,
/// <summary></summary>
S8,
/// <summary></summary>
S16,
/// <summary></summary>
S32,
/// <summary></summary>
F32,
/// <summary></summary>
F64,
/// <summary></summary>
LLUUID,
/// <summary></summary>
BOOL,
/// <summary></summary>
LLVector3,
/// <summary></summary>
LLVector3d,
/// <summary></summary>
LLVector4,
/// <summary></summary>
LLQuaternion,
/// <summary></summary>
IPADDR,
/// <summary></summary>
IPPORT,
/// <summary></summary>
Variable,
/// <summary></summary>
Fixed,
/// <summary></summary>
Single,
/// <summary></summary>
Multiple
}
/// <summary>
///
/// </summary>
public class MapField : IComparable
{
/// <summary></summary>
public int KeywordPosition;
/// <summary></summary>
public string Name;
/// <summary></summary>
public FieldType Type;
/// <summary></summary>
public int Count;
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public int CompareTo(object obj)
{
MapField temp = (MapField)obj;
if (this.KeywordPosition > temp.KeywordPosition)
{
return 1;
}
else
{
if(temp.KeywordPosition == this.KeywordPosition)
{
return 0;
}
else
{
return -1;
}
}
}
}
/// <summary>
///
/// </summary>
public class MapBlock : IComparable
{
/// <summary></summary>
public int KeywordPosition;
/// <summary></summary>
public string Name;
/// <summary></summary>
public int Count;
/// <summary></summary>
public List<MapField> Fields;
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public int CompareTo(object obj)
{
MapBlock temp = (MapBlock)obj;
if (this.KeywordPosition > temp.KeywordPosition)
{
return 1;
}
else
{
if(temp.KeywordPosition == this.KeywordPosition)
{
return 0;
}
else
{
return -1;
}
}
}
}
/// <summary>
///
/// </summary>
public class MapPacket
{
/// <summary></summary>
public ushort ID;
/// <summary></summary>
public string Name;
/// <summary></summary>
public PacketFrequency Frequency;
/// <summary></summary>
public bool Trusted;
/// <summary></summary>
public bool Encoded;
/// <summary></summary>
public List<MapBlock> Blocks;
}
/// <summary>
///
/// </summary>
public class ProtocolManager
{
/// <summary></summary>
public Dictionary<FieldType, int> TypeSizes;
/// <summary></summary>
public Dictionary<string, int> KeywordPositions;
/// <summary></summary>
public MapPacket[] LowMaps;
/// <summary></summary>
public MapPacket[] MediumMaps;
/// <summary></summary>
public MapPacket[] HighMaps;
/// <summary>
///
/// </summary>
/// <param name="keywordFile"></param>
/// <param name="mapFile"></param>
/// <param name="client"></param>
public ProtocolManager(string mapFile)
{
// Initialize the map arrays
LowMaps = new MapPacket[65536];
MediumMaps = new MapPacket[256];
HighMaps = new MapPacket[256];
// Build the type size hash table
TypeSizes = new Dictionary<FieldType,int>();
TypeSizes.Add(FieldType.U8, 1);
TypeSizes.Add(FieldType.U16, 2);
TypeSizes.Add(FieldType.U32, 4);
TypeSizes.Add(FieldType.U64, 8);
TypeSizes.Add(FieldType.S8, 1);
TypeSizes.Add(FieldType.S16, 2);
TypeSizes.Add(FieldType.S32, 4);
TypeSizes.Add(FieldType.F32, 4);
TypeSizes.Add(FieldType.F64, 8);
TypeSizes.Add(FieldType.LLUUID, 16);
TypeSizes.Add(FieldType.BOOL, 1);
TypeSizes.Add(FieldType.LLVector3, 12);
TypeSizes.Add(FieldType.LLVector3d, 24);
TypeSizes.Add(FieldType.LLVector4, 16);
TypeSizes.Add(FieldType.LLQuaternion, 16);
TypeSizes.Add(FieldType.IPADDR, 4);
TypeSizes.Add(FieldType.IPPORT, 2);
TypeSizes.Add(FieldType.Variable, -1);
TypeSizes.Add(FieldType.Fixed, -2);
KeywordPositions = new Dictionary<string, int>();
LoadMapFile(mapFile);
}
/// <summary>
///
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
public MapPacket Command(string command)
{
foreach (MapPacket map in HighMaps)
{
if (map != null)
{
if (command == map.Name)
{
return map;
}
}
}
foreach (MapPacket map in MediumMaps)
{
if (map != null)
{
if (command == map.Name)
{
return map;
}
}
}
foreach (MapPacket map in LowMaps)
{
if (map != null)
{
if (command == map.Name)
{
return map;
}
}
}
throw new Exception("Cannot find map for command \"" + command + "\"");
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public MapPacket Command(byte[] data)
{
ushort command;
if (data.Length < 5)
{
return null;
}
if (data[4] == 0xFF)
{
if ((byte)data[5] == 0xFF)
{
// Low frequency
command = (ushort)(data[6] * 256 + data[7]);
return Command(command, PacketFrequency.Low);
}
else
{
// Medium frequency
command = (ushort)data[5];
return Command(command, PacketFrequency.Medium);
}
}
else
{
// High frequency
command = (ushort)data[4];
return Command(command, PacketFrequency.High);
}
}
/// <summary>
///
/// </summary>
/// <param name="command"></param>
/// <param name="frequency"></param>
/// <returns></returns>
public MapPacket Command(ushort command, PacketFrequency frequency)
{
switch (frequency)
{
case PacketFrequency.High:
return HighMaps[command];
case PacketFrequency.Medium:
return MediumMaps[command];
case PacketFrequency.Low:
return LowMaps[command];
}
throw new Exception("Cannot find map for command \"" + command + "\" with frequency \"" + frequency + "\"");
}
/// <summary>
///
/// </summary>
public void PrintMap(TextWriter writer)
{
PrintOneMap(writer, LowMaps, "Low ");
PrintOneMap(writer, MediumMaps, "Medium");
PrintOneMap(writer, HighMaps, "High ");
}
/// <summary>
///
/// </summary>
/// <param name="map"></param>
/// <param name="frequency"></param>
private void PrintOneMap(TextWriter writer, MapPacket[] map, string frequency) {
int i;
for (i = 0; i < map.Length; ++i)
{
if (map[i] != null)
{
writer.WriteLine("{0} {1,5} - {2} - {3} - {4}", frequency, i, map[i].Name,
map[i].Trusted ? "Trusted" : "Untrusted",
map[i].Encoded ? "Zerocoded" : "Unencoded");
foreach (MapBlock block in map[i].Blocks)
{
if (block.Count == -1)
{
writer.WriteLine("\t{0,4} {1} (Variable)", block.KeywordPosition, block.Name);
}
else
{
writer.WriteLine("\t{0,4} {1} ({2})", block.KeywordPosition, block.Name, block.Count);
}
foreach (MapField field in block.Fields)
{
writer.WriteLine("\t\t{0,4} {1} ({2} / {3})", field.KeywordPosition, field.Name,
field.Type, field.Count);
}
}
}
}
}
/// <summary>
///
/// </summary>
/// <param name="mapFile"></param>
/// <param name="outputFile"></param>
public static void DecodeMapFile(string mapFile, string outputFile)
{
byte magicKey = 0;
byte[] buffer = new byte[2048];
int nread;
BinaryReader map;
BinaryWriter output;
try
{
map = new BinaryReader(new FileStream(mapFile, FileMode.Open));
}
catch(Exception e)
{
throw new Exception("Map file error", e);
}
try
{
output = new BinaryWriter(new FileStream(outputFile, FileMode.CreateNew));
}
catch(Exception e)
{
throw new Exception("Map file error", e);
}
while ((nread = map.Read(buffer, 0, 2048)) != 0)
{
for (int i = 0; i < nread; ++i)
{
buffer[i] ^= magicKey;
magicKey += 43;
}
output.Write(buffer, 0, nread);
}
map.Close();
output.Close();
}
/// <summary>
///
/// </summary>
/// <param name="mapFile"></param>
private void LoadMapFile(string mapFile)
{
FileStream map;
// Load the protocol map file
try
{
map = new FileStream(mapFile, FileMode.Open, FileAccess.Read);
}
catch(Exception e)
{
throw new Exception("Map file error", e);
}
try
{
StreamReader r = new StreamReader(map);
r.BaseStream.Seek(0, SeekOrigin.Begin);
string newline;
string trimmedline;
bool inPacket = false;
bool inBlock = false;
MapPacket currentPacket = null;
MapBlock currentBlock = null;
char[] trimArray = new char[] {' ', '\t'};
// While not at the end of the file
while (r.Peek() > -1)
{
#region ParseMap
newline = r.ReadLine();
trimmedline = System.Text.RegularExpressions.Regex.Replace(newline, @"\s+", " ");
trimmedline = trimmedline.Trim(trimArray);
if (!inPacket)
{
// Outside of all packet blocks
if (trimmedline == "{")
{
inPacket = true;
}
}
else
{
// Inside of a packet block
if (!inBlock)
{
// Inside a packet block, outside of the blocks
if (trimmedline == "{")
{
inBlock = true;
}
else if (trimmedline == "}")
{
// Reached the end of the packet
// currentPacket.Blocks.Sort();
inPacket = false;
}
else
{
// Skip comments
if (trimmedline.StartsWith("//")) continue;
// The packet header
#region ParsePacketHeader
// Splice the string in to tokens
string[] tokens = trimmedline.Split(new char[] {' ', '\t'});
if (tokens.Length > 3)
{
//Hash packet name to insure correct keyword ordering
KeywordPosition(tokens[0]);
uint packetID;
// Remove the leading "0x"
if (tokens[2].Length > 2 && tokens[2].Substring(0, 2) == "0x")
{
tokens[2] = tokens[2].Substring(2, tokens[2].Length - 2);
packetID = UInt32.Parse(tokens[2], System.Globalization.NumberStyles.HexNumber);
} else {
packetID = UInt32.Parse(tokens[2]);
}
if (tokens[1] == "Fixed")
{
// Truncate the id to a short
packetID &= 0xFFFF;
LowMaps[packetID] = new MapPacket();
LowMaps[packetID].ID = (ushort)packetID;
LowMaps[packetID].Frequency = PacketFrequency.Low;
LowMaps[packetID].Name = tokens[0];
LowMaps[packetID].Trusted = (tokens[3] == "Trusted");
LowMaps[packetID].Encoded = (tokens[4] == "Zerocoded");
LowMaps[packetID].Blocks = new List<MapBlock>();
currentPacket = LowMaps[packetID];
}
else if (tokens[1] == "Low")
{
LowMaps[packetID] = new MapPacket();
LowMaps[packetID].ID = (ushort)packetID;
LowMaps[packetID].Frequency = PacketFrequency.Low;
LowMaps[packetID].Name = tokens[0];
LowMaps[packetID].Trusted = (tokens[2] == "Trusted");
LowMaps[packetID].Encoded = (tokens[4] == "Zerocoded");
LowMaps[packetID].Blocks = new List<MapBlock>();
currentPacket = LowMaps[packetID];
}
else if (tokens[1] == "Medium")
{
MediumMaps[packetID] = new MapPacket();
MediumMaps[packetID].ID = (ushort)packetID;
MediumMaps[packetID].Frequency = PacketFrequency.Medium;
MediumMaps[packetID].Name = tokens[0];
MediumMaps[packetID].Trusted = (tokens[2] == "Trusted");
MediumMaps[packetID].Encoded = (tokens[4] == "Zerocoded");
MediumMaps[packetID].Blocks = new List<MapBlock>();
currentPacket = MediumMaps[packetID];
}
else if (tokens[1] == "High")
{
HighMaps[packetID] = new MapPacket();
HighMaps[packetID].ID = (ushort)packetID;
HighMaps[packetID].Frequency = PacketFrequency.High;
HighMaps[packetID].Name = tokens[0];
HighMaps[packetID].Trusted = (tokens[2] == "Trusted");
HighMaps[packetID].Encoded = (tokens[4] == "Zerocoded");
HighMaps[packetID].Blocks = new List<MapBlock>();
currentPacket = HighMaps[packetID];
}
else
{
//Client.Log("Unknown packet frequency", Helpers.LogLevel.Error);
throw new Exception("Unknown packet frequency");
}
}
#endregion
}
}
else
{
if (trimmedline.Length > 0 && trimmedline.Substring(0, 1) == "{")
{
// A field
#region ParseField
MapField field = new MapField();
// Splice the string in to tokens
string[] tokens = trimmedline.Split(new char[] {' ', '\t'});
field.Name = tokens[1];
field.KeywordPosition = KeywordPosition(field.Name);
field.Type = (FieldType)Enum.Parse(typeof(FieldType), tokens[2], true);
if (tokens[3] != "}")
{
field.Count = Int32.Parse(tokens[3]);
}
else
{
field.Count = 1;
}
// Save this field to the current block
currentBlock.Fields.Add(field);
#endregion
}
else if (trimmedline == "}")
{
// currentBlock.Fields.Sort();
inBlock = false;
}
else if (trimmedline.Length != 0 && trimmedline.Substring(0, 2) != "//")
{
// The block header
#region ParseBlockHeader
currentBlock = new MapBlock();
// Splice the string in to tokens
string[] tokens = trimmedline.Split(new char[] {' ', '\t'});
currentBlock.Name = tokens[0];
currentBlock.KeywordPosition = KeywordPosition(currentBlock.Name);
currentBlock.Fields = new List<MapField>();
currentPacket.Blocks.Add(currentBlock);
if (tokens[1] == "Single")
{
currentBlock.Count = 1;
}
else if (tokens[1] == "Multiple")
{
currentBlock.Count = Int32.Parse(tokens[2]);
}
else if (tokens[1] == "Variable")
{
currentBlock.Count = -1;
}
else
{
//Client.Log("Unknown block frequency", Helpers.LogLevel.Error);
throw new Exception("Unknown block frequency");
}
#endregion
}
}
}
#endregion
}
r.Close();
map.Close();
}
catch (Exception e)
{
throw e;
}
}
private int KeywordPosition(string keyword)
{
if (KeywordPositions.ContainsKey(keyword))
{
return KeywordPositions[keyword];
}
int hash = 0;
for (int i = 1; i < keyword.Length; i++)
{
hash = (hash + (int)(keyword[i])) * 2;
}
hash *= 2;
hash &= 0x1FFF;
int startHash = hash;
while (KeywordPositions.ContainsValue(hash))
{
hash++;
hash &= 0x1FFF;
if (hash == startHash)
{
//Give up looking, went through all values and they were all taken.
throw new Exception("All hash values are taken. Failed to add keyword: " + keyword);
}
}
KeywordPositions[keyword] = hash;
return hash;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>14.0.25123</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{2867B4B3-0000-0000-0000-000000000000}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<ApplicationIcon></ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>mapgenerator</AssemblyName>
<DefaultClientScript>JScript</DefaultClientScript>
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
<DefaultTargetSchema>IE50</DefaultTargetSchema>
<DelaySign>false</DelaySign>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<OutputType>Exe</OutputType>
<AppDesignerFolder></AppDesignerFolder>
<RootNamespace>mapgenerator</RootNamespace>
<StartupObject></StartupObject>
<StartArguments></StartArguments>
<FileUpgradeFlags>
</FileUpgradeFlags>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<DocumentationFile></DocumentationFile>
<DebugSymbols>True</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<Optimize>False</Optimize>
<OutputPath>..\..\bin\</OutputPath>
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<NoStdLib>False</NoStdLib>
<NoWarn>1591,1574,0419</NoWarn>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile></DocumentationFile>
<DebugSymbols>False</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<Optimize>True</Optimize>
<OutputPath>..\..\bin\</OutputPath>
<RegisterForComInterop>False</RegisterForComInterop>
<RemoveIntegerChecks>False</RemoveIntegerChecks>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<NoStdLib>False</NoStdLib>
<NoWarn>1591,1574,0419</NoWarn>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" >
<Name>System</Name>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<Compile Include="mapgenerator.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ProtocolManager.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,253 @@
/*
* Copyright (c) 2006-2016, openmetaverse.co
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the Second Life Reverse Engineering Team nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Text;
using OpenMetaverse;
namespace OpenMetaverse
{
/// <summary>
///
/// </summary>
public enum PacketFrequency : byte
{
/// <summary></summary>
Low,
/// <summary></summary>
Medium,
/// <summary></summary>
High
}
}
namespace OpenMetaverse.Packets
{
/// <summary>
/// Thrown when a packet could not be successfully deserialized
/// </summary>
public class MalformedDataException : ApplicationException
{
/// <summary>
/// Default constructor
/// </summary>
public MalformedDataException() { }
/// <summary>
/// Constructor that takes an additional error message
/// </summary>
/// <param name="Message">An error message to attach to this exception</param>
public MalformedDataException(string Message)
: base(Message)
{
this.Source = "Packet decoding";
}
}
/// <summary>
/// The header of a message template packet. Holds packet flags, sequence
/// number, packet ID, and any ACKs that will be appended at the end of
/// the packet
/// </summary>
public struct Header
{
public bool Reliable;
public bool Resent;
public bool Zerocoded;
public bool AppendedAcks;
public uint Sequence;
public ushort ID;
public PacketFrequency Frequency;
public uint[] AckList;
public void ToBytes(byte[] bytes, ref int i)
{
byte flags = 0;
if (Reliable) flags |= Helpers.MSG_RELIABLE;
if (Resent) flags |= Helpers.MSG_RESENT;
if (Zerocoded) flags |= Helpers.MSG_ZEROCODED;
if (AppendedAcks) flags |= Helpers.MSG_APPENDED_ACKS;
// Flags
bytes[i++] = flags;
// Sequence number
Utils.UIntToBytesBig(Sequence, bytes, i);
i += 4;
// Extra byte
bytes[i++] = 0;
// Packet ID
switch (Frequency)
{
case PacketFrequency.High:
// 1 byte ID
bytes[i++] = (byte)ID;
break;
case PacketFrequency.Medium:
// 2 byte ID
bytes[i++] = 0xFF;
bytes[i++] = (byte)ID;
break;
case PacketFrequency.Low:
// 4 byte ID
bytes[i++] = 0xFF;
bytes[i++] = 0xFF;
Utils.UInt16ToBytesBig(ID, bytes, i);
i += 2;
break;
}
}
public void FromBytes(byte[] bytes, ref int pos, ref int packetEnd)
{
this = BuildHeader(bytes, ref pos, ref packetEnd);
}
/// <summary>
/// Convert the AckList to a byte array, used for packet serializing
/// </summary>
/// <param name="bytes">Reference to the target byte array</param>
/// <param name="i">Beginning position to start writing to in the byte
/// array, will be updated with the ending position of the ACK list</param>
public void AcksToBytes(byte[] bytes, ref int i)
{
foreach (uint ack in AckList)
{
Utils.UIntToBytesBig(ack, bytes, i);
i += 4;
}
if (AckList.Length > 0) { bytes[i++] = (byte)AckList.Length; }
}
/// <summary>
///
/// </summary>
/// <param name="bytes"></param>
/// <param name="pos"></param>
/// <param name="packetEnd"></param>
/// <returns></returns>
public static Header BuildHeader(byte[] bytes, ref int pos, ref int packetEnd)
{
Header header;
byte flags = bytes[pos];
header.AppendedAcks = (flags & Helpers.MSG_APPENDED_ACKS) != 0;
header.Reliable = (flags & Helpers.MSG_RELIABLE) != 0;
header.Resent = (flags & Helpers.MSG_RESENT) != 0;
header.Zerocoded = (flags & Helpers.MSG_ZEROCODED) != 0;
header.Sequence = (uint)((bytes[pos + 1] << 24) + (bytes[pos + 2] << 16) + (bytes[pos + 3] << 8) + bytes[pos + 4]);
// Set the frequency and packet ID number
if (bytes[pos + 6] == 0xFF)
{
if (bytes[pos + 7] == 0xFF)
{
header.Frequency = PacketFrequency.Low;
if (header.Zerocoded && bytes[pos + 8] == 0)
header.ID = bytes[pos + 10];
else
header.ID = (ushort)((bytes[pos + 8] << 8) + bytes[pos + 9]);
pos += 10;
}
else
{
header.Frequency = PacketFrequency.Medium;
header.ID = bytes[pos + 7];
pos += 8;
}
}
else
{
header.Frequency = PacketFrequency.High;
header.ID = bytes[pos + 6];
pos += 7;
}
header.AckList = null;
CreateAckList(ref header, bytes, ref packetEnd);
return header;
}
/// <summary>
///
/// </summary>
/// <param name="header"></param>
/// <param name="bytes"></param>
/// <param name="packetEnd"></param>
static void CreateAckList(ref Header header, byte[] bytes, ref int packetEnd)
{
if (header.AppendedAcks)
{
int count = bytes[packetEnd--];
header.AckList = new uint[count];
for (int i = 0; i < count; i++)
{
header.AckList[i] = (uint)(
(bytes[(packetEnd - i * 4) - 3] << 24) |
(bytes[(packetEnd - i * 4) - 2] << 16) |
(bytes[(packetEnd - i * 4) - 1] << 8) |
(bytes[(packetEnd - i * 4) ]));
}
packetEnd -= (count * 4);
}
}
}
/// <summary>
/// A block of data in a packet. Packets are composed of one or more blocks,
/// each block containing one or more fields
/// </summary>
public abstract class PacketBlock
{
/// <summary>Current length of the data in this packet</summary>
public abstract int Length { get; }
/// <summary>
/// Create a block from a byte array
/// </summary>
/// <param name="bytes">Byte array containing the serialized block</param>
/// <param name="i">Starting position of the block in the byte array.
/// This will point to the data after the end of the block when the
/// call returns</param>
public abstract void FromBytes(byte[] bytes, ref int i);
/// <summary>
/// Serialize this block into a byte array
/// </summary>
/// <param name="bytes">Byte array to serialize this block into</param>
/// <param name="i">Starting position in the byte array to serialize to.
/// This will point to the position directly after the end of the
/// serialized block when the call returns</param>
public abstract void ToBytes(byte[] bytes, ref int i);
}

View File

@@ -0,0 +1,124 @@
AddCircuitCode
RelayLogControl
NeighborList
SimulatorAssign
SpaceServerSimulatorTimeMessage
ClosestSimulator
AvatarTextureUpdate
SimulatorMapUpdate
SimulatorSetMap
SubscribeLoad
UnsubscribeLoad
SimulatorStart
SimulatorReady
SimulatorPresentAtLocation
SimulatorLoad
SimulatorShutdownRequest
RegionPresenceRequestByRegionID
RegionPresenceRequestByHandle
RegionPresenceResponse
RecordAgentPresence
EraseAgentPresence
AgentPresenceRequest
AgentPresenceResponse
UpdateSimulator
TrackAgentSession
ClearAgentSessions
LogDwellTime
FeatureDisabled
LogFailedMoneyTransaction
UserReportInternal
SetSimStatusInDatabase
SetSimPresenceInDatabase
AvatarPickerRequestBackend
DirFindQueryBackend
DirPlacesQueryBackend
DirClassifiedQueryBackend
DirPicksQueryBackend
DirLandQueryBackend
DirPopularQueryBackend
OnlineStatusRequest
OnlineStatusReply
GroupNoticeAdd
DataHomeLocationRequest
DataHomeLocationReply
SpaceLocationTeleportRequest
SpaceLocationTeleportReply
CompleteLure
AddModifyAbility
RemoveModifyAbility
NearestLandingRegionRequest
NearestLandingRegionReply
NearestLandingPointUpdated
TeleportLandingStatusChanged
SystemKickUser
AvatarPropertiesRequestBackend
RequestParcelTransfer
UpdateParcel
RemoveParcel
MergeParcel
LogParcelChanges
CheckParcelSales
ParcelSales
StartAuction
ConfirmAuctionStart
CompleteAuction
CancelAuction
CheckParcelAuctions
ParcelAuctions
ChatPass
EdgeDataPacket
SimStatus
PassObject
AtomicPassObject
KillChildAgents
LogLogin
DataServerLogout
TransferInventory
TransferInventoryAck
EventLocationRequest
EventLocationReply
MoneyTransferBackend
BulkMoneyTransfer
SetStartLocation
NetTest
SetCPURatio
SimCrashed
NameValuePair
RemoveNameValuePair
GetNameValuePair
UpdateAttachment
RemoveAttachment
EmailMessageRequest
EmailMessageReply
InternalScriptMail
ScriptDataRequest
ScriptDataReply
InviteGroupResponse
TallyVotes
LogTextMessage
StartExpungeProcess
StartExpungeProcessAck
StartParcelRename
StartParcelRenameAck
BulkParcelRename
ParcelRename
StartParcelRemove
BulkParcelRemove
RpcChannelRequest
RpcChannelReply
RpcScriptRequestInbound
RpcScriptRequestInboundForward
RpcScriptReplyInbound
MailTaskSimRequest
MailTaskSimReply
ScriptMailRegistration
NearestLandingRegionUpdated
KickUserAck
RequestInventoryAsset
InventoryAssetResponse
FormFriendship
CreateTrustedCircuit
DenyTrustedCircuit
RequestTrustedCircuit
SystemMessage