This is partially reformatted Wolfpack UO packets referense (Yoko).

UO Client/Server Protocol
------------------------{Game Packets Structure}
In every packet from or to client, the very first byte is a command identifier,
represented here as cmd into packet's structure.

For simplicity, bytes are used, in this document.  If the size of a piece
of data is larger than a byte, the size will be written afterwards, enclosed
in []'s. Sometimes, unknown or default values will be enclosed in ()'s. 


=========={Create Character [0x00]}- 
This message is sent from UO client when user selects to create a new
character. Since this packet comes with character's initial attributes,
it's important to check for consistency before using information contained
in there. 


Create Character (104 bytes)
BYTE cmd
BYTE[4] pattern1 (0xedededed)
BYTE[4] pattern2 (0xffffffff)
BYTE pattern3 (0x00)
BYTE[30] char name
BYTE[30] char password
BYTE sex (0=male, 1=female)
BYTE str
BYTE dex
BYTE int
BYTE skill1
BYTE skill1value
BYTE skill2
BYTE skill2value
BYTE skill3
BYTE skill3value
BYTE[2] skinColor
BYTE[2] hairStyle
BYTE[2] hairColor
BYTE[2] facial hair
BYTE[2] facial hair color
BYTE[2] location // from starting list
BYTE[2] unknown1
BYTE[2] slot
BYTE[4] clientIP
BYTE[2] shirt color
BYTE[2] pants color



Notes:
Str, dex and int should always sum to 65.
Str, dex and int should always be between 10 and 45, inclusive.
Skill1, skill2, and skill3 should never be the same value.
Skill1, skill2, and skill3 should always be between 0 and 45, inclusive.\footnote{Check Skills table for the meaning skill numbers}
Skill1value, skill2value, and skill3value should always sum to 100.
Skill1value, skill2value, and skill3value should always be between 0 and 50, inclusive.
SkinColor should always be between 0x3EA and 0x422, exclusive.
HairColor and facialHairColor should always be between 0x44E and 0x4AD, exclusive.
HairStyle should be between 0x203B and 0x204A, exclusive, and it should also exclude 0x203D to 0x2044, exclusive.
FacialHairStyle should be between 0x203E and 0x204D
Shirt color and Pants color need bounds checking too.

=========={Disconnect Notification [0x01]}- 
This is a message sent from client to server when the user chooses to return to the main
menu from the character select menu. Since the character select menu no longer has a main
menu button, this message is no longer used.


Disconnect Notification (5 bytes)
BYTE cmd
BYTE[4] pattern (0xFFFFFFFF)


=========={Move Request [0x02]}- 
Client message sent when user is walking/running.

Move Request (7 bytes)
BYTE cmd
BYTE direction
BYTE sequence number
BYTE[4] fastwalk prevention key


The festwalk prevention key is a number sent by the server into the MOVE ACK,
telling the client the next key to be used. This is used to prevent exploits
where client sends "MOVE" message without waitting for the MOVE ACK from the
server.

Note: Sequence number starts at 0, is reseted when reaches 255. However, when it's
reseted, the next sequence number is 1, not 0.

