1911 lines
388 KiB
HTML
1911 lines
388 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="description" content="Network packet documentation for the Ultima Online Server Emulator ModernUO">
|
|
<meta name="author" content="ModernUO Development Team">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
|
<link rel="icon" href="https://modernuo.com/branding/favicon.png">
|
|
<title>ModernUO Packet Documentation</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&family=Roboto+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
<script src="https://cdn.tailwindcss.com/3.4.1?plugins=typography@0.5.10"></script>
|
|
<script>
|
|
tailwind.config = {
|
|
theme: {
|
|
extend: {
|
|
fontFamily: {
|
|
mono: ['Roboto Mono', 'monospace'],
|
|
},
|
|
colors: {
|
|
"modern-black": "#212121",
|
|
"modern-black-hover": "#2F2F2F",
|
|
"modern-dark-black": "#1A1A1A",
|
|
"incoming": "#3b82f6",
|
|
"outgoing": "#22c55e",
|
|
"both": "#a855f7",
|
|
gold: {
|
|
50: "#fbf3ee",
|
|
100: "#f8e9dd",
|
|
200: "#f0d9bd",
|
|
300: "#e8cea1",
|
|
400: "#dfc688",
|
|
500: "#d5bf74",
|
|
600: "#cab664",
|
|
700: "#bdab58",
|
|
800: "#b09f4f",
|
|
900: "#a29147",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
<style>
|
|
/* Mobile viewport fix: 100vh doesn't account for browser chrome/gesture nav */
|
|
.h-dvh {
|
|
height: 100vh; /* fallback for older browsers */
|
|
height: 100dvh; /* dynamic viewport height - adjusts for browser chrome */
|
|
}
|
|
|
|
/* Safe area insets for edge-to-edge phones (notches, gesture nav) */
|
|
@supports (padding-bottom: env(safe-area-inset-bottom)) {
|
|
.safe-area-bottom {
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
}
|
|
}
|
|
|
|
.packet-list::-webkit-scrollbar {
|
|
width: 8px;
|
|
}
|
|
.packet-list::-webkit-scrollbar-track {
|
|
background: #1A1A1A;
|
|
}
|
|
.packet-list::-webkit-scrollbar-thumb {
|
|
background: #404040;
|
|
border-radius: 4px;
|
|
}
|
|
.packet-list::-webkit-scrollbar-thumb:hover {
|
|
background: #525252;
|
|
}
|
|
.field-row:nth-child(even) {
|
|
background-color: rgba(255, 255, 255, 0.02);
|
|
}
|
|
.loop-field {
|
|
border-left: 2px solid #d5bf74;
|
|
margin-left: 1rem;
|
|
padding-left: 0.75rem;
|
|
}
|
|
select {
|
|
appearance: none;
|
|
-webkit-appearance: none;
|
|
-moz-appearance: none;
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23d5bf74' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
|
|
background-repeat: no-repeat;
|
|
background-position: right 0.75rem center;
|
|
padding-right: 2rem;
|
|
}
|
|
.client-badge {
|
|
font-size: 0.65rem;
|
|
padding: 1px 4px;
|
|
border-radius: 3px;
|
|
font-weight: 500;
|
|
}
|
|
.client-cc { background: rgba(59, 130, 246, 0.3); color: #93c5fd; }
|
|
.client-ec { background: rgba(168, 85, 247, 0.3); color: #d8b4fe; }
|
|
</style>
|
|
</head>
|
|
|
|
<body class="bg-modern-dark-black text-gold-300 font-sans h-dvh overflow-hidden safe-area-bottom">
|
|
<div id="app" class="h-dvh flex flex-col">
|
|
<!-- Header -->
|
|
<header class="bg-modern-black p-3 md:p-4 shadow-lg border-b border-gold-500/30">
|
|
<div class="max-w-7xl mx-auto flex items-center justify-between gap-2">
|
|
<div class="flex items-center space-x-2 md:space-x-4 min-w-0">
|
|
<img src="https://modernuo.com/branding/logo.svg" class="h-8 w-8 md:h-12 md:w-12 flex-shrink-0">
|
|
<div class="min-w-0">
|
|
<h1 class="text-white text-base md:text-xl font-medium">
|
|
<span class="md:hidden">Packet Documentation</span>
|
|
<span class="hidden md:inline">ModernUO Packet Documentation</span>
|
|
</h1>
|
|
<p class="text-gold-500/70 text-xs md:text-sm hidden sm:block">Ultima Online Network Protocol Reference</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center space-x-2 md:space-x-4 flex-shrink-0">
|
|
<button id="typeLegendBtn" class="px-2 md:px-3 py-1.5 text-sm bg-modern-dark-black text-gold-400 rounded border border-gold-500/30 hover:border-gold-500 hover:bg-gold-500/10 transition-colors flex items-center space-x-1.5">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
|
<span class="hidden sm:inline">Types</span>
|
|
</button>
|
|
<span id="packetCount" class="text-gold-500/70 text-xs md:text-sm whitespace-nowrap"></span>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Main Content -->
|
|
<div class="flex-1 flex overflow-hidden min-h-0">
|
|
<!-- Left Panel: Packet List -->
|
|
<aside id="sidebar" class="w-full md:w-80 bg-modern-black border-r border-gold-500/30 flex flex-col overflow-hidden">
|
|
<!-- Search & Filter -->
|
|
<div class="p-3 border-b border-gold-500/20 space-y-2">
|
|
<!-- Collapse button for medium screens -->
|
|
<div class="hidden md:flex xl:hidden justify-end -mt-1 -mr-1 mb-1">
|
|
<button id="collapseSidebarBtn" class="p-1 text-gold-500/70 hover:text-gold-500 transition-colors" title="Collapse sidebar">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 19l-7-7 7-7m8 14l-7-7 7-7"></path></svg>
|
|
</button>
|
|
</div>
|
|
<input
|
|
type="text"
|
|
id="searchInput"
|
|
placeholder="Search packets (ID, name, field)..."
|
|
class="w-full bg-modern-dark-black text-gold-300 placeholder-gold-500/50 px-3 py-2 rounded border border-gold-500/30 focus:outline-none focus:border-gold-500 text-sm"
|
|
>
|
|
<div class="flex space-x-1">
|
|
<button data-filter="all" class="filter-btn flex-1 px-2 py-1 text-xs rounded bg-gold-500 text-modern-black font-medium">All</button>
|
|
<button data-filter="incoming" class="filter-btn flex-1 px-2 py-1 text-xs rounded bg-modern-dark-black text-incoming border border-incoming/50 hover:bg-incoming/20">In</button>
|
|
<button data-filter="outgoing" class="filter-btn flex-1 px-2 py-1 text-xs rounded bg-modern-dark-black text-outgoing border border-outgoing/50 hover:bg-outgoing/20">Out</button>
|
|
<button data-filter="both" class="filter-btn flex-1 px-2 py-1 text-xs rounded bg-modern-dark-black text-both border border-both/50 hover:bg-both/20">Both</button>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<button id="toggleTagsBtn" class="md:hidden text-gold-500/70 text-xs flex items-center gap-1 hover:text-gold-400">
|
|
<span>Tags</span>
|
|
<svg id="toggleTagsIcon" class="w-3 h-3 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
|
|
</button>
|
|
<span class="text-gold-500/70 text-xs flex-shrink-0 hidden md:inline">Tags:</span>
|
|
<button id="clearTagsBtn" class="text-xs px-2 py-0.5 rounded bg-modern-dark-black text-gold-500/70 border border-gold-500/30 hover:border-gold-500 hover:text-gold-400 hidden">Clear</button>
|
|
</div>
|
|
<div id="tagFilter" class="hidden md:flex flex-wrap gap-1 max-h-32 overflow-y-auto">
|
|
<!-- Tags will be populated by JavaScript -->
|
|
</div>
|
|
|
|
<!-- Client Type Filter -->
|
|
<div class="flex items-center gap-2 mt-2">
|
|
<span class="text-gold-500/70 text-xs flex-shrink-0">Client:</span>
|
|
</div>
|
|
<div class="flex space-x-1 mt-1">
|
|
<button data-client="all" class="client-btn flex-1 px-2 py-1 text-xs rounded bg-gold-500 text-modern-black font-medium">All</button>
|
|
<button data-client="classic" class="client-btn flex-1 px-2 py-1 text-xs rounded bg-modern-dark-black text-blue-400 border border-blue-500/50 hover:bg-blue-500/20">Classic</button>
|
|
<button data-client="enhanced" class="client-btn flex-1 px-2 py-1 text-xs rounded bg-modern-dark-black text-purple-400 border border-purple-500/50 hover:bg-purple-500/20">Enhanced</button>
|
|
</div>
|
|
|
|
<!-- Version Filter -->
|
|
<div class="mt-2">
|
|
<input
|
|
type="text"
|
|
id="versionInput"
|
|
placeholder="Version (e.g., 7.0.9.0)"
|
|
class="w-full bg-modern-dark-black text-gold-300 placeholder-gold-500/50 px-3 py-1.5 rounded border border-gold-500/30 focus:outline-none focus:border-gold-500 text-xs font-mono"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Packet List -->
|
|
<div id="packetList" class="packet-list flex-1 overflow-y-auto min-h-0">
|
|
<!-- Populated by JavaScript -->
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Expand sidebar button (shown when collapsed on medium screens) -->
|
|
<button id="expandSidebarBtn" class="hidden bg-modern-black border-r border-gold-500/30 px-2 py-4 text-gold-500/70 hover:text-gold-500 hover:bg-modern-black-hover transition-colors" title="Expand sidebar">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 5l7 7-7 7M5 5l7 7-7 7"></path></svg>
|
|
</button>
|
|
|
|
<!-- Right Panel: Packet Details -->
|
|
<main id="detailPanel" class="hidden md:block flex-1 overflow-y-auto bg-modern-dark-black">
|
|
<div id="packetDetails" class="p-4 md:p-6 max-w-4xl mx-auto">
|
|
<!-- Mobile back button -->
|
|
<button id="mobileBackBtn" class="md:hidden flex items-center space-x-2 text-gold-500 hover:text-gold-400 mb-4 -ml-1">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
|
|
<span>Back to list</span>
|
|
</button>
|
|
|
|
<!-- Welcome message when no packet selected -->
|
|
<div id="welcomeMessage" class="text-center py-16">
|
|
<div class="text-gold-500/50 text-6xl mb-4">📦</div>
|
|
<h2 class="text-gold-500 text-xl mb-2">Select a Packet</h2>
|
|
<p class="text-gold-500/70">Choose a packet from the list to view its documentation.</p>
|
|
<p class="text-gold-500/50 text-sm mt-4">Use the search box to find packets by ID (0x02), name, or field names.</p>
|
|
</div>
|
|
|
|
<!-- Packet detail content (hidden by default) -->
|
|
<div id="packetContent" class="hidden">
|
|
<!-- Header -->
|
|
<div class="flex items-start justify-between mb-6">
|
|
<div>
|
|
<div class="flex items-center space-x-3 mb-2">
|
|
<span id="detailId" class="font-mono text-2xl text-white"></span>
|
|
<span id="detailSubId" class="font-mono text-lg text-gold-500/70 hidden"></span>
|
|
<span id="detailDirection" class="px-2 py-0.5 rounded text-xs font-medium uppercase"></span>
|
|
</div>
|
|
<h2 id="detailName" class="text-xl text-gold-500 font-medium"></h2>
|
|
</div>
|
|
<a id="sourceLink" href="#" target="_blank" class="flex items-center space-x-1 text-sm text-gold-500/70 hover:text-gold-500 transition-colors" title="View Source on GitHub">
|
|
<svg class="w-5 h-5 md:w-4 md:h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
|
<span class="hidden md:inline">View Source</span>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Description -->
|
|
<p id="detailDescription" class="text-gold-300/90 mb-6 leading-relaxed"></p>
|
|
|
|
<!-- Size Info -->
|
|
<div class="bg-modern-black rounded-lg p-4 mb-6 border border-gold-500/20">
|
|
<div class="flex items-center space-x-6">
|
|
<div>
|
|
<span class="text-gold-500/70 text-sm">Size:</span>
|
|
<span id="detailSize" class="text-white font-mono ml-2"></span>
|
|
</div>
|
|
<div id="detailDynamic" class="hidden">
|
|
<span class="px-2 py-0.5 bg-gold-500/20 text-gold-500 rounded text-xs">Dynamic Length</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Client Version Requirements -->
|
|
<div id="clientVersionSection" class="bg-modern-black rounded-lg p-4 mb-6 border border-gold-500/20 hidden">
|
|
<h3 class="text-gold-500 font-medium mb-3">Client Version Requirements</h3>
|
|
<div id="clientVersionContent" class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
|
<!-- Populated by JavaScript -->
|
|
</div>
|
|
<div id="clientVersionNotes" class="mt-3 text-gold-500/70 text-sm italic hidden"></div>
|
|
</div>
|
|
|
|
<!-- Fields Table -->
|
|
<div id="fieldsSection" class="mb-6">
|
|
<h3 class="text-gold-500 font-medium mb-3">Packet Structure</h3>
|
|
<div class="bg-modern-black rounded-lg border border-gold-500/20 overflow-x-auto">
|
|
<table class="w-full text-sm table-fixed min-w-[600px]">
|
|
<thead>
|
|
<tr class="bg-gold-500/10 text-gold-500">
|
|
<th class="px-4 py-2 text-left font-medium w-16">Offset</th>
|
|
<th class="px-4 py-2 text-left font-medium w-44">Name</th>
|
|
<th class="px-4 py-2 text-left font-medium w-24">Type</th>
|
|
<th class="px-4 py-2 text-left font-medium w-20">Size</th>
|
|
<th class="px-4 py-2 text-left font-medium">Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="fieldsTable">
|
|
<!-- Populated by JavaScript -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Subpackets (for container packets like 0xBF, 0xD7) -->
|
|
<div id="subpacketsSection" class="mb-6 hidden">
|
|
<h3 class="text-gold-500 font-medium mb-3">Subpackets</h3>
|
|
<div class="bg-modern-black rounded-lg border border-gold-500/20 overflow-x-auto">
|
|
<table class="w-full text-sm min-w-[500px]">
|
|
<thead>
|
|
<tr class="bg-gold-500/10 text-gold-500">
|
|
<th class="px-4 py-2 text-left font-medium w-24">SubID</th>
|
|
<th class="px-4 py-2 text-left font-medium w-20">Direction</th>
|
|
<th class="px-4 py-2 text-left font-medium w-48">Name</th>
|
|
<th class="px-4 py-2 text-left font-medium">Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="subpacketsTable">
|
|
<!-- Populated by JavaScript -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Packet Variants -->
|
|
<div id="variantsSection" class="mb-6 hidden">
|
|
<div class="flex items-center justify-between mb-3">
|
|
<h3 class="text-gold-500 font-medium">Packet Variants</h3>
|
|
<select id="variantSelect" class="bg-modern-black text-gold-300 px-3 py-1 rounded border border-gold-500/30 focus:outline-none focus:border-gold-500 text-sm">
|
|
<option value="">Jump to variant...</option>
|
|
</select>
|
|
</div>
|
|
<div id="variantsList" class="space-y-4">
|
|
<!-- Populated by JavaScript -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Related Packets -->
|
|
<div id="relatedSection" class="mb-6 hidden">
|
|
<h3 class="text-gold-500 font-medium mb-3">Related Packets</h3>
|
|
<div id="relatedPackets" class="space-y-2">
|
|
<!-- Populated by JavaScript -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Floating Back to Top Button -->
|
|
<button id="backToTopBtn" class="hidden fixed bottom-6 right-6 bg-modern-black text-gold-300 px-4 py-2 rounded-lg border border-gold-500/30 hover:border-gold-500 hover:bg-gold-500/10 text-sm transition-all shadow-lg z-50" title="Back to Top">
|
|
↑ Top
|
|
</button>
|
|
|
|
<!-- Notes -->
|
|
<div id="notesSection" class="mb-6 hidden">
|
|
<h3 class="text-gold-500 font-medium mb-3">Notes</h3>
|
|
<p id="detailNotes" class="text-gold-300/80 text-sm bg-modern-black rounded-lg p-4 border border-gold-500/20"></p>
|
|
</div>
|
|
|
|
<!-- Compression Info -->
|
|
<div id="compressionSection" class="mb-6 hidden">
|
|
<h3 class="text-gold-500 font-medium mb-3">Compression</h3>
|
|
<div id="compressionContent" class="text-sm bg-modern-black rounded-lg p-4 border border-gold-500/20">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Plane Format (for house packets) -->
|
|
<div id="planeFormatSection" class="mb-6 hidden">
|
|
<h3 class="text-gold-500 font-medium mb-3">Plane Format</h3>
|
|
<div id="planeFormatContent" class="bg-modern-black rounded-lg border border-gold-500/20 overflow-hidden">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Layout Format -->
|
|
<div id="layoutFormatSection" class="mb-6 hidden">
|
|
<h3 class="text-gold-500 font-medium mb-3">Layout Format</h3>
|
|
<div id="layoutFormatContent" class="bg-modern-black rounded-lg border border-gold-500/20 overflow-hidden">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Strings Format -->
|
|
<div id="stringsFormatSection" class="mb-6 hidden">
|
|
<h3 class="text-gold-500 font-medium mb-3">Strings Format</h3>
|
|
<div id="stringsFormatContent" class="bg-modern-black rounded-lg border border-gold-500/20 overflow-hidden">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Type Legend Modal -->
|
|
<div id="typeLegendModal" class="hidden fixed inset-0 z-50 flex items-center justify-center">
|
|
<div class="absolute inset-0 bg-black/60" id="typeLegendBackdrop"></div>
|
|
<div class="relative bg-modern-black rounded-lg border border-gold-500/30 shadow-2xl max-w-2xl w-full mx-4 max-h-[80vh] overflow-hidden">
|
|
<div class="flex items-center justify-between px-4 py-3 border-b border-gold-500/20">
|
|
<h3 class="text-gold-500 font-medium">Type Legend</h3>
|
|
<button id="typeLegendClose" class="text-gold-500/70 hover:text-gold-500 transition-colors">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
|
|
</button>
|
|
</div>
|
|
<div class="p-4 overflow-y-auto max-h-[calc(80vh-60px)]">
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
|
|
<!-- Integer Types -->
|
|
<div class="bg-modern-dark-black rounded-lg p-3 border border-gold-500/10">
|
|
<h4 class="text-gold-400 font-medium mb-2">Integer Types</h4>
|
|
<div class="space-y-1.5 text-gold-300/80">
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">byte</span><span>Unsigned 8-bit (0-255)</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">sbyte</span><span>Signed 8-bit (-128 to 127)</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">bool</span><span>Boolean (0=false, else true)</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">short</span><span>Signed 16-bit BE</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">ushort</span><span>Unsigned 16-bit BE</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">int</span><span>Signed 32-bit BE</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">uint</span><span>Unsigned 32-bit BE</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">long</span><span>Signed 64-bit BE</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">ulong</span><span>Unsigned 64-bit BE</span></div>
|
|
</div>
|
|
</div>
|
|
<!-- String Types -->
|
|
<div class="bg-modern-dark-black rounded-lg p-3 border border-gold-500/10">
|
|
<h4 class="text-gold-400 font-medium mb-2">String Types</h4>
|
|
<p class="text-gold-500/60 text-xs mb-2">-t suffix = null-terminated</p>
|
|
<div class="space-y-1.5 text-gold-300/80">
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">ascii</span><span>Fixed-length ASCII</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">ascii-t</span><span>Null-terminated ASCII</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">utf8</span><span>Fixed-length UTF-8</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">utf8-t</span><span>Null-terminated UTF-8</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">utf16be</span><span>UTF-16 Big Endian</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">utf16be-t</span><span>Null-term UTF-16 BE</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">utf16le</span><span>UTF-16 Little Endian</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">utf16le-t</span><span>Null-term UTF-16 LE</span></div>
|
|
</div>
|
|
</div>
|
|
<!-- Special Types -->
|
|
<div class="bg-modern-dark-black rounded-lg p-3 border border-gold-500/10">
|
|
<h4 class="text-gold-400 font-medium mb-2">Special Types</h4>
|
|
<div class="space-y-1.5 text-gold-300/80">
|
|
<div class="flex"><span class="font-mono text-green-400 w-20 flex-shrink-0">enum</span><span>Enumerated value</span></div>
|
|
<div class="flex"><span class="font-mono text-purple-400 w-20 flex-shrink-0">bitfield</span><span>Bit flags</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">byte[]</span><span>Byte array</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">bytes</span><span>Variable byte data</span></div>
|
|
</div>
|
|
</div>
|
|
<!-- Structure Types -->
|
|
<div class="bg-modern-dark-black rounded-lg p-3 border border-gold-500/10">
|
|
<h4 class="text-gold-400 font-medium mb-2">Structure Types</h4>
|
|
<div class="space-y-1.5 text-gold-300/80">
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">loop</span><span>Repeated field group</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">array</span><span>Array of elements</span></div>
|
|
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">packet</span><span>Embedded packet</span></div>
|
|
</div>
|
|
</div>
|
|
<!-- Client Indicators -->
|
|
<div class="bg-modern-dark-black rounded-lg p-3 border border-gold-500/10">
|
|
<h4 class="text-gold-400 font-medium mb-2">Client Indicators</h4>
|
|
<p class="text-gold-500/60 text-xs mb-2">Shown when a packet is client-specific</p>
|
|
<div class="space-y-1.5 text-gold-300/80">
|
|
<div class="flex items-center"><span class="client-badge client-cc w-12 text-center flex-shrink-0">CC</span><span class="ml-2">Classic Client only (2D)</span></div>
|
|
<div class="flex items-center"><span class="client-badge client-ec w-12 text-center flex-shrink-0">EC</span><span class="ml-2">Enhanced Client only (EC/KR)</span></div>
|
|
</div>
|
|
<p class="text-gold-500/60 text-xs mt-2">Packets without a badge support both clients.</p>
|
|
</div>
|
|
</div>
|
|
<div class="mt-4 text-xs text-gold-500/60">
|
|
<p><strong>Note:</strong> All multi-byte integers use Big Endian (network) byte order unless otherwise specified.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Hidden data containers -->
|
|
<span id="packets" style="display:none; visibility: hidden">
|
|
{"outgoing":[{"id":"0x0B","name":"Damage","description":"Shows damage dealt to a mobile (client 5.0.0a+).","direction":"outgoing","isDynamic":false,"size":7,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x0B","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Serial of damaged mobile"},{"name":"Damage","type":"ushort","size":2,"description":"Damage amount (clamped 0-65535)"}],"clientVersion":{"classic":{"min":"5.0.0a"},"enhanced":{},"notes":"Used by Enhanced Client (all versions) and Classic Client 5.0.0a+"},"notes":"For pre-5.0.0a clients, use 0xBF/0x22 instead. Enhanced Client always uses this packet format (ushort damage allows values up to 65535).","source":{"file":"Projects/Server/Network/Packets/OutgoingDamagePackets.cs","line":34},"category":"Combat","tags":["Combat"]},{"id":"0x11","name":"Mobile Status","description":"Detailed status information for a mobile. Version 0 (compact) is sent when viewing other mobiles. Versions 3-6 are sent for self based on expansion.","direction":"outgoing","isDynamic":true,"size":"Varies","variants":[{"version":"Version 0 (Compact)","name":"Other Mobile Status","condition":"Viewing another mobile (not self)","size":43,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x11","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"43","description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Name","type":"ascii","size":30,"description":"Mobile name"},{"name":"Hits","type":"short","size":2,"description":"Current hits (normalized 0-100)"},{"name":"Hits Max","type":"short","size":2,"value":"100","description":"Maximum hits (always 100 for normalized)"},{"name":"Can Be Renamed","type":"bool","size":1,"description":"Whether the mobile can be renamed by viewer"},{"name":"Version","type":"byte","size":1,"value":"0","description":"Status version (0 = compact)"}]},{"version":"Version 3 (Basic)","name":"Self Status (Pre-AOS)","condition":"Viewing self, pre-AOS expansion","size":70,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x11","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"70","description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Name","type":"ascii","size":30,"description":"Mobile name"},{"name":"Hits","type":"short","size":2,"description":"Current hits"},{"name":"Hits Max","type":"short","size":2,"description":"Maximum hits"},{"name":"Can Be Renamed","type":"bool","size":1,"description":"Whether the mobile can be renamed"},{"name":"Version","type":"byte","size":1,"value":"3","description":"Status version"},{"name":"Female","type":"bool","size":1,"description":"Gender flag (true = female)"},{"name":"Str","type":"short","size":2,"description":"Strength"},{"name":"Dex","type":"short","size":2,"description":"Dexterity"},{"name":"Int","type":"short","size":2,"description":"Intelligence"},{"name":"Stam","type":"short","size":2,"description":"Current stamina"},{"name":"Stam Max","type":"short","size":2,"description":"Maximum stamina"},{"name":"Mana","type":"short","size":2,"description":"Current mana"},{"name":"Mana Max","type":"short","size":2,"description":"Maximum mana"},{"name":"Gold","type":"int","size":4,"description":"Total gold in backpack"},{"name":"Armor Rating","type":"short","size":2,"description":"Armor rating"},{"name":"Weight","type":"short","size":2,"description":"Current weight (body weight + carried)"},{"name":"Stat Cap","type":"short","size":2,"description":"Total stat cap"},{"name":"Followers","type":"byte","size":1,"description":"Current follower count"},{"name":"Followers Max","type":"byte","size":1,"description":"Maximum follower slots"}]},{"version":"Version 4 (AOS)","name":"Self Status (Age of Shadows)","condition":"Viewing self, AOS expansion","size":88,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x11","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"88","description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Name","type":"ascii","size":30,"description":"Mobile name"},{"name":"Hits","type":"short","size":2,"description":"Current hits"},{"name":"Hits Max","type":"short","size":2,"description":"Maximum hits"},{"name":"Can Be Renamed","type":"bool","size":1,"description":"Whether the mobile can be renamed"},{"name":"Version","type":"byte","size":1,"value":"4","description":"Status version"},{"name":"Female","type":"bool","size":1,"description":"Gender flag (true = female)"},{"name":"Str","type":"short","size":2,"description":"Strength"},{"name":"Dex","type":"short","size":2,"description":"Dexterity"},{"name":"Int","type":"short","size":2,"description":"Intelligence"},{"name":"Stam","type":"short","size":2,"description":"Current stamina"},{"name":"Stam Max","type":"short","size":2,"description":"Maximum stamina"},{"name":"Mana","type":"short","size":2,"description":"Current mana"},{"name":"Mana Max","type":"short","size":2,"description":"Maximum mana"},{"name":"Gold","type":"int","size":4,"description":"Total gold in backpack"},{"name":"Physical Resist","type":"short","size":2,"description":"Physical resistance"},{"name":"Weight","type":"short","size":2,"description":"Current weight"},{"name":"Stat Cap","type":"short","size":2,"description":"Total stat cap"},{"name":"Followers","type":"byte","size":1,"description":"Current follower count"},{"name":"Followers Max","type":"byte","size":1,"description":"Maximum follower slots"},{"name":"Fire Resist","type":"short","size":2,"description":"Fire resistance"},{"name":"Cold Resist","type":"short","size":2,"description":"Cold resistance"},{"name":"Poison Resist","type":"short","size":2,"description":"Poison resistance"},{"name":"Energy Resist","type":"short","size":2,"description":"Energy resistance"},{"name":"Luck","type":"short","size":2,"description":"Luck"},{"name":"Damage Min","type":"short","size":2,"description":"Minimum weapon damage"},{"name":"Damage Max","type":"short","size":2,"description":"Maximum weapon damage"},{"name":"Tithing Points","type":"int","size":4,"description":"Tithing points (for Chivalry)"}]},{"version":"Version 5 (ML)","name":"Self Status (Mondain's Legacy)","condition":"Viewing self, ML expansion","size":91,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x11","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"91","description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Name","type":"ascii","size":30,"description":"Mobile name"},{"name":"Hits","type":"short","size":2,"description":"Current hits"},{"name":"Hits Max","type":"short","size":2,"description":"Maximum hits"},{"name":"Can Be Renamed","type":"bool","size":1,"description":"Whether the mobile can be renamed"},{"name":"Version","type":"byte","size":1,"value":"5","description":"Status version"},{"name":"Female","type":"bool","size":1,"description":"Gender flag (true = female)"},{"name":"Str","type":"short","size":2,"description":"Strength"},{"name":"Dex","type":"short","size":2,"description":"Dexterity"},{"name":"Int","type":"short","size":2,"description":"Intelligence"},{"name":"Stam","type":"short","size":2,"description":"Current stamina"},{"name":"Stam Max","type":"short","size":2,"description":"Maximum stamina"},{"name":"Mana","type":"short","size":2,"description":"Current mana"},{"name":"Mana Max","type":"short","size":2,"description":"Maximum mana"},{"name":"Gold","type":"int","size":4,"description":"Total gold in backpack"},{"name":"Physical Resist","type":"short","size":2,"description":"Physical resistance"},{"name":"Weight","type":"short","size":2,"description":"Current weight"},{"name":"Max Weight","type":"short","size":2,"description":"Maximum carry weight"},{"name":"Race","type":"byte","size":1,"description":"Race ID + 1 (1=Human, 2=Elf, 0=none)"},{"name":"Stat Cap","type":"short","size":2,"description":"Total stat cap"},{"name":"Followers","type":"byte","size":1,"description":"Current follower count"},{"name":"Followers Max","type":"byte","size":1,"description":"Maximum follower slots"},{"name":"Fire Resist","type":"short","size":2,"description":"Fire resistance"},{"name":"Cold Resist","type":"short","size":2,"description":"Cold resistance"},{"name":"Poison Resist","type":"short","size":2,"description":"Poison resistance"},{"name":"Energy Resist","type":"short","size":2,"description":"Energy resistance"},{"name":"Luck","type":"short","size":2,"description":"Luck"},{"name":"Damage Min","type":"short","size":2,"description":"Minimum weapon damage"},{"name":"Damage Max","type":"short","size":2,"description":"Maximum weapon damage"},{"name":"Tithing Points","type":"int","size":4,"description":"Tithing points (for Chivalry)"}]},{"version":"Version 6 (HS)","name":"Self Status (High Seas)","condition":"Viewing self, High Seas expansion with ExtendedStatus","size":121,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x11","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"121","description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Name","type":"ascii","size":30,"description":"Mobile name"},{"name":"Hits","type":"short","size":2,"description":"Current hits"},{"name":"Hits Max","type":"short","size":2,"description":"Maximum hits"},{"name":"Can Be Renamed","type":"bool","size":1,"description":"Whether the mobile can be renamed"},{"name":"Version","type":"byte","size":1,"value":"6","description":"Status version"},{"name":"Female","type":"bool","size":1,"description":"Gender flag (true = female)"},{"name":"Str","type":"short","size":2,"description":"Strength"},{"name":"Dex","type":"short","size":2,"description":"Dexterity"},{"name":"Int","type":"short","size":2,"description":"Intelligence"},{"name":"Stam","type":"short","size":2,"description":"Current stamina"},{"name":"Stam Max","type":"short","size":2,"description":"Maximum stamina"},{"name":"Mana","type":"short","size":2,"description":"Current mana"},{"name":"Mana Max","type":"short","size":2,"description":"Maximum mana"},{"name":"Gold","type":"int","size":4,"description":"Total gold in backpack"},{"name":"Physical Resist","type":"short","size":2,"description":"Physical resistance"},{"name":"Weight","type":"short","size":2,"description":"Current weight"},{"name":"Max Weight","type":"short","size":2,"description":"Maximum carry weight"},{"name":"Race","type":"byte","size":1,"description":"Race ID + 1 (1=Human, 2=Elf, 3=Gargoyle)"},{"name":"Stat Cap","type":"short","size":2,"description":"Total stat cap"},{"name":"Followers","type":"byte","size":1,"description":"Current follower count"},{"name":"Followers Max","type":"byte","size":1,"description":"Maximum follower slots"},{"name":"Fire Resist","type":"short","size":2,"description":"Fire resistance"},{"name":"Cold Resist","type":"short","size":2,"description":"Cold resistance"},{"name":"Poison Resist","type":"short","size":2,"description":"Poison resistance"},{"name":"Energy Resist","type":"short","size":2,"description":"Energy resistance"},{"name":"Luck","type":"short","size":2,"description":"Luck"},{"name":"Damage Min","type":"short","size":2,"description":"Minimum weapon damage"},{"name":"Damage Max","type":"short","size":2,"description":"Maximum weapon damage"},{"name":"Tithing Points","type":"int","size":4,"description":"Tithing points (for Chivalry)"},{"name":"Aos Statuses","type":"short[15]","size":30,"description":"Extended AOS status values. Array of 15 shorts indexed by status type.","values":[{"value":0,"name":"Max Physical Resist","description":"Maximum physical resistance cap"},{"value":1,"name":"Max Fire Resist","description":"Maximum fire resistance cap"},{"value":2,"name":"Max Cold Resist","description":"Maximum cold resistance cap"},{"value":3,"name":"Max Poison Resist","description":"Maximum poison resistance cap"},{"value":4,"name":"Max Energy Resist","description":"Maximum energy resistance cap"},{"value":5,"name":"Defense Chance Increase","description":"Current defense chance increase %"},{"value":6,"name":"Defense Chance Cap","description":"Maximum defense chance cap (always 45)"},{"value":7,"name":"Hit Chance Increase","description":"Hit chance increase %"},{"value":8,"name":"Swing Speed Increase","description":"Swing speed increase %"},{"value":9,"name":"Damage Increase","description":"Damage increase %"},{"value":10,"name":"Lower Reagent Cost","description":"Lower reagent cost %"},{"value":11,"name":"Spell Damage Increase","description":"Spell damage increase %"},{"value":12,"name":"Faster Cast Recovery","description":"Faster cast recovery"},{"value":13,"name":"Faster Casting","description":"Faster casting"},{"value":14,"name":"Lower Mana Cost","description":"Lower mana cost %"}]}],"notes":"Enhanced Client supports additional status indices 15-28 (HP/Stam/Mana regen, Reflect Physical, Enhance Potions, Stat Increases). ModernUO does not support Enhanced Client."}],"notes":"ModernUO supports 15 AOS status values (indices 0-14). Enhanced Client extends this to 29 values (indices 0-28), but ModernUO does not support Enhanced Client.","related":[{"id":"0x34","direction":"incoming","relationship":"request","note":"Mobile Query (stats) triggers this response"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":497},"category":"Mobile","tags":["Mobile"]},{"id":"0x15","name":"Follow Message","description":"Instructs client to follow one entity with another.","direction":"outgoing","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x15","description":"Packet identifier"},{"name":"Follower Serial","type":"uint","size":4,"description":"Serial of the follower"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of the target to follow"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMessagePackets.cs","line":231},"category":"Message","tags":["Message"]},{"id":"0x16","name":"Mobile Healthbar","description":"Updates a mobile's healthbar status for Enhanced Client (poison level, yellow bar for invulnerability).","direction":"outgoing","isDynamic":true,"implemented":false,"size":"9 or 12","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x16","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length (9 or 12)"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Show Bar","type":"enum","size":2,"description":"Show bar flag. If 0, packet ends here (no subsequent fields sent).","values":[{"value":"0","name":"Hide","description":"Hide healthbar, packet ends here"},{"value":"1","name":"Show","description":"Show healthbar, following fields included"}]},{"name":"Healthbar Type","type":"enum","size":2,"description":"Type of healthbar overlay (only sent if Show Bar = 1)","values":[{"value":"1","name":"Poison","description":"Poison status bar (green)"},{"value":"2","name":"Yellow","description":"Yellow/invulnerable bar"}]},{"name":"Level","type":"enum","size":1,"description":"Status level (only sent if Show Bar = 1)","values":[{"value":"0","name":"Off","description":"Status disabled"},{"value":"1","name":"Level1/On","description":"Poison level 1 or yellow on"},{"value":"2","name":"Level2","description":"Poison level 2 (Greater)"},{"value":"3","name":"Level3","description":"Poison level 3 (Deadly)"},{"value":"4","name":"Level4","description":"Poison level 4 (Lethal)"}]}],"related":[{"id":"0x17","relationship":"variant","note":"Mobile Healthbar (Classic) - Classic Client version"}],"clientVersion":{"enhanced":{},"notes":"Enhanced Client only. Classic uses 0x17 instead."},"notes":"When Show Bar is 0, the packet is only 9 bytes (no Healthbar Type or Level fields). Poison (green) overrides yellow coloring. ModernUO currently sends 0x17 to all clients; this EC variant needs implementation.","category":"Mobile","tags":["Mobile"]},{"id":"0x17","name":"Mobile Healthbar","description":"Updates a mobile's healthbar status (poison level, yellow bar for invulnerability).","direction":"outgoing","isDynamic":false,"size":12,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x17","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x000C","description":"Packet length (12)"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Show Bar","type":"enum","size":2,"description":"Show bar flag. If 0, packet ends here (no subsequent fields sent).","values":[{"value":"0","name":"Hide","description":"Hide healthbar, packet ends here"},{"value":"1","name":"Show","description":"Show healthbar, following fields included"}]},{"name":"Healthbar Type","type":"enum","size":2,"description":"Type of healthbar overlay (only sent if Show Bar = 1)","values":[{"value":"1","name":"Poison","description":"Poison status bar (green)"},{"value":"2","name":"Yellow","description":"Yellow/invulnerable bar"}]},{"name":"Level","type":"enum","size":1,"description":"Status level (only sent if Show Bar = 1)","values":[{"value":"0","name":"Off","description":"Status disabled"},{"value":"1","name":"Level1/On","description":"Poison level 1 or yellow on"},{"value":"2","name":"Level2","description":"Poison level 2 (Greater)"},{"value":"3","name":"Level3","description":"Poison level 3 (Deadly)"},{"value":"4","name":"Level4","description":"Poison level 4 (Lethal)"}]}],"related":[{"id":"0x16","relationship":"variant","note":"Mobile Healthbar (EC) - Enhanced Client version"}],"clientVersion":{"classic":{},"notes":"Classic Client only. EC uses 0x16 instead."},"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":419},"notes":"When Show Bar is 0, the packet is only 9 bytes (no Healthbar Type or Level fields). Poison (green) overrides yellow coloring.","category":"Mobile","tags":["Mobile"]},{"id":"0x1A","name":"World Item","description":"Displays an item in the world (pre-Stygian Abyss clients).","direction":"outgoing","isDynamic":true,"size":"14+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x1A","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length (14-20)"},{"name":"Serial","type":"uint","size":4,"description":"Item serial (bit 31 set if amount present)"},{"name":"Item ID","type":"ushort","size":2,"description":"Item graphic ID (bit 14 set for multi)"},{"name":"Amount","type":"ushort","size":2,"description":"Stack amount (if serial bit 31 set)","condition":"serial & 0x80000000"},{"name":"X","type":"ushort","size":2,"description":"X coordinate (bit 15 set if direction present)"},{"name":"Y","type":"ushort","size":2,"description":"Y coordinate (bit 15=hue, bit 14=flags)"},{"name":"Direction","type":"byte","size":1,"description":"Direction (if x bit 15 set)","condition":"x & 0x8000"},{"name":"Z","type":"sbyte","size":1,"description":"Z coordinate"},{"name":"Hue","type":"ushort","size":2,"description":"Item hue (if y bit 15 set)","condition":"y & 0x8000"},{"name":"Flags","type":"byte","size":1,"description":"Packet flags (if y bit 14 set)","condition":"y & 0x4000"}],"related":[{"id":"0xF3","relationship":"variant","note":"World Entity packet for SA+ clients"}],"notes":"For Stygian Abyss+ clients, use 0xF3 World Entity instead.","clientVersion":{"classic":{"max":"6.0.14.2"},"notes":"Replaced by 0xF3 for SA+ clients"},"source":{"file":"Projects/Server/Network/Packets/OutgoingItemPackets.cs","line":24},"category":"Items","tags":["Items"]},{"id":"0x1B","name":"Login Confirmation","description":"Sent when entering the world. Confirms the player's mobile serial and initial position.","direction":"outgoing","isDynamic":false,"size":37,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x1B","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Player mobile serial"},{"name":"Unknown","type":"int","size":4,"value":"0","description":"Unknown (always 0)"},{"name":"Body","type":"short","size":2,"description":"Player body ID"},{"name":"X","type":"short","size":2,"description":"X coordinate"},{"name":"Y","type":"short","size":2,"description":"Y coordinate"},{"name":"Z","type":"short","size":2,"description":"Z coordinate"},{"name":"Direction","type":"byte","size":1,"description":"Facing direction"},{"name":"Unknown2","type":"byte","size":1,"value":"0","description":"Unknown"},{"name":"Unknown3","type":"int","size":4,"value":"-1","description":"Unknown (always -1)"},{"name":"Unknown4","type":"int","size":4,"value":"0","description":"Unknown"},{"name":"Map Width","type":"short","size":2,"description":"Map width in tiles"},{"name":"Map Height","type":"short","size":2,"description":"Map height in tiles"},{"name":"Unknown5","type":"byte[6]","size":6,"description":"Unknown (zeros)"}],"related":[{"id":"0x5D","relationship":"request","note":"Play character request"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":190},"category":"Account","tags":["Account"]},{"id":"0x1C","name":"ASCII Message","description":"Server sends ASCII-encoded message to client.","direction":"outgoing","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x1C","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Serial of speaker (0xFFFFFFFF for system)"},{"name":"Graphic","type":"short","size":2,"description":"Body graphic of speaker"},{"name":"Type","type":"enum","enumType":"sequential","size":1,"description":"Message type","values":[{"value":0,"name":"Regular","description":"Normal speech"},{"value":1,"name":"System","description":"System message"},{"value":2,"name":"Emote","description":"Emote (*action*)"},{"value":6,"name":"Label","description":"Object label"},{"value":7,"name":"Focus","description":"Focused message"},{"value":8,"name":"Whisper","description":"Whisper"},{"value":9,"name":"Yell","description":"Yell"},{"value":10,"name":"Spell","description":"Spell words"},{"value":13,"name":"Guild","description":"Guild chat"},{"value":14,"name":"Alliance","description":"Alliance chat"},{"value":15,"name":"Command","description":"Command"}]},{"name":"Hue","type":"short","size":2,"description":"Text color hue"},{"name":"Font","type":"short","size":2,"description":"Font ID"},{"name":"Name","type":"ascii","size":30,"description":"Speaker name"},{"name":"Text","type":"ascii-t","description":"Message text"}],"related":[{"id":"0x03","relationship":"request","note":"ASCII Speech from client"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMessagePackets.cs","line":180},"category":"Message","tags":["Message"]},{"id":"0x1D","name":"Remove Entity","description":"Removes an entity (item, mobile, or multi) from the client's view.","direction":"outgoing","isDynamic":false,"size":5,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x1D","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Serial of entity to remove"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingEntityPackets.cs","line":75},"category":"Item","tags":["Item","Mobile"]},{"id":"0x20","name":"Mobile Update","description":"Updates a mobile's basic display information (body, hue, position, flags).","direction":"outgoing","isDynamic":false,"size":19,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x20","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Body","type":"short","size":2,"description":"Body/graphic ID"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown (always 0)"},{"name":"Hue","type":"short","size":2,"description":"Hue/color (or solid hue override)"},{"name":"Flags","type":"byte","size":1,"description":"Packet flags (hidden, poisoned, etc.)"},{"name":"X","type":"short","size":2,"description":"X coordinate"},{"name":"Y","type":"short","size":2,"description":"Y coordinate"},{"name":"Unknown2","type":"short","size":2,"description":"Unknown (always 0)"},{"name":"Direction","type":"byte","size":1,"description":"Facing direction"},{"name":"Z","type":"sbyte","size":1,"description":"Z coordinate"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":578},"category":"Mobile","tags":["Mobile"]},{"id":"0x21","name":"Movement Rejection","description":"Sent by the server when player movement is blocked (collision, teleport area, etc). Contains the corrected position the client should snap back to.","direction":"outgoing","isDynamic":false,"size":8,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x21","description":"Packet identifier"},{"name":"Sequence","type":"byte","size":1,"description":"Sequence number of the rejected movement request"},{"name":"X","type":"short","size":2,"description":"Correct X coordinate"},{"name":"Y","type":"short","size":2,"description":"Correct Y coordinate"},{"name":"Direction","type":"byte","size":1,"description":"Correct facing direction (0-7)"},{"name":"Z","type":"sbyte","size":1,"description":"Correct Z coordinate"}],"related":[{"id":"0x02","relationship":"request","note":"The movement request that was rejected"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMovementPackets.cs","line":45},"category":"Movement","tags":["Movement"]},{"id":"0x22","name":"Movement Acknowledgment","description":"Sent by the server to confirm successful player movement. Includes the player's current notoriety for display purposes.","direction":"outgoing","noMerge":true,"isDynamic":false,"size":3,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x22","description":"Packet identifier"},{"name":"Sequence","type":"byte","size":1,"description":"Sequence number of the accepted movement request"},{"name":"Notoriety","type":"enum","enumType":"sequential","size":1,"description":"Player's current notoriety flag","values":[{"value":0,"name":"Innocent","description":"Blue - innocent player"},{"value":1,"name":"Friend","description":"Green - ally/friend"},{"value":2,"name":"Attackable","description":"Gray - can be attacked"},{"value":3,"name":"Criminal","description":"Gray - criminal flag"},{"value":4,"name":"Enemy","description":"Orange - enemy"},{"value":5,"name":"Murderer","description":"Red - murderer"},{"value":6,"name":"Invulnerable","description":"Yellow - invulnerable"}]}],"related":[{"id":"0x02","relationship":"request","note":"The movement request that was accepted"}],"notes":"Not related to incoming 0x22 (Resynchronize) despite sharing the same packet ID.","source":{"file":"Projects/Server/Network/Packets/OutgoingMovementPackets.cs","line":42},"category":"Movement","tags":["Movement"]},{"id":"0x23","name":"Drag Effect","description":"Displays a drag/drop visual effect between two points.","direction":"outgoing","isDynamic":false,"size":26,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x23","description":"Packet identifier"},{"name":"Item ID","type":"short","size":2,"description":"Item graphic ID"},{"name":"Unknown","type":"byte","size":1,"value":"0x00","description":"Unknown"},{"name":"Hue","type":"short","size":2,"description":"Item hue"},{"name":"Amount","type":"short","size":2,"description":"Item amount"},{"name":"Src Serial","type":"uint","size":4,"description":"Source entity serial"},{"name":"Src X","type":"short","size":2,"description":"Source X coordinate"},{"name":"Src Y","type":"short","size":2,"description":"Source Y coordinate"},{"name":"Src Z","type":"sbyte","size":1,"description":"Source Z coordinate"},{"name":"Dst Serial","type":"uint","size":4,"description":"Destination entity serial"},{"name":"Dst X","type":"short","size":2,"description":"Destination X coordinate"},{"name":"Dst Y","type":"short","size":2,"description":"Destination Y coordinate"},{"name":"Dst Z","type":"sbyte","size":1,"description":"Destination Z coordinate"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":198},"category":"Player","tags":["Player"]},{"id":"0x24","name":"Display Container","description":"Opens a container gump on the client.","direction":"outgoing","isDynamic":false,"size":"Varies","variants":[{"name":"Classic","size":7,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x24","description":"Packet identifier"},{"name":"Container Serial","type":"uint","size":4,"description":"Serial of the container"},{"name":"Gump ID","type":"ushort","size":2,"description":"Gump graphic ID"}]},{"name":"High Seas Extended","condition":"Client version >= 7.0.9.0 (HighSeas)","size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x24","description":"Packet identifier"},{"name":"Container Serial","type":"uint","size":4,"description":"Serial of the container"},{"name":"Gump ID","type":"ushort","size":2,"description":"Gump graphic ID"},{"name":"Container Type","type":"short","size":2,"value":"0x007D","description":"Container type (125)"}]}],"clientVersion":{"classic":{},"enhanced":{},"notes":"HighSeas (7.0.9.0+) adds containerType field"},"source":{"file":"Projects/Server/Network/Packets/OutgoingContainerPackets.cs","line":108},"category":"Container","tags":["Container"]},{"id":"0x25","name":"Container Content Update","description":"Updates a single item in a container.","direction":"outgoing","isDynamic":false,"size":"Varies","variants":[{"name":"Classic","size":20,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x25","description":"Packet identifier"},{"name":"Item Serial","type":"uint","size":4,"description":"Serial of the item"},{"name":"Item ID","type":"ushort","size":2,"description":"Item graphic ID"},{"name":"Item ID Offset","type":"byte","size":1,"value":"0x00","description":"Item ID offset (signed)"},{"name":"Amount","type":"ushort","size":2,"description":"Stack amount"},{"name":"X","type":"short","size":2,"description":"X position in container"},{"name":"Y","type":"short","size":2,"description":"Y position in container"},{"name":"Container Serial","type":"uint","size":4,"description":"Serial of parent container"},{"name":"Hue","type":"ushort","size":2,"description":"Item hue"}]},{"name":"Container Grid Lines","condition":"Client version >= 6.0.1.7 (ContainerGridLines)","size":21,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x25","description":"Packet identifier"},{"name":"Item Serial","type":"uint","size":4,"description":"Serial of the item"},{"name":"Item ID","type":"ushort","size":2,"description":"Item graphic ID"},{"name":"Item ID Offset","type":"byte","size":1,"value":"0x00","description":"Item ID offset (signed)"},{"name":"Amount","type":"ushort","size":2,"description":"Stack amount"},{"name":"X","type":"short","size":2,"description":"X position in container"},{"name":"Y","type":"short","size":2,"description":"Y position in container"},{"name":"Grid Location","type":"byte","size":1,"description":"Grid slot position"},{"name":"Container Serial","type":"uint","size":4,"description":"Serial of parent container"},{"name":"Hue","type":"ushort","size":2,"description":"Item hue"}]}],"clientVersion":{"classic":{},"enhanced":{},"notes":"ContainerGridLines (6.0.1.7+) adds gridLocation byte"},"source":{"file":"Projects/Server/Network/Packets/OutgoingContainerPackets.cs","line":127},"category":"Container","tags":["Container"]},{"id":"0x27","name":"Lift Reject","description":"Server rejects a lift/pick up request.","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x27","description":"Packet identifier"},{"name":"Reason","type":"enum","enumType":"sequential","size":1,"description":"Rejection reason","values":[{"value":0,"name":"Cannot Lift","description":"You cannot pick that up"},{"value":1,"name":"Out Of Range","description":"That is out of range"},{"value":2,"name":"Out Of Sight","description":"That is out of sight"},{"value":3,"name":"Try To Steal","description":"That does not belong to you"},{"value":4,"name":"Are Holding","description":"You are already holding an item"},{"value":5,"name":"Inspecific","description":"You cannot pick that up"}]}],"related":[{"id":"0x07","relationship":"request","note":"Lift Request that was rejected"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":90},"category":"Player","tags":["Player"]},{"id":"0x2C","name":"Death Status","description":"Notifies client of death/resurrection state.","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x2C","description":"Packet identifier"},{"name":"Dead","type":"byte","size":1,"value":"0x02","description":"Always 2 (dead)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":63},"category":"Player","tags":["Player"]},{"id":"0x2D","name":"Mobile Attributes","description":"Updates all three attribute bars (hits, mana, stamina) in a single packet.","direction":"outgoing","isDynamic":false,"size":17,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x2D","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Hits Max","type":"short","size":2,"description":"Maximum hits"},{"name":"Hits","type":"short","size":2,"description":"Current hits"},{"name":"Mana Max","type":"short","size":2,"description":"Maximum mana"},{"name":"Mana","type":"short","size":2,"description":"Current mana"},{"name":"Stam Max","type":"short","size":2,"description":"Maximum stamina"},{"name":"Stam","type":"short","size":2,"description":"Current stamina"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":285},"category":"Mobile","tags":["Mobile"]},{"id":"0x2E","name":"Equip Update","description":"Notifies client that an item has been equipped on a mobile.","direction":"outgoing","isDynamic":false,"size":15,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x2E","description":"Packet identifier"},{"name":"Item Serial","type":"uint","size":4,"description":"Serial of the equipped item"},{"name":"Item ID","type":"short","size":2,"description":"Item graphic ID"},{"name":"Layer","type":"ushort","size":2,"description":"Equipment layer"},{"name":"Mobile Serial","type":"uint","size":4,"description":"Serial of the mobile wearing the item"},{"name":"Hue","type":"short","size":2,"description":"Item hue (may be overridden by SolidHueOverride)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingEquipmentPackets.cs","line":86},"category":"Equipment","tags":["Equipment"]},{"id":"0x2F","name":"Swing","description":"Notifies client of a melee swing between two mobiles.","direction":"outgoing","isDynamic":false,"size":10,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x2F","description":"Packet identifier"},{"name":"Unknown","type":"byte","size":1,"value":"0x00","description":"Unknown"},{"name":"Attacker Serial","type":"uint","size":4,"description":"Serial of attacker"},{"name":"Defender Serial","type":"uint","size":4,"description":"Serial of defender"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingCombatPackets.cs","line":23},"category":"Combat","tags":["Combat"]},{"id":"0x38","name":"Pathfind Message","description":"Instructs client to pathfind to a location.","direction":"outgoing","isDynamic":false,"size":7,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x38","description":"Packet identifier"},{"name":"X","type":"short","size":2,"description":"Target X coordinate"},{"name":"Y","type":"short","size":2,"description":"Target Y coordinate"},{"name":"Z","type":"short","size":2,"description":"Target Z coordinate"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":319},"category":"Player","tags":["Player"]},{"id":"0x3A","name":"Skills Update","description":"Sends full skills list or single skill update to client.","direction":"outgoing","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x3A","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Type","type":"enum","enumType":"sequential","size":1,"description":"Update type","values":[{"value":"0x00","name":"Full No Caps","description":"Full list without caps"},{"value":"0x02","name":"Full With Caps","description":"Full list with skill caps"},{"value":"0xDF","name":"Single With Caps","description":"Single skill update with cap"},{"value":"0xFF","name":"Single No Caps","description":"Single skill update"}]},{"name":"Skills","type":"loop","loop":{"until":"skillId == 0","fields":[{"name":"Skill ID","type":"ushort","size":2,"description":"Skill ID + 1 (0 terminates)"},{"name":"Value","type":"ushort","size":2,"description":"Current skill value * 10"},{"name":"Base","type":"ushort","size":2,"description":"Base skill value * 10"},{"name":"Lock","type":"enum","enumType":"sequential","size":1,"description":"Skill lock state","values":[{"value":0,"name":"Up","description":"Skill gains enabled"},{"value":1,"name":"Down","description":"Skill decreases enabled"},{"value":2,"name":"Locked","description":"Skill locked"}]},{"name":"Cap","type":"ushort","size":2,"description":"Skill cap * 10 (if type includes caps)"}]}}],"related":[{"id":"0x34","direction":"incoming","relationship":"request","note":"Mobile Query (skills) triggers this response"},{"id":"0x3A","direction":"incoming","relationship":"related","note":"Change Skill Lock may trigger update"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":121},"category":"Player","tags":["Player"]},{"id":"0x3B","name":"End Vendor Transaction","description":"Ends a vendor buy or sell transaction.","direction":"outgoing","isDynamic":false,"size":8,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x3B","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"8","description":"Packet length"},{"name":"Vendor Serial","type":"uint","size":4,"description":"Serial of the vendor"},{"name":"Item Count","type":"byte","size":1,"value":"0","description":"Item count (0 = end transaction)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingVendorBuyPackets.cs","line":111},"category":"Vendor","tags":["Vendor"]},{"id":"0x3C","name":"Container & Old Spellbook Content","description":"Sends full contents of a container. Also used for corpse contents and old-style spellbook content (pre-AOS clients). For AOS+ spellbooks, use 0xBF/0x1B instead.","direction":"outgoing","isDynamic":true,"size":"Varies","variants":[{"name":"Classic Format","condition":"Client version < 6.0.1.7","size":"5 + (itemCount x 19)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x3C","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Item Count","type":"ushort","size":2,"description":"Number of items"},{"name":"Items","type":"loop","description":"Item entries (19 bytes each)","loop":{"countField":"itemCount","itemSize":19,"fields":[{"name":"Item Serial","type":"uint","size":4,"description":"Serial of the item"},{"name":"Item ID","type":"ushort","size":2,"description":"Item graphic ID"},{"name":"Item ID Offset","type":"byte","size":1,"description":"Item ID offset (signed)"},{"name":"Amount","type":"ushort","size":2,"description":"Stack amount"},{"name":"X","type":"short","size":2,"description":"X position in container"},{"name":"Y","type":"short","size":2,"description":"Y position in container"},{"name":"Container Serial","type":"uint","size":4,"description":"Serial of parent container"},{"name":"Hue","type":"ushort","size":2,"description":"Item hue"}]}}]},{"name":"Grid Location Format","condition":"Client version >= 6.0.1.7 (ContainerGridLines)","size":"5 + (itemCount x 20)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x3C","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Item Count","type":"ushort","size":2,"description":"Number of items"},{"name":"Items","type":"loop","description":"Item entries (20 bytes each)","loop":{"countField":"itemCount","itemSize":20,"fields":[{"name":"Item Serial","type":"uint","size":4,"description":"Serial of the item"},{"name":"Item ID","type":"ushort","size":2,"description":"Item graphic ID"},{"name":"Item ID Offset","type":"byte","size":1,"description":"Item ID offset (signed)"},{"name":"Amount","type":"ushort","size":2,"description":"Stack amount"},{"name":"X","type":"short","size":2,"description":"X position in container"},{"name":"Y","type":"short","size":2,"description":"Y position in container"},{"name":"Grid Location","type":"byte","size":1,"description":"Grid slot position in container"},{"name":"Container Serial","type":"uint","size":4,"description":"Serial of parent container"},{"name":"Hue","type":"ushort","size":2,"description":"Item hue"}]}}]}],"related":[{"id":"0xBF/0x1B","relationship":"variant","note":"New Spellbook Content for AOS+ clients"},{"id":"0x89","relationship":"related","note":"Corpse Equipment (layer mappings for corpse items)"}],"clientVersion":{"classic":{},"enhanced":{},"notes":"ContainerGridLines (6.0.1.7+) adds gridLocation byte per item"},"notes":"Also used for corpse contents. Corpses are special containers that display equipped items on a body graphic. Use with 0x89 Corpse Equipment for full corpse display.","source":{"file":"Projects/Server/Network/Packets/OutgoingContainerPackets.cs","line":169},"category":"Container","tags":["Container","Spellbook","Corpse"]},{"id":"0x4E","name":"Personal Light Level","description":"Sets the light level for a specific entity.","direction":"outgoing","isDynamic":false,"size":6,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x4E","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Serial of entity"},{"name":"Level","type":"byte","size":1,"description":"Light level (0=brightest, 25-30=typical night)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingLightPackets.cs","line":23},"category":"Light","tags":["Light"]},{"id":"0x4F","name":"Global Light Level","description":"Sets the global ambient light level for the client.","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x4F","description":"Packet identifier"},{"name":"Level","type":"byte","size":1,"description":"Light level (0=brightest, 25-30=typical night)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingLightPackets.cs","line":39},"category":"Light","tags":["Light"]},{"id":"0x51","name":"Compact Shard Stats","description":"Server response to compact shard stats query (0xF1/0xFE).","direction":"outgoing","isDynamic":false,"size":27,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x51","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x001B","description":"Packet length (27)"},{"name":"Clients","type":"int","size":4,"description":"Current client count"},{"name":"Items","type":"int","size":4,"description":"Total item count"},{"name":"Mobiles","type":"int","size":4,"description":"Total mobile count"},{"name":"Age","type":"uint","size":4,"description":"Server uptime in seconds"},{"name":"Memory","type":"long","size":8,"description":"Memory usage in bytes"}],"related":[{"id":"0xF1/0xFE","relationship":"request","note":"Query Compact Shard Stats request"}],"source":{"file":"Projects/UOContent/Network/UOGateway.cs","line":60},"category":"FreeShard Protocol","tags":["FreeShard Protocol"]},{"id":"0x53","name":"Popup Message","description":"Displays a predefined popup message to the client.","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x53","description":"Packet identifier"},{"name":"Message ID","type":"enum","size":1,"description":"Predefined message identifier","values":[{"value":"1","name":"CharNoExist","description":"Character does not exist"},{"value":"2","name":"CharExists","description":"Character already exists"},{"value":"5","name":"CharInWorld","description":"Character is in world"},{"value":"6","name":"LoginSyncError","description":"Login synchronization error"},{"value":"7","name":"IdleWarning","description":"Idle timeout warning"}]}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":131},"category":"Account","tags":["Account"]},{"id":"0x54","name":"Sound Effect","description":"Plays a sound effect at a location.","direction":"outgoing","isDynamic":false,"size":12,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x54","description":"Packet identifier"},{"name":"Flags","type":"byte","size":1,"value":"0x01","description":"Sound flags"},{"name":"Sound ID","type":"short","size":2,"description":"Sound effect ID"},{"name":"Volume","type":"short","size":2,"value":"0x0000","description":"Volume (unused)"},{"name":"X","type":"short","size":2,"description":"X coordinate"},{"name":"Y","type":"short","size":2,"description":"Y coordinate"},{"name":"Z","type":"short","size":2,"description":"Z coordinate"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingEffectPackets.cs","line":41},"category":"Effects","tags":["Effects"]},{"id":"0x55","name":"Login Complete","description":"Final packet in the login sequence. Signals that the client can begin normal gameplay.","direction":"outgoing","isDynamic":false,"size":1,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x55","description":"Packet identifier"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":231},"category":"Account","tags":["Account"]},{"id":"0x56","name":"Map Command","description":"Server sends map pin commands to update the client's map display.","direction":"outgoing","isDynamic":false,"size":11,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x56","description":"Packet identifier"},{"name":"Map Serial","type":"uint","size":4,"description":"Serial of the map item"},{"name":"Command","type":"enum","size":1,"description":"Map command type","values":[{"value":"1","name":"AddPin","description":"Add a pin to the map"},{"value":"5","name":"DisplayMap","description":"Display the map to client"},{"value":"7","name":"SetEditable","description":"Set map editable state"}]},{"name":"Editable","type":"bool","size":1,"description":"True if map is editable (for command 7)"},{"name":"X","type":"short","size":2,"description":"X coordinate of pin"},{"name":"Y","type":"short","size":2,"description":"Y coordinate of pin"}],"related":[{"id":"0x56","direction":"incoming","relationship":"related","note":"Client map pin commands"},{"id":"0x90","relationship":"related","note":"Map Details packet (old)"},{"id":"0xF5","relationship":"related","note":"Map Details packet (new)"}],"source":{"file":"Projects/UOContent/Items/Maps/MapItemPackets.cs","line":106},"category":"Map","tags":["Map"]},{"id":"0x5B","name":"Current Time","description":"Sends current server time to client.","direction":"outgoing","isDynamic":false,"size":4,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x5B","description":"Packet identifier"},{"name":"Hour","type":"byte","size":1,"description":"Hour (0-23)"},{"name":"Minute","type":"byte","size":1,"description":"Minute (0-59)"},{"name":"Second","type":"byte","size":1,"description":"Second (0-59)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":316},"category":"Player","tags":["Player"]},{"id":"0x65","name":"Weather","description":"Sets weather conditions for client.","direction":"outgoing","isDynamic":false,"size":4,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x65","description":"Packet identifier"},{"name":"Type","type":"enum","enumType":"sequential","size":1,"description":"Weather type","values":[{"value":0,"name":"Rain","description":"Raining"},{"value":1,"name":"Storm Brewing","description":"Storm brewing"},{"value":2,"name":"Snow","description":"Snowing"},{"value":3,"name":"Storm","description":"Storm in progress"},{"value":254,"name":"None","description":"No weather"},{"value":255,"name":"Clear","description":"Clear weather (stops current)"}]},{"name":"Intensity","type":"byte","size":1,"description":"Weather intensity (0-255)"},{"name":"Temperature","type":"byte","size":1,"description":"Temperature value"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":97},"category":"Player","tags":["Player"]},{"id":"0x66","name":"Book Content","description":"Sends full book content including all pages and lines.","direction":"outgoing","isDynamic":true,"size":"9+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x66","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Book Serial","type":"uint","size":4,"description":"Serial of the book"},{"name":"Page Count","type":"ushort","size":2,"description":"Number of pages"},{"name":"Pages","type":"loop","description":"Page contents","loop":{"countField":"pageCount","fields":[{"name":"Page Number","type":"ushort","size":2,"description":"Page number (1-indexed)"},{"name":"Line Count","type":"ushort","size":2,"description":"Number of lines on page"},{"name":"Lines","type":"loop","description":"Lines on the page","loop":{"countField":"lineCount","fields":[{"name":"Text","type":"utf8-t","description":"Line text"}]}}]}}],"source":{"file":"Projects/UOContent/Items/Books/BookPackets.cs","line":136},"category":"Book","tags":["Book"]},{"id":"0x6C","name":"Target Request","description":"Requests the client to select a target.","direction":"outgoing","isDynamic":false,"size":19,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6C","description":"Packet identifier"},{"name":"Allow Ground","type":"bool","size":1,"description":"True = allow ground targeting"},{"name":"Target ID","type":"int","size":4,"description":"Target cursor ID for matching response"},{"name":"Flags","type":"enum","enumType":"sequential","size":1,"description":"Target cursor flags","values":[{"value":0,"name":"Neutral","description":"Neutral targeting (gray cursor)"},{"value":1,"name":"Harmful","description":"Harmful action (red cursor)"},{"value":2,"name":"Beneficial","description":"Beneficial action (green cursor)"},{"value":3,"name":"Cancel","description":"Cancel targeting"}]},{"name":"Padding","type":"byte[]","size":12,"description":"Padding (zeros)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingTargetPackets.cs","line":57},"category":"Targeting","tags":["Targeting"]},{"id":"0x6D","name":"Play Music","description":"Plays background music on client.","direction":"outgoing","isDynamic":false,"size":3,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6D","description":"Packet identifier"},{"name":"Music ID","type":"short","size":2,"description":"Music track ID (0x1FFF = stop)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":275},"category":"Player","tags":["Player"]},{"id":"0x6E","name":"Mobile Animation","description":"Triggers an animation on a mobile.","direction":"outgoing","isDynamic":false,"size":14,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6E","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Action","type":"short","size":2,"description":"Animation action ID"},{"name":"Frame Count","type":"short","size":2,"description":"Number of frames"},{"name":"Repeat Count","type":"short","size":2,"description":"Number of times to repeat"},{"name":"Reverse","type":"bool","size":1,"description":"Play animation in reverse"},{"name":"Repeat","type":"bool","size":1,"description":"Loop the animation"},{"name":"Delay","type":"byte","size":1,"description":"Frame delay"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":318},"category":"Mobile","tags":["Mobile"]},{"id":"0x6F","name":"Secure Trade","description":"Manages secure trade windows between players.","direction":"outgoing","isDynamic":true,"size":"Varies","variants":[{"name":"Display Trade Window","condition":"flag == Display (0)","size":47,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6F","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"47","description":"Packet length"},{"name":"Flag","type":"enum","enumType":"sequential","size":1,"value":"0","description":"Trade action flag","values":[{"value":0,"name":"Display","description":"Open trade window"},{"value":1,"name":"Close","description":"Close trade window"},{"value":2,"name":"Update","description":"Update accept status"},{"value":3,"name":"Update Gold","description":"Update gold amounts"},{"value":4,"name":"Update Ledger","description":"Update ledger"}]},{"name":"Partner Serial","type":"uint","size":4,"description":"Serial of trading partner"},{"name":"First Container Serial","type":"uint","size":4,"description":"Serial of your trade container"},{"name":"Second Container Serial","type":"uint","size":4,"description":"Serial of partner's trade container"},{"name":"Has Name","type":"bool","size":1,"value":"true","description":"Name field follows"},{"name":"Partner Name","type":"ascii","size":30,"description":"Trading partner's name"}]},{"name":"Close Trade Window","condition":"flag == Close (1)","size":17,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6F","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"17","description":"Packet length"},{"name":"Flag","type":"byte","size":1,"value":"1","description":"Close flag"},{"name":"Container Serial","type":"uint","size":4,"description":"Trade container serial"},{"name":"Unused1","type":"int","size":4,"value":"0","description":"Unused"},{"name":"Unused2","type":"int","size":4,"value":"0","description":"Unused"},{"name":"Has Name","type":"bool","size":1,"value":"false","description":"No name follows"}]},{"name":"Update Accept Status","condition":"flag == Update (2)","size":17,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6F","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"17","description":"Packet length"},{"name":"Flag","type":"byte","size":1,"value":"2","description":"Update flag"},{"name":"Container Serial","type":"uint","size":4,"description":"Trade container serial"},{"name":"Your Accept","type":"int","size":4,"description":"Your accept status (0 or 1)"},{"name":"Partner Accept","type":"int","size":4,"description":"Partner's accept status (0 or 1)"},{"name":"Has Name","type":"bool","size":1,"value":"false","description":"No name follows"}]},{"name":"Update Gold/Platinum","condition":"flag == UpdateGold (3)","size":17,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6F","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"17","description":"Packet length"},{"name":"Flag","type":"byte","size":1,"value":"3","description":"UpdateGold flag"},{"name":"Container Serial","type":"uint","size":4,"description":"Trade container serial"},{"name":"Gold","type":"int","size":4,"description":"Gold amount"},{"name":"Platinum","type":"int","size":4,"description":"Platinum amount"},{"name":"Has Name","type":"bool","size":1,"value":"false","description":"No name follows"}]}],"related":[{"id":"0x6F","direction":"incoming","relationship":"request","note":"Client trade actions"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingSecureTradePackets.cs","line":32},"category":"Secure Trade","tags":["Secure Trade"]},{"id":"0x70","name":"Screen Effect","description":"Triggers a screen-wide visual effect (fade in/out).","direction":"outgoing","isDynamic":false,"size":28,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x70","description":"Packet identifier"},{"name":"Effect Type","type":"byte","size":1,"value":"0x04","description":"Effect type (4)"},{"name":"Padding1","type":"byte[]","size":8,"description":"Padding (zeros)"},{"name":"Type","type":"enum","enumType":"sequential","size":2,"description":"Screen effect type","values":[{"value":0,"name":"Fade Out","description":"Fade screen to black"},{"value":1,"name":"Fade In","description":"Fade screen from black"},{"value":2,"name":"Light Flash","description":"Light flash effect"},{"value":3,"name":"Fade In Out","description":"Fade out then in"},{"value":4,"name":"Darken Screen","description":"Darken screen"}]},{"name":"Padding2","type":"byte[]","size":16,"description":"Padding (zeros)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingEffectPackets.cs","line":322},"category":"Effects","tags":["Effects"]},{"id":"0x71","name":"Bulletin Board","description":"Bulletin board display and message packets.","direction":"outgoing","isDynamic":true,"size":"Varies","variants":[{"name":"Display Board","condition":"command == 0x00","size":38,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x71","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"38","description":"Packet length"},{"name":"Command","type":"byte","size":1,"value":"0x00","description":"Display board command"},{"name":"Board Serial","type":"uint","size":4,"description":"Serial of the bulletin board"},{"name":"Board Name","type":"utf8","size":30,"description":"Board name (null-padded to 30 bytes)"}]},{"name":"Message Header","condition":"command == 0x01","size":"22+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x71","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Command","type":"byte","size":1,"value":"0x01","description":"Message header command"},{"name":"Board Serial","type":"uint","size":4,"description":"Serial of the bulletin board"},{"name":"Message Serial","type":"uint","size":4,"description":"Serial of the message"},{"name":"Thread Serial","type":"uint","size":4,"description":"Serial of parent thread (0 if root)"},{"name":"Poster Length","type":"byte","size":1,"description":"Length of poster name"},{"name":"Poster","type":"utf8-t","description":"Poster name"},{"name":"Subject Length","type":"byte","size":1,"description":"Length of subject"},{"name":"Subject","type":"utf8-t","description":"Message subject"},{"name":"Time Length","type":"byte","size":1,"description":"Length of time string"},{"name":"Time","type":"utf8-t","description":"Posted time string"}]},{"name":"Message Content","condition":"command == 0x02","size":"22+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x71","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Command","type":"byte","size":1,"value":"0x02","description":"Message content command"},{"name":"Board Serial","type":"uint","size":4,"description":"Serial of the bulletin board"},{"name":"Message Serial","type":"uint","size":4,"description":"Serial of the message"},{"name":"Poster Length","type":"byte","size":1,"description":"Length of poster name"},{"name":"Poster","type":"utf8-t","description":"Poster name"},{"name":"Subject Length","type":"byte","size":1,"description":"Length of subject"},{"name":"Subject","type":"utf8-t","description":"Message subject"},{"name":"Time Length","type":"byte","size":1,"description":"Length of time string"},{"name":"Time","type":"utf8-t","description":"Posted time string"},{"name":"Poster Body","type":"short","size":2,"description":"Poster body graphic"},{"name":"Poster Hue","type":"short","size":2,"description":"Poster body hue"},{"name":"Equip Count","type":"byte","size":1,"description":"Number of equipment items"},{"name":"Equipment","type":"loop","description":"Poster's equipment","loop":{"countField":"equipCount","fields":[{"name":"Item ID","type":"short","size":2,"description":"Equipment item graphic"},{"name":"Hue","type":"short","size":2,"description":"Equipment hue"}]}},{"name":"Line Count","type":"byte","size":1,"description":"Number of text lines"},{"name":"Lines","type":"loop","description":"Message lines","loop":{"countField":"lineCount","fields":[{"name":"Line Length","type":"byte","size":1,"description":"Line length"},{"name":"Line","type":"utf8","description":"Line text with 2-byte terminator (old client bug)"}]}}]}],"source":{"file":"Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs","line":168},"category":"Bulletin Board","tags":["Bulletin Board"]},{"id":"0x72","name":"Set War Mode","description":"Sets the client's war/peace mode state.","direction":"outgoing","isDynamic":false,"size":5,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x72","description":"Packet identifier"},{"name":"Warmode","type":"bool","size":1,"description":"True = war mode, False = peace mode"},{"name":"Unknown1","type":"byte","size":1,"value":"0x00","description":"Unknown"},{"name":"Unknown2","type":"byte","size":1,"value":"0x32","description":"Unknown (50)"},{"name":"Unknown3","type":"byte","size":1,"value":"0x00","description":"Unknown"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingCombatPackets.cs","line":40},"category":"Combat","tags":["Combat"]},{"id":"0x73","name":"Ping Ack","description":"Server acknowledges ping request.","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x73","description":"Packet identifier"},{"name":"Sequence","type":"byte","size":1,"description":"Ping sequence (echoed from request)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":336},"category":"Player","tags":["Player"]},{"id":"0x74","name":"Vendor Buy List","description":"Sends the list of items available for purchase from a vendor with prices.","direction":"outgoing","isDynamic":true,"size":"8+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x74","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Container Serial","type":"uint","size":4,"description":"Serial of vendor's buy container"},{"name":"Item Count","type":"byte","size":1,"description":"Number of items"},{"name":"Items","type":"loop","description":"Buy items with prices","loop":{"countField":"itemCount","fields":[{"name":"Price","type":"int","size":4,"description":"Item price"},{"name":"Desc Length","type":"byte","size":1,"description":"Description length + 1"},{"name":"Description","type":"ascii-t","description":"Item description"}]}}],"related":[{"id":"0x3C","relationship":"request","note":"Container Content with items"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingVendorBuyPackets.cs","line":77},"category":"Vendor","tags":["Vendor"]},{"id":"0x76","name":"Server Change","description":"Notifies client of server/map transition.","direction":"outgoing","isDynamic":false,"size":16,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x76","description":"Packet identifier"},{"name":"X","type":"short","size":2,"description":"New X coordinate"},{"name":"Y","type":"short","size":2,"description":"New Y coordinate"},{"name":"Z","type":"short","size":2,"description":"New Z coordinate"},{"name":"Unknown","type":"byte","size":1,"value":"0x00","description":"Unknown"},{"name":"Unknown2","type":"short","size":2,"value":"0x0000","description":"Unknown"},{"name":"Unknown3","type":"short","size":2,"value":"0x0000","description":"Unknown"},{"name":"Map Width","type":"short","size":2,"description":"Map width"},{"name":"Map Height","type":"short","size":2,"description":"Map height"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":100},"category":"Player","tags":["Player"]},{"id":"0x77","name":"Mobile Moving","description":"Sent when a mobile moves. Contains position, direction, hue, and notoriety.","direction":"outgoing","isDynamic":false,"size":17,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x77","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Body","type":"short","size":2,"description":"Body/graphic ID"},{"name":"X","type":"short","size":2,"description":"X coordinate"},{"name":"Y","type":"short","size":2,"description":"Y coordinate"},{"name":"Z","type":"sbyte","size":1,"description":"Z coordinate"},{"name":"Direction","type":"byte","size":1,"description":"Direction (0-7) with running flag (0x80)"},{"name":"Hue","type":"short","size":2,"description":"Hue/color"},{"name":"Flags","type":"byte","size":1,"description":"Packet flags"},{"name":"Notoriety","type":"enum","enumType":"sequential","size":1,"description":"Notoriety flag","values":[{"value":0,"name":"Innocent","description":"Blue - innocent player"},{"value":1,"name":"Friend","description":"Green - ally/friend"},{"value":2,"name":"Attackable","description":"Gray - can be attacked"},{"value":3,"name":"Criminal","description":"Gray - criminal flag"},{"value":4,"name":"Enemy","description":"Orange - enemy"},{"value":5,"name":"Murderer","description":"Red - murderer"},{"value":6,"name":"Invulnerable","description":"Yellow - invulnerable"}]}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":104},"category":"Mobile","tags":["Mobile"]},{"id":"0x78","name":"Mobile Incoming","description":"Full mobile information including equipped items. Sent when a mobile enters view range. Structure varies by client version.","direction":"outgoing","isDynamic":true,"size":"23+","variants":[{"name":"Pre-Stygian Abyss","condition":"Classic client < 7.0.0.0","size":"23+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x78","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Body","type":"short","size":2,"description":"Body/graphic ID"},{"name":"X","type":"short","size":2,"description":"X coordinate"},{"name":"Y","type":"short","size":2,"description":"Y coordinate"},{"name":"Z","type":"sbyte","size":1,"description":"Z coordinate"},{"name":"Direction","type":"byte","size":1,"description":"Facing direction"},{"name":"Hue","type":"short","size":2,"description":"Hue/color"},{"name":"Flags","type":"byte","size":1,"description":"Packet flags"},{"name":"Notoriety","type":"enum","enumType":"sequential","size":1,"description":"Notoriety flag","values":[{"value":0,"name":"Innocent","description":"Blue - innocent player"},{"value":1,"name":"Friend","description":"Green - ally/friend"},{"value":2,"name":"Attackable","description":"Gray - can be attacked"},{"value":3,"name":"Criminal","description":"Gray - criminal flag"},{"value":4,"name":"Enemy","description":"Orange - enemy"},{"value":5,"name":"Murderer","description":"Red - murderer"},{"value":6,"name":"Invulnerable","description":"Yellow - invulnerable"}]},{"name":"Equipment","type":"array","description":"Equipped items (terminated by 0x00000000)","loop":{"countField":"variable (until terminator)","fields":[{"name":"Item Serial","type":"uint","size":4,"description":"Item serial (0 = end of list)"},{"name":"Item ID","type":"ushort","size":2,"description":"Item graphic ID (15-bit, 0x7FFF mask). Bit 0x8000 indicates hue follows."},{"name":"Layer","type":"byte","size":1,"description":"Equipment layer"},{"name":"Hue","type":"short","size":2,"description":"Item hue (only present if bit 0x8000 set on Item ID)","condition":"Item ID & 0x8000"}]}},{"name":"Terminator","type":"int","size":4,"value":"0x00000000","description":"Equipment list terminator"}]},{"name":"Stygian Abyss","condition":"Classic client 7.0.0.0 - 7.0.33.0, or Enhanced Client","size":"23+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x78","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Body","type":"short","size":2,"description":"Body/graphic ID"},{"name":"X","type":"short","size":2,"description":"X coordinate"},{"name":"Y","type":"short","size":2,"description":"Y coordinate"},{"name":"Z","type":"sbyte","size":1,"description":"Z coordinate"},{"name":"Direction","type":"byte","size":1,"description":"Facing direction"},{"name":"Hue","type":"short","size":2,"description":"Hue/color"},{"name":"Flags","type":"byte","size":1,"description":"Packet flags (SA format)"},{"name":"Notoriety","type":"enum","enumType":"sequential","size":1,"description":"Notoriety flag","values":[{"value":0,"name":"Innocent","description":"Blue - innocent player"},{"value":1,"name":"Friend","description":"Green - ally/friend"},{"value":2,"name":"Attackable","description":"Gray - can be attacked"},{"value":3,"name":"Criminal","description":"Gray - criminal flag"},{"value":4,"name":"Enemy","description":"Orange - enemy"},{"value":5,"name":"Murderer","description":"Red - murderer"},{"value":6,"name":"Invulnerable","description":"Yellow - invulnerable"}]},{"name":"Equipment","type":"array","description":"Equipped items (terminated by 0x00000000)","loop":{"countField":"variable (until terminator)","fields":[{"name":"Item Serial","type":"uint","size":4,"description":"Item serial (0 = end of list)"},{"name":"Item ID","type":"ushort","size":2,"description":"Item graphic ID (15-bit, 0x7FFF mask). Bit 0x8000 indicates hue follows."},{"name":"Layer","type":"byte","size":1,"description":"Equipment layer"},{"name":"Hue","type":"short","size":2,"description":"Item hue (only present if bit 0x8000 set on Item ID)","condition":"Item ID & 0x8000"}]}},{"name":"Terminator","type":"int","size":4,"value":"0x00000000","description":"Equipment list terminator"}]},{"name":"NewMobileIncoming","condition":"Classic client >= 7.0.33.1","size":"23+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x78","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Body","type":"short","size":2,"description":"Body/graphic ID"},{"name":"X","type":"short","size":2,"description":"X coordinate"},{"name":"Y","type":"short","size":2,"description":"Y coordinate"},{"name":"Z","type":"sbyte","size":1,"description":"Z coordinate"},{"name":"Direction","type":"byte","size":1,"description":"Facing direction"},{"name":"Hue","type":"short","size":2,"description":"Hue/color"},{"name":"Flags","type":"byte","size":1,"description":"Packet flags (SA format)"},{"name":"Notoriety","type":"enum","enumType":"sequential","size":1,"description":"Notoriety flag","values":[{"value":0,"name":"Innocent","description":"Blue - innocent player"},{"value":1,"name":"Friend","description":"Green - ally/friend"},{"value":2,"name":"Attackable","description":"Gray - can be attacked"},{"value":3,"name":"Criminal","description":"Gray - criminal flag"},{"value":4,"name":"Enemy","description":"Orange - enemy"},{"value":5,"name":"Murderer","description":"Red - murderer"},{"value":6,"name":"Invulnerable","description":"Yellow - invulnerable"}]},{"name":"Equipment","type":"array","description":"Equipped items (terminated by 0x00000000). Always includes hue field.","loop":{"countField":"variable (until terminator)","fields":[{"name":"Item Serial","type":"uint","size":4,"description":"Item serial (0 = end of list)"},{"name":"Item ID","type":"ushort","size":2,"description":"Item graphic ID (full 16-bit, 0xFFFF mask)"},{"name":"Layer","type":"byte","size":1,"description":"Equipment layer"},{"name":"Hue","type":"short","size":2,"description":"Item hue (always present)"}]}},{"name":"Terminator","type":"int","size":4,"value":"0x00000000","description":"Equipment list terminator"}]}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":601},"category":"Mobile","tags":["Mobile"]},{"id":"0x7B","name":"Sequence","description":"Sends sequence number to client for synchronization.","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x7B","description":"Packet identifier"},{"name":"Sequence","type":"byte","size":1,"description":"Sequence number"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":154},"category":"Player","tags":["Player"]},{"id":"0x7C","name":"Display Menu","description":"Displays an item list menu or question menu to the client.","direction":"outgoing","isDynamic":true,"size":"Varies","variants":[{"name":"Item List Menu","condition":"Menu is ItemListMenu","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x7C","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Menu Serial","type":"uint","size":4,"description":"Menu serial"},{"name":"Menu ID","type":"ushort","size":2,"value":"0x0000","description":"Menu ID (always 0)"},{"name":"Question Length","type":"byte","size":1,"description":"Length of question text"},{"name":"Question","type":"ascii","description":"Question text"},{"name":"Entry Count","type":"byte","size":1,"description":"Number of menu entries"},{"name":"Entries","type":"loop","description":"Menu entries","loop":{"countField":"entryCount","fields":[{"name":"Item ID","type":"ushort","size":2,"description":"Item graphic ID"},{"name":"Hue","type":"short","size":2,"description":"Item hue"},{"name":"Name Length","type":"byte","size":1,"description":"Length of entry name"},{"name":"Name","type":"ascii","description":"Entry name"}]}}]},{"name":"Question Menu","condition":"Menu is QuestionMenu","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x7C","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Menu Serial","type":"uint","size":4,"description":"Menu serial"},{"name":"Menu ID","type":"ushort","size":2,"value":"0x0000","description":"Menu ID (always 0)"},{"name":"Question Length","type":"byte","size":1,"description":"Length of question text"},{"name":"Question","type":"ascii","description":"Question text"},{"name":"Answer Count","type":"byte","size":1,"description":"Number of answers"},{"name":"Answers","type":"loop","description":"Answer options","loop":{"countField":"answerCount","fields":[{"name":"Padding","type":"int","size":4,"value":"0","description":"Unused padding"},{"name":"Answer Length","type":"byte","size":1,"description":"Length of answer text"},{"name":"Answer","type":"ascii","description":"Answer text"}]}}]}],"related":[{"id":"0x7D","relationship":"response","note":"Menu Response from client"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMenuPackets.cs","line":36},"category":"Menu","tags":["Menu"]},{"id":"0x81","name":"Change Character","description":"Updates the character list during reconnection. Currently unused.","direction":"outgoing","isDynamic":true,"size":"5 + (60 x charCount)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x81","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Char Count","type":"ushort","size":2,"description":"Number of characters"},{"name":"Characters","type":"array","description":"Character list entries","loop":{"countField":"charCount","fields":[{"name":"Name","type":"ascii","size":30,"description":"Character name"},{"name":"Password","type":"ascii","size":30,"description":"Always empty"}]}}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":63},"notes":"Currently unused in ModernUO.","category":"Account","tags":["Account"]},{"id":"0x82","name":"Account Login Rejected","description":"Sent when account login fails. Contains the reason for rejection.","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x82","description":"Packet identifier"},{"name":"Reason","type":"enum","size":1,"description":"Rejection reason code","values":[{"value":"0","name":"Invalid","description":"Invalid credentials"},{"value":"1","name":"InUse","description":"Account already in use"},{"value":"2","name":"Blocked","description":"Account blocked"},{"value":"3","name":"BadPass","description":"Incorrect password"},{"value":"254","name":"Idle","description":"Idle timeout"},{"value":"255","name":"BadComm","description":"Communication error"}]}],"related":[{"id":"0x80","relationship":"request","note":"The login attempt that failed"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":402},"category":"Account","tags":["Account"]},{"id":"0x85","name":"Character Delete Result","description":"Result of a character deletion request.","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x85","description":"Packet identifier"},{"name":"Result","type":"enum","size":1,"description":"Deletion result code","values":[{"value":"0","name":"PasswordInvalid","description":"Password is invalid"},{"value":"1","name":"CharNotExist","description":"Character does not exist"},{"value":"2","name":"CharBeingPlayed","description":"Character is being played"},{"value":"3","name":"CharTooYoung","description":"Character too young to delete"},{"value":"4","name":"CharQueued","description":"Character queued for deletion"},{"value":"5","name":"BadRequest","description":"Invalid request"}]}],"related":[{"id":"0x83","relationship":"request","note":"The delete request"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":121},"category":"Account","tags":["Account"]},{"id":"0x86","name":"Character List Update","description":"Updates the character list after character creation or deletion.","direction":"outgoing","isDynamic":true,"size":"4 + (60 x charCount)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x86","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Char Count","type":"byte","size":1,"description":"Number of character slots"},{"name":"Characters","type":"array","description":"Character list entries","loop":{"countField":"charCount","fields":[{"name":"Name","type":"ascii","size":30,"description":"Character name (empty if slot unused)"},{"name":"Password","type":"ascii","size":30,"description":"Always empty"}]}}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":242},"category":"Account","tags":["Account"]},{"id":"0x88","name":"Display Paperdoll","description":"Opens paperdoll window for a mobile.","direction":"outgoing","isDynamic":false,"size":66,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x88","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Serial of mobile"},{"name":"Title","type":"ascii","size":60,"description":"Title/name displayed"},{"name":"Flags","type":"bitfield","size":1,"description":"Paperdoll flags","flags":[{"bit":"0","name":"Warmode","description":"Mobile is in war mode"},{"bit":"1","name":"Can Lift","description":"Viewer can lift equipment"}]}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":247},"category":"Player","tags":["Player"]},{"id":"0x89","name":"Corpse Equipment","description":"Sends the equipment layer mapping for items on a corpse, including virtual hair and facial hair items.","direction":"outgoing","isDynamic":true,"size":"8+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x89","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Corpse Serial","type":"uint","size":4,"description":"Serial of the corpse"},{"name":"Equipment","type":"loop","description":"Equipment layer mappings (5 bytes each, until terminator)","loop":{"terminator":"Layer == 0","fields":[{"name":"Layer","type":"byte","size":1,"description":"Equipment layer + 1 (0 = terminator)"},{"name":"Item Serial","type":"uint","size":4,"description":"Serial of item in this layer"}]}},{"name":"Terminator","type":"byte","size":1,"value":"0x00","description":"Layer.Invalid (0) marks end of list"}],"notes":"Layer values are offset by +1 (e.g., Layer.Hair (0x0B) is sent as 0x0C). Hair and facial hair use virtual serials.","related":[{"id":"0x3C","direction":"outgoing","relationship":"related","note":"Container Content (also used for corpse items)"}],"source":{"file":"Projects/UOContent/Items/Misc/Corpses/CorpsePackets.cs","line":24},"category":"Corpse","tags":["Corpse"]},{"id":"0x8B","name":"Display Sign Gump","description":"Displays a sign gump with text to the client.","direction":"outgoing","isDynamic":true,"size":"15+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x8B","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Sign serial"},{"name":"Gump ID","type":"short","size":2,"description":"Gump graphic ID"},{"name":"Unknown Length","type":"short","size":2,"description":"Length of unknown text + 1"},{"name":"Unknown","type":"ascii-t","description":"Unknown text"},{"name":"Caption Length","type":"short","size":2,"description":"Length of caption + 1"},{"name":"Caption","type":"ascii-t","description":"Caption text"}],"source":{"file":"Projects/UOContent/Gumps/Base/OutgoingGumpPackets.cs","line":58},"category":"Gump","tags":["Gump"]},{"id":"0x8C","name":"Play Server Ack","description":"Sent after selecting a server. Contains connection details for the game server.","direction":"outgoing","isDynamic":false,"size":11,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x8C","description":"Packet identifier"},{"name":"IP Address","type":"uint","size":4,"description":"Game server IP address (little-endian)"},{"name":"Port","type":"short","size":2,"description":"Game server port"},{"name":"Auth ID","type":"int","size":4,"description":"Authentication ID for game login"}],"related":[{"id":"0xA0","relationship":"request","note":"The server selection request"},{"id":"0x91","relationship":"response","note":"Client sends game login with this authId"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":447},"category":"Account","tags":["Account"]},{"id":"0x90","name":"Map Details","description":"Sends map details including bounds, dimensions, and graphic ID. Pre-NewCharacterList clients.","direction":"outgoing","isDynamic":false,"size":19,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x90","description":"Packet identifier"},{"name":"Map Serial","type":"uint","size":4,"description":"Serial of the map item"},{"name":"Graphic ID","type":"short","size":2,"value":"0x139D","description":"Map gump graphic ID"},{"name":"Start X","type":"short","size":2,"description":"Map bounds start X coordinate"},{"name":"Start Y","type":"short","size":2,"description":"Map bounds start Y coordinate"},{"name":"End X","type":"short","size":2,"description":"Map bounds end X coordinate"},{"name":"End Y","type":"short","size":2,"description":"Map bounds end Y coordinate"},{"name":"Width","type":"short","size":2,"description":"Map width in pixels"},{"name":"Height","type":"short","size":2,"description":"Map height in pixels"}],"related":[{"id":"0x56","direction":"both","relationship":"related","note":"Map pin commands (client and server)"},{"id":"0xF5","relationship":"variant","note":"New Map Details for NewCharacterList clients"}],"source":{"file":"Projects/UOContent/Items/Maps/MapItemPackets.cs","line":78},"category":"Map","tags":["Map"]},{"id":"0x93","name":"Old Book Header","description":"Old format for book cover (fixed-size ASCII strings).","direction":"outgoing","isDynamic":false,"size":99,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x93","description":"Packet identifier"},{"name":"Book Serial","type":"uint","size":4,"description":"Serial of the book"},{"name":"Flags","type":"byte","size":1,"description":"Book flags"},{"name":"Page Count","type":"ushort","size":2,"description":"Number of pages"},{"name":"Title","type":"ascii","size":60,"description":"Book title (fixed 60 bytes)"},{"name":"Author","type":"ascii","size":30,"description":"Book author (fixed 30 bytes)"}],"related":[{"id":"0xD4","relationship":"variant","note":"New Book Header format (outgoing)"}],"notes":"Old format used by older clients. Title and author are fixed-size ASCII.","category":"Book","tags":["Book"]},{"id":"0x95","name":"Display Hue Picker","description":"Opens hue picker dialog on client.","direction":"outgoing","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x95","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Hue picker serial"},{"name":"Unknown","type":"short","size":2,"value":"0x0000","description":"Unknown"},{"name":"Item ID","type":"short","size":2,"description":"Item graphic to preview hue on"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":338},"category":"Player","tags":["Player"]},{"id":"0x97","name":"Move Player","description":"Server-initiated player movement. Forces the client to move in a direction (used for pushback effects, conveyors, etc).","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x97","description":"Packet identifier"},{"name":"Direction","type":"byte","size":1,"description":"Direction to move (0-7). Bit 0x80 indicates running."}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMovementPackets.cs","line":35},"category":"Movement","tags":["Movement"]},{"id":"0x98","name":"Mobile Name","description":"Returns a mobile's name in response to a name request.","direction":"outgoing","isDynamic":false,"size":37,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x98","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0025","description":"Packet length (37)"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Name","type":"ascii","size":30,"description":"Mobile name (null-terminated)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":301},"category":"Mobile","tags":["Mobile"]},{"id":"0x99","name":"Multi Target Request","description":"Requests the client to place a multi (house/boat) structure.","direction":"outgoing","isDynamic":false,"size":"Varies","variants":[{"version":"pre-HighSeas","name":"Pre-HighSeas (26 bytes)","size":26,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x99","description":"Packet identifier"},{"name":"Allow Ground","type":"bool","size":1,"description":"Allow ground targeting"},{"name":"Target ID","type":"int","size":4,"description":"Target cursor ID"},{"name":"Flags","type":"byte","size":1,"description":"Target cursor flags"},{"name":"Padding","type":"byte[]","size":11,"description":"Padding (zeros)"},{"name":"Multi ID","type":"short","size":2,"description":"Multi graphic ID"},{"name":"Offset X","type":"short","size":2,"description":"X offset for placement"},{"name":"Offset Y","type":"short","size":2,"description":"Y offset for placement"},{"name":"Offset Z","type":"short","size":2,"description":"Z offset for placement"}]},{"version":"HighSeas+","name":"HighSeas / Enhanced (30 bytes)","condition":"Classic >= 7.0.9.0, or Enhanced Client (any version)","size":30,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x99","description":"Packet identifier"},{"name":"Allow Ground","type":"bool","size":1,"description":"Allow ground targeting"},{"name":"Target ID","type":"int","size":4,"description":"Target cursor ID"},{"name":"Flags","type":"byte","size":1,"description":"Target cursor flags"},{"name":"Padding","type":"byte[]","size":11,"description":"Padding (zeros)"},{"name":"Multi ID","type":"short","size":2,"description":"Multi graphic ID"},{"name":"Offset X","type":"short","size":2,"description":"X offset for placement"},{"name":"Offset Y","type":"short","size":2,"description":"Y offset for placement"},{"name":"Offset Z","type":"short","size":2,"description":"Z offset for placement"},{"name":"Unknown","type":"int","size":4,"description":"Unknown (HighSeas extension)"}]}],"clientVersion":{"classic":{},"enhanced":{},"notes":"HighSeas (7.0.9.0+) adds 4 bytes. EC always uses 30-byte variant."},"source":{"file":"Projects/Server/Network/Packets/OutgoingTargetPackets.cs","line":23},"category":"Targeting","tags":["Targeting"]},{"id":"0x9E","name":"Vendor Sell List","description":"Sends the list of items the vendor will buy from the player.","direction":"outgoing","isDynamic":true,"size":"9+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x9E","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Vendor Serial","type":"uint","size":4,"description":"Serial of the vendor"},{"name":"Item Count","type":"ushort","size":2,"description":"Number of items"},{"name":"Items","type":"loop","description":"Sell items with prices","loop":{"countField":"itemCount","fields":[{"name":"Item Serial","type":"uint","size":4,"description":"Item serial"},{"name":"Item ID","type":"ushort","size":2,"description":"Item graphic ID"},{"name":"Hue","type":"ushort","size":2,"description":"Item hue"},{"name":"Amount","type":"ushort","size":2,"description":"Item amount"},{"name":"Price","type":"ushort","size":2,"description":"Price per unit"},{"name":"Name Length","type":"ushort","size":2,"description":"Name length"},{"name":"Name","type":"ascii","description":"Item name"}]}}],"related":[{"id":"0x9F","relationship":"response","note":"Vendor Sell Reply from client"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingVendorSellPackets.cs","line":25},"category":"Vendor","tags":["Vendor"]},{"id":"0xA1","name":"Mobile Hits","description":"Updates a mobile's hit points. Can be normalized to 0-100 scale for non-self mobiles.","direction":"outgoing","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA1","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Hits Max","type":"short","size":2,"description":"Maximum hits"},{"name":"Hits","type":"short","size":2,"description":"Current hits"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":210},"category":"Mobile","tags":["Mobile"]},{"id":"0xA2","name":"Mobile Mana","description":"Updates a mobile's mana points.","direction":"outgoing","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA2","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Mana Max","type":"short","size":2,"description":"Maximum mana"},{"name":"Mana","type":"short","size":2,"description":"Current mana"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":235},"category":"Mobile","tags":["Mobile"]},{"id":"0xA3","name":"Mobile Stamina","description":"Updates a mobile's stamina points.","direction":"outgoing","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA3","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Stam Max","type":"short","size":2,"description":"Maximum stamina"},{"name":"Stam","type":"short","size":2,"description":"Current stamina"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":260},"category":"Mobile","tags":["Mobile"]},{"id":"0xA5","name":"Launch Browser","description":"Opens a URL in client's web browser.","direction":"outgoing","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA5","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"URL","type":"ascii-t","description":"URL to open"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":180},"category":"Player","tags":["Player"]},{"id":"0xA6","name":"Scroll Message","description":"Displays a scrollable tips/message window.","direction":"outgoing","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA6","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Type","type":"byte","size":1,"description":"Scroll type"},{"name":"Tip Number","type":"int","size":4,"description":"Tip/message number"},{"name":"Text Length","type":"ushort","size":2,"description":"Length of text"},{"name":"Text","type":"ascii","description":"Message text"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":291},"category":"Player","tags":["Player"]},{"id":"0xA8","name":"Account Login Ack (Server List)","description":"Sent after successful account login. Contains the list of available game servers.","direction":"outgoing","isDynamic":true,"size":"6 + (40 x serverCount)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA8","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"System Info Flag","type":"byte","size":1,"value":"0x5D","description":"System info flag"},{"name":"Server Count","type":"ushort","size":2,"description":"Number of servers in list"},{"name":"Servers","type":"array","description":"Server list entries","loop":{"countField":"serverCount","fields":[{"name":"Index","type":"ushort","size":2,"description":"Server index"},{"name":"Name","type":"ascii","size":32,"description":"Server name"},{"name":"Full Percent","type":"byte","size":1,"description":"Server load percentage"},{"name":"Timezone","type":"sbyte","size":1,"description":"Server timezone offset"},{"name":"IP Address","type":"uint","size":4,"description":"Server IP address (IPv4)"}]}}],"related":[{"id":"0x80","relationship":"request","note":"The successful login request"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":411},"category":"Account","tags":["Account"]},{"id":"0xA9","name":"Character List","description":"Sent after game login. Contains the list of characters on the account and starting city information. Extended format in 7.0.13.0+ includes city coordinates.","direction":"outgoing","isDynamic":true,"size":"Varies","variants":[{"version":"Classic","name":"Pre-7.0.13.0 Format","condition":"Client version < 7.0.13.0","size":"9+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA9","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Char Count","type":"byte","size":1,"description":"Number of character slots (1, 5, 6, or 7)"},{"name":"Characters","type":"loop","description":"Character list entries (60 bytes each)","loop":{"countField":"charCount","itemSize":60,"fields":[{"name":"Name","type":"ascii","size":30,"description":"Character name (empty if slot unused)"},{"name":"Password","type":"ascii","size":30,"description":"Always empty (legacy field)"}]}},{"name":"City Count","type":"byte","size":1,"description":"Number of starting cities"},{"name":"Cities","type":"loop","description":"Starting city entries (63 bytes each)","loop":{"countField":"cityCount","itemSize":63,"fields":[{"name":"Index","type":"byte","size":1,"description":"City index"},{"name":"City Name","type":"ascii","size":31,"description":"City name"},{"name":"Building Name","type":"ascii","size":31,"description":"Building/tavern name"}]}},{"name":"Flags","type":"bitfield","size":4,"description":"Character list flags","flags":[{"bit":"0","name":"Unknown1","description":"Unknown"},{"bit":"1","name":"Overwrite Config","description":"Overwrite configuration file"},{"bit":"2","name":"One Character Slot","description":"Limit to 1 character slot"},{"bit":"3","name":"Context Menus","description":"Enable context menus"},{"bit":"4","name":"Slot Limit","description":"Limit character slots"},{"bit":"5","name":"AOS","description":"Age of Shadows features"},{"bit":"6","name":"Sixth Character Slot","description":"Enable 6th character slot"},{"bit":"7","name":"SE","description":"Samurai Empire features"},{"bit":"8","name":"ML","description":"Mondain's Legacy features"},{"bit":"9","name":"Unknown2","description":"Unknown"},{"bit":"10","name":"KR","description":"Kingdom Reborn features"},{"bit":"11","name":"SA","description":"Stygian Abyss features"},{"bit":"12","name":"HS","description":"High Seas features"},{"bit":"13","name":"Seventh Character Slot","description":"Enable 7th character slot"},{"bit":"14","name":"Unknown3","description":"Unknown"},{"bit":"15","name":"New Movement","description":"New movement system"},{"bit":"16","name":"New Felucca Areas","description":"New Felucca areas"}]}]},{"version":"NewCharacterList (7.0.13.0+)","name":"Extended City Format","condition":"Client version >= 7.0.13.0 (NewCharacterList)","size":"11+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA9","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Char Count","type":"byte","size":1,"description":"Number of character slots (1, 5, 6, or 7)"},{"name":"Characters","type":"loop","description":"Character list entries (60 bytes each)","loop":{"countField":"charCount","itemSize":60,"fields":[{"name":"Name","type":"ascii","size":30,"description":"Character name (empty if slot unused)"},{"name":"Password","type":"ascii","size":30,"description":"Always empty (legacy field)"}]}},{"name":"City Count","type":"byte","size":1,"description":"Number of starting cities"},{"name":"Cities","type":"loop","description":"Starting city entries (89 bytes each, extended format)","loop":{"countField":"cityCount","itemSize":89,"fields":[{"name":"Index","type":"byte","size":1,"description":"City index"},{"name":"City Name","type":"ascii","size":32,"description":"City name (1 byte longer than classic)"},{"name":"Building Name","type":"ascii","size":32,"description":"Building/tavern name (1 byte longer than classic)"},{"name":"X","type":"int","size":4,"description":"X coordinate of starting location"},{"name":"Y","type":"int","size":4,"description":"Y coordinate of starting location"},{"name":"Z","type":"int","size":4,"description":"Z coordinate of starting location"},{"name":"Map ID","type":"int","size":4,"description":"Map ID for starting location"},{"name":"Cliloc","type":"int","size":4,"description":"Cliloc ID for city description"},{"name":"Unknown","type":"int","size":4,"value":"0","description":"Unknown (always 0)"}]}},{"name":"Flags","type":"bitfield","size":4,"description":"Character list flags (same as classic format)","flags":[{"bit":"2","name":"One Character Slot","description":"Limit to 1 character slot"},{"bit":"3","name":"Context Menus","description":"Enable context menus"},{"bit":"4","name":"Slot Limit","description":"Limit character slots"},{"bit":"5","name":"AOS","description":"Age of Shadows features"},{"bit":"6","name":"Sixth Character Slot","description":"Enable 6th character slot"},{"bit":"7","name":"SE","description":"Samurai Empire features"},{"bit":"8","name":"ML","description":"Mondain's Legacy features"},{"bit":"11","name":"SA","description":"Stygian Abyss features"},{"bit":"12","name":"HS","description":"High Seas features"},{"bit":"13","name":"Seventh Character Slot","description":"Enable 7th character slot"}]},{"name":"Last Char Slot","type":"short","size":2,"value":"-1","description":"Last played character slot index (-1 if none)"}]}],"related":[{"id":"0x91","relationship":"request","note":"Game login request"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":293},"category":"Account","tags":["Account"]},{"id":"0xAA","name":"Change Combatant","description":"Notifies client of current combat target.","direction":"outgoing","isDynamic":false,"size":5,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xAA","description":"Packet identifier"},{"name":"Combatant Serial","type":"uint","size":4,"description":"Serial of current combatant (0 = none)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingCombatPackets.cs","line":43},"category":"Combat","tags":["Combat"]},{"id":"0xAE","name":"Unicode Message","description":"Server sends Unicode-encoded message to client.","direction":"outgoing","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xAE","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Serial of speaker (0xFFFFFFFF for system)"},{"name":"Graphic","type":"short","size":2,"description":"Body graphic of speaker"},{"name":"Type","type":"byte","size":1,"description":"Message type (see 0x1C)"},{"name":"Hue","type":"short","size":2,"description":"Text color hue"},{"name":"Font","type":"short","size":2,"description":"Font ID"},{"name":"Language","type":"ascii","size":4,"description":"Language code (e.g., 'ENU')"},{"name":"Name","type":"ascii","size":30,"description":"Speaker name"},{"name":"Text","type":"utf16be-t","description":"Message text (Big Endian Unicode)"}],"related":[{"id":"0xAD","relationship":"request","note":"Unicode Speech from client"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMessagePackets.cs","line":180},"category":"Message","tags":["Message"]},{"id":"0xAF","name":"Death Animation","description":"Triggers the death animation and corpse creation for a mobile.","direction":"outgoing","isDynamic":false,"size":13,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xAF","description":"Packet identifier"},{"name":"Killed Serial","type":"uint","size":4,"description":"Serial of the killed mobile"},{"name":"Corpse Serial","type":"uint","size":4,"description":"Serial of the corpse created"},{"name":"Unknown","type":"int","size":4,"description":"Unknown (always 0)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":78},"category":"Mobile","tags":["Mobile"]},{"id":"0xB2","name":"Chat Message","description":"Server sends chat system messages and commands to the client.","direction":"outgoing","isDynamic":true,"size":"13+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB2","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Command","type":"ushort","size":2,"description":"Chat command number (original number minus 20)"},{"name":"Language","type":"ascii","size":4,"description":"Language code (e.g., 'enu' for English)"},{"name":"Param 1","type":"utf16be-t","description":"First parameter (Big Endian Unicode, null-terminated)"},{"name":"Param 2","type":"utf16be-t","description":"Second parameter (Big Endian Unicode, null-terminated)"}],"related":[{"id":"0xB3","direction":"incoming","relationship":"request","note":"Client sends Chat Action"},{"id":"0xB5","direction":"incoming","relationship":"request","note":"Client sends Open Chat Window Request"}],"notes":"Part of the in-game chat system. Command numbers are offset by -20 from original values.","source":{"file":"Projects/UOContent/Engines/Chat/ChatPackets.cs","line":104},"category":"Chat","tags":["Chat"]},{"id":"0xB7","name":"Help Response","description":"Server sends help text response to client.","direction":"outgoing","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Serial of entity"},{"name":"Text","type":"utf16be-t","description":"Help text"}],"related":[{"id":"0xB6","relationship":"request","note":"Object Help Request from client"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMessagePackets.cs","line":263},"category":"Message","tags":["Message"]},{"id":"0xB8","name":"Display Profile","description":"Displays a mobile's profile.","direction":"outgoing","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB8","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Serial of mobile"},{"name":"Header","type":"ascii-t","description":"Profile header"},{"name":"Footer","type":"utf16be-t","description":"Profile footer"},{"name":"Body","type":"utf16be-t","description":"Profile body text"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":66},"category":"Player","tags":["Player"]},{"id":"0xB9","name":"Supported Features","description":"Informs the client which features are enabled on the server. Feature flags control T2A, LBR, AOS, SE, ML, SA, HS features and character slot limits.","direction":"outgoing","isDynamic":false,"size":"Varies","variants":[{"version":"Classic","name":"16-bit Feature Flags","condition":"Client without ExtendedSupportedFeatures","size":3,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB9","description":"Packet identifier"},{"name":"Features","type":"bitfield","size":2,"description":"16-bit feature flags bitmask","flags":[{"bit":"0","name":"T2A","description":"The Second Age features"},{"bit":"1","name":"Renaissance","description":"Renaissance features"},{"bit":"2","name":"Third Dawn","description":"Third Dawn (3D client) features"},{"bit":"3","name":"LBR","description":"Lord Blackthorn's Revenge features"},{"bit":"4","name":"AOS","description":"Age of Shadows features"},{"bit":"5","name":"Sixth Character Slot","description":"Enable 6th character slot"},{"bit":"6","name":"SE","description":"Samurai Empire features"},{"bit":"7","name":"ML","description":"Mondain's Legacy features"},{"bit":"8","name":"Eighth Age","description":"Eighth Age splash screen"},{"bit":"9","name":"Ninth Age","description":"Ninth Age splash screen"},{"bit":"10","name":"Tenth Age","description":"Tenth Age splash screen"},{"bit":"11","name":"Increased Storage","description":"Increased storage"},{"bit":"12","name":"Seventh Character Slot","description":"Enable 7th character slot"},{"bit":"13","name":"Roleplay Faces","description":"Roleplay face selection"},{"bit":"14","name":"Trial Account","description":"Trial account flag"},{"bit":"15","name":"Live Account","description":"Live (paid) account flag"}]}]},{"version":"Extended","name":"32-bit Feature Flags","condition":"Client with ExtendedSupportedFeatures","size":5,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB9","description":"Packet identifier"},{"name":"Features","type":"bitfield","size":4,"description":"32-bit feature flags bitmask (includes all 16-bit flags plus expansion flags)","flags":[{"bit":"0","name":"T2A","description":"The Second Age features"},{"bit":"1","name":"Renaissance","description":"Renaissance features"},{"bit":"2","name":"Third Dawn","description":"Third Dawn (3D client) features"},{"bit":"3","name":"LBR","description":"Lord Blackthorn's Revenge features"},{"bit":"4","name":"AOS","description":"Age of Shadows features"},{"bit":"5","name":"Sixth Character Slot","description":"Enable 6th character slot"},{"bit":"6","name":"SE","description":"Samurai Empire features"},{"bit":"7","name":"ML","description":"Mondain's Legacy features"},{"bit":"8","name":"Eighth Age","description":"Eighth Age splash screen"},{"bit":"9","name":"Ninth Age","description":"Ninth Age splash screen"},{"bit":"10","name":"Tenth Age","description":"Tenth Age splash screen"},{"bit":"11","name":"Increased Storage","description":"Increased storage"},{"bit":"12","name":"Seventh Character Slot","description":"Enable 7th character slot"},{"bit":"13","name":"Roleplay Faces","description":"Roleplay face selection"},{"bit":"14","name":"Trial Account","description":"Trial account flag"},{"bit":"15","name":"Live Account","description":"Live (paid) account flag"},{"bit":"16","name":"SA","description":"Stygian Abyss features"},{"bit":"17","name":"HS","description":"High Seas features"},{"bit":"18","name":"Gothic","description":"Gothic housing tiles"},{"bit":"19","name":"Rustic","description":"Rustic housing tiles"},{"bit":"20","name":"Jungle","description":"Jungle housing tiles"},{"bit":"21","name":"Shadowguard","description":"Shadowguard content"},{"bit":"22","name":"TOL","description":"Time of Legends features"},{"bit":"23","name":"EJ","description":"Endless Journey (F2P) features"}]}]}],"clientVersion":{"classic":{},"enhanced":{},"notes":"ExtendedSupportedFeatures determines which variant is sent"},"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":140},"category":"Account","tags":["Account"]},{"id":"0xBA","name":"Quest Arrow","description":"Sets or cancels the quest tracking arrow on the client.","direction":"outgoing","isDynamic":false,"size":"Varies","variants":[{"name":"Pre-High Seas Set Arrow","condition":"command == 1 (Set), pre-HighSeas client","size":6,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBA","description":"Packet identifier"},{"name":"Command","type":"byte","size":1,"value":"0x01","description":"Set arrow command"},{"name":"X","type":"short","size":2,"description":"Target X coordinate"},{"name":"Y","type":"short","size":2,"description":"Target Y coordinate"}]},{"name":"Pre-High Seas Cancel Arrow","condition":"command == 0 (Cancel), pre-HighSeas client","size":6,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBA","description":"Packet identifier"},{"name":"Command","type":"byte","size":1,"value":"0x00","description":"Cancel arrow command"},{"name":"X","type":"short","size":2,"value":"-1","description":"X coordinate (-1)"},{"name":"Y","type":"short","size":2,"value":"-1","description":"Y coordinate (-1)"}]},{"name":"High Seas","condition":"HighSeas client (7.0.9.0+)","size":10,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBA","description":"Packet identifier"},{"name":"Command","type":"byte","size":1,"description":"Command (0 = cancel, 1 = set)"},{"name":"X","type":"short","size":2,"description":"Target X coordinate"},{"name":"Y","type":"short","size":2,"description":"Target Y coordinate"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of tracked target"}]}],"related":[{"id":"0xBF/0x07","relationship":"request","note":"Quest Arrow Click from client"}],"clientVersion":{"classic":{},"enhanced":{},"notes":"HighSeas (7.0.9.0+) adds target serial. Pre-HS clients use 6-byte variant, HS+ clients use 10-byte variant."},"source":{"file":"Projects/UOContent/Skills/Tracking/OutgoingArrowPackets.cs","line":29},"category":"Quest","tags":["Quest"]},{"id":"0xBC","name":"Season Change","description":"Changes the visual season on client.","direction":"outgoing","isDynamic":false,"size":3,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBC","description":"Packet identifier"},{"name":"Season","type":"enum","enumType":"sequential","size":1,"description":"Season value","values":[{"value":0,"name":"Spring","description":"Spring season"},{"value":1,"name":"Summer","description":"Summer season"},{"value":2,"name":"Fall","description":"Fall/Autumn season"},{"value":3,"name":"Winter","description":"Winter season"},{"value":4,"name":"Desolation","description":"Desolation (dead trees)"}]},{"name":"Play Sound","type":"bool","size":1,"description":"Play season change sound"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":244},"category":"Player","tags":["Player"]},{"id":"0xBD","name":"Client Version Request","description":"Request for the client to send its version string.","direction":"outgoing","isDynamic":false,"size":3,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBD","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0003","description":"Packet length"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingAccountPackets.cs","line":112},"notes":"Same packet ID (0xBD) is used for both request (server) and response (client).","category":"Account","tags":["Account"]},{"id":"0xBE","name":"Assistant Version Request","description":"Server requests assistant version information from the client.","direction":"outgoing","isDynamic":false,"size":3,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBE","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0003","description":"Packet length (3)"}],"source":{"file":"Projects/UOContent/Assistants/AssistantHandler.cs","line":122},"category":"Assistant","tags":["Assistant"]},{"id":"0xBF","subId":"0x04","name":"Close Gump","description":"Instructs client to close a specific gump.","direction":"outgoing","isDynamic":false,"size":13,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"13","description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0004","description":"Close Gump subcommand"},{"name":"Gump Type ID","type":"int","size":4,"description":"Gump type ID to close"},{"name":"Button ID","type":"int","size":4,"description":"Button ID (0 to close without response)"}],"source":{"file":"Projects/UOContent/Gumps/Base/OutgoingGumpPackets.cs","line":83},"category":"Gump","tags":["Gump"]},{"id":"0xBF","subId":"0x06","name":"Party Message","description":"Party system messages with various subcommands.","direction":"outgoing","isDynamic":true,"size":"Varies","variants":[{"name":"Member List","condition":"command == 0x01","size":"7 + (memberCount x 4)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0006","description":"Party subcommand"},{"name":"Command","type":"byte","size":1,"value":"0x01","description":"Member list command"},{"name":"Member Count","type":"byte","size":1,"description":"Number of party members"},{"name":"Members","type":"loop","description":"Party members","loop":{"countField":"memberCount","fields":[{"name":"Serial","type":"uint","size":4,"description":"Member's serial"}]}}]},{"name":"Remove Member","condition":"command == 0x02","size":"11 + (memberCount x 4)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0006","description":"Party subcommand"},{"name":"Command","type":"byte","size":1,"value":"0x02","description":"Remove member command"},{"name":"Member Count","type":"byte","size":1,"description":"Number of remaining members"},{"name":"Removed Serial","type":"uint","size":4,"description":"Serial of removed member"},{"name":"Members","type":"loop","description":"Remaining party members","loop":{"countField":"memberCount","fields":[{"name":"Serial","type":"uint","size":4,"description":"Member's serial"}]}}]},{"name":"Private Message","condition":"command == 0x03","size":"12 + (text.Length x 2)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0006","description":"Party subcommand"},{"name":"Command","type":"byte","size":1,"value":"0x03","description":"Private message command"},{"name":"Sender Serial","type":"uint","size":4,"description":"Serial of message sender"},{"name":"Text","type":"utf16be-t","description":"Message text"}]},{"name":"Public Message","condition":"command == 0x04","size":"12 + (text.Length x 2)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0006","description":"Party subcommand"},{"name":"Command","type":"byte","size":1,"value":"0x04","description":"Public message command"},{"name":"Sender Serial","type":"uint","size":4,"description":"Serial of message sender"},{"name":"Text","type":"utf16be-t","description":"Message text"}]},{"name":"Party Invitation","condition":"command == 0x07","size":10,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"10","description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0006","description":"Party subcommand"},{"name":"Command","type":"byte","size":1,"value":"0x07","description":"Invitation command"},{"name":"Leader Serial","type":"uint","size":4,"description":"Serial of party leader"}]}],"related":[{"id":"0xBF/0x06","relationship":"request","note":"Party Message from client"}],"source":{"file":"Projects/UOContent/Engines/Party/PartyPackets.cs","line":28},"category":"Party","tags":["Party"]},{"id":"0xBF","subId":"0x08","name":"Map Change","description":"Notifies client of a facet/map change.","direction":"outgoing","isDynamic":false,"size":6,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0006","description":"Packet length (6)"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0008","description":"Map Change subcommand"},{"name":"Map ID","type":"enum","enumType":"sequential","size":1,"description":"Map/Facet ID","values":[{"value":0,"name":"Felucca","description":"Felucca facet"},{"value":1,"name":"Trammel","description":"Trammel facet"},{"value":2,"name":"Ilshenar","description":"Ilshenar facet"},{"value":3,"name":"Malas","description":"Malas facet"},{"value":4,"name":"Tokuno","description":"Tokuno Islands facet"},{"value":5,"name":"Ter Mur","description":"Ter Mur facet"}]}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMapPackets.cs","line":55},"category":"Map","tags":["Map"]},{"id":"0xBF","subId":"0x10","name":"Display Equipment Info","description":"Displays detailed equipment information including crafter name and magical properties.","direction":"outgoing","isDynamic":true,"size":"17+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0010","description":"Display Equipment Info subcommand"},{"name":"Item Serial","type":"uint","size":4,"description":"Serial of the item"},{"name":"Cliloc Number","type":"int","size":4,"description":"Base cliloc number for item name"},{"name":"Crafter Info","type":"conditional","description":"Crafter information (if present)","condition":"crafterName.Length > 0","fields":[{"name":"Crafted By","type":"int","size":4,"value":"-3","description":"Crafter marker"},{"name":"Crafter Name Length","type":"ushort","size":2,"description":"Length of crafter name"},{"name":"Crafter Name","type":"ascii","description":"Crafter name"}]},{"name":"Unidentified","type":"conditional","description":"Unidentified marker","condition":"unidentified","fields":[{"name":"Unidentified Marker","type":"int","size":4,"value":"-4","description":"Unidentified marker"}]},{"name":"Attributes","type":"loop","description":"Equipment attributes","loop":{"countField":"variable","fields":[{"name":"Attribute Number","type":"int","size":4,"description":"Attribute cliloc number"},{"name":"Charges","type":"short","size":2,"description":"Charges (-1 if not applicable)"}]}},{"name":"Terminator","type":"int","size":4,"value":"-1","description":"End of attributes marker"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingEquipmentPackets.cs","line":37},"category":"Equipment","tags":["Equipment"]},{"id":"0xBF","subId":"0x14","name":"Display Context Menu","description":"Displays a context menu for an entity.","direction":"outgoing","isDynamic":true,"size":"Varies","variants":[{"name":"Old Format","condition":"command == 0x01 (pre-NewHaven)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0014","description":"Context Menu subcommand"},{"name":"Command","type":"short","size":2,"value":"0x0001","description":"Old format command"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of the target entity"},{"name":"Entry Count","type":"byte","size":1,"description":"Number of menu entries"},{"name":"Entries","type":"loop","description":"Menu entries","loop":{"countField":"entryCount","fields":[{"name":"Index","type":"short","size":2,"description":"Entry index"},{"name":"Cliloc Offset","type":"ushort","size":2,"description":"Cliloc number - 3000000"},{"name":"Flags","type":"bitfield","size":2,"description":"Entry flags","flags":[{"bit":"0","name":"Disabled","description":"Entry is disabled"},{"bit":"1","name":"Arrow","description":"Show arrow"},{"bit":"2","name":"Highlighted","description":"Entry is highlighted"},{"bit":"5","name":"Colored","description":"Entry uses custom color"}]},{"name":"Hue","type":"short","size":2,"description":"Text hue (if Colored flag set)","condition":"flags & 0x20"}]}}]},{"name":"New Format","condition":"command == 0x02 (NewHaven+)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0014","description":"Context Menu subcommand"},{"name":"Command","type":"short","size":2,"value":"0x0002","description":"New format command"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of the target entity"},{"name":"Entry Count","type":"byte","size":1,"description":"Number of menu entries"},{"name":"Entries","type":"loop","description":"Menu entries","loop":{"countField":"entryCount","fields":[{"name":"Cliloc Number","type":"int","size":4,"description":"Full cliloc number"},{"name":"Index","type":"short","size":2,"description":"Entry index"},{"name":"Flags","type":"short","size":2,"description":"Entry flags (see Old Format)"}]}}]}],"related":[{"id":"0xBF/0x13","relationship":"request","note":"Context Menu Request from client"},{"id":"0xBF/0x15","relationship":"response","note":"Context Menu Response from client"}],"clientVersion":{"classic":{},"enhanced":{},"notes":"NewHaven clients (6.0.0.0+) use command 0x02"},"source":{"file":"Projects/UOContent/Context Menus/ContextMenuSystem.cs","line":142},"category":"Context Menu","tags":["Context Menu"]},{"id":"0xBF","subId":"0x18","name":"Map Patches","description":"Sends map patch information for static and land blocks.","direction":"outgoing","isDynamic":false,"size":41,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0029","description":"Packet length (41)"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0018","description":"Map Patches subcommand"},{"name":"Map Count","type":"int","size":4,"value":"4","description":"Number of maps (always 4)"},{"name":"Patches","type":"loop","description":"Patch counts for each map (Felucca, Trammel, Ilshenar, Malas)","loop":{"countField":"4","fields":[{"name":"Static Blocks","type":"int","size":4,"description":"Number of patched static blocks"},{"name":"Land Blocks","type":"int","size":4,"description":"Number of patched land blocks"}]}}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMapPackets.cs","line":25},"category":"Map","tags":["Map"]},{"id":"0xBF/0x19","name":"Extended Status","description":"Multi-purpose status packet. The Type byte determines the payload: Type 0 for pet bonded status, Type 2/5 for player stat locks.","direction":"outgoing","isDynamic":false,"size":"Varies","fields":[],"variants":[{"name":"Bonded Status (Type 0)","condition":"Type = 0: Pet bonding status","size":11,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"11","description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0019","description":"Extended Status subcommand"},{"name":"Type","type":"byte","size":1,"value":"0x00","description":"Type 0 = Bonded Status"},{"name":"Serial","type":"uint","size":4,"description":"Pet mobile serial"},{"name":"Bonded","type":"bool","size":1,"description":"True if pet is bonded to owner"}],"notes":"Sent when a pet's bonded status changes or when pet info is requested."},{"name":"Stat Lock Info - Classic (Type 2)","condition":"Type = 2: Classic Client stat locks","size":12,"clientVersion":{"classic":{}},"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"12","description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0019","description":"Extended Status subcommand"},{"name":"Type","type":"byte","size":1,"value":"0x02","description":"Type 2 = Stat Lock Info (Classic Client)"},{"name":"Serial","type":"uint","size":4,"description":"Player mobile serial"},{"name":"Unknown","type":"byte","size":1,"value":"0x00","description":"Unknown (always 0)"},{"name":"Lock Bits","type":"bitfield","size":1,"description":"Packed stat lock states (00SSDDII)","flags":[{"bit":"5-4","name":"Str Lock","description":"Strength lock (value << 4)"},{"bit":"3-2","name":"Dex Lock","description":"Dexterity lock (value << 2)"},{"bit":"1-0","name":"Int Lock","description":"Intelligence lock (value << 0)"}],"values":[{"value":0,"name":"Up","description":"Stat gains enabled"},{"value":1,"name":"Down","description":"Stat decreases enabled"},{"value":2,"name":"Locked","description":"Stat locked"}],"notes":"Formula: (StrLock << 4) | (DexLock << 2) | IntLock"}]},{"name":"Stat Lock Info - Enhanced (Type 5)","condition":"Type = 5: Enhanced Client stat locks","size":12,"clientVersion":{"enhanced":{}},"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"12","description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0019","description":"Extended Status subcommand"},{"name":"Type","type":"byte","size":1,"value":"0x05","description":"Type 5 = Stat Lock Info (Enhanced Client)"},{"name":"Serial","type":"uint","size":4,"description":"Player mobile serial"},{"name":"Unknown","type":"byte","size":1,"value":"0x00","description":"Unknown (always 0)"},{"name":"Lock Bits","type":"bitfield","size":1,"description":"Packed stat lock states (00SSDDII)","flags":[{"bit":"5-4","name":"Str Lock","description":"Strength lock (value << 4)"},{"bit":"3-2","name":"Dex Lock","description":"Dexterity lock (value << 2)"},{"bit":"1-0","name":"Int Lock","description":"Intelligence lock (value << 0)"}],"values":[{"value":0,"name":"Up","description":"Stat gains enabled"},{"value":1,"name":"Down","description":"Stat decreases enabled"},{"value":2,"name":"Locked","description":"Stat locked"}],"notes":"Formula: (StrLock << 4) | (DexLock << 2) | IntLock"}],"notes":"Enhanced Client uses Type 5 instead of Type 2"}],"notes":"The Type byte after the sub-command determines the packet structure. Type 0 is for pet bonding, Types 2/5 are for player stat locks (Classic/Enhanced Client respectively).","source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":36},"category":"Player","tags":["Player","Mobile"]},{"id":"0xBF","subId":"0x1B","name":"New Spellbook Content","description":"Sends spellbook contents using AOS format with a 64-bit bitmask of known spells.","direction":"outgoing","isDynamic":false,"size":23,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0017","description":"Packet length (23)"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x001B","description":"Subcommand (New Spellbook Content)"},{"name":"Command","type":"short","size":2,"value":"0x0001","description":"Command (always 1)"},{"name":"Book Serial","type":"uint","size":4,"description":"Serial of the spellbook"},{"name":"Graphic","type":"short","size":2,"description":"Spellbook graphic ID"},{"name":"Offset","type":"short","size":2,"description":"Spell offset (circle/school start)"},{"name":"Spell Bits","type":"ulong","size":8,"description":"64-bit mask of known spells (written byte-by-byte, Little Endian)"}],"related":[{"id":"0x3C","relationship":"variant","note":"Old Spellbook Content for pre-AOS clients"}],"clientVersion":{"classic":{"min":"5.0.0a"},"enhanced":{},"notes":"NewSpellbook feature (Core.AOS)"},"notes":"Used when Core.AOS && ns.NewSpellbook. Otherwise, old 0x3C format is used with spells as pseudo-items.","source":{"file":"Projects/Server/Network/Packets/OutgoingContainerPackets.cs","line":46},"category":"Container","tags":["Container","Spell","Spellbook","Extended Commands (0xBF)"]},{"id":"0xBF","subId":"0x1D","name":"Design State General","description":"Sends house design revision information. Client requests full details if revision differs.","direction":"outgoing","isDynamic":false,"size":13,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x000D","description":"Packet length (13)"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x001D","description":"Design State General subcommand"},{"name":"House Serial","type":"uint","size":4,"description":"Serial of the house"},{"name":"Revision","type":"int","size":4,"description":"Design revision number"}],"related":[{"id":"0xD8","relationship":"related","note":"Full design details requested if revision differs"}],"source":{"file":"Projects/UOContent/Multis/Houses/HousePackets.cs","line":72},"category":"House","tags":["Extended Commands (0xBF)","House"]},{"id":"0xBF","subId":"0x20","name":"Begin House Customization","description":"Notifies client to enter house customization mode.","direction":"outgoing","isDynamic":false,"size":17,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0011","description":"Packet length (17)"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0020","description":"House Customization subcommand"},{"name":"House Serial","type":"uint","size":4,"description":"Serial of the house"},{"name":"Command","type":"byte","size":1,"value":"0x04","description":"Begin customization command"},{"name":"Unknown 1","type":"ushort","size":2,"value":"0x0000","description":"Unknown (always 0)"},{"name":"Unknown 2","type":"ushort","size":2,"value":"0xFFFF","description":"Unknown (always 0xFFFF)"},{"name":"Unknown 3","type":"ushort","size":2,"value":"0xFFFF","description":"Unknown (always 0xFFFF)"},{"name":"Unknown 4","type":"byte","size":1,"value":"0xFF","description":"Unknown (always 0xFF)"}],"related":[{"id":"0xBF/0x20","relationship":"variant","note":"End House Customization uses command 0x05"}],"source":{"file":"Projects/UOContent/Multis/Houses/HousePackets.cs","line":30},"category":"House","tags":["Extended Commands (0xBF)","House"]},{"id":"0xBF","subId":"0x21","name":"Clear Weapon Ability","description":"Clears the currently selected weapon ability.","direction":"outgoing","isDynamic":false,"size":5,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"5","description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0021","description":"Clear Weapon Ability subcommand"}],"source":{"file":"Projects/UOContent/Items/Weapons/Abilities/WeaponAbilityPackets.cs","line":37},"category":"Weapon Ability","tags":["Weapon Ability"]},{"id":"0xBF/0x22","name":"Damage (Old)","description":"Shows damage dealt to a mobile (pre-5.0.0a clients).","direction":"outgoing","isDynamic":false,"size":11,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"11","description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x22","description":"Subcommand (Damage)"},{"name":"Unknown","type":"byte","size":1,"value":"0x01","description":"Unknown (always 1)"},{"name":"Serial","type":"uint","size":4,"description":"Serial of damaged mobile"},{"name":"Damage","type":"byte","size":1,"description":"Damage amount (clamped 0-255)"}],"clientVersion":{"classic":{"max":"5.0.0a"},"notes":"For Classic Client before DamagePacket feature. Not used by Enhanced Client."},"notes":"Damage is capped at 255 for old clients. Classic Client only; Enhanced Client uses 0x0B packet.","source":{"file":"Projects/Server/Network/Packets/OutgoingDamagePackets.cs","line":40},"category":"Combat","tags":["Combat"]},{"id":"0xBF","subId":"0x25","name":"Toggle Special Ability","description":"Toggles a special weapon ability on or off.","direction":"outgoing","isDynamic":false,"size":8,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"8","description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0025","description":"Toggle Special Ability subcommand"},{"name":"Ability ID","type":"short","size":2,"description":"Ability ID"},{"name":"Active","type":"bool","size":1,"description":"True if ability is active"}],"source":{"file":"Projects/UOContent/Items/Weapons/Abilities/WeaponAbilityPackets.cs","line":40},"category":"Weapon Ability","tags":["Weapon Ability"]},{"id":"0xBF","subId":"0x26","name":"Speed Control","description":"Controls the player's movement speed. Used for mount speed changes, walk/run restrictions, etc.","direction":"outgoing","isDynamic":false,"size":6,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0006","description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0026","description":"Sub-command for speed control"},{"name":"Speed Setting","type":"enum","size":1,"description":"Movement speed mode","values":[{"value":"0","name":"Disable","description":"Normal speed (remove override)"},{"value":"1","name":"MountSpeed","description":"Force mounted movement speed"},{"value":"2","name":"WalkOnly","description":"Force walk speed only"}]}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMovementPackets.cs","line":31},"category":"Movement","tags":["Movement"]},{"id":"0xC0","name":"Hued Effect","description":"Displays a graphical effect with hue and render mode.","direction":"outgoing","isDynamic":false,"size":36,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xC0","description":"Packet identifier"},{"name":"Effect Type","type":"enum","enumType":"sequential","size":1,"description":"Effect type","values":[{"value":0,"name":"Moving","description":"Effect moves between two points"},{"value":1,"name":"Lightning","description":"Lightning bolt effect"},{"value":2,"name":"Fixed XYZ","description":"Effect at fixed location"},{"value":3,"name":"Fixed From","description":"Effect attached to source"}]},{"name":"Source Serial","type":"uint","size":4,"description":"Serial of source entity"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of target entity"},{"name":"Item ID","type":"short","size":2,"description":"Effect graphic ID"},{"name":"Src X","type":"short","size":2,"description":"Source X coordinate"},{"name":"Src Y","type":"short","size":2,"description":"Source Y coordinate"},{"name":"Src Z","type":"sbyte","size":1,"description":"Source Z coordinate"},{"name":"Dst X","type":"short","size":2,"description":"Destination X coordinate"},{"name":"Dst Y","type":"short","size":2,"description":"Destination Y coordinate"},{"name":"Dst Z","type":"sbyte","size":1,"description":"Destination Z coordinate"},{"name":"Speed","type":"byte","size":1,"description":"Effect speed"},{"name":"Duration","type":"byte","size":1,"description":"Effect duration"},{"name":"Unknown1","type":"byte","size":1,"value":"0x00","description":"Unknown"},{"name":"Unknown2","type":"byte","size":1,"value":"0x00","description":"Unknown"},{"name":"Fixed Direction","type":"bool","size":1,"description":"Fixed direction"},{"name":"Explode","type":"bool","size":1,"description":"Explode on impact"},{"name":"Hue","type":"int","size":4,"description":"Effect hue"},{"name":"Render Mode","type":"int","size":4,"description":"Render mode"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingEffectPackets.cs","line":175},"category":"Effects","tags":["Effects"]},{"id":"0xC1","name":"Localized Message","description":"Server sends a localized (cliloc) message to client.","direction":"outgoing","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xC1","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Serial of speaker"},{"name":"Graphic","type":"short","size":2,"description":"Body graphic of speaker"},{"name":"Type","type":"byte","size":1,"description":"Message type (see 0x1C)"},{"name":"Hue","type":"short","size":2,"description":"Text color hue"},{"name":"Font","type":"short","size":2,"description":"Font ID"},{"name":"Cliloc Number","type":"int","size":4,"description":"Cliloc entry number"},{"name":"Name","type":"ascii","size":30,"description":"Speaker name"},{"name":"Arguments","type":"utf16le-t","description":"Tab-separated arguments for cliloc"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMessagePackets.cs","line":55},"category":"Message","tags":["Message"]},{"id":"0xC2","name":"Unicode Prompt","description":"Server requests text input from client.","direction":"outgoing","isDynamic":false,"size":21,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xC2","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"21","description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Prompt serial"},{"name":"Prompt ID","type":"uint","size":4,"description":"Prompt ID (same as serial)"},{"name":"Padding","type":"byte[]","size":10,"description":"Unused padding (zeros)"}],"related":[{"id":"0x9A","direction":"incoming","relationship":"response","note":"ASCII Prompt Response"},{"id":"0xC2","direction":"incoming","relationship":"response","note":"Unicode Prompt Response"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMessagePackets.cs","line":246},"category":"Message","tags":["Message","Menu"]},{"id":"0xC6","name":"Invalid Map","description":"Notifies client that the current map is invalid.","direction":"outgoing","isDynamic":false,"size":1,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xC6","description":"Packet identifier"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMapPackets.cs","line":53},"category":"Map","tags":["Map"]},{"id":"0xC7","name":"Particle Effect","description":"Displays an advanced particle effect with extended parameters.","direction":"outgoing","isDynamic":false,"size":49,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xC7","description":"Packet identifier"},{"name":"Effect Type","type":"byte","size":1,"description":"Effect type (see 0xC0)"},{"name":"Source Serial","type":"uint","size":4,"description":"Serial of source entity"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of target entity"},{"name":"Item ID","type":"short","size":2,"description":"Effect graphic ID"},{"name":"Src X","type":"short","size":2,"description":"Source X coordinate"},{"name":"Src Y","type":"short","size":2,"description":"Source Y coordinate"},{"name":"Src Z","type":"sbyte","size":1,"description":"Source Z coordinate"},{"name":"Dst X","type":"short","size":2,"description":"Destination X coordinate"},{"name":"Dst Y","type":"short","size":2,"description":"Destination Y coordinate"},{"name":"Dst Z","type":"sbyte","size":1,"description":"Destination Z coordinate"},{"name":"Speed","type":"byte","size":1,"description":"Effect speed"},{"name":"Duration","type":"byte","size":1,"description":"Effect duration"},{"name":"Unknown1","type":"byte","size":1,"value":"0x00","description":"Unknown"},{"name":"Unknown2","type":"byte","size":1,"value":"0x00","description":"Unknown"},{"name":"Fixed Direction","type":"bool","size":1,"description":"Fixed direction"},{"name":"Explode","type":"bool","size":1,"description":"Explode on impact"},{"name":"Hue","type":"int","size":4,"description":"Effect hue"},{"name":"Render Mode","type":"int","size":4,"description":"Render mode"},{"name":"Effect","type":"short","size":2,"description":"Particle effect ID"},{"name":"Explode Effect","type":"short","size":2,"description":"Explosion effect ID"},{"name":"Explode Sound","type":"short","size":2,"description":"Explosion sound ID"},{"name":"Serial","type":"uint","size":4,"description":"Associated entity serial"},{"name":"Layer","type":"byte","size":1,"description":"Effect layer"},{"name":"Unknown3","type":"short","size":2,"description":"Unknown"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingEffectPackets.cs","line":58},"category":"Effects","tags":["Effects"]},{"id":"0xC8","name":"Change Update Range","description":"Sets the client's update range.","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xC8","description":"Packet identifier"},{"name":"Range","type":"byte","size":1,"description":"Update range (typically 18)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":59},"category":"Player","tags":["Player"]},{"id":"0xCC","name":"Localized Message Affix","description":"Server sends a localized message with text prefix/suffix.","direction":"outgoing","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xCC","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Serial of speaker"},{"name":"Graphic","type":"short","size":2,"description":"Body graphic of speaker"},{"name":"Type","type":"byte","size":1,"description":"Message type (see 0x1C)"},{"name":"Hue","type":"short","size":2,"description":"Text color hue"},{"name":"Font","type":"short","size":2,"description":"Font ID"},{"name":"Cliloc Number","type":"int","size":4,"description":"Cliloc entry number"},{"name":"Affix Type","type":"enum","size":1,"description":"How to apply the affix","values":[{"value":0,"name":"Append","description":"Append affix to end"},{"value":1,"name":"Prepend","description":"Prepend affix to start"},{"value":2,"name":"System","description":"System message style"}]},{"name":"Name","type":"ascii","size":30,"description":"Speaker name"},{"name":"Affix","type":"ascii-t","description":"Text to prepend/append"},{"name":"Arguments","type":"utf16be-t","description":"Tab-separated arguments for cliloc"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMessagePackets.cs","line":112},"category":"Message","tags":["Message"]},{"id":"0xD1","name":"Logout Ack","description":"Server acknowledges logout request.","direction":"outgoing","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD1","description":"Packet identifier"},{"name":"Ack","type":"byte","size":1,"value":"0x01","description":"Acknowledgment (1 = OK)"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingPlayerPackets.cs","line":94},"category":"Player","tags":["Player"]},{"id":"0xD4","name":"Book Header","description":"Sends book cover information (title, author, writable status).","direction":"outgoing","isDynamic":true,"size":"17+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD4","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Book Serial","type":"uint","size":4,"description":"Serial of the book"},{"name":"Flag On","type":"byte","size":1,"value":"0x01","description":"Flag on (always 1)"},{"name":"Writable","type":"bool","size":1,"description":"True if book is writable and in range"},{"name":"Page Count","type":"ushort","size":2,"description":"Number of pages"},{"name":"Title Length","type":"ushort","size":2,"description":"Length of title + 1 (for null)"},{"name":"Title","type":"utf8-t","description":"Book title"},{"name":"Author Length","type":"ushort","size":2,"description":"Length of author + 1 (for null)"},{"name":"Author","type":"utf8-t","description":"Book author"}],"related":[{"id":"0x93","relationship":"variant","note":"Old Book Header format (outgoing)"}],"source":{"file":"Projects/UOContent/Items/Books/BookPackets.cs","line":184},"category":"Book","tags":["Book"]},{"id":"0xD6","name":"Object Property List","description":"Sends the full Object Property List (tooltip) for an entity. Contains a hash for client caching and a list of localized property entries.","direction":"outgoing","isDynamic":true,"size":"15+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD6","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Unknown1","type":"ushort","size":2,"value":"0x0001","description":"Unknown (always 1)"},{"name":"Serial","type":"uint","size":4,"description":"Entity serial"},{"name":"Unknown2","type":"ushort","size":2,"value":"0x0000","description":"Unknown (always 0)"},{"name":"Hash","type":"int","size":4,"description":"XOR hash of all properties (computed with 26-bit mask)"},{"name":"Properties","type":"array","description":"Property entries, terminated by number=0","loop":{"terminator":"number == 0","fields":[{"name":"Number","type":"int","size":4,"description":"Cliloc number (0 = end of list)"},{"name":"String Length","type":"ushort","size":2,"description":"Length of arguments in bytes (0 if no arguments)"},{"name":"Arguments","type":"utf16le","size":"var","description":"Unicode LE string with tab-separated cliloc arguments. Length = String Length field"}]}}],"related":[{"id":"0xDC","relationship":"notification","note":"OPL Info notifies client of hash change, triggering 0xD6 request"}],"clientVersion":{"classic":{"min":"4.0.0a"},"enhanced":{},"notes":"AOS tooltips feature"},"notes":"Hash is calculated by XORing each property's cliloc number with ((hash >> 31) & 1) ^ (hash << 1). Properties are cliloc entries with optional Unicode LE arguments separated by tabs.","source":{"file":"Projects/Server/PropertyList/ObjectPropertyList.cs","line":19},"category":"Item","tags":["Item","Mobile"]},{"id":"0xD8","name":"House Design State Detailed","description":"Sends detailed house customization design data. Contains compressed plane data organized by floor level and component type. Tiles are encoded using grid-based or coordinate-based formats depending on their Z-height.","direction":"outgoing","isDynamic":true,"size":"18+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD8","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Compression Type","type":"byte","size":1,"value":"0x03","description":"Compression type (always 3 = compressed)"},{"name":"Unknown","type":"byte","size":1,"value":"0x00","description":"Unknown (always 0)"},{"name":"House Serial","type":"uint","size":4,"description":"Serial of the house foundation"},{"name":"Revision","type":"int","size":4,"description":"Design revision number"},{"name":"Tile Count","type":"ushort","size":2,"description":"Total number of tiles in the design"},{"name":"Buffer Length","type":"ushort","size":2,"description":"Length of remaining data (plane count + all plane sections)"},{"name":"Plane Count","type":"byte","size":1,"description":"Number of plane/buffer sections that follow"},{"name":"Plane Sections","type":"array","description":"Each section has a 4-byte header followed by compressed tile data","loop":{"countField":"Plane Count","fields":[{"name":"Section Header","type":"uint","size":4,"description":"Packed header: bits 28-31=mode, bits 24-27=planeZ, bits 16-23+(bits 4-7<<8)=decompLen, bits 8-15+(bits 0-3<<8)=compLen"},{"name":"Compressed Data","type":"bytes","size":"var","description":"DEFLATE compressed tile data (length from header)"}]}}],"planeFormat":{"description":"Tiles are organized into planes based on Z-height. Planes 0-8 use grid encoding; planes 9+ use explicit coordinates for overflow items.","headerDecoding":{"mode":"(header >> 28) & 0x0F","planeZ":"(header >> 24) & 0x0F","decompLen":"((header & 0xFF0000) >> 16) | ((header & 0xF0) << 4)","compLen":"((header & 0xFF00) >> 8) | ((header & 0x0F) << 8)"},"planeZMapping":[{"plane":0,"z":0,"description":"Ground floor"},{"plane":1,"z":7,"description":"1st storey (floor items)"},{"plane":2,"z":27,"description":"2nd storey (floor items)"},{"plane":3,"z":47,"description":"3rd storey (floor items)"},{"plane":4,"z":67,"description":"4th storey (floor items)"},{"plane":"5-8","z":"7/27/47/67","description":"Non-floor items per storey"},{"plane":"9+","z":"varies","description":"Overflow/stair buffers (explicit coords)"}],"encodingModes":[{"mode":0,"name":"Full Coordinates","bytesPerTile":5,"format":"ushort itemId, sbyte x, sbyte y, sbyte z","description":"Used for overflow buffers with non-standard Z heights"},{"mode":1,"name":"XY Coordinates","bytesPerTile":4,"format":"ushort itemId, sbyte x, sbyte y","description":"Z calculated: ((planeZ - 1) % 4) * 20 + 7"},{"mode":2,"name":"Grid-Based","bytesPerTile":2,"format":"ushort itemId (0x0000 = empty)","description":"X,Y from grid index: x = i / gridHeight, y = i % gridHeight"}],"gridSizes":[{"plane":0,"width":"width","height":"height","notes":"Full foundation footprint"},{"plane":"1-4","width":"width - 1","height":"height - 2","notes":"Interior (floor items), offset by (1,1)"},{"plane":"5-8","width":"width","height":"height - 1","notes":"Interior (non-floor items)"}]},"compression":{"algorithm":"DEFLATE","notes":"Raw DEFLATE compression (no zlib header/footer). Each plane buffer compressed independently. Max 750 items per overflow buffer (splits into multiple buffers if exceeded)."},"related":[{"id":"0xBF/0x1D","relationship":"related","note":"Design State General provides revision info only"},{"id":"0xBF/0x20","relationship":"related","note":"Begin/End House Customization commands"}],"clientVersion":{"classic":{"min":"4.0.0a"},"enhanced":{},"notes":"AOS House Customization feature"},"source":{"file":"Projects/UOContent/Multis/Houses/HousePackets.cs","line":93},"category":"House","tags":["House"]},{"id":"0xDA","subId":"0x02","name":"Mahjong Players Info","description":"Sends information about all players in the Mahjong game.","direction":"outgoing","isDynamic":true,"size":"11+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Command","type":"ushort","size":2,"value":"0x0002","description":"Players Info command"},{"name":"Seat Count","type":"ushort","size":2,"description":"Number of seats with data"},{"name":"Players","type":"loop","description":"Player data for each seat","loop":{"countField":"Seat Count","fields":[{"name":"Player Serial","type":"uint","size":4,"description":"Serial of player (0 if empty)"},{"name":"Dealer Flag","type":"byte","size":1,"description":"1=Dealer, 2=Not dealer"},{"name":"Position","type":"byte","size":1,"description":"Seat position index"},{"name":"Score","type":"int","size":4,"description":"Player's current score"},{"name":"Reserved","type":"short","size":2,"value":"0","description":"Reserved (always 0)"},{"name":"Reserved 2","type":"byte","size":1,"value":"0","description":"Reserved (always 0)"},{"name":"Public Hand","type":"bool","size":1,"description":"True if hand is visible to others"},{"name":"Name","type":"ascii","size":30,"description":"Player name"},{"name":"Empty Seat","type":"bool","size":1,"description":"True if seat is empty or not in game"}]}}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":304},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x03","name":"Mahjong Tile Info","description":"Sends information about a single Mahjong tile.","direction":"outgoing","isDynamic":false,"size":18,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0012","description":"Packet length (18)"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Command","type":"ushort","size":2,"value":"0x0003","description":"Tile Info command"},{"name":"Tile Number","type":"byte","size":1,"description":"Tile index number"},{"name":"Tile Value","type":"byte","size":1,"description":"Tile face value (0 if hidden)"},{"name":"Y Position","type":"short","size":2,"description":"Tile Y coordinate"},{"name":"X Position","type":"short","size":2,"description":"Tile X coordinate"},{"name":"Stack Level","type":"byte","size":1,"description":"Stack level for overlapping tiles"},{"name":"Direction","type":"byte","size":1,"description":"Tile direction (0=Up, 1=Left, 2=Down, 3=Right)"},{"name":"Flipped","type":"byte","size":1,"description":"0x10 if flipped/face-up, 0x00 if face-down"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":362},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x04","name":"Mahjong Tiles Info","description":"Sends information about all tiles in the Mahjong game.","direction":"outgoing","isDynamic":true,"size":"11+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Command","type":"ushort","size":2,"value":"0x0004","description":"Tiles Info command"},{"name":"Tile Count","type":"short","size":2,"description":"Number of tiles"},{"name":"Tiles","type":"loop","description":"Tile data for each tile","loop":{"countField":"Tile Count","fields":[{"name":"Tile Number","type":"byte","size":1,"description":"Tile index number"},{"name":"Tile Value","type":"byte","size":1,"description":"Tile face value (0 if hidden)"},{"name":"Y Position","type":"short","size":2,"description":"Tile Y coordinate"},{"name":"X Position","type":"short","size":2,"description":"Tile X coordinate"},{"name":"Stack Level","type":"byte","size":1,"description":"Stack level"},{"name":"Direction","type":"byte","size":1,"description":"Tile direction"},{"name":"Flipped","type":"byte","size":1,"description":"0x10 if flipped, 0x00 otherwise"}]}}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":408},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x05","name":"Mahjong General Info","description":"Sends general game state including dice values, dealer indicator, and wall break position.","direction":"outgoing","isDynamic":false,"size":25,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0019","description":"Packet length (25)"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Command","type":"ushort","size":2,"value":"0x0005","description":"General Info command"},{"name":"Reserved","type":"short","size":2,"value":"0","description":"Reserved"},{"name":"Reserved 2","type":"byte","size":1,"value":"0","description":"Reserved"},{"name":"Options","type":"byte","size":1,"description":"Bit 0: Show Scores, Bit 1: Spectator Vision"},{"name":"Dice 1","type":"byte","size":1,"description":"First dice value"},{"name":"Dice 2","type":"byte","size":1,"description":"Second dice value"},{"name":"Dealer Wind","type":"enum","size":1,"description":"Dealer indicator wind direction","values":[{"value":"0","name":"North","description":"North wind"},{"value":"1","name":"East","description":"East wind"},{"value":"2","name":"South","description":"South wind"},{"value":"3","name":"West","description":"West wind"}]},{"name":"Dealer Y","type":"short","size":2,"description":"Dealer indicator Y position"},{"name":"Dealer X","type":"short","size":2,"description":"Dealer indicator X position"},{"name":"Dealer Direction","type":"byte","size":1,"description":"Dealer indicator direction"},{"name":"Wall Break Y","type":"short","size":2,"description":"Wall break indicator Y position"},{"name":"Wall Break X","type":"short","size":2,"description":"Wall break indicator X position"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":461},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x19","name":"Mahjong Join Game","description":"Notifies client to open the Mahjong game interface.","direction":"outgoing","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0009","description":"Packet length (9)"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Command","type":"ushort","size":2,"value":"0x0019","description":"Join Game command"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":288},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x1A","name":"Mahjong Relieve","description":"Notifies client to close the Mahjong game interface.","direction":"outgoing","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x0009","description":"Packet length (9)"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Command","type":"ushort","size":2,"value":"0x001A","description":"Relieve command"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":504},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDC","name":"OPL Info (Object Property List)","description":"Notifies the client of an entity's Object Property List hash. Client compares hash to cached version and requests full OPL if different.","direction":"outgoing","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDC","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Entity serial"},{"name":"Hash","type":"int","size":4,"description":"Hash of the Object Property List"}],"related":[{"id":"0xD6","direction":"outgoing","relationship":"data","note":"Full Object Property List packet"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingEntityPackets.cs","line":33},"category":"Item","tags":["Item","Mobile"]},{"id":"0xDD","name":"Dynamic Gump (Compressed)","description":"Sends a custom gump dialog with compressed layout and text strings. Uses raw DEFLATE compression (no zlib headers).","direction":"outgoing","isDynamic":true,"size":"23+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDD","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Gump serial (unique per gump instance)"},{"name":"Type ID","type":"uint","size":4,"description":"Gump type ID (identifies the gump class)"},{"name":"X","type":"int","size":4,"description":"Screen X position"},{"name":"Y","type":"int","size":4,"description":"Screen Y position"},{"name":"Layout Compressed Length","type":"int","size":4,"description":"Compressed layout data length (includes +4)"},{"name":"Layout Uncompressed Length","type":"int","size":4,"description":"Uncompressed layout data length"},{"name":"Layout Data","type":"bytes","size":"var","description":"DEFLATE compressed layout commands (ASCII, no zlib header/footer). Length = Layout Compressed Length - 4"},{"name":"String Count","type":"int","size":4,"description":"Number of text strings"},{"name":"Strings Compressed Length","type":"int","size":4,"description":"Compressed strings data length (includes +4)"},{"name":"Strings Uncompressed Length","type":"int","size":4,"description":"Uncompressed strings data length"},{"name":"Strings Data","type":"bytes","size":"var","description":"DEFLATE compressed strings (no zlib header/footer). Length = Strings Compressed Length - 4"}],"compression":{"algorithm":"DEFLATE (raw)","notes":"Uses libdeflate. NO zlib header (0x78 0x9C) or footer (adler32 checksum). Layout and strings are compressed separately."},"layoutFormat":{"description":"Layout is a custom ASCII text format. Each command is brace-wrapped: { command param1 param2 ... }","encoding":"ASCII (arguments must be ASCII characters only)","commands":[{"name":"Noclose","description":"Prevent closing via right-click or ESC"},{"name":"Nomove","description":"Prevent dragging the gump"},{"name":"Noresize","description":"Prevent resizing (Enhanced Client)","tags":["EC"],"notes":"Enhanced Client only"},{"name":"Nodispose","description":"Prevent server-side disposal"},{"name":"Page","description":"Define page (0=base visible on all pages)","args":[{"name":"N","type":"int","description":"Page number (0 = always visible)"}]},{"name":"Group","description":"Radio button group ID","args":[{"name":"Group ID","type":"int","description":"Group identifier for radio buttons"}]},{"name":"Resizepic","description":"Resizable background panel (9-slice)","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"Gump ID","type":"int","description":"Gump graphic ID for the background"},{"name":"W","type":"int","description":"Width in pixels"},{"name":"H","type":"int","description":"Height in pixels"}]},{"name":"Gumppic","description":"Static gump image","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"Gump ID","type":"int","description":"Gump graphic ID"},{"name":"Hue=N","type":"int","description":"Optional hue override","optional":true},{"name":"Class=S","type":"string","description":"Optional CSS class (Enhanced Client)","optional":true}]},{"name":"Gumppictiled","description":"Tiled gump image","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"W","type":"int","description":"Width in pixels"},{"name":"H","type":"int","description":"Height in pixels"},{"name":"Gump ID","type":"int","description":"Gump graphic ID to tile"}]},{"name":"Tilepic","description":"Item/tile graphic from art.mul","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"Item ID","type":"int","description":"Item graphic ID from art.mul"}]},{"name":"Tilepichue","description":"Item graphic with hue","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"Item ID","type":"int","description":"Item graphic ID"},{"name":"Hue","type":"int","description":"Color hue"}]},{"name":"Picinpic","description":"Cropped sprite from gump (sprite image rendering)","tags":["EC"],"notes":"Also known as GumpSpriteImage. EC-compatible.","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"Gump ID","type":"int","description":"Gump graphic ID"},{"name":"W","type":"int","description":"Display width"},{"name":"H","type":"int","description":"Display height"},{"name":"Sprite X","type":"int","description":"X offset within sprite"},{"name":"Sprite Y","type":"int","description":"Y offset within sprite"}]},{"name":"Checkertrans","description":"Checkerboard transparency region","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"W","type":"int","description":"Width in pixels"},{"name":"H","type":"int","description":"Height in pixels"}]},{"name":"Text","description":"Static text label","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"Hue","type":"int","description":"Text color hue"},{"name":"String Index","type":"int","description":"Index into strings array"}]},{"name":"Croppedtext","description":"Cropped/clipped text","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"W","type":"int","description":"Crop width"},{"name":"H","type":"int","description":"Crop height"},{"name":"Hue","type":"int","description":"Text color hue"},{"name":"String Index","type":"int","description":"Index into strings array"}]},{"name":"Htmlgump","description":"HTML text area","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"W","type":"int","description":"Width in pixels"},{"name":"H","type":"int","description":"Height in pixels"},{"name":"String Index","type":"int","description":"Index into strings array (HTML content)"},{"name":"BG","type":"bool","description":"Display background panel"},{"name":"Scroll","type":"bool","description":"Display scrollbar"}]},{"name":"Xmfhtmlgump","description":"Localized HTML from cliloc","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"W","type":"int","description":"Width in pixels"},{"name":"H","type":"int","description":"Height in pixels"},{"name":"Cliloc","type":"int","description":"Cliloc string number"},{"name":"BG","type":"bool","description":"Display background panel"},{"name":"Scroll","type":"bool","description":"Display scrollbar"}]},{"name":"Xmfhtmlgumpcolor","description":"Localized HTML with color","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"W","type":"int","description":"Width in pixels"},{"name":"H","type":"int","description":"Height in pixels"},{"name":"Cliloc","type":"int","description":"Cliloc string number"},{"name":"BG","type":"bool","description":"Display background panel"},{"name":"Scroll","type":"bool","description":"Display scrollbar"},{"name":"Color","type":"int","description":"Text color (RGB format)"}]},{"name":"Xmfhtmltok","description":"Localized HTML with arguments","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"W","type":"int","description":"Width in pixels"},{"name":"H","type":"int","description":"Height in pixels"},{"name":"BG","type":"bool","description":"Display background panel"},{"name":"Scroll","type":"bool","description":"Display scrollbar"},{"name":"Color","type":"int","description":"Text color (RGB format)"},{"name":"Cliloc","type":"int","description":"Cliloc string number"},{"name":"@Args@","type":"string","description":"Tab-separated cliloc arguments"}]},{"name":"Button","description":"Clickable button","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"Normal ID","type":"int","description":"Gump ID for normal state"},{"name":"Pressed ID","type":"int","description":"Gump ID for pressed state"},{"name":"Type","type":"enum","description":"Button type","values":[{"value":"0","name":"PageChange","description":"Navigate to different page"},{"value":"1","name":"ServerReply","description":"Send response to server"}]},{"name":"Param","type":"int","description":"Page number (Type=0) or unused (Type=1)"},{"name":"Button ID","type":"int","description":"Button ID sent to server on click"}]},{"name":"Buttontileart","description":"Button with item overlay","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"Normal ID","type":"int","description":"Gump ID for normal state"},{"name":"Pressed ID","type":"int","description":"Gump ID for pressed state"},{"name":"Type","type":"enum","description":"Button type","values":[{"value":"0","name":"PageChange","description":"Navigate to different page"},{"value":"1","name":"ServerReply","description":"Send response to server"}]},{"name":"Param","type":"int","description":"Page number (Type=0) or unused (Type=1)"},{"name":"Button ID","type":"int","description":"Button ID sent to server on click"},{"name":"Item ID","type":"int","description":"Item graphic ID to overlay"},{"name":"Hue","type":"int","description":"Item hue"},{"name":"W","type":"int","description":"Item display width"},{"name":"H","type":"int","description":"Item display height"}]},{"name":"Checkbox","description":"Checkbox toggle","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"Inactive ID","type":"int","description":"Gump ID when unchecked"},{"name":"Active ID","type":"int","description":"Gump ID when checked"},{"name":"State","type":"bool","description":"Initial checked state"},{"name":"Switch ID","type":"int","description":"Switch ID sent to server"}]},{"name":"Radio","description":"Radio button (use with group)","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"Inactive ID","type":"int","description":"Gump ID when unselected"},{"name":"Active ID","type":"int","description":"Gump ID when selected"},{"name":"State","type":"bool","description":"Initial selected state"},{"name":"Switch ID","type":"int","description":"Switch ID sent to server"}]},{"name":"Textentry","description":"Text input field","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"W","type":"int","description":"Width in pixels"},{"name":"H","type":"int","description":"Height in pixels"},{"name":"Hue","type":"int","description":"Text color hue"},{"name":"Entry ID","type":"int","description":"Entry ID for server response"},{"name":"String Index","type":"int","description":"Index into strings array (default text)"}]},{"name":"Textentrylimited","description":"Text input with max length","args":[{"name":"X","type":"int","description":"X coordinate"},{"name":"Y","type":"int","description":"Y coordinate"},{"name":"W","type":"int","description":"Width in pixels"},{"name":"H","type":"int","description":"Height in pixels"},{"name":"Hue","type":"int","description":"Text color hue"},{"name":"Entry ID","type":"int","description":"Entry ID for server response"},{"name":"String Index","type":"int","description":"Index into strings array (default text)"},{"name":"Max Len","type":"int","description":"Maximum character length"}]},{"name":"Tooltip","description":"Tooltip on previous element (GumpTooltip)","tags":["EC"],"notes":"EC-compatible tooltip display.","args":[{"name":"Cliloc","type":"int","description":"Cliloc string number for tooltip"},{"name":"@Args@","type":"string","description":"Optional cliloc arguments","optional":true}]},{"name":"Itemproperty","description":"Display item's OPL tooltip (GumpItemProperty)","tags":["EC"],"notes":"EC-compatible property display for items.","args":[{"name":"Serial","type":"int","description":"Item serial number"}]},{"name":"Mastergump","description":"Master gump ID override","args":[{"name":"Gump ID","type":"int","description":"Master gump identifier"}]},{"name":"Echandleinput","description":"EC-specific input handler","tags":["EC"],"notes":"Enhanced Client only"}]},"stringsFormat":{"description":"Array of UTF-16 BE encoded strings for text/textentry elements","encoding":"UTF-16 Big Endian","entryFormat":[{"name":"Length","type":"ushort","size":2,"description":"String length in characters (Big Endian)"},{"name":"Text","type":"utf16be","size":"var","description":"UTF-16 BE encoded text. Length = Length field * 2 bytes"}]},"related":[{"id":"0xB1","relationship":"response","note":"Gump Response - client reply to button/checkbox/text"}],"clientVersion":{"classic":{"min":"3.0.0"},"enhanced":{},"notes":"Compressed gumps supported since Classic Client 3.0.0"},"notes":"Layout uses ASCII encoding only. The compressed lengths include a +4 offset. Decompression produces: layout as ASCII text, strings as length-prefixed UTF-16 BE entries.","source":{"file":"Projects/UOContent/Gumps/Base/DynamicGump.cs","line":105},"category":"Gump","tags":["Gump"]},{"id":"0xDF","name":"Buff/Debuff System","description":"Manages buff and debuff icons displayed on the client.","direction":"outgoing","isDynamic":true,"size":"Varies","variants":[{"name":"Remove Buff","condition":"command == 0 (Remove)","size":15,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"15","description":"Packet length"},{"name":"Mobile Serial","type":"uint","size":4,"description":"Serial of the mobile"},{"name":"Icon ID","type":"short","size":2,"description":"Buff icon ID"},{"name":"Command","type":"short","size":2,"value":"0x0000","description":"Remove command"},{"name":"Unused","type":"int","size":4,"value":"0","description":"Unused"}]},{"name":"Add Buff (No Args)","condition":"command == 1 (Add), no arguments","size":46,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"46","description":"Packet length"},{"name":"Mobile Serial","type":"uint","size":4,"description":"Serial of the mobile"},{"name":"Icon ID","type":"short","size":2,"description":"Buff icon ID"},{"name":"Command1","type":"short","size":2,"value":"0x0001","description":"Add command"},{"name":"Unused1","type":"int","size":4,"value":"0","description":"Unused"},{"name":"Icon Id2","type":"short","size":2,"description":"Buff icon ID (repeated)"},{"name":"Command2","type":"short","size":2,"value":"0x0001","description":"Add command (repeated)"},{"name":"Unused2","type":"int","size":4,"value":"0","description":"Unused"},{"name":"Duration","type":"short","size":2,"description":"Duration in seconds"},{"name":"Padding","type":"byte[]","size":3,"description":"Padding (zeros)"},{"name":"Title Cliloc","type":"int","size":4,"description":"Title cliloc number"},{"name":"Secondary Cliloc","type":"int","size":4,"description":"Secondary cliloc number"},{"name":"Empty Args","type":"byte[]","size":10,"description":"Empty arguments (zeros)"}]},{"name":"Add Buff (With Args)","condition":"command == 1 (Add), with arguments","size":"52 + (args.Length x 2)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Mobile Serial","type":"uint","size":4,"description":"Serial of the mobile"},{"name":"Icon ID","type":"short","size":2,"description":"Buff icon ID"},{"name":"Command1","type":"short","size":2,"value":"0x0001","description":"Add command"},{"name":"Unused1","type":"int","size":4,"value":"0","description":"Unused"},{"name":"Icon Id2","type":"short","size":2,"description":"Buff icon ID (repeated)"},{"name":"Command2","type":"short","size":2,"value":"0x0001","description":"Add command (repeated)"},{"name":"Unused2","type":"int","size":4,"value":"0","description":"Unused"},{"name":"Duration","type":"short","size":2,"description":"Duration in seconds"},{"name":"Padding","type":"byte[]","size":3,"description":"Padding (zeros)"},{"name":"Title Cliloc","type":"int","size":4,"description":"Title cliloc number"},{"name":"Secondary Cliloc","type":"int","size":4,"description":"Secondary cliloc number"},{"name":"Unused3","type":"int","size":4,"value":"0","description":"Unused"},{"name":"Has Args","type":"short","size":2,"value":"0x0001","description":"Has arguments flag"},{"name":"Unused4","type":"ushort","size":2,"value":"0","description":"Unused"},{"name":"Tab Prefix","type":"utf16le","size":2,"value":"\\t","description":"Tab character prefix"},{"name":"Arguments","type":"utf16le-t","description":"Cliloc arguments"},{"name":"Has Args2","type":"short","size":2,"value":"0x0001","description":"Has arguments flag (repeated)"},{"name":"Unused5","type":"ushort","size":2,"value":"0","description":"Unused"}]}],"clientVersion":{"classic":{"min":"5.0.2b"},"enhanced":{},"notes":"BuffIcon feature supported in Classic Client 5.0.2b+"},"source":{"file":"Projects/UOContent/Engines/BuffIcons/BuffIconPackets.cs","line":8},"category":"Buff Icon","tags":["Buff Icon"]},{"id":"0xE2","name":"New Mobile Animation","description":"Simplified animation packet for newer clients.","direction":"outgoing","isDynamic":false,"size":10,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xE2","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Mobile serial"},{"name":"Action","type":"short","size":2,"description":"Animation action ID"},{"name":"Frame Count","type":"short","size":2,"description":"Number of frames"},{"name":"Delay","type":"byte","size":1,"description":"Frame delay"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMobilePackets.cs","line":354},"category":"Mobile","tags":["Mobile"]},{"id":"0xF0","name":"Assistant Handshake","description":"Server sends handshake to negotiate assistant features with Razor-style clients. Contains disallowed feature flags.","direction":"outgoing","isDynamic":false,"size":12,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF0","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"value":"0x000C","description":"Packet length (12)"},{"name":"Command","type":"byte","size":1,"value":"0xFE","description":"Handshake command"},{"name":"Disallowed Features","type":"ulong","size":8,"description":"Bitmask of disallowed assistant features"}],"notes":"Used for assistant negotiation with Razor Community Edition and similar clients. If negotiation fails within 30 seconds, the server may kick the player.","source":{"file":"Projects/UOContent/Assistants/AssistantHandler.cs","line":132},"category":"Assistant","tags":["Assistant"]},{"id":"0xF2","name":"Time Sync Response","description":"Server response to client time synchronization request. Contains tick counts for latency calculation.","direction":"outgoing","isDynamic":false,"size":25,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF2","description":"Packet identifier"},{"name":"Tick Count1","type":"long","size":8,"description":"Server tick count"},{"name":"Tick Count2","type":"long","size":8,"description":"Server tick count"},{"name":"Tick Count3","type":"long","size":8,"description":"Server tick count"}],"source":{"file":"Projects/Server/Network/Packets/OutgoingMovementPackets.cs","line":63},"category":"Movement","tags":["Movement"]},{"id":"0xF3","name":"World Entity (SA+)","description":"Unified entity packet for items, mobiles, and multis. Replaces older 0x1A World Item packet for Stygian Abyss+ clients. High Seas clients add 2 extra bytes.","direction":"outgoing","isDynamic":false,"size":"Varies","variants":[{"version":"Stygian Abyss","name":"SA Format","condition":"Client version 7.0.0.0 - 7.0.8.x (StygianAbyss, pre-HighSeas)","size":24,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF3","description":"Packet identifier"},{"name":"Command","type":"short","size":2,"value":"0x0001","description":"Command (always 1)"},{"name":"Entity Type","type":"enum","size":1,"description":"Entity type","values":[{"value":"0","name":"Item","description":"World item"},{"value":"1","name":"Mobile","description":"Mobile/creature"},{"value":"2","name":"Multi","description":"Multi/structure"}]},{"name":"Serial","type":"uint","size":4,"description":"Entity serial"},{"name":"Graphic ID","type":"ushort","size":2,"description":"Graphic/Body ID (masked with 0x7FFF)"},{"name":"Direction","type":"byte","size":1,"description":"Direction (mobiles) or 0"},{"name":"Amount Min","type":"short","size":2,"description":"Minimum amount (items) or 1"},{"name":"Amount Max","type":"short","size":2,"description":"Maximum amount (items) or 1"},{"name":"X","type":"short","size":2,"description":"X coordinate (masked with 0x7FFF)"},{"name":"Y","type":"short","size":2,"description":"Y coordinate (masked with 0x3FFF)"},{"name":"Z","type":"sbyte","size":1,"description":"Z coordinate"},{"name":"Light","type":"byte","size":1,"description":"Light level (items)"},{"name":"Hue","type":"short","size":2,"description":"Hue/color"},{"name":"Flags","type":"byte","size":1,"description":"Packet flags (hidden, blessed, etc.)"}]},{"version":"High Seas+","name":"HS Format","condition":"Client version >= 7.0.9.0 (HighSeas)","size":26,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF3","description":"Packet identifier"},{"name":"Command","type":"short","size":2,"value":"0x0001","description":"Command (always 1)"},{"name":"Entity Type","type":"enum","size":1,"description":"Entity type","values":[{"value":"0","name":"Item","description":"World item"},{"value":"1","name":"Mobile","description":"Mobile/creature"},{"value":"2","name":"Multi","description":"Multi/structure"}]},{"name":"Serial","type":"uint","size":4,"description":"Entity serial"},{"name":"Graphic ID","type":"ushort","size":2,"description":"Graphic/Body ID (masked with 0xFFFF, supports higher IDs)"},{"name":"Direction","type":"byte","size":1,"description":"Direction (mobiles) or 0"},{"name":"Amount Min","type":"short","size":2,"description":"Minimum amount (items) or 1"},{"name":"Amount Max","type":"short","size":2,"description":"Maximum amount (items) or 1"},{"name":"X","type":"short","size":2,"description":"X coordinate (masked with 0x7FFF)"},{"name":"Y","type":"short","size":2,"description":"Y coordinate (masked with 0x3FFF)"},{"name":"Z","type":"sbyte","size":1,"description":"Z coordinate"},{"name":"Light","type":"byte","size":1,"description":"Light level (items)"},{"name":"Hue","type":"short","size":2,"description":"Hue/color"},{"name":"Flags","type":"byte","size":1,"description":"Packet flags (hidden, blessed, etc.)"},{"name":"Unknown","type":"short","size":2,"value":"0x0000","description":"Unknown (always 0)"}]}],"related":[{"id":"0x1A","relationship":"variant","note":"Legacy World Item packet for pre-SA clients"}],"clientVersion":{"classic":{"min":"7.0.0.0"},"enhanced":{},"notes":"StygianAbyss expansion feature"},"source":{"file":"Projects/Server/Network/Packets/OutgoingEntityPackets.cs","line":88},"category":"Item","tags":["Item","Mobile"]},{"id":"0xF5","name":"Map Details (New)","description":"Sends map details for NewCharacterList clients. Includes facet ID.","direction":"outgoing","isDynamic":false,"size":21,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF5","description":"Packet identifier"},{"name":"Map Serial","type":"uint","size":4,"description":"Serial of the map item"},{"name":"Graphic ID","type":"short","size":2,"value":"0x139D","description":"Map gump graphic ID"},{"name":"Start X","type":"short","size":2,"description":"Map bounds start X coordinate"},{"name":"Start Y","type":"short","size":2,"description":"Map bounds start Y coordinate"},{"name":"End X","type":"short","size":2,"description":"Map bounds end X coordinate"},{"name":"End Y","type":"short","size":2,"description":"Map bounds end Y coordinate"},{"name":"Width","type":"short","size":2,"description":"Map width in pixels"},{"name":"Height","type":"short","size":2,"description":"Map height in pixels"},{"name":"Facet ID","type":"enum","size":2,"description":"Map facet/world identifier","values":[{"value":"0","name":"Felucca","description":"Felucca facet"},{"value":"1","name":"Trammel","description":"Trammel facet"},{"value":"2","name":"Ilshenar","description":"Ilshenar facet"},{"value":"3","name":"Malas","description":"Malas facet"},{"value":"4","name":"Tokuno","description":"Tokuno Islands"},{"value":"5","name":"TerMur","description":"Ter Mur facet"}]}],"related":[{"id":"0x56","direction":"both","relationship":"related","note":"Map pin commands (client and server)"},{"id":"0x90","relationship":"variant","note":"Old Map Details for pre-NewCharacterList clients"}],"clientVersion":{"classic":{"min":"7.0.13.0"},"enhanced":{},"notes":"NewCharacterList feature"},"source":{"file":"Projects/UOContent/Items/Maps/MapItemPackets.cs","line":78},"category":"Map","tags":["Map"]},{"id":"0xF6","name":"Boat Move (High Seas)","description":"Sent when a boat moves, containing the boat's new position and all entities on board with their updated positions.","direction":"outgoing","isDynamic":true,"size":"18 + (entityCount x 10)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF6","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Boat Serial","type":"uint","size":4,"description":"Serial of the boat"},{"name":"Speed","type":"byte","size":1,"description":"Boat movement speed"},{"name":"Direction","type":"byte","size":1,"description":"Movement direction (0-7)"},{"name":"Facing","type":"byte","size":1,"description":"Boat facing direction"},{"name":"X","type":"short","size":2,"description":"Boat X coordinate"},{"name":"Y","type":"short","size":2,"description":"Boat Y coordinate"},{"name":"Z","type":"short","size":2,"description":"Boat Z coordinate"},{"name":"Entity Count","type":"short","size":2,"description":"Number of entities on boat (max 65535)"},{"name":"Entities","type":"array","description":"Entities on the boat with their positions","loop":{"countField":"entityCount","fields":[{"name":"Serial","type":"uint","size":4,"description":"Entity serial"},{"name":"X","type":"short","size":2,"description":"Entity X coordinate (boat offset applied)"},{"name":"Y","type":"short","size":2,"description":"Entity Y coordinate (boat offset applied)"},{"name":"Z","type":"short","size":2,"description":"Entity Z coordinate"}]}}],"clientVersion":{"classic":{"min":"7.0.9.0"},"enhanced":{},"notes":"High Seas expansion feature"},"source":{"file":"Projects/UOContent/Multis/Boats/BoatPackets.cs","line":27},"notes":"High Seas expansion only. Entities include mobiles and items on the boat. Coordinates include the boat's movement offset.","category":"Boat","tags":["Boat"]},{"id":"0xF7","name":"Packet Container","description":"Container packet for batching multiple entity packets. Used for sending groups of related entities efficiently, such as all items and mobiles visible on a boat.","direction":"outgoing","isDynamic":true,"size":"5+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Total packet length"},{"name":"Packet Count","type":"ushort","size":2,"description":"Number of embedded packets"},{"name":"Packets","type":"array","description":"Embedded packets (typically 0xF3 World Entity packets)","loop":{"countField":"packetCount","fields":[{"name":"Embedded Packet","type":"bytes","size":"var","description":"Complete embedded packet (typically 24-26 byte 0xF3 World Entity)"}]}}],"related":[{"id":"0xF3","relationship":"contains","note":"Typically contains World Entity packets"},{"id":"0xF6","relationship":"variant","note":"Used alongside Move Boat HS for boat display"}],"clientVersion":{"classic":{"min":"7.0.9.0"},"enhanced":{},"notes":"HighSeas expansion feature"},"notes":"Uses PacketContainerBuilder for efficient dynamic growth. Commonly used by boat system to batch all visible entities on deck. Minimum packet length is 5 bytes (header only).","source":{"file":"Projects/Server/Network/Packets/PacketContainerBuilder.cs","line":23},"category":"Container","tags":["Container","Boat"]}],"incoming":[{"id":"0x00","name":"Create Character (Old)","description":"Request to create a new character. This is the older 104-byte version with 3 starting skills. Replaced by 0xF8 in client 7.0.16.0+.","direction":"incoming","isDynamic":false,"size":104,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x00","description":"Packet identifier"},{"name":"Unknown1","type":"int","size":4,"description":"Unknown"},{"name":"Unknown2","type":"int","size":4,"description":"Unknown"},{"name":"Unknown3","type":"byte","size":1,"description":"Unknown"},{"name":"Name","type":"ascii","size":30,"description":"Character name"},{"name":"Unknown4","type":"byte[2]","size":2,"description":"Unknown"},{"name":"Flags","type":"int","size":4,"description":"Client flags"},{"name":"Unknown5","type":"byte[8]","size":8,"description":"Unknown"},{"name":"Profession","type":"byte","size":1,"description":"Starting profession"},{"name":"Unknown6","type":"byte[15]","size":15,"description":"Unknown"},{"name":"Gender Race","type":"byte","size":1,"description":"Gender and race combined value"},{"name":"Strength","type":"byte","size":1,"description":"Starting strength"},{"name":"Dexterity","type":"byte","size":1,"description":"Starting dexterity"},{"name":"Intelligence","type":"byte","size":1,"description":"Starting intelligence"},{"name":"Skill1Id","type":"byte","size":1,"description":"First skill ID"},{"name":"Skill1Value","type":"byte","size":1,"description":"First skill value"},{"name":"Skill2Id","type":"byte","size":1,"description":"Second skill ID"},{"name":"Skill2Value","type":"byte","size":1,"description":"Second skill value"},{"name":"Skill3Id","type":"byte","size":1,"description":"Third skill ID"},{"name":"Skill3Value","type":"byte","size":1,"description":"Third skill value"},{"name":"Skin Hue","type":"ushort","size":2,"description":"Skin color hue"},{"name":"Hair Style","type":"short","size":2,"description":"Hair style ID"},{"name":"Hair Hue","type":"short","size":2,"description":"Hair color hue"},{"name":"Facial Hair Style","type":"short","size":2,"description":"Facial hair style ID"},{"name":"Facial Hair Hue","type":"short","size":2,"description":"Facial hair color hue"},{"name":"Unknown7","type":"byte","size":1,"description":"Unknown"},{"name":"City Index","type":"byte","size":1,"description":"Starting city index"},{"name":"Char Slot","type":"int","size":4,"description":"Character slot"},{"name":"Client IP","type":"int","size":4,"description":"Client IP"},{"name":"Shirt Hue","type":"short","size":2,"description":"Starting shirt hue"},{"name":"Pants Hue","type":"short","size":2,"description":"Starting pants hue"}],"related":[{"id":"0xF8","relationship":"variant","note":"Create Character (New) for Classic 7.0.16.0+ with 4th skill"},{"id":"0x8D","relationship":"variant","note":"Create Character (EC) for Enhanced Client"}],"clientVersion":{"classic":{"max":"7.0.15.x"},"notes":"Replaced by 0xF8 in Classic Client 7.0.16.0+. EC uses 0x8D instead."},"source":{"file":"Projects/UOContent/Network/Packets/IncomingAccountPackets.cs","line":58},"category":"Account","tags":["Account"]},{"id":"0x01","name":"Disconnect","description":"Client sends disconnect notification.","direction":"incoming","isDynamic":false,"size":5,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x01","description":"Packet identifier"},{"name":"Minus One","type":"int","size":4,"value":"0xFFFFFFFF","description":"Always -1"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":317},"category":"Player","tags":["Player"]},{"id":"0x02","name":"Movement Request","description":"Sent by the client when the player attempts to move in a direction. The server responds with either MovementAck (0x22) if successful or MovementRej (0x21) if blocked.","direction":"incoming","isDynamic":false,"size":7,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x02","description":"Packet identifier"},{"name":"Direction","type":"byte","size":1,"description":"Movement direction (0-7). Bit 0x80 indicates running."},{"name":"Sequence","type":"byte","size":1,"description":"Movement sequence number (1-255, wraps). Used for ack/rej matching."},{"name":"Fastwalk Key","type":"uint","size":4,"description":"Anti-speedhack prevention key. Set to 0 if fastwalk prevention is disabled."}],"related":[{"id":"0x21","relationship":"rej","note":"Sent if movement is blocked"},{"id":"0x22","relationship":"ack","note":"Sent if movement is successful"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingMovementPackets.cs","line":83},"category":"Movement","tags":["Movement"]},{"id":"0x03","name":"ASCII Speech","description":"Client sends ASCII-encoded speech message.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x03","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Type","type":"enum","enumType":"sequential","size":1,"description":"Message type","values":[{"value":0,"name":"Regular","description":"Normal speech"},{"value":1,"name":"System","description":"System message"},{"value":2,"name":"Emote","description":"Emote (*action*)"},{"value":6,"name":"Label","description":"Object label"},{"value":7,"name":"Focus","description":"Focused message"},{"value":8,"name":"Whisper","description":"Whisper"},{"value":9,"name":"Yell","description":"Yell"},{"value":10,"name":"Spell","description":"Spell words"},{"value":13,"name":"Guild","description":"Guild chat"},{"value":14,"name":"Alliance","description":"Alliance chat"},{"value":15,"name":"Command","description":"Command"}]},{"name":"Hue","type":"short","size":2,"description":"Text color hue"},{"name":"Font","type":"short","size":2,"description":"Font ID"},{"name":"Text","type":"ascii-t","description":"Speech text (max 128 chars)"}],"related":[{"id":"0x1C","relationship":"response","note":"ASCII Message sent to other clients"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingMessagePackets.cs","line":31},"category":"Message","tags":["Message"]},{"id":"0x05","name":"Attack Request","description":"Client requests to attack a mobile.","direction":"incoming","isDynamic":false,"size":5,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x05","description":"Packet identifier"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of mobile to attack"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":69},"category":"Player","tags":["Player"]},{"id":"0x06","name":"Use Request (Double-Click)","description":"Sent when the player double-clicks an item or mobile. Can also trigger paperdoll if high bit is set.","direction":"incoming","isDynamic":false,"size":5,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x06","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Serial of the target. If high bit (0x80000000) is set, opens player's paperdoll instead."}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingEntityPackets.cs","line":61},"category":"Item","tags":["Item","Mobile"]},{"id":"0x07","name":"Lift Request","description":"Client requests to pick up an item from the world or a container.","direction":"incoming","isDynamic":false,"size":7,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x07","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Serial of the item to lift"},{"name":"Amount","type":"ushort","size":2,"description":"Amount to pick up"}],"related":[{"id":"0x27","relationship":"rej","note":"Sent if lift is rejected"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingItemPackets.cs","line":35},"category":"Items","tags":["Items"]},{"id":"0x08","name":"Drop Request","description":"Client requests to drop an item at a location or into a container. Size varies by client version.","direction":"incoming","isDynamic":false,"size":"Varies","variants":[{"name":"Classic","size":14,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x08","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Serial of item being dropped (ignored)"},{"name":"X","type":"short","size":2,"description":"Target X coordinate"},{"name":"Y","type":"short","size":2,"description":"Target Y coordinate"},{"name":"Z","type":"sbyte","size":1,"description":"Target Z coordinate"},{"name":"Dest","type":"uint","size":4,"description":"Target container/mobile serial, or 0xFFFFFFFF for world"}]},{"name":"Container Grid Lines","condition":"Client version >= 6.0.1.7 (ContainerGridLines)","size":15,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x08","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Serial of item being dropped (ignored)"},{"name":"X","type":"short","size":2,"description":"Target X coordinate"},{"name":"Y","type":"short","size":2,"description":"Target Y coordinate"},{"name":"Z","type":"sbyte","size":1,"description":"Target Z coordinate"},{"name":"Grid Location","type":"byte","size":1,"description":"Grid slot position in container"},{"name":"Dest","type":"uint","size":4,"description":"Target container/mobile serial, or 0xFFFFFFFF for world"}]}],"clientVersion":{"classic":{},"enhanced":{},"notes":"ContainerGridLines (6.0.1.7+) adds gridLocation byte"},"source":{"file":"Projects/UOContent/Network/Packets/IncomingItemPackets.cs","line":69},"category":"Items","tags":["Items"]},{"id":"0x09","name":"Look Request (Single-Click)","description":"Sent when the player single-clicks an item or mobile to see its name/properties.","direction":"incoming","isDynamic":false,"size":5,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x09","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Serial of the target entity"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingEntityPackets.cs","line":105},"category":"Item","tags":["Item","Mobile"]},{"id":"0x12","name":"Text Command","description":"Client sends text-based commands for skills, spells, virtues, etc.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x12","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Command Type","type":"enum","enumType":"sequential","size":1,"description":"Type of text command","values":[{"value":"0x24","name":"Use Skill","description":"Use a skill by ID"},{"value":"0x27","name":"Cast Spell From Book","description":"Cast spell from spellbook"},{"value":"0x2F","name":"Old Scroll Click","description":"Old scroll double-click"},{"value":"0x43","name":"Open Spellbook","description":"Open spellbook of type"},{"value":"0x56","name":"Cast Spell Macro","description":"Cast spell from macro"},{"value":"0x58","name":"Open Door","description":"Open door macro"},{"value":"0xC7","name":"Animate","description":"Play animation"},{"value":"0xF4","name":"Invoke Virtue","description":"Invoke virtue from macro"}]},{"name":"Command","type":"ascii-t","description":"Command-specific text (skill ID, spell ID, etc.)"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":119},"category":"Player","tags":["Player"]},{"id":"0x13","name":"Equip Request","description":"Client requests to equip a held item on a mobile.","direction":"incoming","isDynamic":false,"size":10,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x13","description":"Packet identifier"},{"name":"Item Serial","type":"uint","size":4,"description":"Serial of item to equip"},{"name":"Layer","type":"byte","size":1,"description":"Equipment layer"},{"name":"Mobile Serial","type":"uint","size":4,"description":"Serial of target mobile"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingItemPackets.cs","line":44},"category":"Items","tags":["Items"]},{"id":"0x22","name":"Resynchronize","description":"Client requests full world state resync.","direction":"incoming","noMerge":true,"isDynamic":false,"size":3,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x22","description":"Packet identifier"},{"name":"Padding","type":"ushort","size":2,"description":"Unused padding"}],"notes":"Not related to outgoing 0x22 (Movement Acknowledgment) despite sharing the same packet ID.","source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":349},"category":"Player","tags":["Player"]},{"id":"0x2C","name":"Death Status Response","description":"Client acknowledges death status packet. Currently ignored by server.","direction":"incoming","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x2C","description":"Packet identifier"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":58},"category":"Player","tags":["Player"]},{"id":"0x34","name":"Mobile Query","description":"Client queries information about a mobile (stats or skills).","direction":"incoming","isDynamic":false,"size":10,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x34","description":"Packet identifier"},{"name":"Pattern","type":"uint","size":4,"value":"0xEDEDEDED","description":"Fixed pattern"},{"name":"Query Type","type":"enum","enumType":"sequential","size":1,"description":"Type of query","values":[{"value":"0x04","name":"Stats","description":"Request mobile stats"},{"value":"0x05","name":"Skills","description":"Request mobile skills"}]},{"name":"Mobile Serial","type":"uint","size":4,"description":"Serial of mobile to query"}],"related":[{"id":"0x11","relationship":"response","note":"Mobile Status packet sent in response to stats query"},{"id":"0x3A","relationship":"response","note":"Skills Update sent in response to skills query"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":376},"category":"Player","tags":["Player"]},{"id":"0x3A","name":"Change Skill Lock","description":"Client changes the lock state of a skill.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x3A","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Skill Index","type":"short","size":2,"description":"Skill index to change"},{"name":"Lock State","type":"enum","enumType":"sequential","size":1,"description":"New lock state","values":[{"value":0,"name":"Up","description":"Skill gains enabled"},{"value":1,"name":"Down","description":"Skill decreases enabled"},{"value":2,"name":"Locked","description":"Skill locked at current value"}]}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":331},"category":"Player","tags":["Player"]},{"id":"0x3B","name":"Vendor Buy Reply","description":"Client confirms items to purchase from a vendor.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x3B","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Vendor Serial","type":"uint","size":4,"description":"Serial of the vendor"},{"name":"Flag","type":"byte","size":1,"description":"0x00 = buy, 0x02 = cancel"},{"name":"Items","type":"loop","loop":{"untilEnd":true,"fields":[{"name":"Layer","type":"byte","size":1,"description":"Layer/container index"},{"name":"Item Serial","type":"uint","size":4,"description":"Serial of item to buy"},{"name":"Amount","type":"short","size":2,"description":"Amount to purchase"}]}}],"related":[{"id":"0x74","relationship":"request","note":"Vendor Buy List packet that initiated this"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingVendorPackets.cs","line":25},"category":"Vendor","tags":["Vendor"]},{"id":"0x56","name":"Map Command","description":"Client sends map pin commands for editable map items. Commands include adding, inserting, changing, and removing pins.","direction":"incoming","isDynamic":false,"size":11,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x56","description":"Packet identifier"},{"name":"Map Serial","type":"uint","size":4,"description":"Serial of the map item"},{"name":"Command","type":"enum","size":1,"description":"Map pin command type","values":[{"value":"1","name":"AddPin","description":"Add a new pin"},{"value":"2","name":"InsertPin","description":"Insert pin at position"},{"value":"3","name":"ChangePin","description":"Change existing pin"},{"value":"4","name":"RemovePin","description":"Remove a pin"},{"value":"5","name":"ClearPins","description":"Clear all pins"},{"value":"6","name":"ToggleEditable","description":"Toggle edit mode"}]},{"name":"Number","type":"byte","size":1,"description":"Pin number (for insert, change, remove commands)"},{"name":"X","type":"short","size":2,"description":"X coordinate of pin"},{"name":"Y","type":"short","size":2,"description":"Y coordinate of pin"}],"related":[{"id":"0x56","direction":"outgoing","relationship":"related","note":"Server map pin commands"},{"id":"0x90","direction":"outgoing","relationship":"related","note":"Map Details packet (old)"},{"id":"0xF5","direction":"outgoing","relationship":"related","note":"Map Details packet (new)"}],"source":{"file":"Projects/UOContent/Items/Maps/MapItemPackets.cs","line":28},"category":"Map","tags":["Map"]},{"id":"0x5D","name":"Play Character","description":"Request to enter the world with a selected character from the character list.","direction":"incoming","isDynamic":false,"size":73,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x5D","description":"Packet identifier"},{"name":"Pattern","type":"uint","size":4,"value":"0xEDEDEDED","description":"Fixed pattern"},{"name":"Name","type":"ascii","size":30,"description":"Character name (unused)"},{"name":"Unknown","type":"byte[2]","size":2,"description":"Unknown"},{"name":"Flags","type":"int","size":4,"description":"Client flags"},{"name":"Unknown2","type":"byte[24]","size":24,"description":"Unknown"},{"name":"Char Slot","type":"int","size":4,"description":"Character slot index (0-based)"},{"name":"Client IP","type":"int","size":4,"description":"Client IP address"}],"related":[{"id":"0x1B","relationship":"response","note":"Login confirmation sent on success"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingAccountPackets.cs","line":210},"category":"Account","tags":["Account"]},{"id":"0x66","name":"Book Content Change","description":"Client sends updated book page content when player edits a writable book.","direction":"incoming","isDynamic":true,"size":"9+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x66","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Book Serial","type":"uint","size":4,"description":"Serial of the book being edited"},{"name":"Page Count","type":"ushort","size":2,"description":"Number of pages being updated"},{"name":"Pages","type":"loop","description":"Page contents being updated","loop":{"countField":"pageCount","fields":[{"name":"Page Index","type":"ushort","size":2,"description":"Page number (1-indexed)"},{"name":"Line Count","type":"ushort","size":2,"description":"Number of lines on page (max 8)"},{"name":"Lines","type":"loop","description":"Lines on the page","loop":{"countField":"lineCount","fields":[{"name":"Text","type":"utf8-t","description":"Line text (max 80 characters)"}]}}]}}],"source":{"file":"Projects/UOContent/Items/Books/BookPackets.cs","line":87},"category":"Book","tags":["Book"]},{"id":"0x6C","name":"Target Response","description":"Client responds to a target cursor request.","direction":"incoming","isDynamic":false,"size":19,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6C","description":"Packet identifier"},{"name":"Type","type":"enum","enumType":"sequential","size":1,"description":"Target type","values":[{"value":0,"name":"Object","description":"Targeting a specific object (mobile/item)"},{"value":1,"name":"Location","description":"Targeting a location/tile"}]},{"name":"Target ID","type":"int","size":4,"description":"Target cursor ID to match request"},{"name":"Flags","type":"enum","enumType":"sequential","size":1,"description":"Target flags","values":[{"value":0,"name":"Neutral","description":"Neutral targeting"},{"value":1,"name":"Harmful","description":"Harmful action"},{"value":2,"name":"Beneficial","description":"Beneficial action"},{"value":3,"name":"Cancel","description":"Targeting canceled"}]},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of targeted object (0 for ground)"},{"name":"X","type":"short","size":2,"description":"Target X coordinate (-1 if canceled)"},{"name":"Y","type":"short","size":2,"description":"Target Y coordinate (-1 if canceled)"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown (typically 0)"},{"name":"Z","type":"sbyte","size":1,"description":"Target Z coordinate"},{"name":"Graphic","type":"ushort","size":2,"description":"Graphic ID of targeted tile (0 for land)"}],"notes":"If x == -1 && y == -1 && serial is invalid, user pressed Escape to cancel targeting.","source":{"file":"Projects/UOContent/Network/Packets/IncomingTargetingPackets.cs","line":28},"category":"Targeting","tags":["Targeting"]},{"id":"0x6F","name":"Secure Trade","description":"Client interacts with a secure trade window.","direction":"incoming","isDynamic":true,"size":"Varies","variants":[{"name":"Cancel Trade","condition":"action == Cancel (1)","size":8,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6F","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Action","type":"byte","size":1,"value":"1","description":"Cancel action"},{"name":"Container Serial","type":"uint","size":4,"description":"Serial of the trade container"}]},{"name":"Toggle Accept","condition":"action == Check (2)","size":12,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6F","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Action","type":"byte","size":1,"value":"2","description":"Check/toggle action"},{"name":"Container Serial","type":"uint","size":4,"description":"Serial of the trade container"},{"name":"Accepted","type":"bool","size":4,"description":"True if accepting the trade"}]},{"name":"Update Gold/Platinum","condition":"action == UpdateGold (3)","size":16,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x6F","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Action","type":"byte","size":1,"value":"3","description":"Update gold action"},{"name":"Container Serial","type":"uint","size":4,"description":"Serial of the trade container"},{"name":"Gold","type":"int","size":4,"description":"Gold amount to trade"},{"name":"Platinum","type":"int","size":4,"description":"Platinum amount to trade"}]}],"related":[{"id":"0x6F","direction":"outgoing","relationship":"response","note":"Server sends trade window updates"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingMobilePackets.cs","line":93},"category":"Secure Trade","tags":["Secure Trade"]},{"id":"0x71","subId":"0x03","name":"Bulletin Board Request Content","description":"Client requests the full content of a bulletin board message.","direction":"incoming","isDynamic":true,"size":"12","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x71","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Command","type":"byte","size":1,"value":"0x03","description":"Request Content command"},{"name":"Board Serial","type":"uint","size":4,"description":"Serial of the bulletin board"},{"name":"Message Serial","type":"uint","size":4,"description":"Serial of the message to read"}],"related":[{"id":"0x71","subId":"0x02","direction":"outgoing","relationship":"response","note":"Message Content response"}],"source":{"file":"Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs","line":78},"category":"Bulletin Board","tags":["Bulletin Board"]},{"id":"0x71","subId":"0x04","name":"Bulletin Board Request Header","description":"Client requests the header (poster, subject, time) of a bulletin board message.","direction":"incoming","isDynamic":true,"size":"12","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x71","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Command","type":"byte","size":1,"value":"0x04","description":"Request Header command"},{"name":"Board Serial","type":"uint","size":4,"description":"Serial of the bulletin board"},{"name":"Message Serial","type":"uint","size":4,"description":"Serial of the message"}],"related":[{"id":"0x71","subId":"0x01","direction":"outgoing","relationship":"response","note":"Message Header response"}],"source":{"file":"Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs","line":88},"category":"Bulletin Board","tags":["Bulletin Board"]},{"id":"0x71","subId":"0x05","name":"Bulletin Board Post Message","description":"Client posts a new message or reply to the bulletin board.","direction":"incoming","isDynamic":true,"size":"12+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x71","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Command","type":"byte","size":1,"value":"0x05","description":"Post Message command"},{"name":"Board Serial","type":"uint","size":4,"description":"Serial of the bulletin board"},{"name":"Thread Serial","type":"uint","size":4,"description":"Serial of parent message (0 for new thread)"},{"name":"Subject Length","type":"byte","size":1,"description":"Length of subject string"},{"name":"Subject","type":"utf8","description":"Message subject"},{"name":"Line Count","type":"byte","size":1,"description":"Number of message lines"},{"name":"Lines","type":"loop","description":"Message body lines","loop":{"countField":"Line Count","fields":[{"name":"Line Length","type":"byte","size":1,"description":"Length of this line"},{"name":"Line","type":"utf8","description":"Line text"}]}}],"source":{"file":"Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs","line":98},"category":"Bulletin Board","tags":["Bulletin Board"]},{"id":"0x71","subId":"0x06","name":"Bulletin Board Remove Message","description":"Client requests to delete a bulletin board message.","direction":"incoming","isDynamic":true,"size":"12","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x71","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Command","type":"byte","size":1,"value":"0x06","description":"Remove Message command"},{"name":"Board Serial","type":"uint","size":4,"description":"Serial of the bulletin board"},{"name":"Message Serial","type":"uint","size":4,"description":"Serial of the message to delete"}],"notes":"Only the message poster or GameMaster+ can delete messages.","source":{"file":"Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs","line":153},"category":"Bulletin Board","tags":["Bulletin Board"]},{"id":"0x72","name":"Set War Mode","description":"Client toggles war/peace mode.","direction":"incoming","isDynamic":false,"size":5,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x72","description":"Packet identifier"},{"name":"Warmode","type":"bool","size":1,"description":"True = war mode, False = peace mode"},{"name":"Padding","type":"byte","size":3,"description":"Unused padding (0x00, 0x32, 0x00)"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":343},"category":"Player","tags":["Player"]},{"id":"0x73","name":"Ping Request","description":"Client sends ping for latency measurement.","direction":"incoming","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x73","description":"Packet identifier"},{"name":"Sequence","type":"byte","size":1,"description":"Ping sequence number"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":366},"category":"Player","tags":["Player"]},{"id":"0x75","name":"Rename Request","description":"Client requests to rename a mobile (pet).","direction":"incoming","isDynamic":false,"size":35,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x75","description":"Packet identifier"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of mobile to rename"},{"name":"New Name","type":"ascii","size":30,"description":"New name for the mobile"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingMobilePackets.cs","line":32},"category":"Mobile","tags":["Mobile"]},{"id":"0x7D","name":"Menu Response","description":"Client responds to a displayed item menu.","direction":"incoming","isDynamic":false,"size":13,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x7D","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Menu dialog serial"},{"name":"Menu ID","type":"short","size":2,"description":"Menu ID (unused in implementation)"},{"name":"Index","type":"short","size":2,"description":"Selected item index (1-based, 0 = cancel)"},{"name":"Item ID","type":"short","size":2,"description":"Item graphic ID of selection"},{"name":"Hue","type":"short","size":2,"description":"Hue of selection"}],"related":[{"id":"0x7C","relationship":"request","note":"Display Item List Menu packet"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":287},"category":"Player","tags":["Player"]},{"id":"0x80","name":"Account Login","description":"Initial login request sent to the login server. Contains account credentials for authentication.","direction":"incoming","isDynamic":false,"size":62,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x80","description":"Packet identifier"},{"name":"Username","type":"ascii","size":30,"description":"Account username (null-terminated)"},{"name":"Password","type":"ascii","size":30,"description":"Account password (null-terminated)"},{"name":"Next Login Key","type":"byte","size":1,"description":"Next login key"}],"related":[{"id":"0x82","relationship":"rej","note":"Sent if login fails"},{"id":"0xA8","relationship":"ack","note":"Sent if login succeeds (server list)"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingAccountPackets.cs","line":439},"category":"Account","tags":["Account"]},{"id":"0x83","name":"Delete Character","description":"Request to delete a character from the account.","direction":"incoming","isDynamic":false,"size":39,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x83","description":"Packet identifier"},{"name":"Password","type":"ascii","size":30,"description":"Account password for verification"},{"name":"Char Index","type":"int","size":4,"description":"Character slot index to delete"},{"name":"Client IP","type":"int","size":4,"description":"Client IP address"}],"related":[{"id":"0x85","relationship":"response","note":"Delete result"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingAccountPackets.cs","line":185},"category":"Account","tags":["Account"]},{"id":"0x8D","name":"Create Character","description":"Request to create a new character from Enhanced Client (KR/SA 3D clients). Variable length packet with different field layout than Classic client versions.","direction":"incoming","isDynamic":true,"size":"var","implemented":false,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x8D","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Pattern1","type":"uint","size":4,"value":"0xEDEDEDED","description":"Fixed pattern"},{"name":"Character Index","type":"uint","size":4,"description":"Character slot index"},{"name":"Name","type":"ascii","size":30,"description":"Character name"},{"name":"Unknown","type":"byte[30]","size":30,"description":"Unknown (possibly password field)"},{"name":"Profession","type":"byte","size":1,"description":"Starting profession"},{"name":"Client Flags","type":"byte","size":1,"description":"Client flags (0x41 or 0x3F)"},{"name":"Gender","type":"byte","size":1,"description":"0=male, 1=female"},{"name":"Race","type":"byte","size":1,"description":"0=human, 1=elf, 2=gargoyle"},{"name":"Strength","type":"byte","size":1,"description":"Starting strength"},{"name":"Dexterity","type":"byte","size":1,"description":"Starting dexterity"},{"name":"Intelligence","type":"byte","size":1,"description":"Starting intelligence"},{"name":"Skin Color","type":"ushort","size":2,"description":"Character skin hue"},{"name":"Unknown2","type":"byte[8]","size":8,"description":"Unknown padding"},{"name":"Skill 1 ID","type":"byte","size":1,"description":"First skill ID"},{"name":"Skill 1 Value","type":"byte","size":1,"description":"First skill starting value"},{"name":"Skill 2 ID","type":"byte","size":1,"description":"Second skill ID"},{"name":"Skill 2 Value","type":"byte","size":1,"description":"Second skill starting value"},{"name":"Skill 3 ID","type":"byte","size":1,"description":"Third skill ID"},{"name":"Skill 3 Value","type":"byte","size":1,"description":"Third skill starting value"},{"name":"Skill 4 ID","type":"byte","size":1,"description":"Fourth skill ID"},{"name":"Skill 4 Value","type":"byte","size":1,"description":"Fourth skill starting value"},{"name":"Unknown3","type":"byte[26]","size":26,"description":"Unknown padding and appearance fields"},{"name":"Hair Color","type":"ushort","size":2,"description":"Hair hue"},{"name":"Hair Style","type":"ushort","size":2,"description":"Hair graphic ID"},{"name":"Shirt Color","type":"ushort","size":2,"description":"Shirt hue"},{"name":"Shirt Style","type":"ushort","size":2,"description":"Shirt graphic ID"},{"name":"Face Color","type":"ushort","size":2,"description":"Face hue"},{"name":"Face Style","type":"ushort","size":2,"description":"Face graphic ID"},{"name":"Beard Color","type":"ushort","size":2,"description":"Facial hair hue"},{"name":"Beard Style","type":"ushort","size":2,"description":"Facial hair graphic ID"}],"related":[{"id":"0x00","relationship":"variant","note":"Create Character (Old) for Classic Client pre-7.0.16.0"},{"id":"0xF8","relationship":"variant","note":"Create Character (New) for Classic Client 7.0.16.0+"}],"clientVersion":{"enhanced":{},"notes":"Enhanced Client only. Uses different field layout with separate gender/race bytes."},"notes":"EC clients use this packet instead of 0x00/0xF8. The field layout differs significantly from Classic client versions, with separate gender and race bytes instead of combined genderRace field.","category":"Account","tags":["Account"]},{"id":"0x91","name":"Game Login","description":"Login request sent to the game server after selecting a shard from the server list.","direction":"incoming","isDynamic":false,"size":65,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x91","description":"Packet identifier"},{"name":"Auth ID","type":"int","size":4,"description":"Authentication ID from PlayServerAck (0x8C)"},{"name":"Username","type":"ascii","size":30,"description":"Account username"},{"name":"Password","type":"ascii","size":30,"description":"Account password"}],"related":[{"id":"0xA9","relationship":"response","note":"Character list sent on success"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingAccountPackets.cs","line":345},"category":"Account","tags":["Account"]},{"id":"0x93","name":"Old Book Header Change","description":"Legacy format for book header changes. Uses fixed-size ASCII strings.","direction":"incoming","isDynamic":false,"size":99,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x93","description":"Packet identifier"},{"name":"Book Serial","type":"uint","size":4,"description":"Serial of the book being edited"},{"name":"Flags","type":"ushort","size":2,"description":"Book flags (ignored by server)"},{"name":"Page Count","type":"ushort","size":2,"description":"Number of pages (ignored by server)"},{"name":"Title","type":"ascii","size":60,"description":"Book title (fixed 60 bytes, null-padded)"},{"name":"Author","type":"ascii","size":30,"description":"Book author (fixed 30 bytes, null-padded)"}],"related":[{"id":"0xD4","direction":"incoming","relationship":"variant","note":"New Header Change format for newer clients"}],"notes":"Old format used by older clients. Title and author are fixed-size ASCII.","source":{"file":"Projects/UOContent/Items/Books/BookPackets.cs","line":32},"category":"Book","tags":["Book"]},{"id":"0x95","name":"Hue Picker Response","description":"Client responds to a hue picker dialog.","direction":"incoming","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x95","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Hue picker serial"},{"name":"Item ID","type":"short","size":2,"description":"Item ID (unused)"},{"name":"Hue","type":"short","size":2,"description":"Selected hue (masked with 0x3FFF)"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":86},"category":"Player","tags":["Player"]},{"id":"0x98","name":"Mobile Name Request","description":"Client requests the name of a mobile.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x98","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Mobile Serial","type":"uint","size":4,"description":"Serial of mobile to query"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingMobilePackets.cs","line":43},"category":"Mobile","tags":["Mobile"]},{"id":"0x9A","name":"ASCII Prompt Response","description":"Client responds to an ASCII text prompt.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x9A","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Prompt serial"},{"name":"Prompt ID","type":"int","size":4,"description":"Prompt ID"},{"name":"Type","type":"int","size":4,"description":"Response type: 0 = cancel, other = submit"},{"name":"Text","type":"ascii-t","description":"Response text (max 128 chars)"}],"related":[{"id":"0xC2","relationship":"request","note":"Unicode Prompt packet that triggered this response"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":214},"category":"Player","tags":["Player","Menu"]},{"id":"0x9B","name":"Help Request","description":"Client requests help/GM assistance.","direction":"incoming","isDynamic":false,"size":258,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x9B","description":"Packet identifier"},{"name":"Data","type":"byte[]","size":257,"description":"Help request data (format TBD)"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":338},"category":"Player","tags":["Player"]},{"id":"0x9F","name":"Vendor Sell Reply","description":"Client confirms items to sell to a vendor.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0x9F","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Vendor Serial","type":"uint","size":4,"description":"Serial of the vendor"},{"name":"Item Count","type":"ushort","size":2,"description":"Number of items to sell"},{"name":"Items","type":"loop","loop":{"countField":"itemCount","fields":[{"name":"Item Serial","type":"uint","size":4,"description":"Serial of item to sell"},{"name":"Amount","type":"short","size":2,"description":"Amount to sell"}]}}],"related":[{"id":"0x9E","relationship":"request","note":"Vendor Sell List packet that initiated this"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingVendorPackets.cs","line":26},"category":"Vendor","tags":["Vendor"]},{"id":"0xA0","name":"Play Server","description":"Request to connect to a specific game server from the server list.","direction":"incoming","isDynamic":false,"size":3,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA0","description":"Packet identifier"},{"name":"Server Index","type":"short","size":2,"description":"Index of selected server in the list"}],"related":[{"id":"0x8C","relationship":"response","note":"Server connection details"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingAccountPackets.cs","line":398},"category":"Account","tags":["Account"]},{"id":"0xA4","name":"System Info","description":"Client sends system/hardware information.","direction":"incoming","isDynamic":false,"size":149,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA4","description":"Packet identifier"},{"name":"Unknown1","type":"byte","size":1,"description":"Unknown"},{"name":"Unknown2","type":"ushort","size":2,"description":"Unknown"},{"name":"Unknown3","type":"byte","size":1,"description":"Unknown"},{"name":"String1","type":"ascii","size":32,"description":"System string 1"},{"name":"String2","type":"ascii","size":32,"description":"System string 2"},{"name":"String3","type":"ascii","size":32,"description":"System string 3"},{"name":"String4","type":"ascii","size":32,"description":"System string 4"},{"name":"Unknown4","type":"ushort","size":2,"description":"Unknown"},{"name":"Unknown5","type":"ushort","size":2,"description":"Unknown"},{"name":"Unknown6","type":"int","size":4,"description":"Unknown"},{"name":"Unknown7","type":"int","size":4,"description":"Unknown"},{"name":"Unknown8","type":"int","size":4,"description":"Unknown"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":103},"category":"Player","tags":["Player"]},{"id":"0xA7","name":"Request Scroll Window","description":"Client requests a tips/scroll window.","direction":"incoming","isDynamic":false,"size":4,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xA7","description":"Packet identifier"},{"name":"Last Tip","type":"short","size":2,"description":"Last tip ID viewed"},{"name":"Type","type":"byte","size":1,"description":"Scroll type"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":63},"category":"Player","tags":["Player"]},{"id":"0xAD","name":"Unicode Speech","description":"Client sends Unicode-encoded speech message. Type byte upper bits (0xC0) indicate if keywords are encoded.","direction":"incoming","isDynamic":true,"size":"Varies","variants":[{"name":"Standard Unicode","condition":"type & 0xC0 == 0","size":"12+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xAD","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Type","type":"enum","size":1,"description":"Message type (0xC0 bits clear)","values":[{"value":0,"name":"Regular","description":"Normal speech"},{"value":1,"name":"System","description":"System message"},{"value":2,"name":"Emote","description":"Emote (*action*)"},{"value":8,"name":"Whisper","description":"Whisper"},{"value":9,"name":"Yell","description":"Yell"},{"value":13,"name":"Guild","description":"Guild chat"},{"value":14,"name":"Alliance","description":"Alliance chat"},{"value":15,"name":"Command","description":"Command"}]},{"name":"Hue","type":"short","size":2,"description":"Text color hue"},{"name":"Font","type":"short","size":2,"description":"Font ID"},{"name":"Language","type":"ascii","size":4,"description":"Language code (e.g., 'ENU')"},{"name":"Text","type":"utf16be-t","description":"Speech text (Big Endian Unicode, null-terminated)"}]},{"name":"Encoded Keywords","condition":"type & 0xC0 != 0","size":"14+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xAD","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Type","type":"byte","size":1,"description":"Message type with 0xC0 flag set. Lower 4 bits = message type (see Standard variant)"},{"name":"Hue","type":"short","size":2,"description":"Text color hue"},{"name":"Font","type":"short","size":2,"description":"Font ID"},{"name":"Language","type":"ascii","size":4,"description":"Language code (e.g., 'ENU')"},{"name":"Keyword Header","type":"ushort","size":2,"description":"Bits 15-4: keyword count (0-50), Bits 3-0: first hold value for packed IDs"},{"name":"Packed Keywords","type":"byte[]","description":"12-bit keyword IDs packed alternating: even indices use hold<<8|byte, odd indices use (short&0xFFF0)>>4 with new hold"},{"name":"Text","type":"utf8-t","description":"Speech text (UTF-8, null-terminated)"}]}],"notes":"Encoded keywords use 12-bit speech IDs packed efficiently. Keyword count must be 0-50. The packing alternates: even-indexed keywords combine the previous 4-bit hold with a new byte (12 bits total), odd-indexed keywords read a short and extract bits 15-4 as the ID, bits 3-0 as the next hold.","related":[{"id":"0x03","direction":"incoming","relationship":"variant","note":"ASCII Speech (simpler format)"},{"id":"0xAE","direction":"outgoing","relationship":"response","note":"Unicode Message sent to other clients"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingMessagePackets.cs","line":58},"category":"Message","tags":["Message"]},{"id":"0xB1","name":"Gump Response","description":"Client response to a generic gump dialog (button press, checkbox/radio selections, text entries).","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB1","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Serial from the 0xB0/0xDD gump packet"},{"name":"Gump ID","type":"uint","size":4,"description":"Gump type ID from the 0xB0/0xDD gump packet"},{"name":"Button ID","type":"uint","size":4,"description":"ID of button pressed (0 if gump closed without pressing a button)"},{"name":"Switch Count","type":"uint","size":4,"description":"Number of active switches (checkboxes/radio buttons)"},{"name":"Switches","type":"array","description":"Array of switch IDs that are active/checked","entries":[{"name":"Switch ID","type":"uint","size":4,"description":"ID of an active switch"}]},{"name":"Text Entry Count","type":"uint","size":4,"description":"Number of text entries"},{"name":"Text Entries","type":"array","description":"Array of text entry responses","entries":[{"name":"Entry ID","type":"ushort","size":2,"description":"Text entry field ID"},{"name":"Text Length","type":"ushort","size":2,"description":"Length of text in characters"},{"name":"Text","type":"unicode-be","size":"var","description":"UTF-16 BE encoded text (length * 2 bytes, not null-terminated)"}]}],"related":[{"id":"0xB0","relationship":"response","note":"Generic Gump (uncompressed) - server sends this to display the gump"},{"id":"0xDD","relationship":"response","note":"Compressed Gump - server sends this to display a compressed gump"}],"clientVersion":{"classic":{},"enhanced":{}},"source":{"file":"Projects/UOContent/Gumps/Base/GumpSystem.cs","line":31},"category":"Gump","tags":["Gump"]},{"id":"0xB3","name":"Chat Action","description":"Client sends chat action commands like sending messages, joining channels, etc.","direction":"incoming","isDynamic":true,"size":"8+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB3","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Language","type":"ascii","size":4,"description":"Language code (e.g., 'enu' for English)"},{"name":"Action ID","type":"short","size":2,"description":"Chat action ID"},{"name":"Parameter","type":"utf16be","size":"var","description":"Action parameter (Big Endian Unicode)"}],"related":[{"id":"0xB2","direction":"outgoing","relationship":"response","note":"Server responds with Chat Message"}],"source":{"file":"Projects/UOContent/Engines/Chat/ChatPackets.cs","line":51},"category":"Chat","tags":["Chat"]},{"id":"0xB5","name":"Open Chat Window Request","description":"Client requests to open the chat window. Newer clients don't send chat username.","direction":"incoming","isDynamic":false,"size":64,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB5","description":"Packet identifier"},{"name":"Reserved","type":"byte[]","size":63,"description":"Reserved/unused (newer clients don't send chat username)"}],"related":[{"id":"0xB2","direction":"outgoing","relationship":"response","note":"Server responds with Chat Message (OpenChatWindow command)"}],"source":{"file":"Projects/UOContent/Engines/Chat/ChatPackets.cs","line":30},"category":"Chat","tags":["Chat"]},{"id":"0xB6","name":"Object Help Request","description":"Sent when the player requests help/info about an object (Shift+Click or context menu).","direction":"incoming","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB6","description":"Packet identifier"},{"name":"Serial","type":"uint","size":4,"description":"Serial of the target entity"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown"},{"name":"Language","type":"ascii","size":3,"description":"Language code (e.g., 'ENU')"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingEntityPackets.cs","line":32},"category":"Item","tags":["Item","Mobile"]},{"id":"0xB8","name":"Profile Request","description":"Client requests to view or edit a mobile's profile.","direction":"incoming","isDynamic":true,"size":"Varies","variants":[{"name":"Display Profile","condition":"mode == Display (0)","size":8,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB8","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Mode","type":"byte","size":1,"value":"0","description":"Display mode"},{"name":"Mobile Serial","type":"uint","size":4,"description":"Serial of target mobile"}]},{"name":"Edit Profile","condition":"mode == Edit (1)","size":"12+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xB8","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Mode","type":"byte","size":1,"value":"1","description":"Edit mode"},{"name":"Mobile Serial","type":"uint","size":4,"description":"Serial of target mobile"},{"name":"Padding","type":"short","size":2,"description":"Unused padding"},{"name":"Text Length","type":"ushort","size":2,"description":"Length of text in characters"},{"name":"Text","type":"utf16be","description":"New profile text (Big Endian Unicode)"}]}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingMobilePackets.cs","line":53},"category":"Mobile","tags":["Mobile"]},{"id":"0xBD","name":"Client Version","description":"Response to server's version request (0xBD). Contains the client version string.","direction":"incoming","isDynamic":true,"size":"3 + version string length","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBD","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Version","type":"ascii","description":"Client version string (e.g., '7.0.95.0')"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingAccountPackets.cs","line":193},"category":"Account","tags":["Account"]},{"id":"0xBE","name":"Assistant Version","description":"Client sends assistant version information. Razor CE sends version as ASCII string.","direction":"incoming","isDynamic":true,"size":"3+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBE","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Version String","type":"ascii","size":"var","description":"Assistant version string (Razor CE sends 'version' or 'ProductName version')"}],"notes":"Razor Community Edition sends version as ASCII. Legacy UOAssist would send int32 + ASCII client version.","source":{"file":"Projects/UOContent/Assistants/AssistantHandler.cs","line":69},"category":"Assistant","tags":["Assistant"]},{"id":"0xBF","name":"Extended Command","description":"Wrapper packet for extended command subpackets. Used for both client-to-server and server-to-client communication.","direction":"both","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"description":"Extended command ID"},{"name":"Data","type":"byte[]","description":"Subcommand-specific data"}],"subpackets":[{"subId":"0x04","name":"Close Gump","description":"Close a generic gump","direction":"outgoing"},{"subId":"0x05","name":"Screen Size","description":"Client reports screen dimensions","direction":"incoming"},{"subId":"0x06","name":"Party Message","description":"Party system commands and messages","direction":"both"},{"subId":"0x07","name":"Quest Arrow Click","description":"Client clicked the quest tracking arrow","direction":"incoming"},{"subId":"0x08","name":"Map Change","description":"Notify client of map/facet change","direction":"outgoing"},{"subId":"0x09","name":"Disarm Request","description":"Request to disarm opponent","direction":"incoming"},{"subId":"0x0A","name":"Stun Request","description":"Request to stun opponent","direction":"incoming"},{"subId":"0x0B","name":"Language","description":"Client language setting","direction":"incoming"},{"subId":"0x0C","name":"Status Bar Close","description":"Client closed a status bar","direction":"incoming"},{"subId":"0x0E","name":"Animate","description":"Request to play animation","direction":"incoming"},{"subId":"0x0F","name":"Client Info","description":"Client type and flags (Spy on Client)","direction":"incoming"},{"subId":"0x10","name":"Query Object Properties","description":"Request object property list","direction":"incoming"},{"subId":"0x13","name":"Context Menu Request","description":"Request context menu for entity","direction":"incoming"},{"subId":"0x14","name":"Context Menu Display","description":"Display context menu to client","direction":"outgoing"},{"subId":"0x15","name":"Context Menu Response","description":"Selected context menu option","direction":"incoming"},{"subId":"0x18","name":"Map Patches","description":"Send map diff/patch information","direction":"outgoing"},{"subId":"0x19","name":"Stat Lock Info","description":"Stat lock states and bonded status","direction":"outgoing"},{"subId":"0x1A","name":"Stat Lock Change","description":"Change STR/DEX/INT lock state","direction":"incoming"},{"subId":"0x1B","name":"New Spellbook Content","description":"Spellbook spell list (AOS+)","direction":"outgoing"},{"subId":"0x1C","name":"Cast Spell","description":"Cast spell by ID","direction":"incoming"},{"subId":"0x1E","name":"Query Design Details","description":"Request house design details","direction":"incoming"},{"subId":"0x21","name":"Set Weapon Ability","description":"Clear weapon ability selection","direction":"outgoing"},{"subId":"0x22","name":"Damage","description":"Display damage number (old clients)","direction":"outgoing"},{"subId":"0x25","name":"Toggle Special Ability","description":"Toggle weapon special move icon","direction":"outgoing"},{"subId":"0x26","name":"Speed Mode","description":"Set movement speed mode","direction":"outgoing"},{"subId":"0x2A","name":"Race Change Reply","description":"Response to race change confirmation","direction":"incoming"},{"subId":"0x2C","name":"Bandage Target","description":"Apply bandage to target","direction":"incoming"},{"subId":"0x2D","name":"Targeted Spell","description":"Cast spell with pre-selected target","direction":"incoming"},{"subId":"0x2E","name":"Targeted Skill Use","description":"Use skill with pre-selected target","direction":"incoming"},{"subId":"0x30","name":"Target By Resource Macro","description":"Resource-based targeting macro","direction":"incoming"},{"subId":"0x32","name":"Toggle Flying","description":"Toggle gargoyle flying mode","direction":"incoming"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":43},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x05","subId":"0x05","name":"Screen Size","description":"Client reports screen size.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x05","description":"Screen Size subcommand"},{"name":"Width","type":"int","size":4,"description":"Screen width"},{"name":"Unknown","type":"int","size":4,"description":"Unknown value"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":136},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x06","subId":"0x06","name":"Party Message","description":"Client sends party-related commands.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x06","description":"Party Message subcommand"},{"name":"Party Command","type":"enum","enumType":"sequential","size":1,"description":"Party command type","values":[{"value":1,"name":"Add Member","description":"Add member to party"},{"value":2,"name":"Remove Member","description":"Remove member from party"},{"value":3,"name":"Private Message","description":"Send private message to party member"},{"value":4,"name":"Public Message","description":"Send public message to party"},{"value":6,"name":"Set Can Loot","description":"Set loot permission"},{"value":8,"name":"Accept","description":"Accept party invitation"},{"value":9,"name":"Decline","description":"Decline party invitation"}]},{"name":"Data","type":"byte[]","description":"Command-specific data (target serial, message text)"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":142},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x07","subId":"0x07","name":"Quest Arrow Click","description":"Client clicked the quest tracking arrow.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x07","description":"Quest Arrow Click subcommand"},{"name":"Right Click","type":"bool","size":1,"description":"True if right-clicked, false if left-clicked"}],"related":[{"id":"0xBA","relationship":"response","note":"Quest Arrow packet"}],"source":{"file":"Projects/UOContent/Skills/Tracking/Tracking.cs","line":26},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x09","subId":"0x09","name":"Disarm Request","description":"Client requests to disarm opponent.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x09","description":"Disarm Request subcommand"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":289},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x0A","subId":"0x0A","name":"Stun Request","description":"Client requests to stun opponent.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0A","description":"Stun Request subcommand"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":277},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x0B","subId":"0x0B","name":"Language","description":"Client sets language preference.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0B","description":"Language subcommand"},{"name":"Language","type":"ascii","size":4,"description":"Language code (e.g., 'ENU')"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":343},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x0C","subId":"0x0C","name":"Close Status","description":"Client closes a status gump.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0C","description":"Close Status subcommand"},{"name":"Serial","type":"uint","size":4,"description":"Serial of mobile whose status to close"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":338},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x0E","subId":"0x0E","name":"Animate","description":"Client requests to play an animation.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0E","description":"Animate subcommand"},{"name":"Action","type":"int","size":4,"description":"Animation action ID (must be in valid list)"}],"notes":"Only specific animation IDs are allowed for security.","source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":233},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x0F","subId":"0x0F","name":"Client Info","description":"Client type information sent once at login. ModernUO currently ignores this packet data.","direction":"incoming","isDynamic":true,"implemented":false,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x000F","description":"Client Info subcommand"},{"name":"Unknown","type":"byte","size":1,"value":"0x0A","description":"Unknown (always 0x0A)"},{"name":"Client Type","type":"enum","enumType":"sequential","size":4,"description":"Client type flag (same as character create/login)","values":[{"value":"0x00","name":"Classic","description":"Classic 2D Client"},{"value":"0x02","name":"KR","description":"Kingdom Reborn Client"},{"value":"0x03","name":"EC","description":"Enhanced Client (Stygian Abyss)"}]}],"related":[{"id":"0xE1","relationship":"related","note":"Client Type packet - similar client type information"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":52},"notes":"ModernUO registers this packet but ignores its data (calls Empty handler). The client type should match the value in 0xE1 Client Type packet.","category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x10","subId":"0x10","name":"Query Properties","description":"Client queries Object Property List (tooltip) for an entity.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x10","description":"Query Properties subcommand"},{"name":"Serial","type":"uint","size":4,"description":"Serial of entity to query"}],"related":[{"id":"0xDC","direction":"outgoing","relationship":"response","note":"OPL Info packet"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":355},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x13","subId":"0x13","name":"Context Menu Request","description":"Client requests context menu for an entity.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x13","description":"Context Menu Request subcommand"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of entity to show context menu for"}],"related":[{"id":"0xBF/0x14","relationship":"response","note":"Context Menu Display packet"}],"source":{"file":"Projects/UOContent/Context Menus/ContextMenuSystem.cs","line":101},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x15","subId":"0x15","name":"Context Menu Response","description":"Client selects an option from context menu.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x15","description":"Context Menu Response subcommand"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of entity context menu was shown for"},{"name":"Index","type":"ushort","size":2,"description":"Index of selected menu option"}],"related":[{"id":"0xBF/0x13","relationship":"request","note":"Context Menu Request packet"}],"source":{"file":"Projects/UOContent/Context Menus/ContextMenuSystem.cs","line":48},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x1A","subId":"0x1A","name":"Stat Lock Change","description":"Client changes stat lock (STR/DEX/INT).","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x1A","description":"Stat Lock Change subcommand"},{"name":"Stat","type":"enum","enumType":"sequential","size":1,"description":"Which stat to change","values":[{"value":0,"name":"Strength","description":"Strength lock"},{"value":1,"name":"Dexterity","description":"Dexterity lock"},{"value":2,"name":"Intelligence","description":"Intelligence lock"}]},{"name":"Lock Value","type":"enum","enumType":"sequential","size":1,"description":"New lock state","values":[{"value":0,"name":"Up","description":"Stat gains enabled"},{"value":1,"name":"Down","description":"Stat decreases enabled"},{"value":2,"name":"Locked","description":"Stat locked"}]}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":301},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x1C","subId":"0x1C","name":"Cast Spell","description":"Client casts a spell (optionally from spellbook).","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x1C","description":"Cast Spell subcommand"},{"name":"Has Book","type":"short","size":2,"description":"1 if casting from book, 0 otherwise"},{"name":"Book Serial","type":"uint","size":4,"description":"Serial of spellbook (if hasBook)","condition":"hasBook == 1"},{"name":"Spell ID","type":"short","size":2,"description":"Spell ID + 1 (1-based)"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":257},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)","Spell"]},{"id":"0xBF/0x1E","subId":"0x1E","name":"Query Design Details","description":"Client requests house design details.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x1E","description":"Query Design Details subcommand"},{"name":"House Serial","type":"uint","size":4,"description":"Serial of house foundation"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1826},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)","House"]},{"id":"0xBF/0x2A","subId":"0x2A","name":"Race Change Reply","description":"Client response to race change confirmation gump.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x2A","description":"Race Change Reply subcommand"},{"name":"Skin Hue","type":"ushort","size":2,"description":"Selected skin hue","condition":"length > 5"},{"name":"Hair Item ID","type":"ushort","size":2,"description":"Selected hair style","condition":"length > 5"},{"name":"Hair Hue","type":"ushort","size":2,"description":"Selected hair hue","condition":"length > 5"},{"name":"Facial Hair Item ID","type":"ushort","size":2,"description":"Selected facial hair style","condition":"length > 5"},{"name":"Facial Hair Hue","type":"ushort","size":2,"description":"Selected facial hair hue","condition":"length > 5"}],"source":{"file":"Projects/UOContent/Engines/ML Quests/Gumps/RaceChangeGump.cs","line":199},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x2C","subId":"0x2C","name":"Bandage Target","description":"Client uses bandage on a target.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x2C","description":"Bandage Target subcommand"},{"name":"Bandage Serial","type":"uint","size":4,"description":"Serial of the bandage item"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of target mobile"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":387},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x2D","subId":"0x2D","name":"Targeted Spell","description":"Client casts spell with pre-selected target.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x2D","description":"Targeted Spell subcommand"},{"name":"Spell ID","type":"short","size":2,"description":"Spell ID + 1 (1-based)"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of target entity"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":422},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)","Spell"]},{"id":"0xBF/0x2E","subId":"0x2E","name":"Targeted Skill Use","description":"Client uses skill with pre-selected target.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x2E","description":"Targeted Skill Use subcommand"},{"name":"Skill ID","type":"short","size":2,"description":"Skill ID"},{"name":"Target Serial","type":"uint","size":4,"description":"Serial of target entity"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":429},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x30","subId":"0x30","name":"Target By Resource Macro","description":"Client uses resource-based targeting macro.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x30","description":"Target By Resource Macro subcommand"},{"name":"Item Serial","type":"uint","size":4,"description":"Serial of item"},{"name":"Resource Type","type":"short","size":2,"description":"Resource type ID"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":439},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xBF/0x32","subId":"0x32","name":"Toggle Flying","description":"Client toggles gargoyle flying mode.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xBF","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x32","description":"Toggle Flying subcommand"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs","line":272},"category":"Extended Commands (0xBF)","tags":["Extended Commands (0xBF)"]},{"id":"0xC2","name":"Unicode Prompt Response","description":"Client responds to a Unicode text prompt.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xC2","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Prompt serial"},{"name":"Prompt ID","type":"int","size":4,"description":"Prompt ID"},{"name":"Type","type":"int","size":4,"description":"Response type: 0 = cancel, other = submit"},{"name":"Language","type":"ascii","size":4,"description":"Language code (e.g., 'ENU')"},{"name":"Text","type":"utf16le-t","description":"Response text (max 128 chars)"}],"related":[{"id":"0xC2","direction":"outgoing","relationship":"request","note":"Unicode Prompt packet that triggered this response"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":250},"category":"Player","tags":["Player","Menu"]},{"id":"0xC8","name":"Set Update Range","description":"Client requests to change update range. Server ignores and sends back fixed range.","direction":"incoming","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xC8","description":"Packet identifier"},{"name":"Range","type":"byte","size":1,"description":"Requested update range (ignored)"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":371},"category":"Player","tags":["Player"]},{"id":"0xD0","name":"Configuration File","description":"Client sends configuration data. Currently ignored by server.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD0","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Data","type":"byte[]","description":"Configuration data (ignored)"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":322},"category":"Player","tags":["Player"]},{"id":"0xD1","name":"Logout Request","description":"Client requests to logout.","direction":"incoming","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD1","description":"Packet identifier"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown (typically 0x01)"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":326},"category":"Player","tags":["Player"]},{"id":"0xD4","name":"Book Header Change","description":"Client sends updated book title and author when player edits a writable book's cover.","direction":"incoming","isDynamic":true,"size":"13+","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD4","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Book Serial","type":"uint","size":4,"description":"Serial of the book being edited"},{"name":"Flags","type":"ushort","size":2,"description":"Book flags (ignored by server)"},{"name":"Page Count","type":"ushort","size":2,"description":"Number of pages (ignored by server)"},{"name":"Title Length","type":"ushort","size":2,"description":"Length of title string including null terminator (max 61)"},{"name":"Title","type":"utf8-t","description":"Book title (max 60 characters)"},{"name":"Author Length","type":"ushort","size":2,"description":"Length of author string including null terminator (max 31)"},{"name":"Author","type":"utf8-t","description":"Book author (max 30 characters)"}],"related":[{"id":"0x93","direction":"incoming","relationship":"variant","note":"Old Header Change format for older clients"}],"source":{"file":"Projects/UOContent/Items/Books/BookPackets.cs","line":51},"category":"Book","tags":["Book"]},{"id":"0xD6","name":"Batch Query Properties","description":"Sent by the client to request Object Property Lists (tooltips) for multiple entities at once.","direction":"incoming","isDynamic":true,"size":"3 + (4 x entityCount)","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD6","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serials","type":"array","description":"List of entity serials to query","loop":{"countField":"(length-3)/4","fields":[{"name":"Serial","type":"uint","size":4,"description":"Entity serial"}]}}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingEntityPackets.cs","line":154},"category":"Item","tags":["Item","Mobile"]},{"id":"0xD7","name":"Encoded Command","description":"Wrapper packet for encoded commands (0xD7 subpackets). Used for house design, abilities, guild/quest requests.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Entity Serial","type":"uint","size":4,"description":"Serial of target entity"},{"name":"Sub-Command","type":"ushort","size":2,"description":"Encoded command ID"},{"name":"Data","type":"byte[]","description":"Subcommand-specific data"}],"subpackets":[{"subId":"0x02","name":"Backup","description":"Backup current house design state","direction":"incoming"},{"subId":"0x03","name":"Restore","description":"Restore house design from backup","direction":"incoming"},{"subId":"0x04","name":"Commit","description":"Commit house design changes","direction":"incoming"},{"subId":"0x05","name":"Delete Component","description":"Delete component from house","direction":"incoming"},{"subId":"0x06","name":"Build Component","description":"Place component in house","direction":"incoming"},{"subId":"0x0C","name":"Close Tool","description":"Close house design tool","direction":"incoming"},{"subId":"0x0D","name":"Add Stairs","description":"Add stairs to house design","direction":"incoming"},{"subId":"0x0E","name":"Sync Request","description":"Synchronize house design state","direction":"incoming"},{"subId":"0x10","name":"Clear Floor","description":"Clear a floor in house design","direction":"incoming"},{"subId":"0x12","name":"Change Floor Level","description":"Change visible floor level","direction":"incoming"},{"subId":"0x13","name":"Add Roof","description":"Add roof tile (SE+)","direction":"incoming"},{"subId":"0x14","name":"Delete Roof","description":"Delete roof tile (SE+)","direction":"incoming"},{"subId":"0x19","name":"Set Weapon Ability","description":"Select weapon special ability","direction":"incoming"},{"subId":"0x1A","name":"Revert","description":"Revert house to original state","direction":"incoming"},{"subId":"0x28","name":"Guild Gump Request","description":"Open guild gump","direction":"incoming"},{"subId":"0x32","name":"Quest Gump Request","description":"Open quest/MLB gump","direction":"incoming"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":457},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)"]},{"id":"0xD7/0x02","subId":"0x02","name":"House Design: Backup","description":"Client requests to backup current house design state.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x02","description":"Backup subcommand"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1024},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x03","subId":"0x03","name":"House Design: Restore","description":"Client requests to restore house design from backup.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x03","description":"Restore subcommand"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1025},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x04","subId":"0x04","name":"House Design: Commit","description":"Client commits the current house design changes.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x04","description":"Commit subcommand"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1026},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x05","subId":"0x05","name":"House Design: Delete Component","description":"Client requests to delete a component from house design.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x05","description":"Delete subcommand"},{"name":"Tile ID","type":"int","size":4,"description":"Tile graphic ID to delete"},{"name":"X","type":"int","size":4,"description":"X offset from foundation"},{"name":"Y","type":"int","size":4,"description":"Y offset from foundation"},{"name":"Z","type":"int","size":4,"description":"Z offset from foundation"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1027},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x06","subId":"0x06","name":"House Design: Build Component","description":"Client requests to place a component in house design.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x06","description":"Build subcommand"},{"name":"Tile ID","type":"int","size":4,"description":"Tile graphic ID to place"},{"name":"X","type":"int","size":4,"description":"X offset from foundation"},{"name":"Y","type":"int","size":4,"description":"Y offset from foundation"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1028},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x0C","subId":"0x0C","name":"House Design: Close Tool","description":"Client closes the house design tool.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0C","description":"Close subcommand"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1029},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x0D","subId":"0x0D","name":"House Design: Add Stairs","description":"Client requests to add stairs to house design.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0D","description":"Stairs subcommand"},{"name":"Tile ID","type":"int","size":4,"description":"Stair tile graphic ID"},{"name":"X","type":"int","size":4,"description":"X offset from foundation"},{"name":"Y","type":"int","size":4,"description":"Y offset from foundation"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1030},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x0E","subId":"0x0E","name":"House Design: Sync Request","description":"Client requests to synchronize house design state.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x0E","description":"Sync subcommand"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1031},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x10","subId":"0x10","name":"House Design: Clear Floor","description":"Client requests to clear a floor in house design.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x10","description":"Clear subcommand"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1032},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x12","subId":"0x12","name":"House Design: Change Floor Level","description":"Client changes the visible floor level in house design.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x12","description":"Level subcommand"},{"name":"Floor","type":"int","size":4,"description":"Floor level (1-4)"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1033},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x13","subId":"0x13","name":"House Design: Add Roof","description":"Client requests to add a roof tile (Samurai Empire+).","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x13","description":"Roof subcommand"},{"name":"Tile ID","type":"int","size":4,"description":"Roof tile graphic ID"},{"name":"X","type":"int","size":4,"description":"X offset from foundation"},{"name":"Y","type":"int","size":4,"description":"Y offset from foundation"},{"name":"Z","type":"int","size":4,"description":"Z offset for roof placement"}],"clientVersion":{"classic":{"min":"4.0.3a"},"enhanced":{},"notes":"Added with Samurai Empire expansion"},"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1035},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x14","subId":"0x14","name":"House Design: Delete Roof","description":"Client requests to delete a roof tile (Samurai Empire+).","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x14","description":"Roof Delete subcommand"},{"name":"Tile ID","type":"int","size":4,"description":"Roof tile graphic ID"},{"name":"X","type":"int","size":4,"description":"X offset from foundation"},{"name":"Y","type":"int","size":4,"description":"Y offset from foundation"},{"name":"Z","type":"int","size":4,"description":"Z offset of roof to delete"}],"clientVersion":{"classic":{"min":"4.0.3a"},"enhanced":{},"notes":"Added with Samurai Empire expansion"},"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1036},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x19","subId":"0x19","name":"Set Weapon Ability","description":"Client selects a weapon special ability.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Player serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x19","description":"Set Ability subcommand"},{"name":"Ability Index","type":"int","size":4,"description":"Ability index (0 = clear, 1+ = ability index)"}],"related":[{"id":"0xBF/0x21","relationship":"response","note":"Clear Weapon Ability"},{"id":"0xBF/0x25","relationship":"response","note":"Toggle Special Ability"}],"source":{"file":"Projects/UOContent/Items/Weapons/Abilities/WeaponAbilityPackets.cs","line":11},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","Combat"]},{"id":"0xD7/0x1A","subId":"0x1A","name":"House Design: Revert","description":"Client requests to revert house design to original state.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"House foundation serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x1A","description":"Revert subcommand"}],"source":{"file":"Projects/UOContent/Multis/Houses/HouseFoundation.cs","line":1038},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","House"]},{"id":"0xD7/0x28","subId":"0x28","name":"Guild Gump Request","description":"Client requests to open the guild gump.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Player serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x28","description":"Guild Gump subcommand"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":54},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","Guild"]},{"id":"0xD7/0x32","subId":"0x32","name":"Quest Gump Request","description":"Client requests to open the quest/MLB gump.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD7","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Serial","type":"uint","size":4,"description":"Player serial"},{"name":"Sub-Command","type":"ushort","size":2,"value":"0x32","description":"Quest Gump subcommand"}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":55},"category":"Encoded Commands (0xD7)","tags":["Encoded Commands (0xD7)","Quest"]},{"id":"0xD9","name":"Hardware Info","description":"Client sends hardware and system information. Also known as 'Spy on Client' packet.","direction":"incoming","isDynamic":false,"size":268,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xD9","description":"Packet identifier"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown (1 for pre-4.0.1a, 2 for 4.0.1a+)"},{"name":"Instance ID","type":"int","size":4,"description":"UO client instance identifier"},{"name":"OS Major","type":"int","size":4,"description":"Operating system major version"},{"name":"OS Minor","type":"int","size":4,"description":"Operating system minor version"},{"name":"OS Revision","type":"int","size":4,"description":"Operating system revision"},{"name":"CPU Manufacturer","type":"byte","size":1,"description":"CPU manufacturer code"},{"name":"CPU Family","type":"int","size":4,"description":"CPU family identifier"},{"name":"CPU Model","type":"int","size":4,"description":"CPU model number"},{"name":"CPU Clock Speed","type":"int","size":4,"description":"CPU clock speed in MHz"},{"name":"CPU Quantity","type":"byte","size":1,"description":"Number of CPUs/cores"},{"name":"Physical Memory","type":"int","size":4,"description":"Physical memory in MB"},{"name":"Screen Width","type":"int","size":4,"description":"Screen width in pixels"},{"name":"Screen Height","type":"int","size":4,"description":"Screen height in pixels"},{"name":"Screen Depth","type":"int","size":4,"description":"Screen color depth in bits"},{"name":"DirectX Major","type":"short","size":2,"description":"DirectX major version"},{"name":"DirectX Minor","type":"short","size":2,"description":"DirectX minor version"},{"name":"Video Card Description","type":"unicode-le","size":128,"description":"Video card description string (64 chars, little-endian UTF-16)"},{"name":"Video Card Vendor ID","type":"int","size":4,"description":"Video card vendor identifier"},{"name":"Video Card Device ID","type":"int","size":4,"description":"Video card device identifier"},{"name":"Video Card Memory","type":"int","size":4,"description":"Video card memory in MB"},{"name":"Distribution","type":"byte","size":1,"description":"Distribution type"},{"name":"Clients Running","type":"byte","size":1,"description":"Number of UO clients currently running"},{"name":"Clients Installed","type":"byte","size":1,"description":"Number of UO clients installed"},{"name":"Partial Installed","type":"byte","size":1,"description":"Partial installation flag"},{"name":"Language","type":"unicode-le","size":8,"description":"Language code (4 chars, little-endian UTF-16)"},{"name":"Unknown2","type":"ascii","size":64,"description":"Unknown data"}],"clientVersion":{"classic":{},"enhanced":{},"notes":"Packet size is 268 bytes (0x10C) for clients 4.0.1a+"},"source":{"file":"Projects/UOContent/Misc/HardwareInfo.cs","line":93},"notes":"This packet is sent automatically by the client after login. The server uses this to track hardware information for debugging and statistics purposes.","category":"Hardware","tags":["Hardware"]},{"id":"0xDA","name":"Mahjong Game","description":"Mahjong game packets for controlling the in-game Mahjong table. Used for both client commands and server updates.","direction":"both","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Command","type":"ushort","size":2,"description":"Command ID (incoming uses byte prefix + byte command)"},{"name":"Data","type":"byte[]","description":"Command-specific data"}],"subpackets":[{"subId":"0x02","name":"Players Info","description":"Sends player information for all seats","direction":"outgoing"},{"subId":"0x03","name":"Tile Info","description":"Sends information about a single tile","direction":"outgoing"},{"subId":"0x04","name":"Tiles Info","description":"Sends information about all tiles","direction":"outgoing"},{"subId":"0x05","name":"General Info","description":"Sends game state (dice, dealer, wall break)","direction":"outgoing"},{"subId":"0x06","name":"Exit Game","description":"Client exits the game","direction":"incoming"},{"subId":"0x0A","name":"Give Points","description":"Transfer points to another player","direction":"incoming"},{"subId":"0x0B","name":"Roll Dice","description":"Client requests to roll dice","direction":"incoming"},{"subId":"0x0C","name":"Build Walls","description":"Dealer builds/resets tile walls","direction":"incoming"},{"subId":"0x0D","name":"Reset Scores","description":"Dealer resets all scores","direction":"incoming"},{"subId":"0x0F","name":"Assign Dealer","description":"Assign a new dealer","direction":"incoming"},{"subId":"0x10","name":"Open Seat","description":"Open a seat for new players","direction":"incoming"},{"subId":"0x11","name":"Change Option","description":"Change game options","direction":"incoming"},{"subId":"0x15","name":"Move Wall Break","description":"Move wall break indicator","direction":"incoming"},{"subId":"0x16","name":"Toggle Public Hand","description":"Toggle hand visibility","direction":"incoming"},{"subId":"0x17","name":"Move Tile","description":"Move a tile on the board","direction":"incoming"},{"subId":"0x18","name":"Move Dealer Indicator","description":"Move dealer indicator","direction":"incoming"},{"subId":"0x19","name":"Join Game","description":"Server opens game interface","direction":"outgoing"},{"subId":"0x1A","name":"Relieve","description":"Server closes game interface","direction":"outgoing"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":46},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x06","name":"Mahjong Exit Game","description":"Client requests to exit the Mahjong game.","direction":"incoming","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x06","description":"Exit Game command"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":108},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x0A","name":"Mahjong Give Points","description":"Client transfers points to another player.","direction":"incoming","isDynamic":false,"size":14,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x0A","description":"Give Points command"},{"name":"To Position","type":"byte","size":1,"description":"Target player seat position"},{"name":"Amount","type":"int","size":4,"description":"Points to transfer"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":120},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x0B","name":"Mahjong Roll Dice","description":"Client requests to roll the dice.","direction":"incoming","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x0B","description":"Roll Dice command"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":133},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x0C","name":"Mahjong Build Walls","description":"Dealer requests to reset and build the tile walls.","direction":"incoming","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x0C","description":"Build Walls command"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":143},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x0D","name":"Mahjong Reset Scores","description":"Dealer requests to reset all player scores to base value.","direction":"incoming","isDynamic":false,"size":9,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x0D","description":"Reset Scores command"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":153},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x0F","name":"Mahjong Assign Dealer","description":"Dealer assigns another player as the new dealer.","direction":"incoming","isDynamic":false,"size":10,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x0F","description":"Assign Dealer command"},{"name":"Position","type":"byte","size":1,"description":"Seat position of new dealer"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":163},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x10","name":"Mahjong Open Seat","description":"Dealer opens a seat, removing the current player.","direction":"incoming","isDynamic":false,"size":10,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x10","description":"Open Seat command"},{"name":"Position","type":"byte","size":1,"description":"Seat position to open"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":175},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x11","name":"Mahjong Change Option","description":"Dealer changes game options (show scores, spectator vision).","direction":"incoming","isDynamic":false,"size":13,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x11","description":"Change Option command"},{"name":"Reserved","type":"short","size":2,"description":"Reserved (not used)"},{"name":"Reserved 2","type":"byte","size":1,"description":"Reserved (not used)"},{"name":"Options","type":"bitflags","size":1,"description":"Game options","values":[{"value":"0x01","name":"Show Scores","description":"Display player scores"},{"value":"0x02","name":"Spectator Vision","description":"Spectators can see all tiles"}]}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":192},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x15","name":"Mahjong Move Wall Break Indicator","description":"Dealer moves the wall break indicator position.","direction":"incoming","isDynamic":false,"size":13,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x15","description":"Move Wall Break Indicator command"},{"name":"Y Position","type":"short","size":2,"description":"New Y coordinate"},{"name":"X Position","type":"short","size":2,"description":"New X coordinate"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":208},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x16","name":"Mahjong Toggle Public Hand","description":"Player toggles whether their hand is visible to others.","direction":"incoming","isDynamic":false,"size":13,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x16","description":"Toggle Public Hand command"},{"name":"Reserved","type":"short","size":2,"description":"Reserved (not used)"},{"name":"Reserved 2","type":"byte","size":1,"description":"Reserved (not used)"},{"name":"Public Hand","type":"bool","size":1,"description":"True to show hand publicly"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":221},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x17","name":"Mahjong Move Tile","description":"Player moves a tile to a new position with direction and flip state.","direction":"incoming","isDynamic":false,"size":22,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x17","description":"Move Tile command"},{"name":"Tile Number","type":"byte","size":1,"description":"Tile index number"},{"name":"Current Direction","type":"byte","size":1,"description":"Current tile direction (unused)"},{"name":"New Direction","type":"enum","size":1,"description":"New tile direction","values":[{"value":"0","name":"Up","description":"Facing up"},{"value":"1","name":"Left","description":"Facing left"},{"value":"2","name":"Down","description":"Facing down"},{"value":"3","name":"Right","description":"Facing right"}]},{"name":"Reserved","type":"byte","size":1,"description":"Reserved byte"},{"name":"Flip","type":"bool","size":1,"description":"True to flip tile face-up"},{"name":"Current Y","type":"short","size":2,"description":"Current Y position (unused)"},{"name":"Current X","type":"short","size":2,"description":"Current X position (unused)"},{"name":"Reserved 2","type":"byte","size":1,"description":"Reserved byte"},{"name":"New Y","type":"short","size":2,"description":"New Y position"},{"name":"New X","type":"short","size":2,"description":"New X position"},{"name":"Reserved 3","type":"byte","size":1,"description":"Reserved byte"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":236},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xDA","subId":"0x18","name":"Mahjong Move Dealer Indicator","description":"Dealer moves the dealer indicator with direction and wind.","direction":"incoming","isDynamic":false,"size":15,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xDA","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Game Serial","type":"uint","size":4,"description":"Serial of the Mahjong game"},{"name":"Unknown","type":"byte","size":1,"description":"Unknown byte"},{"name":"Command","type":"byte","size":1,"value":"0x18","description":"Move Dealer Indicator command"},{"name":"Direction","type":"enum","size":1,"description":"Indicator direction","values":[{"value":"0","name":"Up","description":"Facing up"},{"value":"1","name":"Left","description":"Facing left"},{"value":"2","name":"Down","description":"Facing down"},{"value":"3","name":"Right","description":"Facing right"}]},{"name":"Wind","type":"enum","size":1,"description":"Wind direction displayed","values":[{"value":"0","name":"North","description":"North wind"},{"value":"1","name":"East","description":"East wind"},{"value":"2","name":"South","description":"South wind"},{"value":"3","name":"West","description":"West wind"}]},{"name":"Y Position","type":"short","size":2,"description":"New Y position"},{"name":"X Position","type":"short","size":2,"description":"New X position"}],"source":{"file":"Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs","line":271},"category":"Mahjong","tags":["Mahjong"]},{"id":"0xE1","name":"Client Type","description":"Sent by the client to identify the client type and version. Added during Kingdom Reborn/Stygian Abyss expansion.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xE1","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Unknown","type":"ushort","size":2,"value":"0x0001","description":"Unknown (always 0x0001)"},{"name":"Client Type","type":"enum","enumType":"sequential","size":2,"description":"Client type identifier","values":[{"value":"0x00","name":"Classic","description":"Classic 2D Client"},{"value":"0x02","name":"KR","description":"Kingdom Reborn Client"},{"value":"0x03","name":"EC","description":"Enhanced Client (Stygian Abyss)"}]},{"name":"Version","type":"ascii","description":"Client version string"}],"related":[{"id":"0xBF/0x0F","relationship":"related","note":"Client Info - similar client type information sent at login"}],"clientVersion":{"classic":{"min":"6.0.14.3"},"enhanced":{},"notes":"Added during Kingdom Reborn/Stygian Abyss expansion"},"source":{"file":"Projects/UOContent/Network/Packets/IncomingAccountPackets.cs","line":200},"category":"Account","tags":["Account"]},{"id":"0xEC","name":"Equip Macro","description":"Client requests to equip multiple items from a saved macro.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xEC","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Count","type":"byte","size":1,"description":"Number of items to equip"},{"name":"Items","type":"loop","loop":{"countField":"count","fields":[{"name":"Serial","type":"uint","size":4,"description":"Serial of item to equip"}]}}],"clientVersion":{"enhanced":{}},"source":{"file":"Projects/UOContent/Network/Packets/IncomingItemPackets.cs","line":112},"category":"Items","tags":["Items"]},{"id":"0xED","name":"Unequip Macro","description":"Client requests to unequip items from specific layers via macro.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xED","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Count","type":"byte","size":1,"description":"Number of layers to unequip"},{"name":"Layers","type":"loop","loop":{"countField":"count","fields":[{"name":"Layer","type":"ushort","size":2,"description":"Layer to unequip from"}]}}],"clientVersion":{"enhanced":{}},"source":{"file":"Projects/UOContent/Network/Packets/IncomingItemPackets.cs","line":125},"category":"Items","tags":["Items"]},{"id":"0xEF","name":"Login Server Seed","description":"Initial connection packet sent before account login. Contains seed and client version information.","direction":"incoming","isDynamic":false,"size":21,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xEF","description":"Packet identifier"},{"name":"Seed","type":"int","size":4,"description":"Random seed for encryption"},{"name":"Client Major","type":"int","size":4,"description":"Client major version"},{"name":"Client Minor","type":"int","size":4,"description":"Client minor version"},{"name":"Client Revision","type":"int","size":4,"description":"Client revision"},{"name":"Client Patch","type":"int","size":4,"description":"Client patch level"}],"clientVersion":{"classic":{"min":"6.0.5.0"},"enhanced":{},"notes":"Replaces the legacy 4-byte seed for clients 6.0.5.0+. Pre-6.0.5.0 clients send only a 4-byte seed without version info."},"source":{"file":"Projects/UOContent/Network/Packets/IncomingAccountPackets.cs","line":419},"category":"Account","tags":["Account"]},{"id":"0xF1","name":"FreeShard Protocol","description":"Bundle packet for freeshard-specific commands (UOGateway). Sub-command is a single byte.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF1","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"byte","size":1,"description":"Subcommand ID"},{"name":"Data","type":"byte[]","description":"Subcommand-specific data"}],"subpackets":[{"subId":"0xFE","name":"Query Compact Shard Stats","direction":"incoming"},{"subId":"0xFF","name":"Query Extended Shard Stats","direction":"incoming"}],"source":{"file":"Projects/UOContent/Network/FreeshardProtocol.cs","line":21},"category":"FreeShard Protocol (0xF1)","tags":["FreeShard Protocol (0xF1)"]},{"id":"0xF1/0xFE","subId":"0xFE","name":"Query Compact Shard Stats","description":"Query server for compact statistics. Server responds with 0x51.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF1","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"byte","size":1,"value":"0xFE","description":"Query Compact Shard Stats subcommand"}],"notes":"Outgame only. Requires uogateway.enabled configuration.","related":[{"id":"0x51","relationship":"response","note":"Compact Shard Stats response"}],"source":{"file":"Projects/UOContent/Network/UOGateway.cs","line":31},"category":"FreeShard Protocol (0xF1)","tags":["FreeShard Protocol (0xF1)"]},{"id":"0xF1/0xFF","subId":"0xFF","name":"Query Extended Shard Stats","description":"Query server for extended statistics. Server responds with raw UTF-8 string.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF1","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Sub-Command","type":"byte","size":1,"value":"0xFF","description":"Query Extended Shard Stats subcommand"}],"notes":"Outgame only. Requires uogateway.enabled configuration. Response is a raw UTF-8 string (no packet wrapper): 'ModernUO, Name={name}, Age={hours}, Clients={count}, Items={count}, Chars={count}, Mem={kb}K, Ver=2\\0'","source":{"file":"Projects/UOContent/Network/UOGateway.cs","line":32},"category":"FreeShard Protocol (0xF1)","tags":["FreeShard Protocol (0xF1)"]},{"id":"0xF4","name":"Crash Report","description":"Client sends crash/error report.","direction":"incoming","isDynamic":true,"size":"var","fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF4","description":"Packet identifier"},{"name":"Length","type":"ushort","size":2,"description":"Packet length"},{"name":"Client Major","type":"byte","size":1,"description":"Client major version"},{"name":"Client Minor","type":"byte","size":1,"description":"Client minor version"},{"name":"Client Rev","type":"byte","size":1,"description":"Client revision"},{"name":"Client Pat","type":"byte","size":1,"description":"Client patch"},{"name":"X","type":"ushort","size":2,"description":"Player X coordinate at crash"},{"name":"Y","type":"ushort","size":2,"description":"Player Y coordinate at crash"},{"name":"Z","type":"sbyte","size":1,"description":"Player Z coordinate at crash"},{"name":"Map","type":"byte","size":1,"description":"Map ID at crash"},{"name":"Account Name","type":"ascii","size":32,"description":"Account name"},{"name":"Character Name","type":"ascii","size":32,"description":"Character name"},{"name":"IP Address","type":"ascii","size":15,"description":"Client IP address"},{"name":"Unknown1","type":"int","size":4,"description":"Unknown"},{"name":"Exception Code","type":"int","size":4,"description":"Exception code"},{"name":"Process Name","type":"ascii","size":100,"description":"Process name"},{"name":"Report Text","type":"ascii","size":100,"description":"Report text"},{"name":"Terminator","type":"byte","size":1,"value":"0x00","description":"Null terminator"},{"name":"Offset","type":"int","size":4,"description":"Crash offset"},{"name":"Stack Count","type":"byte","size":1,"description":"Number of stack trace entries"},{"name":"Stack Addresses","type":"loop","loop":{"countField":"stackCount","fields":[{"name":"Address","type":"int","size":4,"description":"Stack frame address"}]}}],"source":{"file":"Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs","line":413},"category":"Player","tags":["Player"]},{"id":"0xF8","name":"Create Character (New)","description":"Request to create a new character. This is the newer 106-byte version with support for 4 skills.","direction":"incoming","isDynamic":false,"size":106,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xF8","description":"Packet identifier"},{"name":"Unknown1","type":"int","size":4,"description":"Unknown"},{"name":"Unknown2","type":"int","size":4,"description":"Unknown"},{"name":"Unknown3","type":"byte","size":1,"description":"Unknown"},{"name":"Name","type":"ascii","size":30,"description":"Character name"},{"name":"Unknown4","type":"byte[2]","size":2,"description":"Unknown"},{"name":"Flags","type":"int","size":4,"description":"Client flags"},{"name":"Unknown5","type":"byte[8]","size":8,"description":"Unknown"},{"name":"Profession","type":"byte","size":1,"description":"Starting profession"},{"name":"Unknown6","type":"byte[15]","size":15,"description":"Unknown"},{"name":"Gender Race","type":"byte","size":1,"description":"Gender and race combined value"},{"name":"Strength","type":"byte","size":1,"description":"Starting strength"},{"name":"Dexterity","type":"byte","size":1,"description":"Starting dexterity"},{"name":"Intelligence","type":"byte","size":1,"description":"Starting intelligence"},{"name":"Skill1Id","type":"byte","size":1,"description":"First skill ID"},{"name":"Skill1Value","type":"byte","size":1,"description":"First skill value"},{"name":"Skill2Id","type":"byte","size":1,"description":"Second skill ID"},{"name":"Skill2Value","type":"byte","size":1,"description":"Second skill value"},{"name":"Skill3Id","type":"byte","size":1,"description":"Third skill ID"},{"name":"Skill3Value","type":"byte","size":1,"description":"Third skill value"},{"name":"Skill4Id","type":"byte","size":1,"description":"Fourth skill ID (newer clients)"},{"name":"Skill4Value","type":"byte","size":1,"description":"Fourth skill value (newer clients)"},{"name":"Skin Hue","type":"ushort","size":2,"description":"Skin color hue"},{"name":"Hair Style","type":"short","size":2,"description":"Hair style ID"},{"name":"Hair Hue","type":"short","size":2,"description":"Hair color hue"},{"name":"Facial Hair Style","type":"short","size":2,"description":"Facial hair style ID"},{"name":"Facial Hair Hue","type":"short","size":2,"description":"Facial hair color hue"},{"name":"Unknown7","type":"byte","size":1,"description":"Unknown"},{"name":"City Index","type":"byte","size":1,"description":"Starting city index"},{"name":"Char Slot","type":"int","size":4,"description":"Character slot"},{"name":"Client IP","type":"int","size":4,"description":"Client IP"},{"name":"Shirt Hue","type":"short","size":2,"description":"Starting shirt hue"},{"name":"Pants Hue","type":"short","size":2,"description":"Starting pants hue"}],"related":[{"id":"0x00","relationship":"variant","note":"Create Character (Old) for Classic pre-7.0.16.0 with 3 skills"},{"id":"0x8D","relationship":"variant","note":"Create Character (EC) for Enhanced Client"}],"clientVersion":{"classic":{"min":"7.0.16.0"},"notes":"Classic Client only. Replaces 0x00, adds 4th starting skill. EC uses 0x8D instead."},"source":{"file":"Projects/UOContent/Network/Packets/IncomingAccountPackets.cs","line":58},"notes":"Uses the same handler as 0x00 but with 2 additional bytes for the 4th skill.","category":"Account","tags":["Account"]},{"id":"0xFA","name":"Open UO Store","description":"Client requests to open the Ultima Store interface. Sent when player clicks the UO Store button in the client toolbar (Classic) or selects Ultima Store from the menu (Enhanced).","direction":"incoming","isDynamic":false,"size":1,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xFA","description":"Packet identifier"}],"clientVersion":{"classic":{},"enhanced":{},"notes":"Ultima Store feature"},"source":{"file":"Projects/UOContent/Engines/UltimaStore/UltimaStorePackets.cs","line":10},"notes":"The Ultima Store is an in-game microtransaction store on official servers. ModernUO includes a placeholder that displays a 'not available' message. Free shards may implement their own store functionality using this packet trigger.","category":"Store","tags":["Store"]},{"id":"0xFB","name":"Public House Content","description":"Client toggles whether to receive content updates for public houses. When enabled, the server sends container contents for publicly accessible houses.","direction":"incoming","isDynamic":false,"size":2,"fields":[{"name":"Packet ID","type":"byte","size":1,"value":"0xFB","description":"Packet identifier"},{"name":"Show Contents","type":"bool","size":1,"description":"0 = hide public house contents, 1 = show public house contents"}],"clientVersion":{"classic":{},"enhanced":{}},"source":{"file":"Projects/UOContent/Network/Packets/IncomingHousePackets.cs","line":24},"notes":"This packet allows clients to opt-in or opt-out of receiving container content data for publicly accessible houses, which can reduce bandwidth for players who don't need to see inside public houses.","category":"House","tags":["House"]}]}
|
|
</span>
|
|
|
|
<script>
|
|
// Parse packet data
|
|
let allPackets = { incoming: [], outgoing: [] };
|
|
try {
|
|
allPackets = JSON.parse(document.getElementById('packets').innerText.trim() || '{"incoming":[],"outgoing":[]}');
|
|
} catch (e) {
|
|
console.error('Failed to parse packet data:', e);
|
|
}
|
|
|
|
// Get canonical packet key (handles both "0xBF" with subId and "0xBF/0x05" formats)
|
|
function getPacketKey(p) {
|
|
// If id already contains a slash, it's already a full subpacket id
|
|
if (p.id.includes('/')) return p.id;
|
|
// Otherwise, append subId if present
|
|
return p.subId ? `${p.id}/${p.subId}` : p.id;
|
|
}
|
|
|
|
// Flatten and merge bidirectional packets
|
|
function mergePackets(incoming, outgoing) {
|
|
const incomingMap = new Map();
|
|
const outgoingMap = new Map();
|
|
|
|
// Index incoming packets by ID/subId
|
|
incoming.forEach(p => {
|
|
const key = getPacketKey(p);
|
|
// Preserve original direction if already set to "both"
|
|
const direction = p.direction === 'both' ? 'both' : 'incoming';
|
|
incomingMap.set(key, { ...p, direction });
|
|
});
|
|
|
|
// Index outgoing packets by ID/subId
|
|
outgoing.forEach(p => {
|
|
const key = getPacketKey(p);
|
|
outgoingMap.set(key, { ...p, direction: 'outgoing' });
|
|
});
|
|
|
|
const merged = [];
|
|
const processed = new Set();
|
|
|
|
// Process all incoming packets, checking for bidirectional matches
|
|
incomingMap.forEach((inPacket, key) => {
|
|
const outPacket = outgoingMap.get(key);
|
|
|
|
// If packet is already marked as "both", keep it as-is (don't merge)
|
|
if (inPacket.direction === 'both') {
|
|
merged.push(inPacket);
|
|
processed.add(key); // Mark so outgoing doesn't add duplicate
|
|
return;
|
|
}
|
|
|
|
// If either packet has noMerge flag, don't merge them (they're different packets sharing same ID)
|
|
if (inPacket.noMerge || (outPacket && outPacket.noMerge)) {
|
|
merged.push(inPacket);
|
|
// Don't mark as processed - let outgoing add its own entry
|
|
return;
|
|
}
|
|
|
|
if (outPacket) {
|
|
// Bidirectional packet - merge them
|
|
processed.add(key);
|
|
|
|
// Create direction variants from both packets
|
|
const directionVariants = [];
|
|
|
|
// Incoming variant
|
|
const inVariant = {
|
|
name: 'Incoming',
|
|
direction: 'incoming',
|
|
size: inPacket.size,
|
|
condition: inPacket.description,
|
|
fields: inPacket.fields || []
|
|
};
|
|
if (inPacket.variants && inPacket.variants.length > 0) {
|
|
// If incoming has its own variants, nest them
|
|
inVariant.subVariants = inPacket.variants;
|
|
inVariant.fields = null;
|
|
}
|
|
directionVariants.push(inVariant);
|
|
|
|
// Outgoing variant
|
|
const outVariant = {
|
|
name: 'Outgoing',
|
|
direction: 'outgoing',
|
|
size: outPacket.size,
|
|
condition: outPacket.description,
|
|
fields: outPacket.fields || []
|
|
};
|
|
if (outPacket.variants && outPacket.variants.length > 0) {
|
|
// If outgoing has its own variants, nest them
|
|
outVariant.subVariants = outPacket.variants;
|
|
outVariant.fields = null;
|
|
}
|
|
directionVariants.push(outVariant);
|
|
|
|
// Merge packet info
|
|
merged.push({
|
|
id: inPacket.id,
|
|
subId: inPacket.subId,
|
|
name: inPacket.name || outPacket.name,
|
|
description: `Bidirectional packet used for both client requests and server responses.`,
|
|
direction: 'both',
|
|
category: inPacket.category || outPacket.category,
|
|
isDynamic: inPacket.isDynamic || outPacket.isDynamic,
|
|
size: inPacket.size === outPacket.size ? inPacket.size : 'Variable',
|
|
fields: [], // Empty - use direction variants instead
|
|
directionVariants: directionVariants,
|
|
related: [...(inPacket.related || []), ...(outPacket.related || [])].filter((r, i, arr) =>
|
|
arr.findIndex(x => x.id === r.id) === i // deduplicate
|
|
),
|
|
subpackets: inPacket.subpackets || outPacket.subpackets, // Preserve subpackets
|
|
notes: [inPacket.notes, outPacket.notes].filter(Boolean).join(' '),
|
|
source: inPacket.source || outPacket.source,
|
|
clientVersion: inPacket.clientVersion || outPacket.clientVersion
|
|
});
|
|
} else {
|
|
// Incoming-only packet
|
|
merged.push(inPacket);
|
|
}
|
|
});
|
|
|
|
// Add remaining outgoing-only packets
|
|
outgoingMap.forEach((outPacket, key) => {
|
|
if (!processed.has(key)) {
|
|
merged.push(outPacket);
|
|
}
|
|
});
|
|
|
|
return merged;
|
|
}
|
|
|
|
const packets = mergePackets(
|
|
allPackets.incoming || [],
|
|
allPackets.outgoing || []
|
|
);
|
|
|
|
// Build packet index by ID for quick lookups
|
|
const packetIndex = new Map();
|
|
packets.forEach(p => {
|
|
const key = getPacketKey(p);
|
|
packetIndex.set(key, p);
|
|
// Index by direction:id for direction-specific lookups (e.g., "incoming:0x66")
|
|
if (p.direction) {
|
|
packetIndex.set(`${p.direction}:${p.id}`, p);
|
|
}
|
|
// Also index by base ID for basic lookups (but don't overwrite more specific keys)
|
|
if (!packetIndex.has(p.id)) {
|
|
packetIndex.set(p.id, p);
|
|
}
|
|
});
|
|
|
|
// State
|
|
let currentFilter = 'all';
|
|
let selectedTags = new Set();
|
|
let currentSearch = '';
|
|
let selectedPacket = null;
|
|
let currentClientType = 'all';
|
|
let currentVersion = '';
|
|
|
|
// DOM elements
|
|
const searchInput = document.getElementById('searchInput');
|
|
const tagFilterContainer = document.getElementById('tagFilter');
|
|
const clearTagsBtn = document.getElementById('clearTagsBtn');
|
|
const packetList = document.getElementById('packetList');
|
|
const packetCount = document.getElementById('packetCount');
|
|
const welcomeMessage = document.getElementById('welcomeMessage');
|
|
const packetContent = document.getElementById('packetContent');
|
|
const sidebar = document.getElementById('sidebar');
|
|
const detailPanel = document.getElementById('detailPanel');
|
|
const mobileBackBtn = document.getElementById('mobileBackBtn');
|
|
const collapseSidebarBtn = document.getElementById('collapseSidebarBtn');
|
|
const expandSidebarBtn = document.getElementById('expandSidebarBtn');
|
|
|
|
// Responsive breakpoints
|
|
const MOBILE_BREAKPOINT = 768; // md breakpoint
|
|
const LARGE_BREAKPOINT = 1280; // xl breakpoint
|
|
|
|
function isMobile() {
|
|
return window.innerWidth < MOBILE_BREAKPOINT;
|
|
}
|
|
|
|
function isMediumScreen() {
|
|
return window.innerWidth >= MOBILE_BREAKPOINT && window.innerWidth < LARGE_BREAKPOINT;
|
|
}
|
|
|
|
// Sidebar collapse state (for medium screens)
|
|
let isSidebarCollapsed = false;
|
|
|
|
function collapseSidebar() {
|
|
if (!isMediumScreen()) return;
|
|
isSidebarCollapsed = true;
|
|
sidebar.classList.add('hidden');
|
|
expandSidebarBtn.classList.remove('hidden');
|
|
}
|
|
|
|
function expandSidebar() {
|
|
isSidebarCollapsed = false;
|
|
sidebar.classList.remove('hidden');
|
|
expandSidebarBtn.classList.add('hidden');
|
|
}
|
|
|
|
// Collapse/expand button handlers
|
|
collapseSidebarBtn.addEventListener('click', collapseSidebar);
|
|
expandSidebarBtn.addEventListener('click', expandSidebar);
|
|
|
|
function showMobileDetailView() {
|
|
if (!isMobile()) return;
|
|
sidebar.classList.add('hidden');
|
|
detailPanel.classList.remove('hidden');
|
|
}
|
|
|
|
function showMobileListView() {
|
|
if (!isMobile()) return;
|
|
sidebar.classList.remove('hidden');
|
|
detailPanel.classList.add('hidden');
|
|
}
|
|
|
|
// Back button handler
|
|
mobileBackBtn.addEventListener('click', () => {
|
|
showMobileListView();
|
|
});
|
|
|
|
// Handle window resize - reset to proper state
|
|
window.addEventListener('resize', () => {
|
|
if (isMobile()) {
|
|
// Mobile: hide expand button, handle list/detail toggle
|
|
expandSidebarBtn.classList.add('hidden');
|
|
if (!selectedPacket) {
|
|
sidebar.classList.remove('hidden');
|
|
detailPanel.classList.add('hidden');
|
|
}
|
|
} else if (isMediumScreen()) {
|
|
// Medium: show both panels, respect collapsed state
|
|
detailPanel.classList.remove('hidden');
|
|
if (isSidebarCollapsed) {
|
|
sidebar.classList.add('hidden');
|
|
expandSidebarBtn.classList.remove('hidden');
|
|
} else {
|
|
sidebar.classList.remove('hidden');
|
|
expandSidebarBtn.classList.add('hidden');
|
|
}
|
|
} else {
|
|
// Large: always show both panels, no collapse
|
|
sidebar.classList.remove('hidden');
|
|
detailPanel.classList.remove('hidden');
|
|
expandSidebarBtn.classList.add('hidden');
|
|
isSidebarCollapsed = false;
|
|
}
|
|
});
|
|
|
|
// Tags toggle for mobile
|
|
const toggleTagsBtn = document.getElementById('toggleTagsBtn');
|
|
const toggleTagsIcon = document.getElementById('toggleTagsIcon');
|
|
let tagsExpanded = false;
|
|
|
|
toggleTagsBtn.addEventListener('click', () => {
|
|
tagsExpanded = !tagsExpanded;
|
|
if (tagsExpanded) {
|
|
tagFilterContainer.classList.remove('hidden');
|
|
tagFilterContainer.classList.add('flex');
|
|
toggleTagsIcon.style.transform = 'rotate(180deg)';
|
|
} else {
|
|
tagFilterContainer.classList.add('hidden');
|
|
tagFilterContainer.classList.remove('flex');
|
|
toggleTagsIcon.style.transform = '';
|
|
}
|
|
});
|
|
|
|
// Helper to ensure tags is always an array
|
|
function ensureArray(val) {
|
|
if (!val) return [];
|
|
if (Array.isArray(val)) return val;
|
|
return [val];
|
|
}
|
|
|
|
// Extract all unique tags from all packets
|
|
const allTags = [...new Set(
|
|
packets.flatMap(p => ensureArray(p.tags).length ? ensureArray(p.tags) : [p.category]).filter(Boolean)
|
|
)].sort();
|
|
|
|
// Render tag filter badges
|
|
function renderTagFilter() {
|
|
tagFilterContainer.innerHTML = allTags.map(tag => {
|
|
const isSelected = selectedTags.has(tag);
|
|
return `<button class="tag-badge text-xs px-2 py-0.5 rounded border transition-colors ${
|
|
isSelected
|
|
? 'bg-gold-500 text-modern-black border-gold-500 font-medium'
|
|
: 'bg-modern-dark-black text-gold-300 border-gold-500/30 hover:border-gold-500'
|
|
}" data-tag="${tag}">${tag}</button>`;
|
|
}).join('');
|
|
|
|
// Show/hide clear button
|
|
clearTagsBtn.classList.toggle('hidden', selectedTags.size === 0);
|
|
|
|
// Add click handlers to tag badges
|
|
document.querySelectorAll('.tag-badge').forEach(badge => {
|
|
badge.addEventListener('click', () => {
|
|
const tag = badge.dataset.tag;
|
|
if (selectedTags.has(tag)) {
|
|
selectedTags.delete(tag);
|
|
} else {
|
|
selectedTags.add(tag);
|
|
}
|
|
renderTagFilter();
|
|
renderPacketList();
|
|
});
|
|
});
|
|
}
|
|
|
|
// Clear tags button handler
|
|
clearTagsBtn.addEventListener('click', () => {
|
|
selectedTags.clear();
|
|
renderTagFilter();
|
|
renderPacketList();
|
|
});
|
|
|
|
// Initial render of tag filter
|
|
renderTagFilter();
|
|
|
|
// Update packet count
|
|
function updatePacketCount() {
|
|
const filtered = getFilteredPackets();
|
|
packetCount.textContent = `${filtered.length} of ${packets.length} packets`;
|
|
}
|
|
|
|
// Get direction color class
|
|
function getDirectionClass(direction) {
|
|
switch(direction) {
|
|
case 'incoming': return 'text-incoming';
|
|
case 'outgoing': return 'text-outgoing';
|
|
case 'both': return 'text-both';
|
|
default: return 'text-gold-500';
|
|
}
|
|
}
|
|
|
|
function getDirectionBgClass(direction) {
|
|
switch(direction) {
|
|
case 'incoming': return 'bg-incoming';
|
|
case 'outgoing': return 'bg-outgoing';
|
|
case 'both': return 'bg-both';
|
|
default: return 'bg-gold-500';
|
|
}
|
|
}
|
|
|
|
function getClientSupport(packet) {
|
|
const cv = packet.clientVersion;
|
|
if (!cv) return 'both';
|
|
|
|
const hasClassic = cv.classic !== undefined;
|
|
const hasEnhanced = cv.enhanced !== undefined;
|
|
|
|
if (hasClassic && hasEnhanced) return 'both';
|
|
if (hasClassic) return 'classic';
|
|
if (hasEnhanced) return 'enhanced';
|
|
return 'both';
|
|
}
|
|
|
|
function getClientBadge(packet) {
|
|
const support = getClientSupport(packet);
|
|
if (support === 'both') return '';
|
|
if (support === 'classic') return '<span class="client-badge client-cc">CC</span>';
|
|
if (support === 'enhanced') return '<span class="client-badge client-ec">EC</span>';
|
|
return '';
|
|
}
|
|
|
|
// Version parsing helper - handles "7.0.9.0", "5.0.0a", "66.x.x.x" formats
|
|
function parseVersion(v) {
|
|
if (!v) return null;
|
|
// Remove any trailing letters (like "5.0.0a" -> "5.0.0")
|
|
const cleaned = v.replace(/[a-z]$/i, '');
|
|
const parts = cleaned.split('.').map(part => {
|
|
if (part === 'x' || part === '*') return -1; // Wildcard marker
|
|
const num = parseInt(part, 10);
|
|
return isNaN(num) ? 0 : num;
|
|
});
|
|
// Pad to 4 parts
|
|
while (parts.length < 4) parts.push(0);
|
|
return parts.slice(0, 4);
|
|
}
|
|
|
|
// Compare two version arrays: returns -1, 0, or 1
|
|
function compareVersions(a, b) {
|
|
for (let i = 0; i < 4; i++) {
|
|
// Wildcards (-1) match anything
|
|
if (a[i] === -1 || b[i] === -1) continue;
|
|
if (a[i] < b[i]) return -1;
|
|
if (a[i] > b[i]) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Check if a version is within a client version range
|
|
function isVersionInRange(version, clientVersion, clientType) {
|
|
const v = parseVersion(version);
|
|
if (!v) return true; // Invalid version input, don't filter
|
|
|
|
// Check appropriate client type(s)
|
|
const typesToCheck = clientType === 'all'
|
|
? ['classic', 'enhanced'].filter(t => clientVersion[t])
|
|
: [clientType];
|
|
|
|
if (typesToCheck.length === 0) return true; // No version info for this type
|
|
|
|
return typesToCheck.some(type => {
|
|
const range = clientVersion[type];
|
|
if (!range) return false;
|
|
|
|
const min = range.min ? parseVersion(range.min) : [0, 0, 0, 0];
|
|
const max = range.max ? parseVersion(range.max) : [Infinity, Infinity, Infinity, Infinity];
|
|
|
|
// Handle wildcards in max (e.g., "7.0.8.x" means any 7.0.8.*)
|
|
for (let i = 0; i < 4; i++) {
|
|
if (max[i] === -1) max[i] = Infinity;
|
|
}
|
|
|
|
return compareVersions(v, min) >= 0 && compareVersions(v, max) <= 0;
|
|
});
|
|
}
|
|
|
|
// Filter packets
|
|
function getFilteredPackets() {
|
|
return packets.filter(p => {
|
|
// Direction filter
|
|
if (currentFilter !== 'all' && p.direction !== currentFilter) return false;
|
|
|
|
// Tag filter (OR logic: packet shown if it has ANY selected tag)
|
|
if (selectedTags.size > 0) {
|
|
const packetTags = ensureArray(p.tags).length ? ensureArray(p.tags) : [p.category];
|
|
if (!packetTags.some(tag => selectedTags.has(tag))) return false;
|
|
}
|
|
|
|
// Search filter
|
|
if (currentSearch) {
|
|
const search = currentSearch.toLowerCase();
|
|
const matchId = p.id.toLowerCase().includes(search) ||
|
|
(p.subId && p.subId.toLowerCase().includes(search));
|
|
const matchName = p.name.toLowerCase().includes(search);
|
|
const matchDesc = p.description && p.description.toLowerCase().includes(search);
|
|
const matchFields = p.fields && p.fields.some(f =>
|
|
f.name.toLowerCase().includes(search) ||
|
|
(f.description && f.description.toLowerCase().includes(search))
|
|
);
|
|
|
|
// Also search decimal ID
|
|
const decimalId = parseInt(p.id, 16);
|
|
const matchDecimal = !isNaN(decimalId) && decimalId.toString() === search;
|
|
|
|
if (!matchId && !matchName && !matchDesc && !matchFields && !matchDecimal) return false;
|
|
}
|
|
|
|
// Client type filter - packets without clientVersion always pass (work with all versions)
|
|
if (currentClientType !== 'all' && p.clientVersion) {
|
|
const hasType = currentClientType === 'classic'
|
|
? p.clientVersion.classic
|
|
: p.clientVersion.enhanced;
|
|
if (!hasType) return false;
|
|
}
|
|
|
|
// Version filter (range check) - packets without clientVersion always pass
|
|
if (currentVersion && p.clientVersion) {
|
|
if (!isVersionInRange(currentVersion, p.clientVersion, currentClientType)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
// Render packet list
|
|
function renderPacketList() {
|
|
const filtered = getFilteredPackets();
|
|
|
|
// Sort by ID
|
|
filtered.sort((a, b) => {
|
|
// Extract base ID and subId (handles both "0xBF" and "0xBF/0x22" formats)
|
|
const aParts = a.id.split('/');
|
|
const bParts = b.id.split('/');
|
|
const aId = parseInt(aParts[0], 16);
|
|
const bId = parseInt(bParts[0], 16);
|
|
if (aId !== bId) return aId - bId;
|
|
|
|
// Get subId from property or embedded in id
|
|
const aSubId = a.subId || aParts[1];
|
|
const bSubId = b.subId || bParts[1];
|
|
|
|
// If same ID, sort by subId (base packet without subId comes first)
|
|
if (aSubId && bSubId) {
|
|
return parseInt(aSubId, 16) - parseInt(bSubId, 16);
|
|
}
|
|
return aSubId ? 1 : -1;
|
|
});
|
|
|
|
packetList.innerHTML = filtered.map(p => {
|
|
// Use getPacketKey for consistent display (avoids "0xBF/0x05/0x05")
|
|
const displayId = getPacketKey(p);
|
|
// For noMerge packets, we need to also compare direction to distinguish them
|
|
const isSelected = selectedPacket &&
|
|
selectedPacket.id === p.id &&
|
|
selectedPacket.subId === p.subId &&
|
|
(!p.noMerge || selectedPacket.direction === p.direction);
|
|
|
|
return `
|
|
<div
|
|
class="packet-item px-3 py-2 cursor-pointer border-b border-gold-500/10 hover:bg-modern-black-hover transition-colors ${isSelected ? 'bg-gold-500/20' : ''}"
|
|
data-id="${p.id}"
|
|
data-subid="${p.subId || ''}"
|
|
data-direction="${p.direction}"
|
|
data-nomerge="${p.noMerge || false}"
|
|
>
|
|
<div class="flex items-center space-x-2">
|
|
<span class="font-mono text-sm ${getDirectionClass(p.direction)}">${displayId}</span>
|
|
${getClientBadge(p)}
|
|
<span class="text-gold-300/90 text-sm truncate">${p.name}</span>
|
|
</div>
|
|
<div class="flex flex-wrap gap-1 mt-0.5">
|
|
${(ensureArray(p.tags).length ? ensureArray(p.tags) : [p.category]).filter(Boolean).slice(0, 3).map(tag =>
|
|
`<span class="text-xs px-1 py-0 rounded bg-gold-500/10 text-gold-500/70">${tag}</span>`
|
|
).join('')}${ensureArray(p.tags).length > 3 ? `<span class="text-xs text-gold-500/50">+${(ensureArray(p.tags).length - 3)}</span>` : ''}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}).join('');
|
|
|
|
// Add click handlers
|
|
document.querySelectorAll('.packet-item').forEach(el => {
|
|
el.addEventListener('click', () => {
|
|
const id = el.dataset.id;
|
|
const subId = el.dataset.subid;
|
|
const direction = el.dataset.direction;
|
|
const noMerge = el.dataset.nomerge === 'true';
|
|
// For noMerge packets, also match by direction to find the correct one
|
|
const packet = packets.find(p =>
|
|
p.id === id &&
|
|
(p.subId || '') === subId &&
|
|
(!noMerge || p.direction === direction)
|
|
);
|
|
if (packet) selectPacket(packet);
|
|
});
|
|
});
|
|
|
|
updatePacketCount();
|
|
}
|
|
|
|
// Calculate field offsets
|
|
function calculateOffsets(fields) {
|
|
let offset = 0;
|
|
return fields.map(f => {
|
|
const fieldOffset = offset;
|
|
if (f.size && typeof f.size === 'number') {
|
|
offset += f.size;
|
|
}
|
|
return { ...f, offset: fieldOffset };
|
|
});
|
|
}
|
|
|
|
// Render enum values
|
|
function renderEnumValues(f) {
|
|
if (!f.values || f.values.length === 0) return '';
|
|
|
|
const enumType = f.enumType === 'bitfield' || f.type === 'bitfield' ? 'bitfield' : 'enum';
|
|
const typeLabel = enumType === 'bitfield' ? 'Flags' : 'Values';
|
|
|
|
return `
|
|
<div class="mt-2 text-xs">
|
|
<div class="text-gold-500/70 mb-1">${typeLabel}:</div>
|
|
<div class="grid grid-cols-1 gap-1 pl-2 border-l-2 border-gold-500/30">
|
|
${f.values.map(v => `
|
|
<div class="flex items-start">
|
|
<span class="font-mono text-gold-400 w-16 flex-shrink-0">${typeof v.value === 'number' ? (enumType === 'bitfield' ? '0x' + v.value.toString(16).toUpperCase().padStart(2, '0') : v.value) : v.value}</span>
|
|
<span class="text-gold-300 font-medium">${v.name}</span>
|
|
${v.description ? `<span class="text-gold-500/60 ml-2">- ${v.description}</span>` : ''}
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Render bitfield flags
|
|
function renderBitfieldFlags(f) {
|
|
if (!f.flags || f.flags.length === 0) return '';
|
|
|
|
return `
|
|
<div class="mt-2 text-xs">
|
|
<div class="text-gold-500/70 mb-1">Bit Layout:</div>
|
|
<div class="grid grid-cols-1 gap-1 pl-2 border-l-2 border-purple-500/30">
|
|
${f.flags.map(flag => `
|
|
<div class="flex items-start">
|
|
<span class="font-mono text-purple-400 w-16 flex-shrink-0">${flag.bit}</span>
|
|
<span class="text-gold-300 font-medium">${flag.name}</span>
|
|
${flag.description ? `<span class="text-gold-500/60 ml-2">- ${flag.description}</span>` : ''}
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Render bitfield values (for fields that have both flags and value meanings)
|
|
function renderBitfieldValues(f) {
|
|
if (!f.values || f.values.length === 0) return '';
|
|
|
|
return `
|
|
<div class="mt-2 text-xs">
|
|
<div class="text-gold-500/70 mb-1">Values (per field):</div>
|
|
<div class="grid grid-cols-1 gap-1 pl-2 border-l-2 border-purple-500/30">
|
|
${f.values.map(v => `
|
|
<div class="flex items-start">
|
|
<span class="font-mono text-purple-400 w-16 flex-shrink-0">${v.value}</span>
|
|
<span class="text-gold-300 font-medium">${v.name}</span>
|
|
${v.description ? `<span class="text-gold-500/60 ml-2">- ${v.description}</span>` : ''}
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Render fields table
|
|
function renderFields(fields, parentOffset = 0) {
|
|
const fieldsWithOffsets = calculateOffsets(fields);
|
|
|
|
return fieldsWithOffsets.map(f => {
|
|
const offset = parentOffset + f.offset;
|
|
// Bitfield takes precedence if it has flags, otherwise check for enum/values
|
|
const isBitfield = f.type === 'bitfield' || f.flags;
|
|
const isEnum = !isBitfield && (f.type === 'enum' || f.values);
|
|
const hasValues = f.values && f.values.length > 0;
|
|
const typeDisplay = isBitfield ? 'bitfield' : isEnum ? 'enum' : f.type;
|
|
|
|
let row = `
|
|
<tr class="field-row border-b border-gold-500/10">
|
|
<td class="px-4 py-2 font-mono text-gold-500/70">${f.size ? offset : '-'}</td>
|
|
<td class="px-4 py-2 font-mono text-white">${f.name}</td>
|
|
<td class="px-4 py-2 font-mono ${isBitfield ? 'text-purple-400' : isEnum ? 'text-green-400' : 'text-gold-400'}">${typeDisplay}</td>
|
|
<td class="px-4 py-2 font-mono text-gold-500/70">${f.size || 'var'}</td>
|
|
<td class="px-4 py-2 text-gold-300/80">
|
|
${f.description || ''}
|
|
${f.value ? `<span class="text-gold-500/70 ml-1">(${f.value})</span>` : ''}
|
|
${f.condition ? `<span class="text-gold-400/70 ml-1 text-xs italic">[${f.condition}]</span>` : ''}
|
|
${f.notes ? `<div class="text-gold-500/60 text-xs mt-1 italic">${f.notes}</div>` : ''}
|
|
${isBitfield ? renderBitfieldFlags(f) : ''}
|
|
${isBitfield && hasValues ? renderBitfieldValues(f) : ''}
|
|
${isEnum ? renderEnumValues(f) : ''}
|
|
</td>
|
|
</tr>
|
|
`;
|
|
|
|
// Handle loop fields
|
|
if (f.loop && f.loop.fields) {
|
|
row += `
|
|
<tr class="field-row border-b border-gold-500/10 bg-gold-500/5">
|
|
<td colspan="5" class="px-4 py-2">
|
|
<div class="loop-field">
|
|
<div class="text-gold-500/70 text-xs mb-2">Repeats for each ${f.loop.countField || 'item'}:</div>
|
|
<table class="w-full text-sm table-fixed">
|
|
<colgroup>
|
|
<col class="w-16">
|
|
<col class="w-44">
|
|
<col class="w-24">
|
|
<col class="w-20">
|
|
<col>
|
|
</colgroup>
|
|
<tbody>
|
|
${renderFields(f.loop.fields, 0)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
`;
|
|
}
|
|
|
|
return row;
|
|
}).join('');
|
|
}
|
|
|
|
// Select and display a packet
|
|
function selectPacket(packet) {
|
|
selectedPacket = packet;
|
|
|
|
// Switch to detail view on mobile
|
|
showMobileDetailView();
|
|
|
|
// Update list selection
|
|
document.querySelectorAll('.packet-item').forEach(el => {
|
|
const idMatch = el.dataset.id === packet.id && (el.dataset.subid || '') === (packet.subId || '');
|
|
// For noMerge packets, also check direction to distinguish between same-ID packets
|
|
const noMerge = el.dataset.nomerge === 'true';
|
|
const isMatch = idMatch && (!noMerge || el.dataset.direction === packet.direction);
|
|
el.classList.toggle('bg-gold-500/20', isMatch);
|
|
});
|
|
|
|
// Show content, hide welcome
|
|
welcomeMessage.classList.add('hidden');
|
|
packetContent.classList.remove('hidden');
|
|
|
|
// Populate header
|
|
document.getElementById('detailId').textContent = packet.id;
|
|
|
|
const subIdEl = document.getElementById('detailSubId');
|
|
if (packet.subId) {
|
|
subIdEl.textContent = `/ ${packet.subId}`;
|
|
subIdEl.classList.remove('hidden');
|
|
} else {
|
|
subIdEl.classList.add('hidden');
|
|
}
|
|
|
|
document.getElementById('detailName').textContent = packet.name;
|
|
|
|
const directionEl = document.getElementById('detailDirection');
|
|
directionEl.textContent = packet.direction;
|
|
directionEl.className = `px-2 py-0.5 rounded text-xs font-medium uppercase ${getDirectionBgClass(packet.direction)} text-white`;
|
|
|
|
// Description
|
|
document.getElementById('detailDescription').textContent = packet.description || 'No description available.';
|
|
|
|
// Size
|
|
const sizeText = typeof packet.size === 'number'
|
|
? `${packet.size} bytes`
|
|
: packet.size || 'Variable';
|
|
document.getElementById('detailSize').textContent = sizeText;
|
|
document.getElementById('detailDynamic').classList.toggle('hidden', !packet.isDynamic);
|
|
|
|
// Client version
|
|
const versionSection = document.getElementById('clientVersionSection');
|
|
const versionContent = document.getElementById('clientVersionContent');
|
|
const versionNotes = document.getElementById('clientVersionNotes');
|
|
if (packet.clientVersion) {
|
|
versionSection.classList.remove('hidden');
|
|
let html = '';
|
|
|
|
// Classic Client
|
|
if (packet.clientVersion.classic) {
|
|
const c = packet.clientVersion.classic;
|
|
html += `
|
|
<div class="bg-modern-dark-black rounded p-3 border border-gold-500/10">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<span class="px-2 py-0.5 bg-blue-500/20 text-blue-400 rounded text-xs font-medium">Classic</span>
|
|
</div>
|
|
<div class="text-sm space-y-1">
|
|
${c.min ? `<div><span class="text-gold-500/70">Min:</span> <span class="font-mono text-gold-300">${c.min}</span></div>` : ''}
|
|
${c.max ? `<div><span class="text-gold-500/70">Max:</span> <span class="font-mono text-gold-300">${c.max}</span></div>` : ''}
|
|
${!c.min && !c.max ? `<div class="text-gold-500/50">All versions</div>` : ''}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Enhanced Client
|
|
if (packet.clientVersion.enhanced) {
|
|
const e = packet.clientVersion.enhanced;
|
|
html += `
|
|
<div class="bg-modern-dark-black rounded p-3 border border-gold-500/10">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<span class="px-2 py-0.5 bg-purple-500/20 text-purple-400 rounded text-xs font-medium">Enhanced</span>
|
|
</div>
|
|
<div class="text-sm space-y-1">
|
|
${e.min ? `<div><span class="text-gold-500/70">Min:</span> <span class="font-mono text-gold-300">${e.min}</span></div>` : ''}
|
|
${e.max ? `<div><span class="text-gold-500/70">Max:</span> <span class="font-mono text-gold-300">${e.max}</span></div>` : ''}
|
|
${!e.min && !e.max ? `<div class="text-gold-500/50">All versions</div>` : ''}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
versionContent.innerHTML = html;
|
|
|
|
// Notes
|
|
if (packet.clientVersion.notes) {
|
|
versionNotes.classList.remove('hidden');
|
|
versionNotes.textContent = packet.clientVersion.notes;
|
|
} else {
|
|
versionNotes.classList.add('hidden');
|
|
}
|
|
} else {
|
|
versionSection.classList.add('hidden');
|
|
}
|
|
|
|
// Fields - hide if empty and packet has variants or direction variants
|
|
const fieldsSection = document.getElementById('fieldsSection');
|
|
const fieldsTable = document.getElementById('fieldsTable');
|
|
const hasVariants = (packet.variants && packet.variants.length > 0) ||
|
|
(packet.directionVariants && packet.directionVariants.length > 0);
|
|
|
|
if (packet.fields && packet.fields.length > 0) {
|
|
fieldsSection.classList.remove('hidden');
|
|
fieldsTable.innerHTML = renderFields(packet.fields);
|
|
} else if (hasVariants) {
|
|
// Hide empty fields section if packet has variants (structure is in variants)
|
|
fieldsSection.classList.add('hidden');
|
|
} else {
|
|
fieldsSection.classList.remove('hidden');
|
|
fieldsTable.innerHTML = '<tr><td colspan="5" class="px-4 py-4 text-center text-gold-500/50">No field documentation available</td></tr>';
|
|
}
|
|
|
|
// Subpackets (for container packets like 0xBF, 0xD7)
|
|
const subpacketsSection = document.getElementById('subpacketsSection');
|
|
const subpacketsTable = document.getElementById('subpacketsTable');
|
|
if (packet.subpackets && packet.subpackets.length > 0) {
|
|
subpacketsSection.classList.remove('hidden');
|
|
subpacketsTable.innerHTML = packet.subpackets.map(sp => {
|
|
// Build the full packet ID for lookup (e.g., "0xBF/0x05")
|
|
const fullId = `${packet.id}/${sp.subId}`;
|
|
const subPacket = packetIndex.get(fullId);
|
|
const hasDetails = !!subPacket;
|
|
|
|
// Direction badge for subpacket
|
|
const spDirection = sp.direction || 'incoming';
|
|
const dirBadgeClass = spDirection === 'incoming' ? 'bg-incoming' :
|
|
spDirection === 'outgoing' ? 'bg-outgoing' : 'bg-both';
|
|
const dirBadge = `<span class="px-1.5 py-0.5 rounded text-xs font-medium uppercase ${dirBadgeClass} text-white">${spDirection === 'both' ? 'both' : spDirection.substring(0, 3)}</span>`;
|
|
|
|
return `
|
|
<tr class="field-row border-b border-gold-500/10 ${hasDetails ? 'cursor-pointer hover:bg-gold-500/10' : ''} transition-colors subpacket-row" data-id="${fullId}" data-has-details="${hasDetails}">
|
|
<td class="px-4 py-2 font-mono ${hasDetails ? 'text-gold-400' : 'text-gold-500/70'}">${sp.subId}</td>
|
|
<td class="px-4 py-2">${dirBadge}</td>
|
|
<td class="px-4 py-2 ${hasDetails ? 'text-white' : 'text-gold-300/70'}">${sp.name}</td>
|
|
<td class="px-4 py-2 text-gold-300/80">
|
|
${sp.description || ''}
|
|
${hasDetails ? '<span class="text-gold-500/50 text-xs ml-2">→ Click for details</span>' : ''}
|
|
</td>
|
|
</tr>
|
|
`;
|
|
}).join('');
|
|
|
|
// Add click handlers to subpacket rows
|
|
document.querySelectorAll('.subpacket-row').forEach(el => {
|
|
if (el.dataset.hasDetails === 'true') {
|
|
el.addEventListener('click', () => {
|
|
const id = el.dataset.id;
|
|
const subPacket = packetIndex.get(id);
|
|
if (subPacket) selectPacket(subPacket);
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
subpacketsSection.classList.add('hidden');
|
|
}
|
|
|
|
// Related packets
|
|
const relatedSection = document.getElementById('relatedSection');
|
|
const relatedPackets = document.getElementById('relatedPackets');
|
|
if (packet.related && packet.related.length > 0) {
|
|
relatedSection.classList.remove('hidden');
|
|
relatedPackets.innerHTML = packet.related.map(r => {
|
|
// Look up by direction:id if direction specified, else fall back to just id
|
|
const lookupKey = r.direction ? `${r.direction}:${r.id}` : r.id;
|
|
const relatedPacket = packetIndex.get(lookupKey) || packetIndex.get(r.id);
|
|
const relationshipColors = {
|
|
'request': 'bg-blue-500/20 text-blue-400',
|
|
'response': 'bg-green-500/20 text-green-400',
|
|
'ack': 'bg-green-500/20 text-green-400',
|
|
'rej': 'bg-red-500/20 text-red-400',
|
|
'variant': 'bg-purple-500/20 text-purple-400',
|
|
'notification': 'bg-yellow-500/20 text-yellow-400'
|
|
};
|
|
const colorClass = relationshipColors[r.relationship] || 'bg-gold-500/20 text-gold-400';
|
|
const directionBadge = r.direction ?
|
|
`<span class="px-1.5 py-0.5 rounded text-xs font-medium uppercase ${getDirectionBgClass(r.direction)} text-white">${r.direction}</span>` : '';
|
|
|
|
const idColorClass = relatedPacket ? getDirectionClass(relatedPacket.direction) : 'text-white';
|
|
const clientBadge = relatedPacket ? getClientBadge(relatedPacket) : '';
|
|
|
|
return `
|
|
<div class="flex items-center justify-between bg-modern-black rounded-lg p-3 border border-gold-500/20 cursor-pointer hover:border-gold-500/40 transition-colors related-packet" data-id="${r.id}" data-direction="${r.direction || ''}">
|
|
<div class="flex items-center space-x-3">
|
|
<span class="font-mono ${idColorClass}">${r.id}</span>
|
|
${clientBadge}
|
|
${directionBadge}
|
|
<span class="text-gold-300/90">${relatedPacket?.name || 'Unknown'}</span>
|
|
</div>
|
|
<div class="flex items-center space-x-2">
|
|
<span class="px-2 py-0.5 rounded text-xs ${colorClass}">${r.relationship}</span>
|
|
${r.note ? `<span class="text-gold-500/50 text-sm">${r.note}</span>` : ''}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}).join('');
|
|
|
|
// Add click handlers to related packets
|
|
document.querySelectorAll('.related-packet').forEach(el => {
|
|
el.addEventListener('click', () => {
|
|
const id = el.dataset.id;
|
|
const direction = el.dataset.direction;
|
|
// Look up by direction:id if direction specified, else fall back to just id
|
|
const lookupKey = direction ? `${direction}:${id}` : id;
|
|
const relatedPacket = packetIndex.get(lookupKey) || packetIndex.get(id);
|
|
if (relatedPacket) selectPacket(relatedPacket);
|
|
});
|
|
});
|
|
} else {
|
|
relatedSection.classList.add('hidden');
|
|
}
|
|
|
|
// Render a single variant card
|
|
function renderVariantCard(v, id) {
|
|
const directionBadge = v.direction ?
|
|
`<span class="px-2 py-0.5 rounded text-xs font-medium uppercase ${getDirectionBgClass(v.direction)} text-white ml-2">${v.direction}</span>` : '';
|
|
|
|
let content = '';
|
|
|
|
// If variant has subVariants (nested version variants), render those
|
|
if (v.subVariants && v.subVariants.length > 0) {
|
|
content = v.subVariants.map((sv, svIndex) => `
|
|
<div class="border-t border-gold-500/10">
|
|
<div class="bg-gold-500/5 px-4 py-2 flex items-center justify-between">
|
|
<div>
|
|
<span class="text-gold-400 font-medium text-sm">${sv.name || 'Version ' + (svIndex + 1)}</span>
|
|
${sv.version ? `<span class="text-gold-500/70 ml-2 text-xs">(${sv.version})</span>` : ''}
|
|
</div>
|
|
<div class="flex items-center space-x-3 text-xs">
|
|
${sv.size ? `<span class="text-gold-500/70">Size: <span class="text-white font-mono">${typeof sv.size === 'number' ? sv.size + ' bytes' : sv.size}</span></span>` : ''}
|
|
${sv.condition ? `<span class="text-gold-400/70 italic">${sv.condition}</span>` : ''}
|
|
</div>
|
|
</div>
|
|
${sv.fields && sv.fields.length > 0 ? `
|
|
<table class="w-full text-sm table-fixed">
|
|
<thead>
|
|
<tr class="bg-gold-500/5 text-gold-500 text-xs">
|
|
<th class="px-4 py-1 text-left font-medium w-16">Offset</th>
|
|
<th class="px-4 py-1 text-left font-medium w-44">Name</th>
|
|
<th class="px-4 py-1 text-left font-medium w-24">Type</th>
|
|
<th class="px-4 py-1 text-left font-medium w-20">Size</th>
|
|
<th class="px-4 py-1 text-left font-medium">Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${renderFields(sv.fields)}
|
|
</tbody>
|
|
</table>
|
|
` : ''}
|
|
</div>
|
|
`).join('');
|
|
} else if (v.fields && v.fields.length > 0) {
|
|
// Regular variant with fields
|
|
content = `
|
|
<table class="w-full text-sm table-fixed">
|
|
<thead>
|
|
<tr class="bg-gold-500/5 text-gold-500 text-xs">
|
|
<th class="px-4 py-1 text-left font-medium w-16">Offset</th>
|
|
<th class="px-4 py-1 text-left font-medium w-44">Name</th>
|
|
<th class="px-4 py-1 text-left font-medium w-32">Type</th>
|
|
<th class="px-4 py-1 text-left font-medium w-14">Size</th>
|
|
<th class="px-4 py-1 text-left font-medium">Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${renderFields(v.fields)}
|
|
</tbody>
|
|
</table>
|
|
`;
|
|
}
|
|
|
|
// Show condition/description below header for all variants (not inline)
|
|
const hasCondition = v.condition && !v.subVariants;
|
|
|
|
// Build client version info
|
|
let clientVersionHtml = '';
|
|
if (v.clientVersion) {
|
|
const parts = [];
|
|
if (v.clientVersion.min) parts.push(`Min: ${v.clientVersion.min}`);
|
|
if (v.clientVersion.max) parts.push(`Max: ${v.clientVersion.max}`);
|
|
if (parts.length > 0) {
|
|
clientVersionHtml = `<span class="text-gold-400/70 text-xs ml-3">[${parts.join(', ')}]</span>`;
|
|
}
|
|
}
|
|
|
|
return `
|
|
<div id="${id}" class="bg-modern-black rounded-lg border border-gold-500/20 overflow-hidden">
|
|
<div class="bg-gold-500/10 px-4 py-2 flex items-center justify-between">
|
|
<div class="flex items-center flex-shrink-0">
|
|
<span class="text-gold-500 font-medium">${v.name || 'Variant'}</span>
|
|
${directionBadge}
|
|
${v.version ? `<span class="text-gold-500/70 ml-2 text-sm">(${v.version})</span>` : ''}
|
|
${clientVersionHtml}
|
|
</div>
|
|
<div class="flex items-center space-x-3 text-sm flex-shrink-0">
|
|
${v.size ? `<span class="text-gold-500/70">Size: <span class="text-white font-mono">${typeof v.size === 'number' ? v.size + ' bytes' : v.size}</span></span>` : ''}
|
|
</div>
|
|
</div>
|
|
${hasCondition ? `<div class="px-4 py-2 text-gold-300/80 text-sm border-b border-gold-500/10">${v.condition}</div>` : ''}
|
|
${v.notes ? `<div class="px-4 py-2 text-gold-500/70 text-xs italic border-b border-gold-500/10">${v.notes}</div>` : ''}
|
|
${content}
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Variants (including direction variants for bidirectional packets)
|
|
const variantsSection = document.getElementById('variantsSection');
|
|
const variantsList = document.getElementById('variantsList');
|
|
const variantSelect = document.getElementById('variantSelect');
|
|
|
|
// Combine direction variants and regular variants
|
|
const allVariants = [
|
|
...(packet.directionVariants || []),
|
|
...(packet.variants || [])
|
|
];
|
|
|
|
if (allVariants.length > 0) {
|
|
variantsSection.classList.remove('hidden');
|
|
|
|
// Populate variant dropdown
|
|
variantSelect.innerHTML = `
|
|
<option value="">Jump to variant...</option>
|
|
${allVariants.map((v, index) => `
|
|
<option value="variant-${index}">${v.name || 'Variant ' + (index + 1)}</option>
|
|
`).join('')}
|
|
`;
|
|
|
|
// Render variant cards with IDs for scrolling
|
|
variantsList.innerHTML = allVariants.map((v, index) =>
|
|
renderVariantCard(v, `variant-${index}`)
|
|
).join('');
|
|
|
|
// Handle variant dropdown change
|
|
variantSelect.onchange = function() {
|
|
const value = this.value;
|
|
if (value) {
|
|
const el = document.getElementById(value);
|
|
if (el) {
|
|
el.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
}
|
|
// Reset dropdown
|
|
setTimeout(() => { this.value = ''; }, 100);
|
|
}
|
|
};
|
|
|
|
} else {
|
|
variantsSection.classList.add('hidden');
|
|
}
|
|
|
|
// Notes
|
|
const notesSection = document.getElementById('notesSection');
|
|
const notesEl = document.getElementById('detailNotes');
|
|
if (packet.notes) {
|
|
notesSection.classList.remove('hidden');
|
|
notesEl.textContent = packet.notes;
|
|
} else {
|
|
notesSection.classList.add('hidden');
|
|
}
|
|
|
|
// Compression Info
|
|
const compressionSection = document.getElementById('compressionSection');
|
|
const compressionContent = document.getElementById('compressionContent');
|
|
if (packet.compression) {
|
|
compressionSection.classList.remove('hidden');
|
|
compressionContent.innerHTML = `
|
|
<div class="flex items-center space-x-4">
|
|
<span class="text-gold-400">Algorithm:</span>
|
|
<span class="text-gold-300 font-mono">${packet.compression.algorithm || 'Unknown'}</span>
|
|
</div>
|
|
${packet.compression.notes ? `<p class="text-gold-300/70 mt-2">${packet.compression.notes}</p>` : ''}
|
|
`;
|
|
} else {
|
|
compressionSection.classList.add('hidden');
|
|
}
|
|
|
|
// Plane Format (for house customization packets)
|
|
const planeFormatSection = document.getElementById('planeFormatSection');
|
|
const planeFormatContent = document.getElementById('planeFormatContent');
|
|
if (packet.planeFormat) {
|
|
planeFormatSection.classList.remove('hidden');
|
|
let planeHtml = `
|
|
<div class="p-4 border-b border-gold-500/10">
|
|
<p class="text-gold-300/80 text-sm">${packet.planeFormat.description || ''}</p>
|
|
</div>
|
|
`;
|
|
|
|
// Header Decoding
|
|
if (packet.planeFormat.headerDecoding) {
|
|
const hd = packet.planeFormat.headerDecoding;
|
|
planeHtml += `
|
|
<div class="p-4 border-b border-gold-500/10">
|
|
<h4 class="text-gold-400 font-medium mb-2">Header Decoding (4-byte packed)</h4>
|
|
<table class="w-full text-sm">
|
|
<tbody>
|
|
${Object.entries(hd).map(([key, formula]) => `
|
|
<tr class="border-b border-gold-500/10 last:border-0">
|
|
<td class="py-2 font-mono text-gold-300 w-28">${key}</td>
|
|
<td class="py-2 font-mono text-gold-500/80 text-xs">${formula}</td>
|
|
</tr>
|
|
`).join('')}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Plane Z Mapping
|
|
if (packet.planeFormat.planeZMapping && packet.planeFormat.planeZMapping.length > 0) {
|
|
planeHtml += `
|
|
<div class="p-4 border-b border-gold-500/10">
|
|
<h4 class="text-gold-400 font-medium mb-2">Plane Z-Height Mapping</h4>
|
|
<table class="w-full text-sm">
|
|
<thead>
|
|
<tr class="bg-gold-500/5 text-gold-500 text-xs">
|
|
<th class="px-3 py-2 text-left font-medium w-24">Plane</th>
|
|
<th class="px-3 py-2 text-left font-medium w-24">Z</th>
|
|
<th class="px-3 py-2 text-left font-medium">Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${packet.planeFormat.planeZMapping.map(m => `
|
|
<tr class="border-b border-gold-500/10 last:border-0">
|
|
<td class="px-3 py-2 font-mono text-gold-300">${m.plane}</td>
|
|
<td class="px-3 py-2 font-mono text-gold-400">${m.z}</td>
|
|
<td class="px-3 py-2 text-gold-300/70">${m.description || ''}</td>
|
|
</tr>
|
|
`).join('')}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Encoding Modes
|
|
if (packet.planeFormat.encodingModes && packet.planeFormat.encodingModes.length > 0) {
|
|
planeHtml += `
|
|
<div class="p-4 border-b border-gold-500/10">
|
|
<h4 class="text-gold-400 font-medium mb-2">Encoding Modes</h4>
|
|
<div class="space-y-3">
|
|
${packet.planeFormat.encodingModes.map(em => `
|
|
<div class="bg-modern-darker rounded p-3">
|
|
<div class="flex items-center gap-3 mb-1">
|
|
<span class="bg-gold-500/20 text-gold-400 px-2 py-0.5 rounded text-xs font-mono">Mode ${em.mode}</span>
|
|
<span class="text-gold-300 font-medium">${em.name}</span>
|
|
<span class="text-gold-500 text-xs">${em.bytesPerTile} bytes/tile</span>
|
|
</div>
|
|
<div class="font-mono text-xs text-gold-500/80 mb-1">${em.format}</div>
|
|
<p class="text-gold-300/60 text-xs">${em.description || ''}</p>
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Grid Sizes
|
|
if (packet.planeFormat.gridSizes && packet.planeFormat.gridSizes.length > 0) {
|
|
planeHtml += `
|
|
<div class="p-4">
|
|
<h4 class="text-gold-400 font-medium mb-2">Grid Sizes by Plane</h4>
|
|
<table class="w-full text-sm">
|
|
<thead>
|
|
<tr class="bg-gold-500/5 text-gold-500 text-xs">
|
|
<th class="px-3 py-2 text-left font-medium w-24">Plane</th>
|
|
<th class="px-3 py-2 text-left font-medium w-32">Width</th>
|
|
<th class="px-3 py-2 text-left font-medium w-32">Height</th>
|
|
<th class="px-3 py-2 text-left font-medium">Notes</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${packet.planeFormat.gridSizes.map(gs => `
|
|
<tr class="border-b border-gold-500/10 last:border-0">
|
|
<td class="px-3 py-2 font-mono text-gold-300">${gs.plane}</td>
|
|
<td class="px-3 py-2 font-mono text-gold-400">${gs.width}</td>
|
|
<td class="px-3 py-2 font-mono text-gold-400">${gs.height}</td>
|
|
<td class="px-3 py-2 text-gold-300/70">${gs.notes || ''}</td>
|
|
</tr>
|
|
`).join('')}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
planeFormatContent.innerHTML = planeHtml;
|
|
} else {
|
|
planeFormatSection.classList.add('hidden');
|
|
}
|
|
|
|
// Layout Format (for gump packets)
|
|
const layoutFormatSection = document.getElementById('layoutFormatSection');
|
|
const layoutFormatContent = document.getElementById('layoutFormatContent');
|
|
if (packet.layoutFormat) {
|
|
layoutFormatSection.classList.remove('hidden');
|
|
let layoutHtml = `
|
|
<div class="p-4 border-b border-gold-500/10">
|
|
<p class="text-gold-300/80 text-sm">${packet.layoutFormat.description || ''}</p>
|
|
${packet.layoutFormat.encoding ? `<p class="text-gold-400 text-sm mt-1">Encoding: <span class="font-mono text-gold-300">${packet.layoutFormat.encoding}</span></p>` : ''}
|
|
</div>
|
|
`;
|
|
if (packet.layoutFormat.commands && packet.layoutFormat.commands.length > 0) {
|
|
layoutHtml += `
|
|
<div class="divide-y divide-gold-500/20">
|
|
${packet.layoutFormat.commands.map(cmd => {
|
|
const hasArgs = cmd.args && cmd.args.length > 0;
|
|
// Build syntax string dynamically: { command arg1 arg2 [optional] }
|
|
const syntaxArgs = hasArgs ? cmd.args.map(arg => arg.optional ? `[${arg.name}]` : arg.name).join(' ') : '';
|
|
const syntax = syntaxArgs ? `{ ${cmd.name} ${syntaxArgs} }` : `{ ${cmd.name} }`;
|
|
|
|
const argsHtml = hasArgs ? `
|
|
<div class="pl-6 pr-4 pb-3 border-l-2 border-gold-500/30 ml-4 mt-1">
|
|
<table class="w-full text-xs">
|
|
<tbody>
|
|
${cmd.args.map((arg, idx) => `
|
|
<tr class="${idx > 0 ? 'border-t border-gold-500/10' : ''}">
|
|
<td class="py-1 font-mono text-gold-300 w-28">${arg.name}${arg.optional ? ' <span class="text-gold-500/50 text-xs">(opt)</span>' : ''}</td>
|
|
<td class="py-1 text-gold-500 w-16">${arg.type}</td>
|
|
<td class="py-1 text-gold-300/60">${arg.description || ''}</td>
|
|
</tr>
|
|
`).join('')}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
` : '';
|
|
|
|
// Build tags HTML if command has tags
|
|
const tagsHtml = cmd.tags && cmd.tags.length > 0 ?
|
|
cmd.tags.map(tag => `<span class="px-1.5 py-0.5 rounded text-xs font-medium bg-purple-500/20 text-purple-400 ml-2">${tag}</span>`).join('') : '';
|
|
|
|
return `
|
|
<div class="py-3 px-4">
|
|
<div class="flex items-start justify-between gap-4">
|
|
<div>
|
|
<span class="font-mono text-gold-400 font-medium">${cmd.name}</span>${tagsHtml}
|
|
<span class="text-gold-300/70 ml-3">${cmd.description || ''}</span>
|
|
</div>
|
|
</div>
|
|
<div class="font-mono text-xs text-gold-500/80 mt-1">${syntax}</div>
|
|
${cmd.notes ? `<div class="text-gold-500/60 text-xs mt-1 italic">${cmd.notes}</div>` : ''}
|
|
${argsHtml}
|
|
</div>
|
|
`;
|
|
}).join('')}
|
|
</div>
|
|
`;
|
|
}
|
|
layoutFormatContent.innerHTML = layoutHtml;
|
|
} else {
|
|
layoutFormatSection.classList.add('hidden');
|
|
}
|
|
|
|
// Strings Format (for gump packets)
|
|
const stringsFormatSection = document.getElementById('stringsFormatSection');
|
|
const stringsFormatContent = document.getElementById('stringsFormatContent');
|
|
if (packet.stringsFormat) {
|
|
stringsFormatSection.classList.remove('hidden');
|
|
let stringsHtml = `
|
|
<div class="p-4 border-b border-gold-500/10">
|
|
<p class="text-gold-300/80 text-sm">${packet.stringsFormat.description || ''}</p>
|
|
${packet.stringsFormat.encoding ? `<p class="text-gold-400 text-sm mt-1">Encoding: <span class="font-mono text-gold-300">${packet.stringsFormat.encoding}</span></p>` : ''}
|
|
</div>
|
|
`;
|
|
if (packet.stringsFormat.entryFormat && packet.stringsFormat.entryFormat.length > 0) {
|
|
stringsHtml += `
|
|
<table class="w-full text-sm">
|
|
<thead>
|
|
<tr class="bg-gold-500/5 text-gold-500 text-xs">
|
|
<th class="px-4 py-2 text-left font-medium w-32">Field</th>
|
|
<th class="px-4 py-2 text-left font-medium w-24">Type</th>
|
|
<th class="px-4 py-2 text-left font-medium w-20">Size</th>
|
|
<th class="px-4 py-2 text-left font-medium">Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${packet.stringsFormat.entryFormat.map(f => `
|
|
<tr class="border-b border-gold-500/10">
|
|
<td class="px-4 py-2 font-mono text-gold-300">${f.name}</td>
|
|
<td class="px-4 py-2 text-gold-400">${f.type}</td>
|
|
<td class="px-4 py-2 text-gold-300/70">${f.size || ''}</td>
|
|
<td class="px-4 py-2 text-gold-300/70">${f.description || ''}</td>
|
|
</tr>
|
|
`).join('')}
|
|
</tbody>
|
|
</table>
|
|
`;
|
|
}
|
|
stringsFormatContent.innerHTML = stringsHtml;
|
|
} else {
|
|
stringsFormatSection.classList.add('hidden');
|
|
}
|
|
|
|
// Source link
|
|
const sourceLink = document.getElementById('sourceLink');
|
|
if (packet.source && packet.source.file) {
|
|
sourceLink.href = `https://github.com/modernuo/ModernUO/blob/main/${packet.source.file}#L${packet.source.line || 1}`;
|
|
sourceLink.classList.remove('hidden');
|
|
} else {
|
|
sourceLink.classList.add('hidden');
|
|
}
|
|
|
|
// Update URL hash
|
|
const hash = packet.subId ? `${packet.id}-${packet.subId}` : packet.id;
|
|
history.replaceState(null, '', `#${hash}`);
|
|
}
|
|
|
|
// Filter button handlers
|
|
document.querySelectorAll('.filter-btn').forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
currentFilter = btn.dataset.filter;
|
|
|
|
// Update button styles
|
|
document.querySelectorAll('.filter-btn').forEach(b => {
|
|
const isActive = b.dataset.filter === currentFilter;
|
|
if (b.dataset.filter === 'all') {
|
|
b.classList.toggle('bg-gold-500', isActive);
|
|
b.classList.toggle('text-modern-black', isActive);
|
|
b.classList.toggle('bg-modern-dark-black', !isActive);
|
|
b.classList.toggle('text-gold-500', !isActive);
|
|
} else {
|
|
const color = b.dataset.filter;
|
|
b.classList.toggle(`bg-${color}/20`, isActive);
|
|
b.classList.toggle('bg-modern-dark-black', !isActive);
|
|
}
|
|
});
|
|
|
|
renderPacketList();
|
|
});
|
|
});
|
|
|
|
// Search handler
|
|
let searchTimeout;
|
|
searchInput.addEventListener('input', (e) => {
|
|
clearTimeout(searchTimeout);
|
|
searchTimeout = setTimeout(() => {
|
|
currentSearch = e.target.value;
|
|
renderPacketList();
|
|
}, 150);
|
|
});
|
|
|
|
// Client type button handlers
|
|
document.querySelectorAll('.client-btn').forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
currentClientType = btn.dataset.client;
|
|
|
|
// Update button styles
|
|
document.querySelectorAll('.client-btn').forEach(b => {
|
|
const isActive = b.dataset.client === currentClientType;
|
|
if (b.dataset.client === 'all') {
|
|
b.classList.toggle('bg-gold-500', isActive);
|
|
b.classList.toggle('text-modern-black', isActive);
|
|
b.classList.toggle('bg-modern-dark-black', !isActive);
|
|
b.classList.toggle('text-gold-500', !isActive);
|
|
} else if (b.dataset.client === 'classic') {
|
|
b.classList.toggle('bg-blue-500/20', isActive);
|
|
b.classList.toggle('bg-modern-dark-black', !isActive);
|
|
} else if (b.dataset.client === 'enhanced') {
|
|
b.classList.toggle('bg-purple-500/20', isActive);
|
|
b.classList.toggle('bg-modern-dark-black', !isActive);
|
|
}
|
|
});
|
|
|
|
renderPacketList();
|
|
});
|
|
});
|
|
|
|
// Version input handler
|
|
const versionInput = document.getElementById('versionInput');
|
|
let versionTimeout;
|
|
versionInput.addEventListener('input', (e) => {
|
|
clearTimeout(versionTimeout);
|
|
versionTimeout = setTimeout(() => {
|
|
currentVersion = e.target.value.trim();
|
|
renderPacketList();
|
|
}, 300);
|
|
});
|
|
|
|
// Keyboard navigation
|
|
document.addEventListener('keydown', (e) => {
|
|
if (e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT') return;
|
|
|
|
const filtered = getFilteredPackets();
|
|
if (filtered.length === 0) return;
|
|
|
|
let currentIndex = selectedPacket
|
|
? filtered.findIndex(p => p.id === selectedPacket.id && p.subId === selectedPacket.subId)
|
|
: -1;
|
|
|
|
if (e.key === 'ArrowDown') {
|
|
e.preventDefault();
|
|
currentIndex = Math.min(currentIndex + 1, filtered.length - 1);
|
|
selectPacket(filtered[currentIndex]);
|
|
} else if (e.key === 'ArrowUp') {
|
|
e.preventDefault();
|
|
currentIndex = Math.max(currentIndex - 1, 0);
|
|
selectPacket(filtered[currentIndex]);
|
|
}
|
|
});
|
|
|
|
// Handle URL hash on load
|
|
function loadFromHash() {
|
|
const hash = window.location.hash.slice(1);
|
|
if (hash) {
|
|
// Try to find packet by hash
|
|
// Formats: 0x02, 0xBF-0x0026, 0x22-incoming, 0x22-outgoing (for noMerge packets)
|
|
const parts = hash.split('-');
|
|
const id = parts[0];
|
|
let subId = null;
|
|
let direction = null;
|
|
|
|
// Check if second part is a direction or a subId
|
|
if (parts[1]) {
|
|
if (['incoming', 'outgoing', 'both'].includes(parts[1].toLowerCase())) {
|
|
direction = parts[1].toLowerCase();
|
|
} else {
|
|
subId = parts[1];
|
|
// Third part could be direction for subpackets with noMerge
|
|
if (parts[2] && ['incoming', 'outgoing', 'both'].includes(parts[2].toLowerCase())) {
|
|
direction = parts[2].toLowerCase();
|
|
}
|
|
}
|
|
}
|
|
|
|
const packet = packets.find(p =>
|
|
p.id.toLowerCase() === id.toLowerCase() &&
|
|
(p.subId || '').toLowerCase() === (subId || '').toLowerCase() &&
|
|
(!direction || p.direction === direction)
|
|
);
|
|
|
|
if (packet) {
|
|
selectPacket(packet);
|
|
// Collapse sidebar on medium screens when loading with hash
|
|
if (isMediumScreen()) {
|
|
collapseSidebar();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize
|
|
renderPacketList();
|
|
loadFromHash();
|
|
|
|
// Handle hash changes
|
|
window.addEventListener('hashchange', loadFromHash);
|
|
|
|
// Back to top button
|
|
const backToTopBtn = document.getElementById('backToTopBtn');
|
|
const mainContent = document.querySelector('main');
|
|
|
|
mainContent.addEventListener('scroll', function() {
|
|
if (mainContent.scrollTop > 200) {
|
|
backToTopBtn.classList.remove('hidden');
|
|
} else {
|
|
backToTopBtn.classList.add('hidden');
|
|
}
|
|
});
|
|
|
|
backToTopBtn.addEventListener('click', function() {
|
|
mainContent.scrollTo({ top: 0, behavior: 'smooth' });
|
|
});
|
|
|
|
// Type Legend Modal
|
|
const typeLegendBtn = document.getElementById('typeLegendBtn');
|
|
const typeLegendModal = document.getElementById('typeLegendModal');
|
|
const typeLegendClose = document.getElementById('typeLegendClose');
|
|
const typeLegendBackdrop = document.getElementById('typeLegendBackdrop');
|
|
|
|
typeLegendBtn.addEventListener('click', () => {
|
|
typeLegendModal.classList.remove('hidden');
|
|
});
|
|
|
|
typeLegendClose.addEventListener('click', () => {
|
|
typeLegendModal.classList.add('hidden');
|
|
});
|
|
|
|
typeLegendBackdrop.addEventListener('click', () => {
|
|
typeLegendModal.classList.add('hidden');
|
|
});
|
|
|
|
document.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Escape' && !typeLegendModal.classList.contains('hidden')) {
|
|
typeLegendModal.classList.add('hidden');
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|