feat: Add interactive packet documentation system

- Create JSON-based packet documentation for 145 packets (66 incoming, 79 outgoing)
- Add HTML template with search, filtering, and navigation
- Support enum/bitfield field display with values and descriptions
- Support packet variants for version-specific structures
- Include 0xBF extended command subpackets documentation
- Add PowerShell build script to generate final HTML

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Kamron Batman 2026-01-01 11:47:31 -08:00
parent ec287d7691
commit f0b65fecb7
No known key found for this signature in database
GPG key ID: 7D81DF26D9A5D94A
28 changed files with 6011 additions and 0 deletions

View file

@ -0,0 +1,735 @@
<!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">
<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>
.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;
}
</style>
</head>
<body class="bg-modern-dark-black text-gold-300 font-sans">
<div id="app" class="min-h-screen flex flex-col">
<!-- Header -->
<header class="bg-modern-black p-4 shadow-lg border-b border-gold-500/30">
<div class="max-w-7xl mx-auto flex items-center justify-between">
<div class="flex items-center space-x-4">
<img src="https://modernuo.com/branding/logo.svg" class="h-12 w-12">
<div>
<h1 class="text-white text-xl font-medium">ModernUO Packet Documentation</h1>
<p class="text-gold-500/70 text-sm">Ultima Online Network Protocol Reference</p>
</div>
</div>
<div class="flex items-center space-x-2">
<span id="packetCount" class="text-gold-500/70 text-sm"></span>
</div>
</div>
</header>
<!-- Main Content -->
<div class="flex-1 flex overflow-hidden">
<!-- Left Panel: Packet List -->
<aside id="sidebar" class="w-80 bg-modern-black border-r border-gold-500/30 flex flex-col">
<!-- Search & Filter -->
<div class="p-3 border-b border-gold-500/20 space-y-2">
<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>
<select id="categoryFilter" class="w-full bg-modern-dark-black text-gold-300 px-3 py-2 rounded border border-gold-500/30 focus:outline-none focus:border-gold-500 text-sm">
<option value="">All Categories</option>
</select>
</div>
<!-- Packet List -->
<div id="packetList" class="packet-list flex-1 overflow-y-auto">
<!-- Populated by JavaScript -->
</div>
</aside>
<!-- Right Panel: Packet Details -->
<main class="flex-1 overflow-y-auto bg-modern-dark-black">
<div id="packetDetails" class="p-6 max-w-4xl mx-auto">
<!-- Welcome message when no packet selected -->
<div id="welcomeMessage" class="text-center py-16">
<div class="text-gold-500/50 text-6xl mb-4">&#x1F4E6;</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">
<svg class="w-4 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>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-2">Client Version Requirements</h3>
<div id="clientVersionContent" class="text-gold-300/80 text-sm"></div>
</div>
<!-- Fields Table -->
<div 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-hidden">
<table class="w-full text-sm">
<thead>
<tr class="bg-gold-500/10 text-gold-500">
<th class="px-4 py-2 text-left font-medium">Offset</th>
<th class="px-4 py-2 text-left font-medium">Name</th>
<th class="px-4 py-2 text-left font-medium">Type</th>
<th class="px-4 py-2 text-left font-medium">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>
<!-- 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>
<!-- Packet Variants -->
<div id="variantsSection" class="mb-6 hidden">
<h3 class="text-gold-500 font-medium mb-3">Packet Variants</h3>
<div id="variantsList" class="space-y-4">
<!-- Populated by JavaScript -->
</div>
</div>
<!-- Notes -->
<div id="notesSection" class="hidden">
<h3 class="text-gold-500 font-medium mb-2">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>
</div>
</div>
</main>
</div>
</div>
<!-- Hidden data containers -->
<span id="packets" style="display:none; visibility: hidden">
<!-- PACKETS -->
</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);
}
// Flatten all packets into a single array with direction info preserved
const packets = [
...allPackets.incoming.map(p => ({ ...p, direction: p.direction || 'incoming' })),
...allPackets.outgoing.map(p => ({ ...p, direction: p.direction || 'outgoing' }))
];
// Build packet index by ID for quick lookups
const packetIndex = new Map();
packets.forEach(p => {
const key = p.subId ? `${p.id}/${p.subId}` : p.id;
packetIndex.set(key, p);
packetIndex.set(p.id, p); // Also index by just ID for basic lookups
});
// State
let currentFilter = 'all';
let currentCategory = '';
let currentSearch = '';
let selectedPacket = null;
// DOM elements
const searchInput = document.getElementById('searchInput');
const categoryFilter = document.getElementById('categoryFilter');
const packetList = document.getElementById('packetList');
const packetCount = document.getElementById('packetCount');
const welcomeMessage = document.getElementById('welcomeMessage');
const packetContent = document.getElementById('packetContent');
// Extract unique categories
const categories = [...new Set(packets.map(p => p.category).filter(Boolean))].sort();
categories.forEach(cat => {
const option = document.createElement('option');
option.value = cat;
option.textContent = cat;
categoryFilter.appendChild(option);
});
// 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';
}
}
// Filter packets
function getFilteredPackets() {
return packets.filter(p => {
// Direction filter
if (currentFilter !== 'all' && p.direction !== currentFilter) return false;
// Category filter
if (currentCategory && p.category !== currentCategory) 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;
}
return true;
});
}
// Render packet list
function renderPacketList() {
const filtered = getFilteredPackets();
// Sort by ID
filtered.sort((a, b) => {
const aId = parseInt(a.id, 16);
const bId = parseInt(b.id, 16);
if (aId !== bId) return aId - bId;
// If same ID, sort by subId
if (a.subId && b.subId) {
return parseInt(a.subId, 16) - parseInt(b.subId, 16);
}
return a.subId ? 1 : -1;
});
packetList.innerHTML = filtered.map(p => {
const displayId = p.subId ? `${p.id}/${p.subId}` : p.id;
const isSelected = selectedPacket &&
selectedPacket.id === p.id &&
selectedPacket.subId === p.subId;
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 || ''}"
>
<div class="flex items-center space-x-2">
<span class="font-mono text-sm ${getDirectionClass(p.direction)}">${displayId}</span>
<span class="text-gold-300/90 text-sm truncate">${p.name}</span>
</div>
<div class="text-gold-500/50 text-xs mt-0.5">${p.category || 'Uncategorized'}</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 packet = packets.find(p => p.id === id && (p.subId || '') === subId);
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">Flags:</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 fields table
function renderFields(fields, parentOffset = 0) {
const fieldsWithOffsets = calculateOffsets(fields);
return fieldsWithOffsets.map(f => {
const offset = parentOffset + f.offset;
const isEnum = f.type === 'enum' || f.values;
const isBitfield = f.type === 'bitfield' || f.flags;
const typeDisplay = isEnum ? `enum (${f.size || 1} byte${(f.size || 1) > 1 ? 's' : ''})` :
isBitfield ? `bitfield (${f.size || 1} byte${(f.size || 1) > 1 ? 's' : ''})` :
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 ${isEnum ? 'text-green-400' : isBitfield ? 'text-purple-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>` : ''}
${isEnum ? renderEnumValues(f) : ''}
${isBitfield ? renderBitfieldFlags(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">
<tbody>
${renderFields(f.loop.fields, 0)}
</tbody>
</table>
</div>
</td>
</tr>
`;
}
return row;
}).join('');
}
// Select and display a packet
function selectPacket(packet) {
selectedPacket = packet;
// Update list selection
document.querySelectorAll('.packet-item').forEach(el => {
const isMatch = el.dataset.id === packet.id && (el.dataset.subid || '') === (packet.subId || '');
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');
if (packet.clientVersion) {
versionSection.classList.remove('hidden');
let versionText = '';
if (packet.clientVersion.min) versionText += `Min: ${packet.clientVersion.min} `;
if (packet.clientVersion.max) versionText += `Max: ${packet.clientVersion.max} `;
if (packet.clientVersion.feature) versionText += `Feature: ${packet.clientVersion.feature} `;
if (packet.clientVersion.notes) versionText += `<br>${packet.clientVersion.notes}`;
versionContent.innerHTML = versionText || 'Version-specific behavior';
} else {
versionSection.classList.add('hidden');
}
// Fields
const fieldsTable = document.getElementById('fieldsTable');
if (packet.fields && packet.fields.length > 0) {
fieldsTable.innerHTML = renderFields(packet.fields);
} else {
fieldsTable.innerHTML = '<tr><td colspan="5" class="px-4 py-4 text-center text-gold-500/50">No field documentation available</td></tr>';
}
// 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 => {
const relatedPacket = 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'
};
const colorClass = relationshipColors[r.relationship] || 'bg-gold-500/20 text-gold-400';
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}">
<div class="flex items-center space-x-3">
<span class="font-mono text-white">${r.id}</span>
<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 relatedPacket = packetIndex.get(id);
if (relatedPacket) selectPacket(relatedPacket);
});
});
} else {
relatedSection.classList.add('hidden');
}
// Variants
const variantsSection = document.getElementById('variantsSection');
const variantsList = document.getElementById('variantsList');
if (packet.variants && packet.variants.length > 0) {
variantsSection.classList.remove('hidden');
variantsList.innerHTML = packet.variants.map((v, index) => `
<div 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>
<span class="text-gold-500 font-medium">${v.name || 'Variant ' + (index + 1)}</span>
${v.version ? `<span class="text-gold-500/70 ml-2 text-sm">(${v.version})</span>` : ''}
</div>
<div class="flex items-center space-x-3 text-sm">
${v.size ? `<span class="text-gold-500/70">Size: <span class="text-white font-mono">${v.size} bytes</span></span>` : ''}
${v.condition ? `<span class="text-gold-400/70 italic">${v.condition}</span>` : ''}
</div>
</div>
${v.fields && v.fields.length > 0 ? `
<table class="w-full text-sm">
<thead>
<tr class="bg-gold-500/5 text-gold-500 text-xs">
<th class="px-4 py-1 text-left font-medium">Offset</th>
<th class="px-4 py-1 text-left font-medium">Name</th>
<th class="px-4 py-1 text-left font-medium">Type</th>
<th class="px-4 py-1 text-left font-medium">Size</th>
<th class="px-4 py-1 text-left font-medium">Description</th>
</tr>
</thead>
<tbody>
${renderFields(v.fields)}
</tbody>
</table>
` : ''}
</div>
`).join('');
} 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');
}
// 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);
});
// Category filter handler
categoryFilter.addEventListener('change', (e) => {
currentCategory = e.target.value;
renderPacketList();
});
// 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 (format: 0x02 or 0xBF-0x0026)
const parts = hash.split('-');
const id = parts[0];
const subId = parts[1];
const packet = packets.find(p =>
p.id.toLowerCase() === id.toLowerCase() &&
(p.subId || '').toLowerCase() === (subId || '').toLowerCase()
);
if (packet) selectPacket(packet);
}
}
// Initialize
renderPacketList();
loadFromHash();
// Handle hash changes
window.addEventListener('hashchange', loadFromHash);
</script>
</body>
</html>

View file

@ -0,0 +1,116 @@
# Packet Documentation Conventions
## String Types
When documenting packet fields, use these specific type names to indicate the encoding and format:
### By Encoding
| Type | Encoding | Description |
|------|----------|-------------|
| `ascii` | ASCII | 7-bit ASCII characters |
| `unicode-le` | Unicode (Little Endian) | UTF-16LE, each character is 2 bytes |
| `unicode-be` | Unicode (Big Endian) | UTF-16BE, each character is 2 bytes |
| `utf8` | UTF-8 | Variable-width encoding (rarely used, mainly book packets) |
### By Format
| Suffix | Format | Example |
|--------|--------|---------|
| (no suffix) | Fixed length, padded/truncated | `ascii` with `size: 30` = exactly 30 bytes |
| `-null` | Null-terminated | `ascii-null` = string followed by 0x00 |
| `-prefixed` | Length-prefixed | `unicode-le-prefixed` = ushort length + characters |
### Common Combinations
| Full Type | Description | SpanWriter Method |
|-----------|-------------|-------------------|
| `ascii` | Fixed-length ASCII | `WriteAscii(text, maxLength)` |
| `ascii-null` | Null-terminated ASCII | `WriteAsciiNull(text)` |
| `unicode-le` | Fixed-length Unicode LE | `WriteLittleUni(text, maxLength)` |
| `unicode-le-null` | Null-terminated Unicode LE | `WriteLittleUniNull(text)` |
| `unicode-be` | Fixed-length Unicode BE | `WriteBigUni(text, maxLength)` |
| `unicode-be-null` | Null-terminated Unicode BE | `WriteBigUniNull(text)` |
| `utf8-null` | Null-terminated UTF-8 | `WriteUtf8Null(text)` |
### Size Calculations
- **Fixed ASCII**: Size in bytes = specified size
- **Fixed Unicode**: Size in bytes = specified size (characters) * 2
- **Null-terminated**: Size = string length + 1 (ASCII) or string length * 2 + 2 (Unicode)
- **Length-prefixed**: Size = 2 (ushort length) + string data
### Examples in JSON
```json
// Fixed-length ASCII (30 bytes exactly)
{ "name": "characterName", "type": "ascii", "size": 30, "description": "Character name" }
// Null-terminated ASCII (variable length)
{ "name": "message", "type": "ascii-null", "description": "Chat message" }
// Fixed-length Unicode Little Endian
{ "name": "text", "type": "unicode-le", "size": 64, "description": "Unicode text (64 chars)" }
// Null-terminated Unicode Big Endian
{ "name": "affix", "type": "unicode-be-null", "description": "Affix string" }
```
## Numeric Types
| Type | Size | Range | Signed |
|------|------|-------|--------|
| `byte` | 1 | 0-255 | No |
| `sbyte` | 1 | -128 to 127 | Yes |
| `short` | 2 | -32768 to 32767 | Yes |
| `ushort` | 2 | 0-65535 | No |
| `int` | 4 | -2^31 to 2^31-1 | Yes |
| `uint` | 4 | 0 to 2^32-1 | No |
| `long` | 8 | -2^63 to 2^63-1 | Yes |
| `ulong` | 8 | 0 to 2^64-1 | No |
| `bool` | 1 | 0 (false) or 1 (true) | N/A |
## Byte Order
- All numeric types are **Big Endian** (network byte order) unless noted otherwise
- IP addresses use Little Endian (marked with `LE` suffix)
- Some client-specific fields may use Little Endian (always documented)
## Packet Flags
Common flag values used in mobile/item packets:
| Flag | Value | Description |
|------|-------|-------------|
| Hidden | 0x80 | Entity is hidden |
| Poisoned | 0x04 | Mobile is poisoned |
| Blessed | 0x08 | Mobile is blessed/invulnerable |
| Warmode | 0x40 | Mobile is in war mode |
| Female | 0x02 | Mobile is female |
## Direction Values
| Value | Direction |
|-------|-----------|
| 0 | North |
| 1 | Right (NE) |
| 2 | East |
| 3 | Down (SE) |
| 4 | South |
| 5 | Left (SW) |
| 6 | West |
| 7 | Up (NW) |
| 0x80 | Running flag (OR with direction) |
## Notoriety Values
| Value | Name | Color |
|-------|------|-------|
| 0 | Invalid | Gray |
| 1 | Innocent | Blue |
| 2 | Ally/Friend | Green |
| 3 | Gray/Attackable | Gray |
| 4 | Criminal | Gray |
| 5 | Enemy | Orange |
| 6 | Murderer | Red |
| 7 | Invulnerable | Yellow |

View file

@ -0,0 +1,505 @@
# Packet Documentation Tracking
## Protocol Version Reference
### Client Version → ProtocolChanges Mapping
| Version | Flag | Description |
|---------|------|-------------|
| 5.0.0a | NewSpellbook | AOS spellbook format (0xBF/0x1B) |
| 5.0.0a | DamagePacket | Damage packet (0x0B) |
| 5.0.2b | BuffIcon | Buff/debuff icons |
| 6.0.0.0 | NewHaven | New Haven starting city |
| **6.0.1.7** | **ContainerGridLines** | Container item grid positions (+1 byte per item) |
| 6.0.14.2 | ExtendedSupportedFeatures | 0xB9 uses 4 bytes instead of 2 |
| 7.0.0.0 | StygianAbyss | SA client features, 0xF3 world entity |
| 7.0.9.0 | HighSeas | HS features, extended 0xF3 |
| 7.0.13.0 | NewCharacterList | Extended city info in 0xA9 |
| 7.0.16.0 | NewCharacterCreation | 4th skill slot |
| 7.0.30.0 | ExtendedStatus | Mobile status version 6 |
| 7.0.33.1 | NewMobileIncoming | 0x78 always includes hue |
| 7.0.45.65 | NewSecureTrading | New secure trade format |
| 7.0.50.0 | UltimaStore | Ultima Store packets |
| 7.0.61.0 | EndlessJourney | EJ features |
### Mobile Status Versions (Expansion-based)
| Version | Expansion | Size | Description |
|---------|-----------|------|-------------|
| 0 | Any | 43 | Compact (viewing others) |
| 3 | Pre-AOS | 70 | Basic stats |
| 4 | AOS | 88 | Resistances, luck, damage |
| 5 | ML | 91 | Weight, race |
| 6 | HS | 121 | Extended AOS status |
---
## Incoming Packets Tracking
### Account (IncomingAccountPackets.cs)
- [x] 0x00 - Create Character (Old, 104 bytes)
- [x] 0x5D - Play Character
- [x] 0x80 - Account Login
- [x] 0x83 - Delete Character
- [x] 0x91 - Game Login
- [x] 0xA0 - Play Server
- [x] 0xBD - Client Version (response)
- [x] 0xE1 - Client Type
- [x] 0xEF - Login Server Seed
- [x] 0xF8 - Create Character (New, 106 bytes)
### Movement (IncomingMovementPackets.cs)
- [x] 0x02 - Movement Request
### Entity (IncomingEntityPackets.cs)
- [x] 0x06 - Use Request (Double-Click)
- [x] 0x09 - Look Request (Single-Click)
- [x] 0xB6 - Object Help Request
- [x] 0xD6 - Batch Query Properties
### Item (IncomingItemPackets.cs)
- [ ] 0x07 - Lift Request
- [ ] 0x08 - Drop Request (VERSION: 6017 adds grid location byte)
- [ ] 0x13 - Equip Request
- [ ] 0xEC - Equip Macro
- [ ] 0xED - Unequip Macro
### Mobile (IncomingMobilePackets.cs)
- [ ] 0x6F - Secure Trade
- [ ] 0x75 - Rename Request
- [ ] 0x98 - Mobile Name Request (incoming)
### Player (IncomingPlayerPackets.cs)
- [ ] 0x01 - Disconnect
- [ ] 0x05 - Attack Request
- [ ] 0x12 - Text Command (skills, cast)
- [ ] 0x22 - Resynchronize
- [ ] 0x2C - Death Status Response
- [ ] 0x34 - Mobile Query
- [ ] 0x3A - Change Skill Lock
- [ ] 0x72 - Set War Mode
- [ ] 0x73 - Ping Request
- [ ] 0x7D - Menu Response
- [ ] 0x95 - Hue Picker Response
- [ ] 0x9A - ASCII Prompt Response
- [ ] 0x9B - Help Request
- [ ] 0xA4 - System Info
- [ ] 0xA7 - Request Scroll Window
- [ ] 0xC2 - Unicode Prompt Response
- [ ] 0xC8 - Set Update Range
- [ ] 0xD0 - Configuration File
- [ ] 0xD1 - Logout Request
- [ ] 0xD7 - Encoded Command (wrapper)
- [ ] 0xF4 - Crash Report
### Message (IncomingMessagePackets.cs)
- [ ] 0x03 - ASCII Speech
- [ ] 0xAD - Unicode Speech
### Vendor (IncomingVendorPackets.cs)
- [ ] 0x3B - Vendor Buy Reply
- [ ] 0x9F - Vendor Sell Reply
### Targeting (IncomingTargetingPackets.cs)
- [ ] 0x6C - Target Response
### House (IncomingHousePackets.cs)
- [ ] 0xFB - Show Public House Content
### Extended Commands (IncomingExtendedCommandPackets.cs) - 0xBF subpackets
- [ ] 0xBF/0x05 - Screen Size
- [ ] 0xBF/0x06 - Party Message
- [ ] 0xBF/0x09 - Disarm Request
- [ ] 0xBF/0x0A - Stun Request
- [ ] 0xBF/0x0B - Language
- [ ] 0xBF/0x0C - Close Status
- [ ] 0xBF/0x0E - Animate
- [ ] 0xBF/0x0F - Empty (unused)
- [ ] 0xBF/0x10 - Query Properties
- [ ] 0xBF/0x13 - Context Menu Request
- [ ] 0xBF/0x15 - Context Menu Response
- [ ] 0xBF/0x1A - Stat Lock Change
- [ ] 0xBF/0x1C - Cast Spell
- [ ] 0xBF/0x1E - Query Design Details
- [ ] 0xBF/0x24 - Unhandled BF
- [ ] 0xBF/0x2A - Race Change Reply
- [ ] 0xBF/0x2C - Bandage Target
- [ ] 0xBF/0x2D - Targeted Spell
- [ ] 0xBF/0x2E - Targeted Skill Use
- [ ] 0xBF/0x30 - Target By Resource Macro
- [ ] 0xBF/0x32 - Toggle Flying
### Encoded Commands (0xD7 subpackets)
- [ ] 0xD7/0x02 - House Designer Backup
- [ ] 0xD7/0x03 - House Designer Restore
- [ ] 0xD7/0x04 - House Designer Commit
- [ ] 0xD7/0x05 - House Designer Delete
- [ ] 0xD7/0x06 - House Designer Build
- [ ] 0xD7/0x0C - House Designer Close
- [ ] 0xD7/0x0D - House Designer Stairs
- [ ] 0xD7/0x0E - House Designer Sync
- [ ] 0xD7/0x10 - House Designer Clear
- [ ] 0xD7/0x12 - House Designer Level
- [ ] 0xD7/0x13 - House Designer Roof
- [ ] 0xD7/0x14 - House Designer Roof Delete
- [ ] 0xD7/0x19 - Set Ability
- [ ] 0xD7/0x1A - House Designer Revert
- [ ] 0xD7/0x28 - Guild Gump Request
- [ ] 0xD7/0x32 - Quest Gump Request
### Gumps (GumpSystem.cs)
- [ ] 0xB1 - Display Gump Response
### Books (BookPackets.cs)
- [ ] 0x66 - Book Content Change
- [ ] 0x93 - Old Book Header Change
- [ ] 0xD4 - Book Header Change
### Bulletin Boards (BulletinBoardPackets.cs)
- [ ] 0x71 - Bulletin Board Request
### Maps (MapItemPackets.cs)
- [ ] 0x56 - Map Command
### Mahjong (MahjongPackets.cs)
- [ ] 0xDA - Mahjong (with subcommands)
### Chat (ChatPackets.cs)
- [ ] 0xB3 - Chat Action
- [ ] 0xB5 - Open Chat Window Request
### Ultima Store (UltimaStorePackets.cs)
- [ ] 0xFA - Ultima Store Open Request
### Hardware Info (HardwareInfo.cs)
- [ ] 0xD9 - Hardware Info
### Assistants (AssistantHandler.cs)
- [ ] 0xBE - Assistant Version
### Tracking (Tracking.cs)
- [ ] 0xBF/0x07 - Quest Arrow Click
---
## Outgoing Packets Tracking
### Account (OutgoingAccountPackets.cs)
- [x] 0x1B - Login Confirmation
- [x] 0x53 - Popup Message
- [x] 0x55 - Login Complete
- [x] 0x81 - Change Character
- [x] 0x82 - Account Login Rejected
- [x] 0x85 - Character Delete Result
- [x] 0x86 - Character List Update
- [x] 0x8C - Play Server Ack
- [x] 0xA8 - Account Login Ack (Server List)
- [x] 0xA9 - Character List (VERSION: 7.0.13.0 extended cities)
- [x] 0xB9 - Supported Features (VERSION: 6.0.14.2 extended to 4 bytes)
- [x] 0xBD - Client Version Request
### Movement (OutgoingMovementPackets.cs)
- [x] 0x21 - Movement Rejection
- [x] 0x22 - Movement Acknowledgment
- [x] 0x97 - Move Player
- [x] 0xBF/0x26 - Speed Control
- [x] 0xF2 - Time Sync Response
### Entity (OutgoingEntityPackets.cs)
- [x] 0x1D - Remove Entity
- [x] 0xDC - OPL Info
- [x] 0xF3 - World Entity (VERSION: 7.0.0.0 SA, 7.0.9.0 HS adds 2 bytes)
### Mobile (OutgoingMobilePackets.cs)
- [x] 0x11 - Mobile Status (VERSION: Multiple versions 0-6 based on expansion)
- [x] 0x17 - Mobile Healthbar
- [x] 0x20 - Mobile Update
- [x] 0x2D - Mobile Attributes
- [x] 0x6E - Mobile Animation
- [x] 0x77 - Mobile Moving
- [x] 0x78 - Mobile Incoming (VERSION: 7.0.33.1 always includes hue)
- [x] 0x98 - Mobile Name
- [x] 0xA1 - Mobile Hits
- [x] 0xA2 - Mobile Mana
- [x] 0xA3 - Mobile Stamina
- [x] 0xAF - Death Animation
- [x] 0xBF/0x19 - Bonded Status
- [x] 0xE2 - New Mobile Animation
### Item (OutgoingItemPackets.cs)
- [ ] 0x1A - World Item (pre-SA)
### Container (OutgoingContainerPackets.cs)
- [ ] 0x24 - Display Container (VERSION: 6017 adds gump type)
- [ ] 0x25 - Container Content Update (VERSION: 6017 adds grid location)
- [ ] 0x3C - Container Content (VERSION: 6017 adds grid location per item)
- [ ] 0xBF/0x1B - New Spellbook Content (AOS)
### Message (OutgoingMessagePackets.cs)
- [ ] 0x15 - Follow Message
- [ ] 0x1C - ASCII Message
- [ ] 0xAE - Unicode Message
- [ ] 0xB7 - Help Response
- [ ] 0xC1 - Localized Message
- [ ] 0xC2 - Prompt (outgoing)
- [ ] 0xCC - Localized Message Affix
### Player (OutgoingPlayerPackets.cs)
- [ ] 0x23 - Drag Effect
- [ ] 0x27 - Lift Reject
- [ ] 0x2C - Death Status
- [ ] 0x38 - Pathfind Message
- [ ] 0x3A - Skills Update
- [ ] 0x5B - Current Time
- [ ] 0x65 - Weather
- [ ] 0x6D - Play Music
- [ ] 0x73 - Ping Ack
- [ ] 0x76 - Server Change
- [ ] 0x7B - Sequence
- [ ] 0x88 - Display Paperdoll
- [ ] 0x95 - Display Hue Picker
- [ ] 0xA5 - Launch Browser
- [ ] 0xA6 - Scroll Message
- [ ] 0xBC - Season Change
- [ ] 0xBF/0x19 - Stat Lock Info
- [ ] 0xC8 - Change Update Range
- [ ] 0xD1 - Logout Ack
### Combat (OutgoingCombatPackets.cs)
- [ ] 0x2F - Swing
- [ ] 0x72 - Set War Mode
- [ ] 0xAA - Change Combatant
### Damage (OutgoingDamagePackets.cs)
- [ ] 0x0B - Damage (VERSION: 5.0.0a, or 0xBF/0x22 for older)
### Light (OutgoingLightPackets.cs)
- [ ] 0x4E - Personal Light Level
- [ ] 0x4F - Global Light Level
### Effects (OutgoingEffectPackets.cs)
- [ ] 0x54 - Sound Effect
- [ ] 0x70 - Screen Effect
- [ ] 0xC0 - Hued Effect
- [ ] 0xC7 - Particle Effect
### Target (OutgoingTargetPackets.cs)
- [ ] 0x6C - Target Request/Cancel (VERSION: HS adds 4 bytes to multi target)
- [ ] 0x99 - Multi Target Request
### Equipment (OutgoingEquipmentPackets.cs)
- [ ] 0x2E - Equip Update
- [ ] 0xBF/0x10 - Display Equipment Info
### Vendor (OutgoingVendorBuyPackets.cs, OutgoingVendorSellPackets.cs)
- [ ] 0x3B - End Vendor Buy
- [ ] 0x74 - Vendor Buy List
- [ ] 0x9E - Vendor Sell List
### Map (OutgoingMapPackets.cs)
- [ ] 0xBF/0x08 - Map Change
- [ ] 0xBF/0x18 - Map Patches
- [ ] 0xC6 - Invalid Map
### Menu (OutgoingMenuPackets.cs)
- [ ] 0x7C - Display Item List Menu
### Secure Trade (OutgoingSecureTradePackets.cs)
- [ ] 0x6F - Secure Trade (VERSION: 7.0.45.65 new format)
### Gumps (OutgoingGumpPackets.cs)
- [ ] 0x8B - Display Sign Gump
- [ ] 0xBF/0x04 - Close Gump
### Party (PartyPackets.cs)
- [ ] 0xBF/0x06 - Party packets (multiple sub-types)
### Buff Icons (BuffIconPackets.cs)
- [ ] 0xDF - Buff/Debuff System
### Books (BookPackets.cs)
- [ ] 0x66 - Book Content
- [ ] 0x93 - Book Header (old)
- [ ] 0xD4 - Book Header (new)
### Bulletin Boards (BulletinBoardPackets.cs)
- [ ] 0x71 - Bulletin Board Content
### Maps (MapItemPackets.cs)
- [ ] 0x56 - Map Details
- [ ] 0x90 - Map Display
- [ ] 0xF5 - New Map Display
### Chat (ChatPackets.cs)
- [ ] 0xB2 - Chat Message
- [ ] 0xB5 - Open Chat Window
### Context Menus (ContextMenuSystem.cs)
- [ ] 0xBF/0x14 - Display Context Menu
### Corpse (CorpsePackets.cs)
- [ ] 0x3C - Corpse Content
### House (HousePackets.cs)
- [ ] House Design packets (multiple)
### Boats (BoatPackets.cs)
- [ ] 0xF6 - Move Boat HS
### Quest (MLQuestPackets.cs)
- [ ] Quest-related packets
### Tracking (OutgoingArrowPackets.cs)
- [ ] 0xBA - Quest Arrow
### Character Statue (CharacterStatuePackets.cs)
- [ ] 0xBF/0x20 - Custom House Info
### Weapon Abilities (WeaponAbilityPackets.cs)
- [ ] 0xBF/0x21 - Clear Weapon Ability
- [ ] 0xBF/0x25 - Toggle Special Ability
### Mahjong (MahjongPackets.cs)
- [ ] 0xDA - Mahjong game packets
---
## Questions for Clarification
### Version/Protocol Questions
1. **Drop Request (0x08)**: The code shows `ContainerGridPacketHandler` - is this the 6017 version that adds the grid byte? What was the original format?
2. **Container Content Update (0x25)**: I see the size varies by `ContainerGridLines`. Is it 20 bytes pre-6017 and 21 bytes post-6017?
3. **Container Content (0x3C)**: Same question - does each item entry gain 1 byte for grid position?
4. **Display Container (0x24)**: The code shows 7 or 9 bytes. What's the difference and which version introduced the extra 2 bytes?
5. **Secure Trade (0x6F)**: What fields changed in 7.0.45.65 (NewSecureTrading)?
6. **Multi Target (0x99)**: You mentioned HS adds bytes - is it 26 pre-HS and 30 post-HS?
7. **Damage Packet**: Pre-5.0.0a clients use 0xBF/0x22, post-5.0.0a use 0x0B. Is this correct?
### Enum/Flag Questions
8. **ALRReason (Account Login Rejection)**: Is this a sequential enum (0-3, 254, 255)?
9. **PMMessage (Popup Message)**: Sequential enum (0-7)?
10. **DeleteResultType**: Sequential enum (0-5)?
11. **Direction**: Sequential 0-7 plus 0x80 running flag - should this be documented as enum + bitflag?
12. **Notoriety**: Sequential 0-7?
13. **Mobile Packet Flags**: This appears to be a bitfield (Hidden=0x80, Poisoned=0x04, etc.) - can you confirm all flag values?
14. **FeatureFlags (0xB9)**: This is a bitfield - should we document all the flag values?
15. **CharacterListFlags (0xA9)**: Also a bitfield?
16. **ClientFlags**: Also a bitfield?
### Packet Structure Questions
17. **Book packets (0x66, 0x93, 0xD4)**: These use UTF-8. Is the string format length-prefixed or null-terminated?
18. **Speech packets (0x03, 0xAD, 0x1C, 0xAE)**: What determines ASCII vs Unicode? Is 0x03/0x1C always ASCII and 0xAD/0xAE always Unicode?
19. **Localized Message (0xC1, 0xCC)**: The arguments field - is it Unicode LE with tab separators?
20. **Extended Packet (0xBF)**: Some subpackets like 0x06 (Party) have further sub-types. Should we nest these or list each as separate packets?
21. **Mobile Status (0x11)**: The version is determined by:
- Version 0 = always used when viewing OTHER mobiles (compact)
- Versions 3-6 = used when viewing SELF, based on ExpansionInfo.MobileStatusVersion
Is this correct?
22. **Mobile Incoming (0x78)**: The equipment list - for pre-NewMobileIncoming clients, the hue field is only included if itemId has bit 0x8000 set. For NewMobileIncoming clients, hue is always included. Is this correct?
---
## Schema Updates Needed
### 1. Enum Field Support
```json
{
"name": "reason",
"type": "enum",
"enumType": "sequential",
"size": 1,
"values": [
{ "value": 0, "name": "Invalid" },
{ "value": 1, "name": "InUse" },
{ "value": 2, "name": "Blocked" },
{ "value": 3, "name": "BadPass" },
{ "value": 254, "name": "Idle" },
{ "value": 255, "name": "BadComm" }
]
}
```
### 2. Bitfield Support
```json
{
"name": "flags",
"type": "bitfield",
"size": 1,
"flags": [
{ "bit": 0x80, "name": "Hidden" },
{ "bit": 0x40, "name": "Warmode" },
{ "bit": 0x08, "name": "Blessed" },
{ "bit": 0x04, "name": "Poisoned" },
{ "bit": 0x02, "name": "Female" }
]
}
```
### 3. Packet Variants Support
```json
{
"id": "0x11",
"name": "Mobile Status",
"variants": [
{
"version": "0",
"name": "Compact (Other Mobile)",
"condition": "Viewing other mobile",
"size": 43,
"fields": [...]
},
{
"version": "3",
"name": "Basic (Pre-AOS)",
"condition": "Self, Expansion < AOS",
"size": 70,
"fields": [...]
}
]
}
```
---
## Progress Summary
- **Incoming Packets**: 66 documented (including 16 extended 0xBF subpackets)
- **Outgoing Packets**: 79 documented
- **Total**: 145 packets
## Recently Added Files
- `incoming/extended.json` - 0xBF extended command subpackets (16 packets)
- `incoming/items.json` - Lift, Drop, Equip packets
- `incoming/player.json` - Attack, TextCommand, Skills, War mode, etc.
- `incoming/message.json` - ASCII/Unicode speech packets
- `incoming/mobile.json` - Secure trade, rename, profile
- `incoming/vendor.json` - Buy/sell responses
- `incoming/targeting.json` - Target response
- `outgoing/message.json` - ASCII/Unicode messages, localized messages
- `outgoing/player.json` - Stats, skills, weather, music, paperdoll
- `outgoing/container.json` - Container display, content, spellbook
- `outgoing/combat.json` - Swing, war mode, combatant
- `outgoing/effects.json` - Sound, particle effects, screen effects
- `outgoing/targeting.json` - Target request, multi target
- `outgoing/items.json` - World item (pre-SA)
- `outgoing/light.json` - Global/personal light levels
- `outgoing/damage.json` - Damage packets (new and old formats)

View file

@ -0,0 +1,262 @@
{
"category": "Account",
"packets": [
{
"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": "packetId", "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": "nextLoginKey", "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
}
},
{
"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": "packetId", "type": "byte", "size": 1, "value": "0x91", "description": "Packet identifier" },
{ "name": "authId", "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
}
},
{
"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": "packetId", "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": "charSlot", "type": "int", "size": 4, "description": "Character slot index (0-based)" },
{ "name": "clientIP", "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
}
},
{
"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": "packetId", "type": "byte", "size": 1, "value": "0xA0", "description": "Packet identifier" },
{ "name": "serverIndex", "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
}
},
{
"id": "0x83",
"name": "Delete Character",
"description": "Request to delete a character from the account.",
"direction": "incoming",
"isDynamic": false,
"size": 39,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x83", "description": "Packet identifier" },
{ "name": "password", "type": "ascii", "size": 30, "description": "Account password for verification" },
{ "name": "charIndex", "type": "int", "size": 4, "description": "Character slot index to delete" },
{ "name": "clientIP", "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
}
},
{
"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": "packetId", "type": "byte", "size": 1, "value": "0xEF", "description": "Packet identifier" },
{ "name": "seed", "type": "int", "size": 4, "description": "Random seed for encryption" },
{ "name": "clientMajor", "type": "int", "size": 4, "description": "Client major version" },
{ "name": "clientMinor", "type": "int", "size": 4, "description": "Client minor version" },
{ "name": "clientRevision", "type": "int", "size": 4, "description": "Client revision" },
{ "name": "clientPatch", "type": "int", "size": 4, "description": "Client patch level" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs",
"line": 419
}
},
{
"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": "packetId", "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
}
},
{
"id": "0xE1",
"name": "Client Type",
"description": "Sent by the client to identify the client type and version.",
"direction": "incoming",
"isDynamic": true,
"size": "variable",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xE1", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "unknown", "type": "ushort", "size": 2, "description": "Unknown" },
{ "name": "clientType", "type": "ushort", "size": 2, "description": "Client type identifier" },
{ "name": "version", "type": "ascii", "description": "Client version string" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs",
"line": 200
}
},
{
"id": "0x00",
"name": "Create Character (Old)",
"description": "Request to create a new character. This is the older 104-byte version.",
"direction": "incoming",
"isDynamic": false,
"size": 104,
"fields": [
{ "name": "packetId", "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": "genderRace", "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": "skinHue", "type": "ushort", "size": 2, "description": "Skin color hue" },
{ "name": "hairStyle", "type": "short", "size": 2, "description": "Hair style ID" },
{ "name": "hairHue", "type": "short", "size": 2, "description": "Hair color hue" },
{ "name": "facialHairStyle", "type": "short", "size": 2, "description": "Facial hair style ID" },
{ "name": "facialHairHue", "type": "short", "size": 2, "description": "Facial hair color hue" },
{ "name": "unknown7", "type": "byte", "size": 1, "description": "Unknown" },
{ "name": "cityIndex", "type": "byte", "size": 1, "description": "Starting city index" },
{ "name": "charSlot", "type": "int", "size": 4, "description": "Character slot" },
{ "name": "clientIP", "type": "int", "size": 4, "description": "Client IP" },
{ "name": "shirtHue", "type": "short", "size": 2, "description": "Starting shirt hue" },
{ "name": "pantsHue", "type": "short", "size": 2, "description": "Starting pants hue" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs",
"line": 58
}
},
{
"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": "packetId", "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": "genderRace", "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": "skinHue", "type": "ushort", "size": 2, "description": "Skin color hue" },
{ "name": "hairStyle", "type": "short", "size": 2, "description": "Hair style ID" },
{ "name": "hairHue", "type": "short", "size": 2, "description": "Hair color hue" },
{ "name": "facialHairStyle", "type": "short", "size": 2, "description": "Facial hair style ID" },
{ "name": "facialHairHue", "type": "short", "size": 2, "description": "Facial hair color hue" },
{ "name": "unknown7", "type": "byte", "size": 1, "description": "Unknown" },
{ "name": "cityIndex", "type": "byte", "size": 1, "description": "Starting city index" },
{ "name": "charSlot", "type": "int", "size": 4, "description": "Character slot" },
{ "name": "clientIP", "type": "int", "size": 4, "description": "Client IP" },
{ "name": "shirtHue", "type": "short", "size": 2, "description": "Starting shirt hue" },
{ "name": "pantsHue", "type": "short", "size": 2, "description": "Starting pants hue" }
],
"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."
}
]
}

View file

@ -0,0 +1,82 @@
{
"category": "Entity",
"packets": [
{
"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": "packetId", "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
}
},
{
"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": "packetId", "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
}
},
{
"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": "packetId", "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
}
},
{
"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 * entityCount)",
"fields": [
{ "name": "packetId", "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
}
}
]
}

View file

@ -0,0 +1,356 @@
{
"category": "Extended Commands (0xBF)",
"packets": [
{
"id": "0xBF",
"name": "Extended Command",
"description": "Wrapper packet for extended command subpackets.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "description": "Extended command ID" },
{ "name": "data", "type": "byte[]", "description": "Subcommand-specific data" }
],
"notes": "See individual 0xBF/0xXX packets for subcommand details.",
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 43
}
},
{
"id": "0xBF/0x05",
"subId": "0x05",
"name": "Screen Size",
"description": "Client reports screen size.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "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
}
},
{
"id": "0xBF/0x06",
"subId": "0x06",
"name": "Party Message",
"description": "Client sends party-related commands.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x06", "description": "Party Message subcommand" },
{
"name": "partyCommand",
"type": "enum",
"enumType": "sequential",
"size": 1,
"description": "Party command type",
"values": [
{ "value": 1, "name": "AddMember", "description": "Add member to party" },
{ "value": 2, "name": "RemoveMember", "description": "Remove member from party" },
{ "value": 3, "name": "PrivateMessage", "description": "Send private message to party member" },
{ "value": 4, "name": "PublicMessage", "description": "Send public message to party" },
{ "value": 6, "name": "SetCanLoot", "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
}
},
{
"id": "0xBF/0x09",
"subId": "0x09",
"name": "Disarm Request",
"description": "Client requests to disarm opponent.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x09", "description": "Disarm Request subcommand" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 289
}
},
{
"id": "0xBF/0x0A",
"subId": "0x0A",
"name": "Stun Request",
"description": "Client requests to stun opponent.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x0A", "description": "Stun Request subcommand" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 277
}
},
{
"id": "0xBF/0x0B",
"subId": "0x0B",
"name": "Language",
"description": "Client sets language preference.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "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
}
},
{
"id": "0xBF/0x0C",
"subId": "0x0C",
"name": "Close Status",
"description": "Client closes a status gump.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "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
}
},
{
"id": "0xBF/0x0E",
"subId": "0x0E",
"name": "Animate",
"description": "Client requests to play an animation.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "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
}
},
{
"id": "0xBF/0x10",
"subId": "0x10",
"name": "Query Properties",
"description": "Client queries Object Property List (tooltip) for an entity.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "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", "relationship": "response", "note": "OPL Info packet" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 355
}
},
{
"id": "0xBF/0x1A",
"subId": "0x1A",
"name": "Stat Lock Change",
"description": "Client changes stat lock (STR/DEX/INT).",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "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": "lockValue",
"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
}
},
{
"id": "0xBF/0x1C",
"subId": "0x1C",
"name": "Cast Spell",
"description": "Client casts a spell (optionally from spellbook).",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x1C", "description": "Cast Spell subcommand" },
{ "name": "hasBook", "type": "short", "size": 2, "description": "1 if casting from book, 0 otherwise" },
{ "name": "bookSerial", "type": "uint", "size": 4, "description": "Serial of spellbook (if hasBook)", "condition": "hasBook == 1" },
{ "name": "spellId", "type": "short", "size": 2, "description": "Spell ID + 1 (1-based)" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 257
}
},
{
"id": "0xBF/0x2C",
"subId": "0x2C",
"name": "Bandage Target",
"description": "Client uses bandage on a target.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x2C", "description": "Bandage Target subcommand" },
{ "name": "bandageSerial", "type": "uint", "size": 4, "description": "Serial of the bandage item" },
{ "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of target mobile" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 387
}
},
{
"id": "0xBF/0x2D",
"subId": "0x2D",
"name": "Targeted Spell",
"description": "Client casts spell with pre-selected target.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x2D", "description": "Targeted Spell subcommand" },
{ "name": "spellId", "type": "short", "size": 2, "description": "Spell ID + 1 (1-based)" },
{ "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of target entity" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 422
}
},
{
"id": "0xBF/0x2E",
"subId": "0x2E",
"name": "Targeted Skill Use",
"description": "Client uses skill with pre-selected target.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x2E", "description": "Targeted Skill Use subcommand" },
{ "name": "skillId", "type": "short", "size": 2, "description": "Skill ID" },
{ "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of target entity" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 429
}
},
{
"id": "0xBF/0x30",
"subId": "0x30",
"name": "Target By Resource Macro",
"description": "Client uses resource-based targeting macro.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x30", "description": "Target By Resource Macro subcommand" },
{ "name": "itemSerial", "type": "uint", "size": 4, "description": "Serial of item" },
{ "name": "resourceType", "type": "short", "size": 2, "description": "Resource type ID" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 439
}
},
{
"id": "0xBF/0x32",
"subId": "0x32",
"name": "Toggle Flying",
"description": "Client toggles gargoyle flying mode.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x32", "description": "Toggle Flying subcommand" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 272
}
}
]
}

View file

@ -0,0 +1,142 @@
{
"category": "Items",
"packets": [
{
"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": "packetId", "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
}
},
{
"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": "14 (pre-6017) or 15 (6017+)",
"variants": [
{
"version": "pre-6017",
"name": "Classic",
"size": 14,
"fields": [
{ "name": "packetId", "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" }
]
},
{
"version": "6017+",
"name": "Container Grid Lines",
"condition": "Client version >= 6.0.1.7 (ContainerGridLines)",
"size": 15,
"fields": [
{ "name": "packetId", "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": "gridLocation", "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": {
"feature": "ContainerGridLines adds gridLocation byte"
},
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs",
"line": 69
}
},
{
"id": "0x13",
"name": "Equip Request",
"description": "Client requests to equip a held item on a mobile.",
"direction": "incoming",
"isDynamic": false,
"size": 10,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x13", "description": "Packet identifier" },
{ "name": "itemSerial", "type": "uint", "size": 4, "description": "Serial of item to equip" },
{ "name": "layer", "type": "byte", "size": 1, "description": "Equipment layer" },
{ "name": "mobileSerial", "type": "uint", "size": 4, "description": "Serial of target mobile" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs",
"line": 44
}
},
{
"id": "0xEC",
"name": "Equip Macro",
"description": "Client requests to equip multiple items from a saved macro.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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" }
]
}
}
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs",
"line": 112
}
},
{
"id": "0xED",
"name": "Unequip Macro",
"description": "Client requests to unequip items from specific layers via macro.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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" }
]
}
}
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs",
"line": 125
}
}
]
}

View file

@ -0,0 +1,97 @@
{
"category": "Message",
"packets": [
{
"id": "0x03",
"name": "ASCII Speech",
"description": "Client sends ASCII-encoded speech message.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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-null", "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
}
},
{
"id": "0xAD",
"name": "Unicode Speech",
"description": "Client sends Unicode-encoded speech message with optional keywords.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xAD", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{
"name": "type",
"type": "bitfield",
"size": 1,
"description": "Message type with possible Encoded flag",
"flags": [
{ "bit": "0x0F", "name": "MessageType", "description": "Base message type (see 0x03)" },
{ "bit": "0xC0", "name": "Encoded", "description": "If set, packet contains encoded keywords" }
]
},
{ "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": "encodedKeywords",
"type": "conditional",
"condition": "type & 0xC0 != 0",
"fields": [
{ "name": "keywordValue", "type": "short", "size": 2, "description": "Keyword count (upper 12 bits) and first hold value (lower 4 bits)" },
{ "name": "keywords", "type": "byte[]", "description": "Packed keyword IDs" },
{ "name": "text", "type": "utf8-null", "description": "Speech text (UTF-8 when encoded)" }
]
},
{
"name": "unicodeText",
"type": "conditional",
"condition": "type & 0xC0 == 0",
"fields": [
{ "name": "text", "type": "unicode-be-null", "description": "Speech text (Big Endian Unicode)" }
]
}
],
"related": [
{ "id": "0xAE", "relationship": "response", "note": "Unicode Message sent to other clients" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingMessagePackets.cs",
"line": 58
}
}
]
}

View file

@ -0,0 +1,132 @@
{
"category": "Mobile",
"packets": [
{
"id": "0x6F",
"name": "Secure Trade",
"description": "Client interacts with a secure trade window.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x6F", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{
"name": "action",
"type": "enum",
"enumType": "sequential",
"size": 1,
"description": "Trade action type",
"values": [
{ "value": 1, "name": "Cancel", "description": "Cancel the trade" },
{ "value": 2, "name": "Check", "description": "Toggle accept checkbox" },
{ "value": 3, "name": "UpdateGold", "description": "Update virtual gold/platinum amounts" }
]
},
{ "name": "containerSerial", "type": "uint", "size": 4, "description": "Serial of the trade container" },
{
"name": "checkData",
"type": "conditional",
"condition": "action == 2",
"fields": [
{ "name": "accepted", "type": "int", "size": 4, "description": "Non-zero if accepting trade" }
]
},
{
"name": "goldData",
"type": "conditional",
"condition": "action == 3",
"fields": [
{ "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", "relationship": "response", "note": "Server sends Secure Trade packet updates" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingMobilePackets.cs",
"line": 93
}
},
{
"id": "0x75",
"name": "Rename Request",
"description": "Client requests to rename a mobile (pet).",
"direction": "incoming",
"isDynamic": false,
"size": 35,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x75", "description": "Packet identifier" },
{ "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of mobile to rename" },
{ "name": "newName", "type": "ascii", "size": 30, "description": "New name for the mobile" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingMobilePackets.cs",
"line": 32
}
},
{
"id": "0x98",
"name": "Mobile Name Request",
"description": "Client requests the name of a mobile.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x98", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "mobileSerial", "type": "uint", "size": 4, "description": "Serial of mobile to query" }
],
"related": [
{ "id": "0x98", "relationship": "response", "note": "Server sends Mobile Name response" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingMobilePackets.cs",
"line": 43
}
},
{
"id": "0xB8",
"name": "Profile Request",
"description": "Client requests to view or edit a mobile's profile.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xB8", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{
"name": "mode",
"type": "enum",
"enumType": "sequential",
"size": 1,
"description": "Request mode",
"values": [
{ "value": 0, "name": "Display", "description": "Request to view profile" },
{ "value": 1, "name": "Edit", "description": "Request to edit profile" }
]
},
{ "name": "mobileSerial", "type": "uint", "size": 4, "description": "Serial of target mobile" },
{
"name": "editData",
"type": "conditional",
"condition": "mode == 1",
"fields": [
{ "name": "padding", "type": "short", "size": 2, "description": "Unused padding" },
{ "name": "textLength", "type": "ushort", "size": 2, "description": "Length of text in characters" },
{ "name": "text", "type": "unicode-be", "description": "New profile text" }
]
}
],
"related": [
{ "id": "0xB8", "relationship": "response", "note": "Display Profile packet" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingMobilePackets.cs",
"line": 53
}
}
]
}

View file

@ -0,0 +1,27 @@
{
"category": "Movement",
"packets": [
{
"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": "packetId", "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": "fastwalkKey", "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
}
}
]
}

View file

@ -0,0 +1,470 @@
{
"category": "Player",
"packets": [
{
"id": "0x01",
"name": "Disconnect",
"description": "Client sends disconnect notification.",
"direction": "incoming",
"isDynamic": false,
"size": 5,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x01", "description": "Packet identifier" },
{ "name": "minusOne", "type": "int", "size": 4, "value": "0xFFFFFFFF", "description": "Always -1" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 317
}
},
{
"id": "0x05",
"name": "Attack Request",
"description": "Client requests to attack a mobile.",
"direction": "incoming",
"isDynamic": false,
"size": 5,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x05", "description": "Packet identifier" },
{ "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of mobile to attack" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 69
}
},
{
"id": "0x12",
"name": "Text Command",
"description": "Client sends text-based commands for skills, spells, virtues, etc.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x12", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{
"name": "commandType",
"type": "enum",
"enumType": "sequential",
"size": 1,
"description": "Type of text command",
"values": [
{ "value": "0x24", "name": "UseSkill", "description": "Use a skill by ID" },
{ "value": "0x27", "name": "CastSpellFromBook", "description": "Cast spell from spellbook" },
{ "value": "0x2F", "name": "OldScrollClick", "description": "Old scroll double-click" },
{ "value": "0x43", "name": "OpenSpellbook", "description": "Open spellbook of type" },
{ "value": "0x56", "name": "CastSpellMacro", "description": "Cast spell from macro" },
{ "value": "0x58", "name": "OpenDoor", "description": "Open door macro" },
{ "value": "0xC7", "name": "Animate", "description": "Play animation" },
{ "value": "0xF4", "name": "InvokeVirtue", "description": "Invoke virtue from macro" }
]
},
{ "name": "command", "type": "ascii-null", "description": "Command-specific text (skill ID, spell ID, etc.)" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 119
}
},
{
"id": "0x22",
"name": "Resynchronize",
"description": "Client requests full world state resync.",
"direction": "incoming",
"isDynamic": false,
"size": 3,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x22", "description": "Packet identifier" },
{ "name": "padding", "type": "ushort", "size": 2, "description": "Unused padding" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 349
}
},
{
"id": "0x2C",
"name": "Death Status Response",
"description": "Client acknowledges death status packet. Currently ignored by server.",
"direction": "incoming",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "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
}
},
{
"id": "0x34",
"name": "Mobile Query",
"description": "Client queries information about a mobile (stats or skills).",
"direction": "incoming",
"isDynamic": false,
"size": 10,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x34", "description": "Packet identifier" },
{ "name": "pattern", "type": "uint", "size": 4, "value": "0xEDEDEDED", "description": "Fixed pattern" },
{
"name": "queryType",
"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": "mobileSerial", "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
}
},
{
"id": "0x3A",
"name": "Change Skill Lock",
"description": "Client changes the lock state of a skill.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x3A", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "skillIndex", "type": "short", "size": 2, "description": "Skill index to change" },
{
"name": "lockState",
"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
}
},
{
"id": "0x72",
"name": "Set War Mode",
"description": "Client toggles war/peace mode.",
"direction": "incoming",
"isDynamic": false,
"size": 5,
"fields": [
{ "name": "packetId", "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)" }
],
"related": [
{ "id": "0x72", "relationship": "response", "note": "Server echoes back war mode state" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 343
}
},
{
"id": "0x73",
"name": "Ping Request",
"description": "Client sends ping for latency measurement.",
"direction": "incoming",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x73", "description": "Packet identifier" },
{ "name": "sequence", "type": "byte", "size": 1, "description": "Ping sequence number" }
],
"related": [
{ "id": "0x73", "relationship": "response", "note": "Server echoes back same sequence" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 366
}
},
{
"id": "0x7D",
"name": "Menu Response",
"description": "Client responds to a displayed item menu.",
"direction": "incoming",
"isDynamic": false,
"size": 13,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x7D", "description": "Packet identifier" },
{ "name": "serial", "type": "uint", "size": 4, "description": "Menu dialog serial" },
{ "name": "menuId", "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": "itemId", "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
}
},
{
"id": "0x95",
"name": "Hue Picker Response",
"description": "Client responds to a hue picker dialog.",
"direction": "incoming",
"isDynamic": false,
"size": 9,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x95", "description": "Packet identifier" },
{ "name": "serial", "type": "uint", "size": 4, "description": "Hue picker serial" },
{ "name": "itemId", "type": "short", "size": 2, "description": "Item ID (unused)" },
{ "name": "hue", "type": "short", "size": 2, "description": "Selected hue (masked with 0x3FFF)" }
],
"related": [
{ "id": "0x95", "relationship": "request", "note": "Display Hue Picker packet" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 86
}
},
{
"id": "0x9A",
"name": "ASCII Prompt Response",
"description": "Client responds to an ASCII text prompt.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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": "promptId", "type": "int", "size": 4, "description": "Prompt ID" },
{ "name": "type", "type": "int", "size": 4, "description": "Response type: 0 = cancel, other = submit" },
{ "name": "text", "type": "ascii-null", "description": "Response text (max 128 chars)" }
],
"related": [
{ "id": "0xC2", "relationship": "request", "note": "Prompt packet that triggered this response" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 214
}
},
{
"id": "0x9B",
"name": "Help Request",
"description": "Client requests help/GM assistance.",
"direction": "incoming",
"isDynamic": false,
"size": 258,
"fields": [
{ "name": "packetId", "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
}
},
{
"id": "0xA4",
"name": "System Info",
"description": "Client sends system/hardware information.",
"direction": "incoming",
"isDynamic": false,
"size": 149,
"fields": [
{ "name": "packetId", "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
}
},
{
"id": "0xA7",
"name": "Request Scroll Window",
"description": "Client requests a tips/scroll window.",
"direction": "incoming",
"isDynamic": false,
"size": 4,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xA7", "description": "Packet identifier" },
{ "name": "lastTip", "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
}
},
{
"id": "0xC2",
"name": "Unicode Prompt Response",
"description": "Client responds to a Unicode text prompt.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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": "promptId", "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": "unicode-le-null", "description": "Response text (max 128 chars)" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 250
}
},
{
"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": "packetId", "type": "byte", "size": 1, "value": "0xC8", "description": "Packet identifier" },
{ "name": "range", "type": "byte", "size": 1, "description": "Requested update range (ignored)" }
],
"related": [
{ "id": "0xC8", "relationship": "response", "note": "Server sends back fixed range (18)" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 371
}
},
{
"id": "0xD0",
"name": "Configuration File",
"description": "Client sends configuration data. Currently ignored by server.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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
}
},
{
"id": "0xD1",
"name": "Logout Request",
"description": "Client requests to logout.",
"direction": "incoming",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xD1", "description": "Packet identifier" },
{ "name": "unknown", "type": "byte", "size": 1, "description": "Unknown (typically 0x01)" }
],
"related": [
{ "id": "0xD1", "relationship": "response", "note": "Server sends Logout Ack" }
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 326
}
},
{
"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": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xD7", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "entitySerial", "type": "uint", "size": 4, "description": "Serial of target entity" },
{ "name": "subCommand", "type": "ushort", "size": 2, "description": "Encoded command ID" },
{ "name": "data", "type": "byte[]", "description": "Subcommand-specific data" }
],
"notes": "See encoded.json for subpacket definitions",
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs",
"line": 457
}
},
{
"id": "0xF4",
"name": "Crash Report",
"description": "Client sends crash/error report.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xF4", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "clientMajor", "type": "byte", "size": 1, "description": "Client major version" },
{ "name": "clientMinor", "type": "byte", "size": 1, "description": "Client minor version" },
{ "name": "clientRev", "type": "byte", "size": 1, "description": "Client revision" },
{ "name": "clientPat", "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": "accountName", "type": "ascii", "size": 32, "description": "Account name" },
{ "name": "characterName", "type": "ascii", "size": 32, "description": "Character name" },
{ "name": "ipAddress", "type": "ascii", "size": 15, "description": "Client IP address" },
{ "name": "unknown1", "type": "int", "size": 4, "description": "Unknown" },
{ "name": "exceptionCode", "type": "int", "size": 4, "description": "Exception code" },
{ "name": "processName", "type": "ascii", "size": 100, "description": "Process name" },
{ "name": "reportText", "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": "stackCount", "type": "byte", "size": 1, "description": "Number of stack trace entries" },
{
"name": "stackAddresses",
"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
}
}
]
}

View file

@ -0,0 +1,55 @@
{
"category": "Targeting",
"packets": [
{
"id": "0x6C",
"name": "Target Response",
"description": "Client responds to a target cursor request.",
"direction": "incoming",
"isDynamic": false,
"size": 19,
"fields": [
{ "name": "packetId", "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": "targetId", "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": "targetSerial", "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)" }
],
"related": [
{ "id": "0x6C", "relationship": "request", "note": "Target Request packet that initiated this" }
],
"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
}
}
]
}

View file

@ -0,0 +1,70 @@
{
"category": "Vendor",
"packets": [
{
"id": "0x3B",
"name": "Vendor Buy Reply",
"description": "Client confirms items to purchase from a vendor.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x3B", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "vendorSerial", "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": "itemSerial", "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
}
},
{
"id": "0x9F",
"name": "Vendor Sell Reply",
"description": "Client confirms items to sell to a vendor.",
"direction": "incoming",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x9F", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "vendorSerial", "type": "uint", "size": 4, "description": "Serial of the vendor" },
{ "name": "itemCount", "type": "ushort", "size": 2, "description": "Number of items to sell" },
{
"name": "items",
"type": "loop",
"loop": {
"countField": "itemCount",
"fields": [
{ "name": "itemSerial", "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
}
}
]
}

View file

@ -0,0 +1,320 @@
{
"category": "Account",
"packets": [
{
"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": "packetId", "type": "byte", "size": 1, "value": "0x82", "description": "Packet identifier" },
{ "name": "reason", "type": "byte", "size": 1, "description": "Rejection reason: 0=Invalid, 1=InUse, 2=Blocked, 3=BadPass, 254=Idle, 255=BadComm" }
],
"related": [
{ "id": "0x80", "relationship": "request", "note": "The login attempt that failed" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs",
"line": 402
}
},
{
"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 * serverCount)",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xA8", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "systemInfoFlag", "type": "byte", "size": 1, "value": "0x5D", "description": "System info flag" },
{ "name": "serverCount", "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": "fullPercent", "type": "byte", "size": 1, "description": "Server load percentage" },
{ "name": "timezone", "type": "sbyte", "size": 1, "description": "Server timezone offset" },
{ "name": "ipAddress", "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
}
},
{
"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": "packetId", "type": "byte", "size": 1, "value": "0x8C", "description": "Packet identifier" },
{ "name": "ipAddress", "type": "uint", "size": 4, "description": "Game server IP address (little-endian)" },
{ "name": "port", "type": "short", "size": 2, "description": "Game server port" },
{ "name": "authId", "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
}
},
{
"id": "0xA9",
"name": "Character List",
"description": "Sent after game login. Contains the list of characters on the account and starting city information.",
"direction": "outgoing",
"isDynamic": true,
"size": "variable (client version dependent)",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xA9", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "charCount", "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" }
]
}
},
{ "name": "cityCount", "type": "byte", "size": 1, "description": "Number of starting cities" },
{
"name": "cities",
"type": "array",
"description": "Starting city entries",
"loop": {
"countField": "cityCount",
"fields": [
{ "name": "index", "type": "byte", "size": 1, "description": "City index" },
{ "name": "cityName", "type": "ascii", "size": 31, "description": "City name (32 for 7.0.13.0+)" },
{ "name": "buildingName", "type": "ascii", "size": 31, "description": "Building name (32 for 7.0.13.0+)" },
{ "name": "x", "type": "int", "size": 4, "description": "X coordinate (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" },
{ "name": "y", "type": "int", "size": 4, "description": "Y coordinate (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" },
{ "name": "z", "type": "int", "size": 4, "description": "Z coordinate (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" },
{ "name": "mapId", "type": "int", "size": 4, "description": "Map ID (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" },
{ "name": "cliloc", "type": "int", "size": 4, "description": "Description cliloc (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" },
{ "name": "unknown", "type": "int", "size": 4, "description": "Unknown (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" }
]
}
},
{ "name": "flags", "type": "int", "size": 4, "description": "Character list flags (slot limits, features)" },
{ "name": "lastCharSlot", "type": "short", "size": 2, "description": "Last played character slot (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" }
],
"clientVersion": {
"feature": "NewCharacterList",
"notes": "Clients 7.0.13.0+ use extended city format with coordinates"
},
"related": [
{ "id": "0x91", "relationship": "request", "note": "Game login request" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs",
"line": 293
}
},
{
"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": "packetId", "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": "mapWidth", "type": "short", "size": 2, "description": "Map width in tiles" },
{ "name": "mapHeight", "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
}
},
{
"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": "packetId", "type": "byte", "size": 1, "value": "0x55", "description": "Packet identifier" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs",
"line": 231
}
},
{
"id": "0xBD",
"name": "Client Version Request",
"description": "Request for the client to send its version string.",
"direction": "outgoing",
"isDynamic": false,
"size": 3,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBD", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "value": "0x0003", "description": "Packet length" }
],
"related": [
{ "id": "0xBD", "relationship": "response", "note": "Client responds with version string" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs",
"line": 112
},
"notes": "Same packet ID (0xBD) is used for both request (server) and response (client)."
},
{
"id": "0xB9",
"name": "Supported Features",
"description": "Informs the client which features are enabled on the server.",
"direction": "outgoing",
"isDynamic": false,
"size": "3 or 5 (client version dependent)",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xB9", "description": "Packet identifier" },
{ "name": "features", "type": "ushort/uint", "size": "2 or 4", "description": "Feature flags bitmask. Extended (4 bytes) for newer clients." }
],
"clientVersion": {
"feature": "ExtendedSupportedFeatures",
"notes": "Clients with ExtendedSupportedFeatures use 4-byte flags instead of 2-byte"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs",
"line": 140
}
},
{
"id": "0x85",
"name": "Character Delete Result",
"description": "Result of a character deletion request.",
"direction": "outgoing",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x85", "description": "Packet identifier" },
{ "name": "result", "type": "byte", "size": 1, "description": "Result: 0=PasswordInvalid, 1=CharNotExist, 2=CharBeingPlayed, 3=CharTooYoung, 4=CharQueued, 5=BadRequest" }
],
"related": [
{ "id": "0x83", "relationship": "request", "note": "The delete request" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs",
"line": 121
}
},
{
"id": "0x53",
"name": "Popup Message",
"description": "Displays a predefined popup message to the client.",
"direction": "outgoing",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x53", "description": "Packet identifier" },
{ "name": "messageId", "type": "byte", "size": 1, "description": "Message ID: 1=CharNoExist, 2=CharExists, 5=CharInWorld, 6=LoginSyncError, 7=IdleWarning" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs",
"line": 131
}
},
{
"id": "0x81",
"name": "Change Character",
"description": "Updates the character list during reconnection. Currently unused.",
"direction": "outgoing",
"isDynamic": true,
"size": "5 + (60 * charCount)",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x81", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "charCount", "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."
},
{
"id": "0x86",
"name": "Character List Update",
"description": "Updates the character list after character creation or deletion.",
"direction": "outgoing",
"isDynamic": true,
"size": "4 + (60 * charCount)",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x86", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "charCount", "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
}
}
]
}

View file

@ -0,0 +1,61 @@
{
"category": "Combat",
"packets": [
{
"id": "0x2F",
"name": "Swing",
"description": "Notifies client of a melee swing between two mobiles.",
"direction": "outgoing",
"isDynamic": false,
"size": 10,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x2F", "description": "Packet identifier" },
{ "name": "unknown", "type": "byte", "size": 1, "value": "0x00", "description": "Unknown" },
{ "name": "attackerSerial", "type": "uint", "size": 4, "description": "Serial of attacker" },
{ "name": "defenderSerial", "type": "uint", "size": 4, "description": "Serial of defender" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingCombatPackets.cs",
"line": 23
}
},
{
"id": "0x72",
"name": "Set War Mode",
"description": "Sets the client's war/peace mode state.",
"direction": "outgoing",
"isDynamic": false,
"size": 5,
"fields": [
{ "name": "packetId", "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" }
],
"related": [
{ "id": "0x72", "relationship": "request", "note": "Set War Mode from client" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingCombatPackets.cs",
"line": 40
}
},
{
"id": "0xAA",
"name": "Change Combatant",
"description": "Notifies client of current combat target.",
"direction": "outgoing",
"isDynamic": false,
"size": 5,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xAA", "description": "Packet identifier" },
{ "name": "combatantSerial", "type": "uint", "size": 4, "description": "Serial of current combatant (0 = none)" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingCombatPackets.cs",
"line": 43
}
}
]
}

View file

@ -0,0 +1,161 @@
{
"category": "Container",
"packets": [
{
"id": "0x24",
"name": "Display Container",
"description": "Opens a container gump on the client.",
"direction": "outgoing",
"isDynamic": false,
"size": "7 (pre-HS) or 9 (HS+)",
"variants": [
{
"version": "pre-HighSeas",
"name": "Classic",
"size": 7,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x24", "description": "Packet identifier" },
{ "name": "containerSerial", "type": "uint", "size": 4, "description": "Serial of the container" },
{ "name": "gumpId", "type": "ushort", "size": 2, "description": "Gump graphic ID" }
]
},
{
"version": "HighSeas+",
"name": "High Seas Extended",
"condition": "Client version >= 7.0.9.0 (HighSeas)",
"size": 9,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x24", "description": "Packet identifier" },
{ "name": "containerSerial", "type": "uint", "size": 4, "description": "Serial of the container" },
{ "name": "gumpId", "type": "ushort", "size": 2, "description": "Gump graphic ID" },
{ "name": "containerType", "type": "short", "size": 2, "value": "0x007D", "description": "Container type (125)" }
]
}
],
"clientVersion": {
"feature": "HighSeas adds containerType field"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs",
"line": 108
}
},
{
"id": "0x25",
"name": "Container Content Update",
"description": "Updates a single item in a container.",
"direction": "outgoing",
"isDynamic": false,
"size": "20 (pre-6017) or 21 (6017+)",
"variants": [
{
"version": "pre-6017",
"name": "Classic",
"size": 20,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x25", "description": "Packet identifier" },
{ "name": "itemSerial", "type": "uint", "size": 4, "description": "Serial of the item" },
{ "name": "itemId", "type": "ushort", "size": 2, "description": "Item graphic ID" },
{ "name": "itemIdOffset", "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": "containerSerial", "type": "uint", "size": 4, "description": "Serial of parent container" },
{ "name": "hue", "type": "ushort", "size": 2, "description": "Item hue" }
]
},
{
"version": "6017+",
"name": "Container Grid Lines",
"condition": "Client version >= 6.0.1.7 (ContainerGridLines)",
"size": 21,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x25", "description": "Packet identifier" },
{ "name": "itemSerial", "type": "uint", "size": 4, "description": "Serial of the item" },
{ "name": "itemId", "type": "ushort", "size": 2, "description": "Item graphic ID" },
{ "name": "itemIdOffset", "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": "gridLocation", "type": "byte", "size": 1, "description": "Grid slot position" },
{ "name": "containerSerial", "type": "uint", "size": 4, "description": "Serial of parent container" },
{ "name": "hue", "type": "ushort", "size": 2, "description": "Item hue" }
]
}
],
"clientVersion": {
"feature": "ContainerGridLines adds gridLocation byte"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs",
"line": 127
}
},
{
"id": "0x3C",
"name": "Container Content",
"description": "Sends full contents of a container.",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x3C", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "itemCount", "type": "ushort", "size": 2, "description": "Number of items" },
{
"name": "items",
"type": "loop",
"loop": {
"countField": "itemCount",
"itemSize": "19 (pre-6017) or 20 (6017+)",
"fields": [
{ "name": "itemSerial", "type": "uint", "size": 4, "description": "Serial of the item" },
{ "name": "itemId", "type": "ushort", "size": 2, "description": "Item graphic ID" },
{ "name": "itemIdOffset", "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": "gridLocation", "type": "byte", "size": 1, "description": "Grid slot (6017+ only)", "condition": "ContainerGridLines" },
{ "name": "containerSerial", "type": "uint", "size": 4, "description": "Serial of parent container" },
{ "name": "hue", "type": "ushort", "size": 2, "description": "Item hue" }
]
}
}
],
"clientVersion": {
"feature": "ContainerGridLines adds gridLocation byte per item"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs",
"line": 169
}
},
{
"id": "0xBF/0x1B",
"name": "New Spellbook Content",
"description": "Sends spellbook contents using AOS format.",
"direction": "outgoing",
"isDynamic": false,
"size": 23,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "value": "23", "description": "Packet length" },
{ "name": "subCommand", "type": "short", "size": 2, "value": "0x1B", "description": "Subcommand (New Spellbook Content)" },
{ "name": "command", "type": "short", "size": 2, "value": "0x01", "description": "Command (always 1)" },
{ "name": "bookSerial", "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": "spellBits", "type": "ulong", "size": 8, "description": "64-bit mask of known spells (Little Endian)" }
],
"clientVersion": {
"min": "5.0.0a",
"feature": "NewSpellbook"
},
"notes": "Used when Core.AOS && ns.NewSpellbook. Otherwise, old 0x3C format is used.",
"source": {
"file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs",
"line": 46
}
}
]
}

View file

@ -0,0 +1,52 @@
{
"category": "Damage",
"packets": [
{
"id": "0x0B",
"name": "Damage",
"description": "Shows damage dealt to a mobile (client 5.0.0a+).",
"direction": "outgoing",
"isDynamic": false,
"size": 7,
"fields": [
{ "name": "packetId", "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": {
"min": "5.0.0a",
"feature": "DamagePacket"
},
"notes": "For pre-5.0.0a clients, use 0xBF/0x22 instead.",
"source": {
"file": "Projects/Server/Network/Packets/OutgoingDamagePackets.cs",
"line": 34
}
},
{
"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": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "value": "11", "description": "Packet length" },
{ "name": "subCommand", "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": {
"max": "5.0.0a",
"notes": "For clients before DamagePacket feature"
},
"notes": "Damage is capped at 255 for old clients.",
"source": {
"file": "Projects/Server/Network/Packets/OutgoingDamagePackets.cs",
"line": 40
}
}
]
}

View file

@ -0,0 +1,142 @@
{
"category": "Effects",
"packets": [
{
"id": "0x54",
"name": "Sound Effect",
"description": "Plays a sound effect at a location.",
"direction": "outgoing",
"isDynamic": false,
"size": 12,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x54", "description": "Packet identifier" },
{ "name": "flags", "type": "byte", "size": 1, "value": "0x01", "description": "Sound flags" },
{ "name": "soundId", "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
}
},
{
"id": "0x70",
"name": "Screen Effect",
"description": "Triggers a screen-wide visual effect (fade in/out).",
"direction": "outgoing",
"isDynamic": false,
"size": 28,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x70", "description": "Packet identifier" },
{ "name": "effectType", "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": "FadeOut", "description": "Fade screen to black" },
{ "value": 1, "name": "FadeIn", "description": "Fade screen from black" },
{ "value": 2, "name": "LightFlash", "description": "Light flash effect" },
{ "value": 3, "name": "FadeInOut", "description": "Fade out then in" },
{ "value": 4, "name": "DarkenScreen", "description": "Darken screen" }
]
},
{ "name": "padding2", "type": "byte[]", "size": 16, "description": "Padding (zeros)" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingEffectPackets.cs",
"line": 322
}
},
{
"id": "0xC0",
"name": "Hued Effect",
"description": "Displays a graphical effect with hue and render mode.",
"direction": "outgoing",
"isDynamic": false,
"size": 36,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xC0", "description": "Packet identifier" },
{
"name": "effectType",
"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": "FixedXYZ", "description": "Effect at fixed location" },
{ "value": 3, "name": "FixedFrom", "description": "Effect attached to source" }
]
},
{ "name": "sourceSerial", "type": "uint", "size": 4, "description": "Serial of source entity" },
{ "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of target entity" },
{ "name": "itemId", "type": "short", "size": 2, "description": "Effect graphic ID" },
{ "name": "srcX", "type": "short", "size": 2, "description": "Source X coordinate" },
{ "name": "srcY", "type": "short", "size": 2, "description": "Source Y coordinate" },
{ "name": "srcZ", "type": "sbyte", "size": 1, "description": "Source Z coordinate" },
{ "name": "dstX", "type": "short", "size": 2, "description": "Destination X coordinate" },
{ "name": "dstY", "type": "short", "size": 2, "description": "Destination Y coordinate" },
{ "name": "dstZ", "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": "fixedDirection", "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": "renderMode", "type": "int", "size": 4, "description": "Render mode" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingEffectPackets.cs",
"line": 175
}
},
{
"id": "0xC7",
"name": "Particle Effect",
"description": "Displays an advanced particle effect with extended parameters.",
"direction": "outgoing",
"isDynamic": false,
"size": 49,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xC7", "description": "Packet identifier" },
{ "name": "effectType", "type": "byte", "size": 1, "description": "Effect type (see 0xC0)" },
{ "name": "sourceSerial", "type": "uint", "size": 4, "description": "Serial of source entity" },
{ "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of target entity" },
{ "name": "itemId", "type": "short", "size": 2, "description": "Effect graphic ID" },
{ "name": "srcX", "type": "short", "size": 2, "description": "Source X coordinate" },
{ "name": "srcY", "type": "short", "size": 2, "description": "Source Y coordinate" },
{ "name": "srcZ", "type": "sbyte", "size": 1, "description": "Source Z coordinate" },
{ "name": "dstX", "type": "short", "size": 2, "description": "Destination X coordinate" },
{ "name": "dstY", "type": "short", "size": 2, "description": "Destination Y coordinate" },
{ "name": "dstZ", "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": "fixedDirection", "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": "renderMode", "type": "int", "size": 4, "description": "Render mode" },
{ "name": "effect", "type": "short", "size": 2, "description": "Particle effect ID" },
{ "name": "explodeEffect", "type": "short", "size": 2, "description": "Explosion effect ID" },
{ "name": "explodeSound", "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
}
}
]
}

View file

@ -0,0 +1,71 @@
{
"category": "Entity",
"packets": [
{
"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": "packetId", "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
}
},
{
"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": "packetId", "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" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingEntityPackets.cs",
"line": 33
}
},
{
"id": "0xF3",
"name": "World Entity (SA+)",
"description": "Unified entity packet for items, mobiles, and multis. Replaces older item/mobile-specific packets for Stygian Abyss+ clients.",
"direction": "outgoing",
"isDynamic": false,
"size": "24 (pre-HS) or 26 (HS+)",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xF3", "description": "Packet identifier" },
{ "name": "command", "type": "short", "size": 2, "value": "0x0001", "description": "Command (always 1)" },
{ "name": "entityType", "type": "byte", "size": 1, "description": "Entity type: 0=Item, 1=Mobile, 2=Multi" },
{ "name": "serial", "type": "uint", "size": 4, "description": "Entity serial" },
{ "name": "graphicId", "type": "ushort", "size": 2, "description": "Graphic/Body ID" },
{ "name": "direction", "type": "byte", "size": 1, "description": "Direction (mobiles) or 0" },
{ "name": "amountMin", "type": "short", "size": 2, "description": "Minimum amount (items) or 1" },
{ "name": "amountMax", "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, "description": "Unknown (HS+ only)", "condition": "HighSeas" }
],
"clientVersion": {
"min": "7.0.9.0",
"feature": "StygianAbyss"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingEntityPackets.cs",
"line": 88
}
}
]
}

View file

@ -0,0 +1,35 @@
{
"category": "Items",
"packets": [
{
"id": "0x1A",
"name": "World Item",
"description": "Displays an item in the world (pre-Stygian Abyss clients).",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic (14-20 bytes)",
"fields": [
{ "name": "packetId", "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": "itemId", "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" }
],
"notes": "For Stygian Abyss+ clients, use 0xF3 World Entity instead.",
"clientVersion": {
"max": "6.0.14.2",
"notes": "Replaced by 0xF3 for SA+ clients"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingItemPackets.cs",
"line": 24
}
}
]
}

View file

@ -0,0 +1,38 @@
{
"category": "Light",
"packets": [
{
"id": "0x4E",
"name": "Personal Light Level",
"description": "Sets the light level for a specific entity.",
"direction": "outgoing",
"isDynamic": false,
"size": 6,
"fields": [
{ "name": "packetId", "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
}
},
{
"id": "0x4F",
"name": "Global Light Level",
"description": "Sets the global ambient light level for the client.",
"direction": "outgoing",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "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
}
}
]
}

View file

@ -0,0 +1,198 @@
{
"category": "Message",
"packets": [
{
"id": "0x15",
"name": "Follow Message",
"description": "Instructs client to follow one entity with another.",
"direction": "outgoing",
"isDynamic": false,
"size": 9,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x15", "description": "Packet identifier" },
{ "name": "followerSerial", "type": "uint", "size": 4, "description": "Serial of the follower" },
{ "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of the target to follow" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs",
"line": 231
}
},
{
"id": "0x1C",
"name": "ASCII Message",
"description": "Server sends ASCII-encoded message to client.",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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-null", "description": "Message text" }
],
"related": [
{ "id": "0x03", "relationship": "request", "note": "ASCII Speech from client" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs",
"line": 180
}
},
{
"id": "0xAE",
"name": "Unicode Message",
"description": "Server sends Unicode-encoded message to client.",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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": "unicode-be-null", "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
}
},
{
"id": "0xB7",
"name": "Help Response",
"description": "Server sends help text response to client.",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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": "unicode-be-null", "description": "Help text" }
],
"related": [
{ "id": "0xB6", "relationship": "request", "note": "Object Help Request from client" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs",
"line": 263
}
},
{
"id": "0xC1",
"name": "Localized Message",
"description": "Server sends a localized (cliloc) message to client.",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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": "clilocNumber", "type": "int", "size": 4, "description": "Cliloc entry number" },
{ "name": "name", "type": "ascii", "size": 30, "description": "Speaker name" },
{ "name": "arguments", "type": "unicode-le-null", "description": "Tab-separated arguments for cliloc" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs",
"line": 55
}
},
{
"id": "0xC2",
"name": "Prompt",
"description": "Server requests text input from client.",
"direction": "outgoing",
"isDynamic": false,
"size": 21,
"fields": [
{ "name": "packetId", "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": "promptId", "type": "uint", "size": 4, "description": "Prompt ID (same as serial)" },
{ "name": "padding", "type": "byte[]", "size": 10, "description": "Unused padding (zeros)" }
],
"related": [
{ "id": "0x9A", "relationship": "response", "note": "ASCII Prompt Response" },
{ "id": "0xC2", "relationship": "response", "note": "Unicode Prompt Response" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs",
"line": 246
}
},
{
"id": "0xCC",
"name": "Localized Message Affix",
"description": "Server sends a localized message with text prefix/suffix.",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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": "clilocNumber", "type": "int", "size": 4, "description": "Cliloc entry number" },
{
"name": "affixType",
"type": "bitfield",
"size": 1,
"description": "How to apply the affix",
"flags": [
{ "bit": "0x00", "name": "Append", "description": "Append affix to end" },
{ "bit": "0x01", "name": "Prepend", "description": "Prepend affix to start" },
{ "bit": "0x02", "name": "System", "description": "System message style" }
]
},
{ "name": "name", "type": "ascii", "size": 30, "description": "Speaker name" },
{ "name": "affix", "type": "ascii-null", "description": "Text to prepend/append" },
{ "name": "arguments", "type": "unicode-be-null", "description": "Tab-separated arguments for cliloc" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs",
"line": 112
}
}
]
}

View file

@ -0,0 +1,339 @@
{
"category": "Mobile",
"packets": [
{
"id": "0x11",
"name": "Mobile Status",
"description": "Detailed status information for a mobile. Length and content varies based on client version and whether viewing self or others.",
"direction": "outgoing",
"isDynamic": true,
"size": "43-121 bytes (version dependent)",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x11", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" },
{ "name": "name", "type": "ascii", "size": 30, "description": "Mobile name" },
{ "name": "hitsMax", "type": "short", "size": 2, "description": "Maximum hits (normalized to 100 for non-self)" },
{ "name": "hits", "type": "short", "size": 2, "description": "Current hits" },
{ "name": "canBeRenamed", "type": "bool", "size": 1, "description": "Whether the mobile can be renamed by viewer" },
{ "name": "version", "type": "byte", "size": 1, "description": "Status version: 0=compact, 3=basic, 4=AOS, 5=ML, 6=HS" },
{ "name": "female", "type": "bool", "size": 1, "description": "Gender flag (version 1+)", "condition": "version >= 1" },
{ "name": "str", "type": "short", "size": 2, "description": "Strength", "condition": "version >= 1" },
{ "name": "dex", "type": "short", "size": 2, "description": "Dexterity", "condition": "version >= 1" },
{ "name": "int", "type": "short", "size": 2, "description": "Intelligence", "condition": "version >= 1" },
{ "name": "stam", "type": "short", "size": 2, "description": "Current stamina", "condition": "version >= 1" },
{ "name": "stamMax", "type": "short", "size": 2, "description": "Maximum stamina", "condition": "version >= 1" },
{ "name": "mana", "type": "short", "size": 2, "description": "Current mana", "condition": "version >= 1" },
{ "name": "manaMax", "type": "short", "size": 2, "description": "Maximum mana", "condition": "version >= 1" },
{ "name": "gold", "type": "int", "size": 4, "description": "Total gold", "condition": "version >= 1" },
{ "name": "armorRating", "type": "short", "size": 2, "description": "Armor rating (physical resist in AOS+)", "condition": "version >= 1" },
{ "name": "weight", "type": "short", "size": 2, "description": "Current weight", "condition": "version >= 1" },
{ "name": "maxWeight", "type": "short", "size": 2, "description": "Maximum weight", "condition": "version >= 5" },
{ "name": "race", "type": "byte", "size": 1, "description": "Race ID + 1 (0 = no race)", "condition": "version >= 5" },
{ "name": "statCap", "type": "short", "size": 2, "description": "Stat cap", "condition": "version >= 1" },
{ "name": "followers", "type": "byte", "size": 1, "description": "Current followers", "condition": "version >= 1" },
{ "name": "followersMax", "type": "byte", "size": 1, "description": "Maximum followers", "condition": "version >= 1" },
{ "name": "fireResist", "type": "short", "size": 2, "description": "Fire resistance", "condition": "version >= 4" },
{ "name": "coldResist", "type": "short", "size": 2, "description": "Cold resistance", "condition": "version >= 4" },
{ "name": "poisonResist", "type": "short", "size": 2, "description": "Poison resistance", "condition": "version >= 4" },
{ "name": "energyResist", "type": "short", "size": 2, "description": "Energy resistance", "condition": "version >= 4" },
{ "name": "luck", "type": "short", "size": 2, "description": "Luck", "condition": "version >= 4" },
{ "name": "damageMin", "type": "short", "size": 2, "description": "Minimum weapon damage", "condition": "version >= 4" },
{ "name": "damageMax", "type": "short", "size": 2, "description": "Maximum weapon damage", "condition": "version >= 4" },
{ "name": "tithingPoints", "type": "int", "size": 4, "description": "Tithing points", "condition": "version >= 4" },
{ "name": "aosStatus", "type": "short[15]", "size": 30, "description": "Extended AOS status values", "condition": "version >= 6" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 497
}
},
{
"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": "packetId", "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
}
},
{
"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": "packetId", "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": "byte", "size": 1, "description": "Notoriety (0=Innocent, 1=Friend, 2=Gray, 3=Criminal, 4=Enemy, 5=Murderer, 6=Invulnerable)" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 104
}
},
{
"id": "0x78",
"name": "Mobile Incoming",
"description": "Full mobile information including equipped items. Sent when a mobile enters view range.",
"direction": "outgoing",
"isDynamic": true,
"size": "23 + (equipment count * 7-9 bytes)",
"fields": [
{ "name": "packetId", "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": "byte", "size": 1, "description": "Notoriety flag" },
{
"name": "equipment",
"type": "array",
"description": "Equipped items (terminated by 0x00000000)",
"loop": {
"countField": "variable (until terminator)",
"fields": [
{ "name": "itemSerial", "type": "uint", "size": 4, "description": "Item serial (0 = end of list)" },
{ "name": "itemId", "type": "ushort", "size": 2, "description": "Item graphic ID (bit 0x8000 = hue follows for old clients)" },
{ "name": "layer", "type": "byte", "size": 1, "description": "Equipment layer" },
{ "name": "hue", "type": "short", "size": 2, "description": "Item hue (only if bit 0x8000 set or NewMobileIncoming)", "condition": "hue flag or NewMobileIncoming" }
]
}
},
{ "name": "terminator", "type": "int", "size": 4, "value": "0x00000000", "description": "Equipment list terminator" }
],
"clientVersion": {
"feature": "NewMobileIncoming",
"notes": "NewMobileIncoming clients always include hue field for equipment"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 601
}
},
{
"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": "packetId", "type": "byte", "size": 1, "value": "0xA1", "description": "Packet identifier" },
{ "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" },
{ "name": "hitsMax", "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
}
},
{
"id": "0xA2",
"name": "Mobile Mana",
"description": "Updates a mobile's mana points.",
"direction": "outgoing",
"isDynamic": false,
"size": 9,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xA2", "description": "Packet identifier" },
{ "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" },
{ "name": "manaMax", "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
}
},
{
"id": "0xA3",
"name": "Mobile Stamina",
"description": "Updates a mobile's stamina points.",
"direction": "outgoing",
"isDynamic": false,
"size": 9,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xA3", "description": "Packet identifier" },
{ "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" },
{ "name": "stamMax", "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
}
},
{
"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": "packetId", "type": "byte", "size": 1, "value": "0x2D", "description": "Packet identifier" },
{ "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" },
{ "name": "hitsMax", "type": "short", "size": 2, "description": "Maximum hits" },
{ "name": "hits", "type": "short", "size": 2, "description": "Current hits" },
{ "name": "manaMax", "type": "short", "size": 2, "description": "Maximum mana" },
{ "name": "mana", "type": "short", "size": 2, "description": "Current mana" },
{ "name": "stamMax", "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
}
},
{
"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": "packetId", "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
}
},
{
"id": "0x6E",
"name": "Mobile Animation",
"description": "Triggers an animation on a mobile.",
"direction": "outgoing",
"isDynamic": false,
"size": 14,
"fields": [
{ "name": "packetId", "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": "frameCount", "type": "short", "size": 2, "description": "Number of frames" },
{ "name": "repeatCount", "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
}
},
{
"id": "0xE2",
"name": "New Mobile Animation",
"description": "Simplified animation packet for newer clients.",
"direction": "outgoing",
"isDynamic": false,
"size": 10,
"fields": [
{ "name": "packetId", "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": "frameCount", "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
}
},
{
"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": "packetId", "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": "showBar", "type": "short", "size": 2, "value": "0x0001", "description": "Show bar (always 1)" },
{ "name": "healthbarType", "type": "short", "size": 2, "description": "Healthbar type: 1=Poison, 2=Yellow" },
{ "name": "level", "type": "byte", "size": 1, "description": "Level (0=off, 1-4 for poison levels, 1=on for yellow)" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 419
}
},
{
"id": "0xAF",
"name": "Death Animation",
"description": "Triggers the death animation and corpse creation for a mobile.",
"direction": "outgoing",
"isDynamic": false,
"size": 13,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xAF", "description": "Packet identifier" },
{ "name": "killedSerial", "type": "uint", "size": 4, "description": "Serial of the killed mobile" },
{ "name": "corpseSerial", "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
}
},
{
"id": "0xBF",
"subId": "0x0019",
"name": "Bonded Status",
"description": "Indicates whether a mobile (pet) is bonded to its owner.",
"direction": "outgoing",
"isDynamic": false,
"size": 11,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "value": "0x000B", "description": "Packet length (11)" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x0019", "description": "Sub-command for bonded status" },
{ "name": "command", "type": "byte", "size": 1, "value": "0x00", "description": "Command type (0 for bonded)" },
{ "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" },
{ "name": "bonded", "type": "bool", "size": 1, "description": "Bonded status" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 44
}
}
]
}

View file

@ -0,0 +1,101 @@
{
"category": "Movement",
"packets": [
{
"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": "packetId", "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
}
},
{
"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",
"isDynamic": false,
"size": 3,
"fields": [
{ "name": "packetId", "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": "byte", "size": 1, "description": "Player's current notoriety flag (0=Innocent, 1=Friend, 2=Gray/Attackable, 3=Criminal, 4=Enemy, 5=Murderer, 6=Invulnerable)" }
],
"related": [
{ "id": "0x02", "relationship": "request", "note": "The movement request that was accepted" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMovementPackets.cs",
"line": 42
}
},
{
"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": "packetId", "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
}
},
{
"id": "0xBF",
"subId": "0x0026",
"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": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "value": "0x0006", "description": "Packet length" },
{ "name": "subCommand", "type": "ushort", "size": 2, "value": "0x0026", "description": "Sub-command for speed control" },
{ "name": "speedSetting", "type": "byte", "size": 1, "description": "Speed setting: 0=Disable (normal), 1=Mount speed, 2=Walk only" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMovementPackets.cs",
"line": 31
}
},
{
"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": "packetId", "type": "byte", "size": 1, "value": "0xF2", "description": "Packet identifier" },
{ "name": "tickCount1", "type": "long", "size": 8, "description": "Server tick count" },
{ "name": "tickCount2", "type": "long", "size": 8, "description": "Server tick count" },
{ "name": "tickCount3", "type": "long", "size": 8, "description": "Server tick count" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMovementPackets.cs",
"line": 63
}
}
]
}

View file

@ -0,0 +1,482 @@
{
"category": "Player",
"packets": [
{
"id": "0x23",
"name": "Drag Effect",
"description": "Displays a drag/drop visual effect between two points.",
"direction": "outgoing",
"isDynamic": false,
"size": 26,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x23", "description": "Packet identifier" },
{ "name": "itemId", "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": "srcSerial", "type": "uint", "size": 4, "description": "Source entity serial" },
{ "name": "srcX", "type": "short", "size": 2, "description": "Source X coordinate" },
{ "name": "srcY", "type": "short", "size": 2, "description": "Source Y coordinate" },
{ "name": "srcZ", "type": "sbyte", "size": 1, "description": "Source Z coordinate" },
{ "name": "dstSerial", "type": "uint", "size": 4, "description": "Destination entity serial" },
{ "name": "dstX", "type": "short", "size": 2, "description": "Destination X coordinate" },
{ "name": "dstY", "type": "short", "size": 2, "description": "Destination Y coordinate" },
{ "name": "dstZ", "type": "sbyte", "size": 1, "description": "Destination Z coordinate" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 198
}
},
{
"id": "0x27",
"name": "Lift Reject",
"description": "Server rejects a lift/pick up request.",
"direction": "outgoing",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x27", "description": "Packet identifier" },
{
"name": "reason",
"type": "enum",
"enumType": "sequential",
"size": 1,
"description": "Rejection reason",
"values": [
{ "value": 0, "name": "CannotLift", "description": "You cannot pick that up" },
{ "value": 1, "name": "OutOfRange", "description": "That is out of range" },
{ "value": 2, "name": "OutOfSight", "description": "That is out of sight" },
{ "value": 3, "name": "TryToSteal", "description": "That does not belong to you" },
{ "value": 4, "name": "AreHolding", "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
}
},
{
"id": "0x2C",
"name": "Death Status",
"description": "Notifies client of death/resurrection state.",
"direction": "outgoing",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "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
}
},
{
"id": "0x38",
"name": "Pathfind Message",
"description": "Instructs client to pathfind to a location.",
"direction": "outgoing",
"isDynamic": false,
"size": 7,
"fields": [
{ "name": "packetId", "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
}
},
{
"id": "0x3A",
"name": "Skills Update",
"description": "Sends full skills list or single skill update to client.",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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": "FullNoCaps", "description": "Full list without caps" },
{ "value": "0x02", "name": "FullWithCaps", "description": "Full list with skill caps" },
{ "value": "0xDF", "name": "SingleWithCaps", "description": "Single skill update with cap" },
{ "value": "0xFF", "name": "SingleNoCaps", "description": "Single skill update" }
]
},
{
"name": "skills",
"type": "loop",
"loop": {
"until": "skillId == 0",
"fields": [
{ "name": "skillId", "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)" }
]
}
}
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 121
}
},
{
"id": "0x5B",
"name": "Current Time",
"description": "Sends current server time to client.",
"direction": "outgoing",
"isDynamic": false,
"size": 4,
"fields": [
{ "name": "packetId", "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
}
},
{
"id": "0x65",
"name": "Weather",
"description": "Sets weather conditions for client.",
"direction": "outgoing",
"isDynamic": false,
"size": 4,
"fields": [
{ "name": "packetId", "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": "StormBrewing", "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
}
},
{
"id": "0x6D",
"name": "Play Music",
"description": "Plays background music on client.",
"direction": "outgoing",
"isDynamic": false,
"size": 3,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x6D", "description": "Packet identifier" },
{ "name": "musicId", "type": "short", "size": 2, "description": "Music track ID (0x1FFF = stop)" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 275
}
},
{
"id": "0x73",
"name": "Ping Ack",
"description": "Server acknowledges ping request.",
"direction": "outgoing",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x73", "description": "Packet identifier" },
{ "name": "sequence", "type": "byte", "size": 1, "description": "Ping sequence (echoed from request)" }
],
"related": [
{ "id": "0x73", "relationship": "request", "note": "Ping Request from client" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 336
}
},
{
"id": "0x76",
"name": "Server Change",
"description": "Notifies client of server/map transition.",
"direction": "outgoing",
"isDynamic": false,
"size": 16,
"fields": [
{ "name": "packetId", "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": "mapWidth", "type": "short", "size": 2, "description": "Map width" },
{ "name": "mapHeight", "type": "short", "size": 2, "description": "Map height" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 100
}
},
{
"id": "0x7B",
"name": "Sequence",
"description": "Sends sequence number to client for synchronization.",
"direction": "outgoing",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "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
}
},
{
"id": "0x88",
"name": "Display Paperdoll",
"description": "Opens paperdoll window for a mobile.",
"direction": "outgoing",
"isDynamic": false,
"size": 66,
"fields": [
{ "name": "packetId", "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": "0x01", "name": "Warmode", "description": "Mobile is in war mode" },
{ "bit": "0x02", "name": "CanLift", "description": "Viewer can lift equipment" }
]
}
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 247
}
},
{
"id": "0x95",
"name": "Display Hue Picker",
"description": "Opens hue picker dialog on client.",
"direction": "outgoing",
"isDynamic": false,
"size": 9,
"fields": [
{ "name": "packetId", "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": "itemId", "type": "short", "size": 2, "description": "Item graphic to preview hue on" }
],
"related": [
{ "id": "0x95", "relationship": "response", "note": "Hue Picker Response from client" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 338
}
},
{
"id": "0xA5",
"name": "Launch Browser",
"description": "Opens a URL in client's web browser.",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xA5", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "description": "Packet length" },
{ "name": "url", "type": "ascii-null", "description": "URL to open" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 180
}
},
{
"id": "0xA6",
"name": "Scroll Message",
"description": "Displays a scrollable tips/message window.",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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": "tipNumber", "type": "int", "size": 4, "description": "Tip/message number" },
{ "name": "textLength", "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
}
},
{
"id": "0xB8",
"name": "Display Profile",
"description": "Displays a mobile's profile.",
"direction": "outgoing",
"isDynamic": true,
"size": "Dynamic",
"fields": [
{ "name": "packetId", "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-null", "description": "Profile header" },
{ "name": "footer", "type": "unicode-be-null", "description": "Profile footer" },
{ "name": "body", "type": "unicode-be-null", "description": "Profile body text" }
],
"related": [
{ "id": "0xB8", "relationship": "request", "note": "Profile Request from client" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 66
}
},
{
"id": "0xBC",
"name": "Season Change",
"description": "Changes the visual season on client.",
"direction": "outgoing",
"isDynamic": false,
"size": 3,
"fields": [
{ "name": "packetId", "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": "playSound", "type": "bool", "size": 1, "description": "Play season change sound" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 244
}
},
{
"id": "0xBF/0x19",
"name": "Stat Lock Info",
"description": "Sends stat lock states (STR/DEX/INT) to client.",
"direction": "outgoing",
"isDynamic": false,
"size": 12,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" },
{ "name": "length", "type": "ushort", "size": 2, "value": "12", "description": "Packet length" },
{ "name": "subCommand", "type": "short", "size": 2, "value": "0x19", "description": "Subcommand (Stat Lock Info)" },
{ "name": "type", "type": "byte", "size": 1, "value": "0x02", "description": "Type (2 = stat locks)" },
{ "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" },
{ "name": "unknown", "type": "byte", "size": 1, "value": "0x00", "description": "Unknown" },
{
"name": "lockBits",
"type": "bitfield",
"size": 1,
"description": "Packed lock states",
"flags": [
{ "bit": "0x30", "name": "StrLock", "description": "Strength lock (bits 4-5)" },
{ "bit": "0x0C", "name": "DexLock", "description": "Dexterity lock (bits 2-3)" },
{ "bit": "0x03", "name": "IntLock", "description": "Intelligence lock (bits 0-1)" }
],
"notes": "Each lock is 2 bits: 0=Up, 1=Down, 2=Locked"
}
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 36
}
},
{
"id": "0xC8",
"name": "Change Update Range",
"description": "Sets the client's update range.",
"direction": "outgoing",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "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
}
},
{
"id": "0xD1",
"name": "Logout Ack",
"description": "Server acknowledges logout request.",
"direction": "outgoing",
"isDynamic": false,
"size": 2,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0xD1", "description": "Packet identifier" },
{ "name": "ack", "type": "byte", "size": 1, "value": "0x01", "description": "Acknowledgment (1 = OK)" }
],
"related": [
{ "id": "0xD1", "relationship": "request", "note": "Logout Request from client" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 94
}
}
]
}

View file

@ -0,0 +1,90 @@
{
"category": "Targeting",
"packets": [
{
"id": "0x6C",
"name": "Target Request",
"description": "Requests the client to select a target.",
"direction": "outgoing",
"isDynamic": false,
"size": 19,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x6C", "description": "Packet identifier" },
{ "name": "allowGround", "type": "bool", "size": 1, "description": "True = allow ground targeting" },
{ "name": "targetId", "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)" }
],
"related": [
{ "id": "0x6C", "relationship": "response", "note": "Target Response from client" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingTargetPackets.cs",
"line": 57
}
},
{
"id": "0x99",
"name": "Multi Target Request",
"description": "Requests the client to place a multi (house/boat) structure.",
"direction": "outgoing",
"isDynamic": false,
"size": "26 (pre-HS) or 30 (HS+)",
"variants": [
{
"version": "pre-HighSeas",
"name": "Classic",
"size": 26,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x99", "description": "Packet identifier" },
{ "name": "allowGround", "type": "bool", "size": 1, "description": "Allow ground targeting" },
{ "name": "targetId", "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": "multiId", "type": "short", "size": 2, "description": "Multi graphic ID" },
{ "name": "offsetX", "type": "short", "size": 2, "description": "X offset for placement" },
{ "name": "offsetY", "type": "short", "size": 2, "description": "Y offset for placement" },
{ "name": "offsetZ", "type": "short", "size": 2, "description": "Z offset for placement" }
]
},
{
"version": "HighSeas+",
"name": "High Seas Extended",
"condition": "Client version >= 7.0.9.0 (HighSeas)",
"size": 30,
"fields": [
{ "name": "packetId", "type": "byte", "size": 1, "value": "0x99", "description": "Packet identifier" },
{ "name": "allowGround", "type": "bool", "size": 1, "description": "Allow ground targeting" },
{ "name": "targetId", "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": "multiId", "type": "short", "size": 2, "description": "Multi graphic ID" },
{ "name": "offsetX", "type": "short", "size": 2, "description": "X offset for placement" },
{ "name": "offsetY", "type": "short", "size": 2, "description": "Y offset for placement" },
{ "name": "offsetZ", "type": "short", "size": 2, "description": "Z offset for placement" },
{ "name": "unknown", "type": "int", "size": 4, "description": "Unknown (HighSeas extension)" }
]
}
],
"clientVersion": {
"feature": "HighSeas adds 4 bytes"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingTargetPackets.cs",
"line": 23
}
}
]
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,136 @@
# build-packets.ps1
# Combines all packet JSON files with the HTML template to generate the final documentation page.
#
# Usage:
# .\build-packets.ps1
# .\build-packets.ps1 -OutputPath "C:\custom\output\packets.html"
param(
[string]$OutputPath = ""
)
$ErrorActionPreference = "Stop"
# Determine paths
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$rootDir = (Resolve-Path (Join-Path $scriptDir "..\..")).Path
$dataDir = Join-Path $rootDir "Distribution\Data"
$packetsDir = Join-Path $dataDir "packets"
$templateFile = Join-Path $dataDir "packets.html"
if (-not $OutputPath) {
$OutputPath = Join-Path $dataDir "web\packets.html"
}
Write-Host "ModernUO Packet Documentation Builder" -ForegroundColor Cyan
Write-Host "======================================" -ForegroundColor Cyan
Write-Host ""
# Verify template exists
if (-not (Test-Path $templateFile)) {
Write-Error "Template file not found: $templateFile"
exit 1
}
# Collect all packet JSON files
$allPackets = @{
incoming = @()
outgoing = @()
}
$incomingDir = Join-Path $packetsDir "incoming"
$outgoingDir = Join-Path $packetsDir "outgoing"
# Read incoming packets
if (Test-Path $incomingDir) {
$incomingFiles = Get-ChildItem "$incomingDir\*.json" -ErrorAction SilentlyContinue
foreach ($file in $incomingFiles) {
Write-Host " Reading: $($file.Name)" -ForegroundColor Gray
try {
$content = Get-Content $file.FullName -Raw -Encoding UTF8
$data = $content | ConvertFrom-Json
if ($data.packets) {
# Add category to each packet if not present
foreach ($packet in $data.packets) {
if (-not $packet.category -and $data.category) {
$packet | Add-Member -NotePropertyName "category" -NotePropertyValue $data.category -Force
}
}
$allPackets.incoming += $data.packets
}
} catch {
Write-Warning "Failed to parse $($file.Name): $_"
}
}
Write-Host " Found $($allPackets.incoming.Count) incoming packets" -ForegroundColor Green
} else {
Write-Host " No incoming packets directory found" -ForegroundColor Yellow
}
# Read outgoing packets
if (Test-Path $outgoingDir) {
$outgoingFiles = Get-ChildItem "$outgoingDir\*.json" -ErrorAction SilentlyContinue
foreach ($file in $outgoingFiles) {
Write-Host " Reading: $($file.Name)" -ForegroundColor Gray
try {
$content = Get-Content $file.FullName -Raw -Encoding UTF8
$data = $content | ConvertFrom-Json
if ($data.packets) {
# Add category to each packet if not present
foreach ($packet in $data.packets) {
if (-not $packet.category -and $data.category) {
$packet | Add-Member -NotePropertyName "category" -NotePropertyValue $data.category -Force
}
}
$allPackets.outgoing += $data.packets
}
} catch {
Write-Warning "Failed to parse $($file.Name): $_"
}
}
Write-Host " Found $($allPackets.outgoing.Count) outgoing packets" -ForegroundColor Green
} else {
Write-Host " No outgoing packets directory found" -ForegroundColor Yellow
}
$totalPackets = $allPackets.incoming.Count + $allPackets.outgoing.Count
Write-Host ""
Write-Host "Total packets: $totalPackets" -ForegroundColor Cyan
if ($totalPackets -eq 0) {
Write-Warning "No packets found! The output will have empty documentation."
}
# Convert to JSON
$packetsJson = $allPackets | ConvertTo-Json -Depth 20 -Compress
# HTML entity escape the JSON to safely embed in HTML
$packetsJson = $packetsJson -replace '<', '&lt;' -replace '>', '&gt;'
# Read template and inject JSON
Write-Host ""
Write-Host "Reading template..." -ForegroundColor Gray
$template = Get-Content $templateFile -Raw -Encoding UTF8
Write-Host "Injecting packet data..." -ForegroundColor Gray
$output = $template -replace '<!-- PACKETS -->', $packetsJson
# Ensure output directory exists
$outputDir = Split-Path $OutputPath -Parent
if (-not (Test-Path $outputDir)) {
Write-Host "Creating output directory: $outputDir" -ForegroundColor Gray
New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
}
# Write output
Write-Host "Writing output..." -ForegroundColor Gray
$output | Set-Content $OutputPath -Encoding UTF8
$outputSize = (Get-Item $OutputPath).Length
$outputSizeKB = [math]::Round($outputSize / 1024, 2)
Write-Host ""
Write-Host "Success!" -ForegroundColor Green
Write-Host " Output: $OutputPath" -ForegroundColor White
Write-Host " Size: $outputSizeKB KB" -ForegroundColor White
Write-Host " Packets: $totalPackets" -ForegroundColor White