=========={Talk Request [0x03]}----
Talk Request (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE SpeechType
BYTE[2] Color
BYTE[2] SpeechFont
BYTE[x] msg - Null Terminated String.


blockSize is calculated as length of msg (x) + 8.

=========={GodMode Toggle [0x04]}
This is a client packet, used in God client, little information
is avaliable about this special client.


Request (2 bytes)
BYTE cmd
BYTE mode (0=off, 1=on)


=========={Attack Request [0x05]-

Client message sent when user tries to attack someone.

Attack Request (5 bytes)
BYTE cmd
BYTE[4] ID to be attacked


=========={Double click [0x06]-

Double click (5 bytes)
BYTE cmd
BYTE[4] ID of double clicked object


=========={Pick up Item(s) [0x07]-

Pick Up Item(s) (7 bytes)
BYTE cmd
BYTE[4] item id
BYTE[2] # of items in stack


=========={Drop Item(s) [0x08]---
Drop Item(s) (14 bytes)
BYTE cmd
BYTE[4] item id
BYTE[2] X Location
BYTE[2] Y Location
BYTE Z Location
BYTE[4] Move Into Container ID (FF FF FF FF if normal world)


=========={Single click [0x09]---
Single click (5 bytes)
BYTE cmd
BYTE[4] ID of single clicked object


=========={PACKET\_EDIT [0xA]-
A client packet.

Unknown packet (11 bytes)
BYTE cmd
BYTE[10] unknown


=========={PACKET\_EDITAREA [0xB]-
A client packet.

Unknown packet (10 bytes)
BYTE cmd
BYTE[9] unknown


=========={PACKET\_TILEDATA [0xC]-
A client packet.

Unknown packet (variable # of bytes-
BYTE cmd


=========={PACKET\_NPCDATA [0xD]-
A client packet.

Unknosn packet (3 bytes)
BYTE cmd
BYTE[2] unknown


=========={PACKET\_TEMPLATEDATA [0xE]-
A server packet.

Unknown packet (variable # of bytes)
BYTE cmd


=========={PACKET\_PAPERDOLL [0xF]---
Unknown packet (61 bytes)
BYTE cmd
BYTE[60] unknown


=========={PACKET\_HUEDATA [0x10]---
Unknown packet (215 bytes)
BYTE cmd
BYTE[214] unknown



=========={Stat window info [0x11]-
Message sent by the server

Stat window info (66 bytes)
BYTE cmd
BYTE[2] packet length (0x0042)
BYTE[4] player id
BYTE[30] playerName
BYTE[2] currentHitpoints
BYTE[2] maxHitpoints
BYTE[1] name change flag (0xFF = allowed, 0 = not allowed)
BYTE[1] flag (0x00 - Stats after this flag are invalid.  0x01 - Stats after this flag are valid)
BYTE sex (0=male, 1=female)
BYTE[2] str
BYTE[2] dex
BYTE[2] int
BYTE[2] currentStamina
BYTE[2] maxStamina
BYTE[2] currentMana
BYTE[2] maxMana
BYTE[4] gold
BYTE[2] armor class
BYTE[2] weight


Note:For characters other than the player, currentHitpoints and maxHitpoints are not the actual values.
MaxHitpointsis a fixed value, and currentHitpoints works like a percentage.

=========={Request Skill/Action/Magic Usage [0x12]-----
Request Skill/Action/Magic Usage (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE type
0x24 ($) - skill
BYTE[blockSize-4] skill (null terminated strings)
"1 0"- anatomy
"2 0"- animal lore
"3 0"- item identification
"4 0"- arms lore
"6 0"- begging
"9 0"- peacemaking
"12 0"- cartography
"14 0"- detect hidden
"15 0"- entice
"16 0"- evaluate intelligence
"19 0"- forensic evaluation
"21 0"- hiding
"22 0"- provocation
"23 0"- inscription
"30 0"- poisoning
"32 0"- spirit speak
"33 0"- stealing
"35 0"- taming
"36 0"- taste identification
"38 0"- tracking
0x56 (V) - Macro'd Spell
BYTE[blockSize-4] Spell (null terminated strings)
"2"- Create Food
"3"- Feeblemind
"4"- Heal
"5"- Magic Arrow
"6"- Night Sight
"7"- Reactive Armor
"8"- Weaken
"9"- Agility
"10"- Cunning
"11"- Cure
"12"- Harm
"13"- Magic Trap
"14"- Magic Untrap
"15"- Protection
"16"- Strength
"17"- Bless
"18"- Fireball
"19"- Magic Lock
"20"- Poison
"21"- Telekenisis
"22"- Teleport
"23"- Unlock
"24"- Wall of Stone
"25"- Arch Cure
"26"- Arch Protection
"27"- Curse
"28"- Fire Field
"29"- Greater Heal
"30"- Lightning
"31"- Mana Drain
"32"- Recall
"33"- Blade Spirit
"34"- Dispel Field
"35"- Incognito
"36"- Reflection
"37"- Mind Blast
"38"- Paralyze
"39"- Poison Field
"40"- Summon Creature
"41"- Dispel
"42"- Energy Bolt
"43"- Explosion
"44"- Invisibility
"45"- Mark
"46"- Mass Curse
"47"- Paralyze Field
"48"- Reveal
"49"- Chain Lightning
"50"- Energy Field
"51"- Flame Strike
"52"- Gate
"53"- Mana Vampire
"54"- Mass Dispel
"55"- Meteor Shower
"56"- Polymorph
"57"- Earthquake
"58"- Energy Vortex
"59"- Ressurection
"60"- Summon Air Elemental
"61"- Summon Daemon
"62"- Summon Earth Elemental
"63"- Summon Fire Elemental
"64"- Summon Water Elemental
0x58 (X) - Open Door
BYTE null termination (0x00)
0xc7 - action
BYTE[blockSize-4] Action (null terminated strings)
"bow"
"salute"


=========={Drop - Wear Item [0x13]---
Drop->Wear Item (10 bytes)
BYTE cmd
BYTE[4] itemid
BYTE layer (see layer list at top)
BYTE[4] playerID

Note: The layer byte should not be trusted.

=========={Object Information [0x1A]-----
Object Information (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] itemID
BYTE[2] model #
if (itemID & 0x80000000)
BYTE[2] item count (or model # for corpses)
if (model & 0x8000)
BYTE Incr Counter (increment model by this #)
BYTE[2] xLoc (only use lowest significant 15 bits)
BYTE[2] yLoc
if (xLoc & 0x8000)
BYTE direction
BYTE zLoc
if (yLoc & 0x8000)
BYTE[2] dye
if (yLoc & 0x4000)
BYTE flag byte (See Apendix)


=========={Char Location and body type [0x1B]---
Char Location and body type (37 bytes)
BYTE cmd
BYTE[4] player id
BYTE[4] unknown1
BYTE[2] bodyType
BYTE[2] xLoc
BYTE[2] yLoc
BYTE[2] zLoc
BYTE direction
BYTE[2] unknown2
BYTE[4] unknown3 (usually has FF somewhere in it)
BYTE[4] unknown4
BYTE flag byte
BYTE highlight color
BYTE[7] unknown5


=========={Send Speech [0x1C]---
Send Speech (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] itemID (FF FF FF FF = system)
BYTE[2] model (item hex # - FF FF = system)
BYTE Type
BYTE[2] Text Color
BYTE[2] Font
BYTE[30] Name
BYTE[?] Null-Terminated Message (? = blockSize - 44)


=========={Delete object [0x1D]-----
Delete object (5 bytes)
BYTE cmd
BYTE[4] item/char id


=========={PACKET\_ANIMATE [0x1E]---
Unknown packet (4 bytes)
BYTE cmd
BYTE[3] unknown


=========={PACKET\_EXPLODE [0x1F]---
Unknown packet (8 bytes)
BYTE cmd
BYTE [7] unknown



=========={Draw Game Player [0x20]---
Draw Game Player (19 bytes)
BYTE cmd
BYTE[4] creature id
BYTE[2] bodyType
BYTE unknown1 (0)
BYTE[2] skin color / hue
BYTE flag byte
BYTE[2] xLoc
BYTE[2] yLoc
BYTE[2] unknown2 (0)
BYTE direction
BYTE zLoc


Note: Only used with the character being played by the client.


=========={Character Move Reject [0x21]---
Message sent by server when a movement request is rejected. 


Character Move Reject (8 bytes)
BYTE cmd
BYTE sequence #
BYTE[2] xLoc
BYTE[2] yLoc
BYTE direction
BYTE zLoc


=========={Character Move ACK/ Resync Request [0x22]---
Character Move ACK/ Resync Request(3 bytes)
BYTE cmd
BYTE sequence (matches sent sequence)
BYTE (0x00)


=========={Dragging of Items [0x23]---
Dragging of Items (26 bytes)
BYTE cmd
BYTE[2] model #
BYTE[3] unknown1
BYTE[2] stack count
BYTE[4] Source ID
BYTE[2] Source xLoc
BYTE[2] Source yLoc
BYTE Source zLoc
BYTE[4] Target id
BYTE[2] Target xLoc
BYTE[2] Target yLoc
BYTE Target zLoc


=========={Draw Container [0x24]---
Draw Container (7 bytes)
BYTE cmd
BYTE[4] item id
BYTE[2] model-Gump
0x003c = backpack


=========={Add Item to Container [0x25]---
Add Item to Container (20 bytes)
BYTE cmd
BYTE[4] item id to add
BYTE[2] model
BYTE unknown1 (0)
BYTE[2] # of items
BYTE[2] xLoc in container
BYTE[2] yLoc in container
BYTE[4] itemID of container
BYTE[2] color


=========={Kick Player [0x26]---
Kick Player (5 bytes)
BYTE cmd
BYTE[4] ID of GM who issued kick?

Note: Server Message

=========={Reject Request to move Items [0x27]---
Kick Player (5 bytes)
BYTE cmd
BYTE[4] ID of GM who issued kick?

Note: Server Message

=========={Clear Square [0x28]---
Clear Square (5 bytes)
BYTE cmd
BYTE[2] xLoc
BYTE[2] yLoc

Note: Server Message

=========={Paperdoll Clothing Added [0x29]---
Paperdoll Clothing Added(1 bytes)
BYTE cmd

Note: Server Message

=========={PACKET\_BLOOD [0x2A]---
Unknown packet (5 bytes)
BYTE cmd
BYTE[4]


=========={Toggle GodMode Reply [0x2B]-
Server packet.

Toggle GodMode Reply (2 bytes)
BYTE cmd
BYTE godmode (0 - off, 1 - on)


=========={Resurrection Menu Choice [0x2C]-
Client and Server message.
Note: Resurrection menu has been removed from UO, thus, this message is
currently unused.

Resurrection Menu Choice (2 bytes)
BYTE cmd
BYTE action (2=ghost, 1=resurrect, 0=from server)
Note: Resurrection menu has been removed from UO.


=========={PACKET\_HEALTH [0x2D]---
Unknown packet (17 bytes)
BYTE cmd
BYTE[16] unknown



=========={Worn Item [0x2E]---
Worn Item (15 bytes)
BYTE cmd
BYTE[4] itemid (always starts 0x40 in my data)
BYTE[2] model (item hex #)
BYTE (0x00)
BYTE layer
BYTE[4] playerID
BYTE[2] color/hue


=========={Fight Occurring [0x2F]---
This packet is sent when there is a fight going on somewhere on screen.


Fight Occurring (10 bytes)
BYTE cmd
BYTE unknown1 (0)
BYTE[4] ID of attacker
BYTE[4] ID of attacked


=========={Pause/Resume Client [0x33]---
Pause/Resume Client (2 bytes)
BYTE cmd
BYTE pause/resume (0=pause, 1=resume)


=========={Get Player Status [0x34]---
Get Player Status (10 bytes)
BYTE cmd
BYTE[4] pattern (0xedededed)
BYTE getType
0x04 - Basic Stats (Packet 0x11 Response)
0x05 = Request Skills (Packet 0x3A Response)
BYTE[4] playerID


=========={Send Skills/Lock state [0x3A]---
Server Version - Send Skills (Variable)
BYTE cmd
BYTE[2] blockSize
BYTE Type (0x00= full list, 0xFF = single skill update)
Repeat next until done - 46 skills
BYTE[2] id # of skill (0x01 - 0x2e)
BYTE[2] skill Value * 10
BYTE[2] Unmodified Value * 10
BYTE skillLock (0=up, 1=down, 2=locked)
BYTE[2] null (00 00)  (ONLY IF TYPE == 0x00)


Note: Can also send just one skill, to update that skill.


Client Version - Set Skill Lock (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[2] id# of skill
BYTE skillLock (0=up, 1=down, 2=locked)


=========={Buy Item(s) [0x3B]---
Buy Item(s) (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] vendorID
BYTE flag
0x00 - no items following
0x02 - items following
For each item
BYTE (0x1A)
BYTE[4] itemID (from 3C packet)
BYTE[2] # bought


=========={Items in Container [0x3C]---
Items in Container (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[2] # of Item segments
Item Segments:
BYTE[4] itemID
BYTE[2] model
BYTE unknown1 (0x00)
BYTE[2] # of items in stack
BYTE[2] xLoc
BYTE[2] yLoc
BYTE[4] Container ItemID
BYTE[2] color


=========={Personal Light Level [0x4E]---
Personal Light Level (6 bytes)
BYTE cmd
BYTE[4] creature id
BYTE level


=========={Overall Light Level [0x4F]---
Overall Light Level (2 bytes)
BYTE cmd
BYTE level
0x00 - day
0x09 - OSI night
0x1F - Black
Max normal val = 0x1F


=========={Idle Warning [0x53]-
Displays a pre-defined message in client.

Idle Warning(2 bytes)
BYTE cmd
BYTE msgid 

Possible values for msgid are:
\begin{itemize-
\item 0x01 - no character
\item 0x02 - char exists
\item 0x03 - can't connect
\item 0x04 - can't connect
\item 0x05 - character already in world
\item 0x06 - login problem
\item 0x07 - idle
\item 0x08 - can't connect
\end{itemize-----
=========={Play Sound Effect [0x54]---
Play Sound Effect (12 bytes)
BYTE cmd
BYTE mode (0x00=quiet, repeating, 0x01=single normally played sound effect)
BYTE[2] SoundModel
BYTE[2] unknown3 (speed/volume modifier? Line of sight stuff?)
BYTE[2] xLoc
BYTE[2] yLoc
BYTE[2] zLoc


=========={Login Complete, start game [0x55]---
Login Complete, Start Game (1 byte)
BYTE cmd


=========={Plot Course [0x56]-
Plot course for ships

BYTE cmd
BYTE[2] Serial
BYTE action (1 - add, 5 - delete, 6 - toggle edit)
BYTE Pin number
WORD Pin X
WORD Pin Y


=========={Time [0x5B]---
Time (4 bytes)
BYTE cmd
BYTE hour
BYTE minute
BYTE second
\end{veratim---
=========={Login Character [0x5D]---
Login Character (73 bytes)
BYTE cmd
BYTE[4] pattern1 (0xedededed)
BYTE[30] char name
BYTE[30] char password
BYTE[4] slot choosen (0-based)
BYTE[4] clientIP

Note: ClientIP should not be trusted.

=========={Set Weather [0x65]---
Set Weather (4 bytes)
BYTE cmd
BYTE type
        0x00 - "It starts to rain"
        0x01 - "A fierce storm approaches."
        0x02 - "It begins to snow"
        0x03 - "A storm is brewing.",
        0xFF - None (turns off sound effects),
        0xFE (no effect?? Set temperature?)
BYTE num (number of weather effects on screen)
BYTE temperature


Note: Temperature has no effect at present.
Note: maximum number of weather effects on screen is 70.
Note: If it is raining, you can add snow by setting the num to the num of
rain currently going, plus the number of snow you want.
Note: Weather messages are only displayed when weather starts.
Note: Weather will end automatically after 6 minutes without any weather
change packets.
Note: You can totally end weather (to display a new message) by teleporting.
I think it's either the 0x78 or 0x20 messages that reset it, though I haven't
checked to be sure (other possibilities, 0x4F or 0x4E)


=========={Book - Page [0x66]---
Books - Page (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] bookID
BYTE[2] # of pages in this packet (when requesting always requests 1)
For each page:
        BYTE[2] page number
        BYTE[2] number of lines on page
                Server -> (-1 = no lines)
                Client -> (-1 = request page)   (No longer used)
                Client -> (> 0 = write page)
        Repeated for each line:
                BYTE[var] null terminated line

Note: Number of lines on page is always -1 for page requests

=========={Targeting Cursor Commands [0x6C]---
Targeting Cursor Commands (19 bytes)
BYTE cmd
BYTE type
        0x00 = Select Object
        0x01 = Select X, Y, Z
BYTE[4] cursorID
BYTE Cursor Type
        Always 0 now
The following are always sent but are only valid if sent by client
BYTE[4] Clicked On ID
BYTE[2] click xLoc
BYTE[2] click yLoc
BYTE unknown (0x00)
BYTE click zLoc
BYTE[2] model # (if a static tile, 0 if a map/landscape tile)


Note: the model number shouldn't be trusted.

=========={Play Midi Music [0x6D]---
Play Midi Music (3 bytes)
BYTE cmd
BYTE[2] musicID


=========={Character Animation [0x6E]---
Character Animation (14 bytes)
BYTE cmd
BYTE[4] item/char ID
BYTE[2] movement model
        0x00 = walk
        0x01 = walk faster
        0x02 = run
        0x03 = run (faster?)
        0x04 = nothing
        0x05 = shift shoulders
        0x06 = hands on hips
        0x07 = attack stance (short)
        0x08 = attack stance (longer)
        0x09 = swing (attack with knife)
        0x0a = stab (underhanded)
        0x0b = swing (attack overhand with sword)
        0x0c = swing (attack with sword over and side)
        0x0d = swing (attack with sword side)
        0x0e = stab with point of sword
        0x0f = ready stance
        0x10 = magic (butter churn!)
        0x11 = hands over head (balerina)
        0x12 = bow shot
        0x13 = crossbow
        0x14 = get hit
        0x15 = fall down and die (backwards)
        0x16 = fall down and die (forwards)
        0x17 = ride horse (long)
        0x18 = ride horse (medium)
        0x19 = ride horse (short)
        0x1a = swing sword from horse
        0x1b = normal bow shot on horse
        0x1c = crossbow shot
        0x1d = block #2 on horse with shield
        0x1e = block on ground with shield
        0x1f = swing, and get hit in middle
        0x20 = bow (deep)
        0x21 = salute
        0x22 = scratch head
        0x23 = 1 foot forward for 2 secs
        0x24 = same
BYTE unknown1 (0x00)
BYTE direction
BYTE[2] repeat (1 = once / 2 = twice / 0 = repeat forever)
BYTE forward/backwards(0x00=forward, 0x01=backwards)
BYTE repeat Flag (0 - Don't repeat / 1 repeat)
BYTE frame Delay (0x00 - fastest / 0xFF - Too slow to watch)


=========={Secure Trading [0x6F]---
Secure Trading (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE action
BYTE[4] id1
BYTE[4] id2
BYTE[4] id3
BYTE nameFollowing (0 or 1)
If (nameFollowing = 1)
BYTE[?] charName



=========={Graphical Effect [0x70]---
Graphical Effect (28 bytes)
BYTE cmd
BYTE direction type
        00 = go from source to dest
        01 = lightning strike at source
        02 = stay at current x,y,z
        03 = stay with current source character id
BYTE[4] character id
BYTE[4] target id
BYTE[2] model of the first frame of the effect
BYTE[2] xLoc
BYTE[2] yLoc
BYTE zLoc
BYTE[2] xLoc of target
BYTE[2] yLoc of target
BYTE zLoc of target
BYTE speed of the animation
BYTE duration (0=really long, 1= shortest)
BYTE[2] unknown2 (0 works)
BYTE adjust direction during animation (1=no)
BYTE explode on impact


=========={Bulletin Board Message [0x71]---
Bulletin Board Message (Variable # of bytes)
BYTE cmd
BYTE[2] len
BYTE subcmd
BYTE[len-4] submessage


-----Submessage 0 - Display Bulletin Board-
Server Message.

Submessage 0 - Display Bulletin Board
BYTE[4] BoardID
BYTE[22] board name (default is "bulletin board", the rest nulls)
BYTE[4] ID (0x402000FF)
BYTE[4] zero (0)


-----Submessage 1 - Message Summary-
Server Message.

Submessage 1 - Message Summary
BYTE[4] BoardID
BYTE[4] MessageID
BYTE[4] ParentID (0 if top level)
BYTE posterLen
BYTE[posterLen] poster (null terminated string)
BYTE subjectLen
BYTE[subjectLen] subject (null terminated string)
BYTE timeLen
BYTE[timeLen] time (null terminated string with time of posting) ("Day 1 @ 11:28")


-----Submessage 2 - Message---
Submessage 2 - Message
BYTE[4] BoardID
BYTE[4] MessageID
BYTE posterLen
BYTE[posterLen] poster (null terminated string)
BYTE subjectLen
BYTE[subjectLen] subject (null terminated string)
BYTE timeLen
BYTE[timeLen] time (null terminated string with time of posting) ("Day 1 @ 11:28")
BYTE[29] constant: (01 91 84 0A 06 1E FD 01 0B 15 2E 01 0B 17 0B 01 BB 20 46 04 66 13 F8 00 00 0E 75 00 00)
BYTE numlines
For each line:
        BYTE linelen
        BYTE[linelen] body (null terminated)



-----Submessage 3 - Request Message-
Client Message.

Submessage 3 - Request Message
BYTE[4] BoardID
BYTE[4] MessageID


-----Submessage 4 - Request Message Summary-
Client Message.

Submessage 4 - Request Message Summary
BYTE[4] BoardID
BYTE[4] MessageID


-----Submessage 5 - Post a message-
Client Message.

BYTE[4] BoardID
BYTE[4] Replying to ID (0 if this is a top level / non-reply post)
BYTE subjectLen  (length of the subject, includes null termination)
BYTE[subjectLen] subject (null terminated)
BYTE numlines
For each line:
        BYTE linelen
        BYTE[linelen] body (null terminated)


-----Submessage 6 - Remove Posted Message-
Client Message.

BYTE[4] BoardID
BYTE[4] MessageID


=========={Request War Mode Change/Send War Mode status [0x72]-
Client/Server message, server replies with 0x77 packet

Request War Mode Change/Send War Mode status (5 bytes)
BYTE cmd
BYTE flag
        0x00 - Normal
        0x01 - Fighting
BYTE[3] unknown1 (always 00 32 00 in testing)


=========={Ping message [0x73]---
Ping message (2 bytes)
BYTE cmd
BYTE seq


=========={Open Buy Window [0x74]---
Open Buy Window (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] (vendorID | 0x40000000)
BYTE # of items
# of items worth of item segments
        BYTE[4] price
        BYTE length of text description
        BYTE[text length] item description

NOTE: This packet is always preceded by a describe contents packet (0x3c) with 
the container id as the (vendorID | 0x40000000) and then an open container
packet (0x24?) with the vendorID only and a model number of 0x0030 (probably
the model number for the buy screen)

=========={Rename Character [0x75]---
Rename Character (35 bytes)
BYTE cmd
BYTE[4] id
BYTE[30] new name


=========={New Subserver [0x76]---
New Subserver (16 bytes)
BYTE cmd
BYTE[2] xLoc
BYTE[2] yLoc
BYTE[2] zLoc
BYTE[9] unknown


=========={Update Player [0x77]---
Update Player (17 bytes)
BYTE cmd
BYTE[4] player id
BYTE[2] model
BYTE[2] xLoc
BYTE[2] yLoc
BYTE zLoc
BYTE direction
BYTE[2] hue/skin color
BYTE flag (bit field)
BYTE highlight color


=========={Draw Object [0x78]---
Draw object (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] itemID/playerID
BYTE[2] model (item hex #)
if (itemID & 0x80000000)
        BYTE[2] amount/Corpse Model Num
BYTE[2] xLoc (only 15 lsb)
BYTE[2] yLoc
if (xLoc & 0x8000)
        BYTE direction
BYTE zLoc
BYTE direction
BYTE[2] dye/skin color
BYTE flag
BYTE notoriety (2's complement signed)
if (BYTE[4] == 0x00 0x00 0x00 0x00)
        DONE
else loop this until above if statement is satisified
        BYTE[4] itemID
        BYTE[2] model (item hex # - only 15 lsb)
        BYTE layer
        if (model & 0x8000)
                BYTE[2] hue


=========={Open Dialog Box [0x7C]---
Open Dialog Box (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] dialogID (echo'd back to the server in 7d)
BYTE[2] menuid (echo'd back to server in 7d)
BYTE length of question
BYTE[length of question] question text
BYTE # of responses
Then for each response:
        BYTE[2] model id # of shown item (if grey menu -- then always 0x00 as msb)
        BYTE[2] unknown2 (00 00 check or not?)
        BYTE response text length
        BYTE[response text length] response text


=========={Client response to Dialog [0x7D]---
Client Response To Dialog (13 bytes)
BYTE cmd
BYTE[4] dialogID (echoed back from 7C packet)
BYTE[2] menuid (echoed back from 7C packet)
BYTE[2] 1-based index of choice
BYTE[2] model # of choice
BYTE[2] unknown1 (00 00)


=========={Login Request [0x80]---
Login Request (62 bytes)
BYTE cmd
BYTE[30] userid
BYTE[30] password
BYTE unknown1 (not usually 0x00 - so not NULL)


=========={Login Denied [0x82]---
Login Denied (2 bytes)
BYTE cmd
BYTE why
        0x00 = unknown user
        0x01 = account already in use
        0x02 = account disabled
        0x03 = password bad
        0x04 and higher = communications failed


=========={Delete Character [0x83]---
Delete Character (39 bytes)
BYTE cmd
BYTE[30] password
BYTE[4] charIndex
BYTE[4] clientIP


=========={Resend Characters After Delete [0x86]---
Resend Characters After Delete (304 bytes)
BYTE cmd
BYTE[2] blockSize
BYTE # of characters
Following repeated 5 times
        BYTE[30] character name
        BYTE[30] character password


=========={Open Paperdoll [0x88]---
Open Paperdoll (66 bytes)
BYTE cmd
BYTE[4] charid
BYTE[60] text
BYTE flag byte


=========={Corpse Clothing [0x89]---
Corpse Clothing (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] corpseID
        BYTE itemLayer
        BYTE[4] itemID
BYTE terminator (0x00)
Followed by a 0x3C message with the contents.


=========={Connect to Game Server [0x8C]---
Connect to Game Server (11 bytes)
BYTE cmd
BYTE[4] gameServer IP
BYTE[2] gameServer port
BYTE[4] new key


=========={Map message [0x90]---
Map message(19 bytes)
BYTE cmd
BYTE[4] key used
BYTE[2] gump art id (0x139D)
BYTE[2] upper left x location
BYTE[2] upper left y location
BYTE[2] lower right x location
BYTE[2] lower right y location
BYTE[2] gump width in pixels
BYTE[2] gump height in pixels


=========={Game Server Login [0x91]---
Game Server Login (65 bytes)
BYTE cmd
BYTE[4] key used
BYTE[30] sid
BYTE[30] password


=========={Book - Title Page [0x93]---
Books - Title Page (99 bytes)
BYTE cmd
BYTE[4] bookID
BYTE write flag
        0x00 - non-writable
        0x01 - writable
BYTE new flag
BYTE[2] # of pages
BYTE[60] title
BYTE[30] author


=========={Dye Window [0x95]---
Dye Window (9 bytes)
BYTE cmd
BYTE[4] itemID of dye target
BYTE[2] ignored on send, model on return
BYTE[2] model on send, color on return  (default on server send is 0x0FAB)

NOTE: This packet is sent by both the server and client.

=========={House/Boat Placement [0x99]-
Bring up house/board placement View.

Bring Up House/Boat Placement View (26 bytes)
BYTE cmd
BYTE request (0x01 from server, 0x00 from client)
BYTE[4] ID of deed
BYTE[12] unknown (all 0)
BYTE[2] multi model (item model - 0x4000)
BYTE[6] unknown (all 0)



=========={Console Entry Prompt [0x9A]---
Console Entry Prompt(16 bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] objectID
BYTE[4] prompt#
BYTE[4] 0=request/esc, 1=reply
BYTE[?] textstring (optional)
BYTE terminator (0x00)


=========={Request Help [0x9B]---
Request Help (258 bytes)
BYTE cmd
BYTE[257] (0x00)


=========={Sell List [0x9E]---
Sell List (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] shopkeeperID
BYTE[2] numItems
For each item, a structure containing:
        BYTE[4] itemID
        BYTE[2] itemModel
        BYTE[2] itemHue/Color
        BYTE[2] itemAmount
        BYTE[2] value
        BYTE[2] nameLength
        BYTE[?] name


=========={Sell Reply [0x9F]---
Sell Reply (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] shopkeeperID
BYTE[2] itemCount
For each item, a structure containing:
        BYTE[4] itemID
        BYTE[2] quantity


=========={Select Server[0xA0]---
Select Server (3 bytes)
BYTE cmd
BYTE[2] server # chosen


=========={Update Current Health [0xA1]---
Update Current Health (9 bytes)
BYTE cmd
BYTE[4] playerID
BYTE[2] maxHealth
BYTE[2] currentHealth


=========={Update Current Mana [0xA2]---
Update Current Mana (9 bytes)
BYTE cmd
BYTE[4] playerID
BYTE[2] maxMana
BYTE[2] currentMana


=========={Update Current Stamina [0xA3]---
Update Current Stamina (9 bytes)
BYTE cmd
BYTE[4] playerID
BYTE[2] maxStamina
BYTE[2] currentStamina


=========={Client Machine info [0xA4]---
Spy on Client (149 bytes)
BYTE cmd
BYTE[148] Unknown (previously, this has had info such as your graphics card name,
free HD space, number of processors, etc.)


=========={Open Web Browser [0xA5]---
Open Web Browser (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[blockSize-3] null terminated full web address


=========={Tip/Notice window [0xA6]---
Tips/Notice window (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE flag
        0x00 - tips window
        0x01 - notice window
BYTE[2] unknown1
BYTE[2] tip #
BYTE[2] msgSize
BYTE[?] message (? = blockSize - 10)

*Null terminated I think (Gimli)


=========={Request Tips/Notice [0xA7]---
Request Tips/Notice (4 bytes)
BYTE cmd
BYTE[2] last tip #
BYTE flag
        0x00 - tips window
        0x01 - notice window


=========={Game Server List [0xA8]---
Game Server List (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE System Info Flag
        0xCC - Don't send
        0x64 - Send Video card
        ?? -
BYTE[2] # of servers
Then each server --
        BYTE[2] serverIndex (0-based)
        BYTE[32] serverName
        BYTE percentFull
        BYTE timezone
        BYTE[4] pingIP


=========={Characters/Starting Locations [0xA9]---
Characters / Starting Locations (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE # of characters
Following repeated 5 times
        BYTE[30] character name
        BYTE[30] character password
        BYTE number of starting locations
Following for as many locations as you have
        BYTE locationIndex (0-based)
        BYTE[31] town (general name)
        BYTE[31] exact name


=========={Attack Request Reply [0xAA]---
OK / Not OK To Attack (5 bytes)
BYTE cmd
BYTE[4] CharID being attacked

ID is set to 00 00 00 00 when attack is refused.


=========={Gump Text Entry Dialog [0xAB]---
Gump Text Entry Dialog (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] id
BYTE parentID
BYTE buttonID
BYTE textlen
BYTE[?] text
BYTE cancel (0=disable, 1=enable)
BYTE style (0=disable, 1=normal, 2=numerical)
BYTE[4] format (if style 1, max text len, if style2, max numeric value)
BYTE text2len
BYTE[?] text2


=========={Gump Text Entry Dialog Reply [0xAC]---
Gump Text Entry Dialog Reply (Variable # of bytes)
BYTE cmd
BYTE[2] length
BYTE[4] ID
BYTE type
BYTE index
BYTE[3] unk
BYTE[?] reply


=========={Unicode speech request [0xAD]-
Note: This has been changed recently, the format shown here is the old one.
It will be updated when I get the new format packet details

Unicode speech request (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE Type
BYTE[2] Color
BYTE[2] Font
BYTE[4] Language (Null Terminated)
        "enu"- United States English
BYTE[?][2] Msg - Null Terminated (blockSize - 12)


=========={Unicode Speech message [0xAE]---
Unicode Speech message(Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] ID
BYTE[2] Model
BYTE Type
BYTE[2] Color
BYTE[2] Font
BYTE[4] Language
BYTE[30] Name
BYTE[?][2] Msg - Null Terminated (blockSize - 48)


=========={Display Death Action [0xAF]---
Display Death Action (13 bytes)
BYTE cmd
BYTE[4] player id
BYTE[4] corpse id
BYTE[4] unknown (all 0)


=========={Send Gump Menu Dialog [0xB0]---
Send Gump Menu Dialog (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] id
BYTE[4] gumpid
BYTE[4] x
BYTE[4] y
BYTE[2] command section length
BYTE[?] commands (zero terminated)
BYTE[2] numTextLines
        BYTE[2] text length (in unicode (2 byte) characters.)
        BYTE[?] text (in unicode)


=========={Gump Menu Selection [0xB1]---
Gump Menu Selection (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] id
BYTE[4] gumpid
BYTE[4] choiceid


=========={Chat Message [0xB2]---
Chat Message (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[2] messageType
If message type==0x03EB (Display Enter Username window)
BYTE[8] unknown (all 0's)
If message type==0x03ED (Username accepted, display window)
BYTE[4] unknown (all 0's)
BYTE[?][2] unicode username
BYTE[4] unknown (all 0's)
If message type==0x03E8
BYTE[4] unknown (all 0's)
BYTE[?][2] unicode channel name
BYTE[2] unknown (0x0000)
BYTE[2] unknown (0x0030)
BYTE[2] unknown (0x0000)


=========={Open Chat Window [0xB5]-
This message is very incomplete.  From the server, just know that it is 0xB5
len len, and pass the data through as is appropriate.


Open Chat window (64 bytes)
BYTE cmd
BYTE[63] chatname, if known by client (all 00 if unknown) (name in unicode)


=========={Send Help/Tip Request [0xB6]---
Send Help/Tip Request (9 bytes)
BYTE cmd
BYTE[4] id
BYTE[1] language # (1 for enu)
BYTE[3] language name (enu for English - United states)


=========={Help/Tip Data [0xB7]---
Help/Tip Data (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE[4] id
BYTE[?][2] message, in unicode
BYTE[2] null terminator (0x0000)
BYTE[2] message terminator (0x3300)


=========={Request Char Profile [0xB8]---
Request Char Profile (Variable # of bytes)
BYTE cmd
BYTE[2] blockSize
BYTE mode (CLIENT ONLY! Does not exist in server message.)
BYTE[4] id
If request, ends here.
If Update request
        BYTE[2] cmdType (0x0001 - Update)
        BYTE[2] msglen (# of unicode characters)
        BYTE[msglen][2] new profile, in unicode, not null terminated.
Else If from server
        BYTE[?] character name (not unicode, null terminated.)
        BYTE[2] (0x0000) (a non-unicode title string?)
        BYTE[?][2] profile (in unicode, ? can be 0)
        BYTE[2] (0x0000)
        BYTE[2] terminator (0x3300)


=========={Enable Chat Button [0xB9]-
Server Message.

Enable Chat Button (3 bytes)
BYTE cmd
BYTE unknown (0x00)
BYTE unknown2 (0x01)


=========={Quest Arrow [0xBA]-
Server Message.

Quest Arrow (6 bytes)
BYTE cmd
BYTE active (1=on, 0=off)
BYTE[2] xLoc
BYTE[2] yLoc


=========={Ultima Messenger [0xBB]-
Both client and server message.

Ultima Messenger  (9 bytes)
BYTE cmd
BYTE[4] id1
BYTE[4] id2


=========={Seasonal Information [0xBC]-
Server Message.
If id2 == 1, then this is a season change. If it's a season change the id1 means:
0 - spring
1 - summer
2 - fall
3 - winter
4 - desolation

Seasonal Information(3 bytes)
BYTE cmd
BYTE id1
BYTE id2


=========={Client Version Message [0xBD]-
Client Message.

Client Version Message (Variable # of bytes)
BYTE cmd
BYTE[2] len
BYTE[len-3] string stating the client version (0 terminated)  (like: "1.26.4")


=========={ {Misc. Commands Packet [0xBF]-
This packet is send by both client and server, and starts with a command byte
(0xBF), followed by two bytes for the length.
After that, there is a two byte value which is a subcommand, and the message varies after that.


General Info (5 bytes, plus specific message)
BYTE cmd
BYTE[2] len
BYTE[2] subcmd
BYTE[len-5] submessage


-----Subcommand 1 - Initialize Fast Walk Prevention-
Server Message. This sets up stack on the client and whenever it moves, it takes
the top value from this stack and uses it. (key1 start at the top, key6 at the botton).


Subcommand 1: Initialize Fast Walk Prevention [24 bytes (for 29 total)]
BYTE[4] key1
BYTE[4] key2
BYTE[4] key3
BYTE[4] key4
BYTE[4] key5
BYTE[4] key6


-----Subcommand 2 - Add key to Fast Walk Stack-
Server message. This key is added to the top of the stack. In other words, it's the
one that will be used next. Basically, the other 5 only get used when the client is
sending moves faster than the server is responding.


Subcommand 2: Add key to Fast Walk Stack (4 bytes (for 9 total))
BYTE[4] newkey


-----Subcommand 5 - Unknown-
Client Message.

Subcommand 5: Unknown (8 bytes (for 13 total))
BYTE[4] unknown (00 00 03 20)
BYTE[4] unknown (00 00 00 05)


-----Subcommand 6 - Party System-
Party system is implemented as subsubcommands.

Subcommand 6: Party System (YES! Subsubcommands)
BYTE subsubcommand #


-----Subsubcommand 1 - Add a party member-
Client Message.

Subsubcommand 1: Add a party member (4 bytes)
BYTE[4] id (if 0, a targeting cursor appears)


-----Subsubcommand 1 - Add party member(s)-
Client Message.

Subsubcommand 1: Add party member(s) (1+ numMembers*4)
BYTE numMembers (total number of members in the party)
Then, for each member in numMembers:
        BYTE[4] id


-----Subsubcommand 2 - Remove a party member-
When it's Client Message:

Subsubcommand 2: Remove a party member (4 bytes)
BYTE[4] id (if 0, a targeting cursor appears)

When it's a Server Message:

Subsubcommand 2: Remove a party member (? Bytes)
BYTE numMembers (total number of members in the new party)
BYTE[4] idofPlayerRemoved
Then, for each member in numMembers:
BYTE[4] id


-----Subsubcommand 3 - Send a message to party member-
Client and Server message.

Subsubcommand 3: Tell party member a message (Variable # of bytes)
BYTE[4] id (of target, from client, of source, from server)
BYTE[n][2] Null terminated Unicode message.


-----Subsubcommand 4 - Send a message to all party members-
Client message:

Subsubcommand 4: Tell full party a message (Variable # of bytes)
BYTE[n][2] Null terminated Unicode message.


Server message:

Subsubcommand 4: Tell full party a message (Variable # of bytes)
BYTE[4] id (of source)
BYTE[n][2] Null terminated Unicode message.


-----Subsubcommand 6 - Party can loot me-
Client message.

Subsubcommand 6: Party Can Loot Me?  (1 byte)
BYTE canloot (0=no, 1=yes)


-----Subsubcommand 8 - Accept join party invitation-
Client message

Subsubcommand 8: Accept join party invitation (4 bytes)
BYTE[4] id (party leader's id)


-----Subsubcommand 9 - Decline join party invitation-
Client message

Subsubcommand 9: Decline join party invitation (4 bytes)
BYTE[4] id (party leader's id)


-----Subcommand 8 - Set cursor hue-
Server message.


Subcommand 8: Set cursor hue (1 byte (for 6 total))
BYTE hue  (0 = Felucca, unhued.  1 = Trammel, hued gold)


-----Subcommand 11 - Client language-
Client message.


Subcommand 11: Client Language (3 bytes (for 8 total)) 
BYTE[3] language  (ENU, for English)


-----Subcommand 12 - Closed Status Gump-
Server Message


Subcommand 12: Closed Status Gump (4 bytes (for 8 total))
BYTE[4] id (character id)


=========={Predefined Message [0xC1]-
Server Message


Predefined Message (Variable # of bytes (always 0x32 at present))
BYTE cmd
BYTE[2] len (0x32)
BYTE[4] id
BYTE[2] body
BYTE type (6 - lower left, 7 on player)
BYTE[2] hue
BYTE[2] font
BYTE[2] type (0x0007 so far)
BYTE[2] message number (0xA120 base)
        0xA12D - "You cannot use skills."
        0xA2E2 - "But that's not dead!"
        0xA5F3 - "Help request aborted."
        0xA5F0 - "Please enter a brief description (up to 40 characters) of
                  your problem:"
BYTE[0x20] - speaker's name



------------------------{Patch Server Protocol---
Connectiong to the patch server and issuing requests mst follow a specific order.
First it connectes to compassion.owo.com:8888 (this can be changed in vercfg file).
Then send a HelloRequest. The server will respond with a PatchServerTransfer.
Disconnect from compassion and connectto the IP address and port returned to you.
You will then send a HelloRequest to the new server, it will return a NoticeBlock.

Now once you've connectd to the patch server and gotten the notice, you may start
looking for patches. First, send a PatchListRequest for the first one, read in the
PatchListData, then send the request for the second verson, and read in that data.

Once you have a list of avaliable patches, you can request the actual patch by
sending a PatchDataRequest. You will then receie the PatchData.
When you have finished downloading the avaliable patches, you can apply them,
and resend the PatchListReqiestuntil there aren't any more patches avaliable.

=========={HelloRequest---
Hello Request (4 bytes)
BYTE 0x15
BYTE 0x00
BYTE 0x00
BYTE 0x00


=========={PatchServerTransfer---
Patch Server Transfer (16 bytes)
BYTE 0x01
BYTE[7] (all bytes 0x00)
BYTE[4] IP Address
BYTE[4] Port


=========={NoticeBlock---
Notice Block (variable length)
BYTE 0x01
BYTE[3] (all bytes 0x00)
BYTE 0x01
BYTE[3] (all bytes 0x00)
BYTE 0x02
BYTE[3] (all bytes 0x00)
BYTE[4] Text Length
BYTE[textlength] Notice Data (NULL Terminated)


=========={PatchListRequest---
Patch List Request (variable length)
BYTE 0x01
BYTE[3] (all bytes 0x00)
BYTE[4] Version Text Lenght
BYTE[textlength] VersionText (ie. Win32_UO_Gold)
BYTE[4] Version


=========={PatchListData---
Patch List Data (variable length)
Repeat until done:
        BYTE[4] File name Length (0 = done)
        BYTE[filenamelength] Filename
        BYTE[4] File size


=========={PatchDataRequest---
Patch Data Request (variable length)
BYTE 0x02
BYTE[3] (all bytes 0x00)
BYTE[4] Filename length
BYTE[filenamelength] Filename
BYTE[4] (all bytes 0x00)


=========={PatchData---
BYTE[4] File name length
BYTE[filenamelength] File name
BYTE[4] File size
Repeat until done:
        BYTE[4] Block Length (0 = done)
        BYTE[blocklength] Block Data

