1 line
No EOL
55 KiB
JavaScript
1 line
No EOL
55 KiB
JavaScript
"use strict";(globalThis.webpackChunkwebsite=globalThis.webpackChunkwebsite||[]).push([[203],{7965(e,s,d){d.r(s),d.d(s,{assets:()=>l,contentTitle:()=>c,default:()=>a,frontMatter:()=>t,metadata:()=>n,toc:()=>h});const n=JSON.parse('{"id":"getting-started/configuration","title":"Configuration","description":"ModernUO is self-configuring. On first launch, the server walks you through an interactive setup and generates all required configuration files. After that, settings take effect on the next server restart (unless otherwise noted).","source":"@site/content/getting-started/configuration.mdx","sourceDirName":"getting-started","slug":"/getting-started/configuration","permalink":"/docs/getting-started/configuration","draft":false,"unlisted":false,"editUrl":"https://github.com/modernuo/ModernUO/tree/main/website/content/getting-started/configuration.mdx","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"sidebar_position":4,"title":"Configuration"},"sidebar":"docsSidebar","previous":{"title":"Starting the Server","permalink":"/docs/getting-started/starting"},"next":{"title":"Items & Mobiles","permalink":"/docs/development/items-and-mobiles"}}');var r=d(4848),i=d(8453);d(3457);const t={sidebar_position:4,title:"Configuration"},c="Configuration",l={},h=[{value:"Configuration Files",id:"configuration-files",level:2},{value:"modernuo.json Structure",id:"modernuojson-structure",level:2},{value:"Feature Flags",id:"feature-flags",level:2},{value:"Built-in Flags",id:"built-in-flags",level:3},{value:"Additional Blocking",id:"additional-blocking",level:3},{value:"Settings Reference",id:"settings-reference",level:2},{value:"Movement",id:"movement",level:3},{value:"Movement Throttling",id:"movement-throttling",level:3},{value:"Client Verification",id:"client-verification",level:3},{value:"Accounts and Security",id:"accounts-and-security",level:3},{value:"World Saves",id:"world-saves",level:3},{value:"Archives and Backups",id:"archives-and-backups",level:3},{value:"Crash Guard",id:"crash-guard",level:3},{value:"Stats and Stamina",id:"stats-and-stamina",level:3},{value:"Combat and Systems",id:"combat-and-systems",level:3},{value:"Player Systems",id:"player-systems",level:3},{value:"Game Systems",id:"game-systems",level:3},{value:"Network",id:"network",level:3},{value:"Server Listing",id:"server-listing",level:3},{value:"Maps and Client Data",id:"maps-and-client-data",level:3},{value:"Miscellaneous",id:"miscellaneous",level:3},{value:"Other Configuration Files",id:"other-configuration-files",level:2},{value:"expansion.json",id:"expansionjson",level:3},{value:"antimacro.json",id:"antimacrojson",level:3},{value:"email-settings.json",id:"email-settingsjson",level:3},{value:"server-access.json",id:"server-accessjson",level:3},{value:"throttles.json",id:"throttlesjson",level:3},{value:"Custom Configuration",id:"custom-configuration",level:2}];function o(e){const s={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.header,{children:(0,r.jsx)(s.h1,{id:"configuration",children:"Configuration"})}),"\n",(0,r.jsx)(s.p,{children:"ModernUO is self-configuring. On first launch, the server walks you through an interactive setup and generates all required configuration files. After that, settings take effect on the next server restart (unless otherwise noted)."}),"\n",(0,r.jsxs)(s.p,{children:["All configuration files live in the ",(0,r.jsx)(s.code,{children:"Configuration/"})," folder inside your ",(0,r.jsx)(s.code,{children:"Distribution"})," directory."]}),"\n",(0,r.jsx)(s.h2,{id:"configuration-files",children:"Configuration Files"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"File"}),(0,r.jsx)(s.th,{children:"Purpose"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"modernuo.json"})}),(0,r.jsxs)(s.td,{children:["Main server settings -- listeners, data paths, and all ",(0,r.jsx)(s.code,{children:"settings"})," key-value pairs"]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"expansion.json"})}),(0,r.jsx)(s.td,{children:"Target expansion, enabled maps, and feature/client flags"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"antimacro.json"})}),(0,r.jsx)(s.td,{children:"Anti-macro skill gain rules (per-skill toggle, area size, cooldowns)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"email-settings.json"})}),(0,r.jsx)(s.td,{children:"SMTP and crash report email configuration"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"server-access.json"})}),(0,r.jsx)(s.td,{children:"Protected accounts that auto-reset to Owner access on login"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"throttles.json"})}),(0,r.jsx)(s.td,{children:"Per-packet throttle delays in milliseconds"})]})]})]}),"\n",(0,r.jsx)(s.admonition,{type:"tip",children:(0,r.jsxs)(s.p,{children:["If you ever want to re-run the first-launch setup wizard, delete ",(0,r.jsx)(s.code,{children:"modernuo.json"})," and ",(0,r.jsx)(s.code,{children:"expansion.json"}),", then restart the server."]})}),"\n",(0,r.jsx)(s.h2,{id:"modernuojson-structure",children:"modernuo.json Structure"}),"\n",(0,r.jsx)(s.p,{children:"The main configuration file has four top-level keys:"}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:'{\n "assemblyDirectories": ["./Assemblies"],\n "dataDirectories": ["/path/to/uo/game/files"],\n "listeners": ["0.0.0.0:2593"],\n "settings": {\n "accountHandler.maxAccountsPerIP": "1",\n "autosave.enabled": "true",\n "autosave.saveDelay": "00:05:00"\n }\n}\n'})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Type"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"assemblyDirectories"})}),(0,r.jsx)(s.td,{children:"string array"}),(0,r.jsx)(s.td,{children:"Directories to search for additional plugin assemblies"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"dataDirectories"})}),(0,r.jsx)(s.td,{children:"string array"}),(0,r.jsxs)(s.td,{children:["Paths to Ultima Online game files (",(0,r.jsx)(s.code,{children:".mul"})," / ",(0,r.jsx)(s.code,{children:".uop"}),")"]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"listeners"})}),(0,r.jsx)(s.td,{children:"string array"}),(0,r.jsxs)(s.td,{children:["IP",":port"," endpoints the server binds to"]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"settings"})}),(0,r.jsx)(s.td,{children:"key-value map"}),(0,r.jsx)(s.td,{children:"All configurable settings (string keys and string values)"})]})]})]}),"\n",(0,r.jsx)(s.admonition,{type:"note",children:(0,r.jsxs)(s.p,{children:["All values in the ",(0,r.jsx)(s.code,{children:"settings"})," map are stored as strings. The server parses them to the appropriate type (bool, int, TimeSpan, etc.) at startup. Unrecognized keys are silently ignored."]})}),"\n",(0,r.jsx)(s.h2,{id:"feature-flags",children:"Feature Flags"}),"\n",(0,r.jsxs)(s.p,{children:["ModernUO includes a runtime feature flag system for toggling game mechanics without restarting the server. Feature flags are managed by the ",(0,r.jsx)(s.code,{children:"FeatureFlagManager"})," and stored in the ",(0,r.jsx)(s.code,{children:"Configuration/FeatureFlags/"})," directory."]}),"\n",(0,r.jsx)(s.h3,{id:"built-in-flags",children:"Built-in Flags"}),"\n",(0,r.jsx)(s.p,{children:"These boolean flags are optimized for hot-path checks and are synchronized from UOContent:"}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)(s.strong,{children:"Server-level flags"})," (checked in the core engine):"]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Flag Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"player_trading"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Allow players to trade items"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"pvp_combat"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Allow player-vs-player combat"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"bank_access"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Allow bank box access"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"speedhack_detection"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Enable speed-hack detection via movement analysis"})]})]})]}),"\n",(0,r.jsxs)(s.p,{children:[(0,r.jsx)(s.strong,{children:"Content-level flags"})," (checked in UOContent game logic):"]}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Flag Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"vendor_purchase"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Allow buying from NPC vendors"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"vendor_sell"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Allow selling to NPC vendors"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"player_vendors"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Allow player vendor usage"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"house_placement"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Allow placing new houses"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"boat_placement"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Allow placing new boats"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"bulk_orders"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Allow bulk order deed system"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"passive_detect_hidden"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Allow passive detect hidden skill"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"additional-blocking",children:"Additional Blocking"}),"\n",(0,r.jsx)(s.p,{children:"Beyond boolean flags, the feature flag system also supports blocking specific:"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Gumps"})," -- prevent specific UI dialogs from opening"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Items"})," -- block use, equip, or container access for specific item types"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Skills"})," -- disable individual skills with a custom message"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Spells"})," -- disable individual spells with a custom message"]}),"\n"]}),"\n",(0,r.jsxs)(s.p,{children:["These are managed through in-game admin commands and the feature flag admin gump, and are persisted as JSON files in ",(0,r.jsx)(s.code,{children:"Configuration/FeatureFlags/"}),"."]}),"\n",(0,r.jsx)(s.h2,{id:"settings-reference",children:"Settings Reference"}),"\n",(0,r.jsxs)(s.p,{children:["The tables below document every setting key available in the ",(0,r.jsx)(s.code,{children:"settings"})," section of ",(0,r.jsx)(s.code,{children:"modernuo.json"}),". Default values marked with an expansion name (e.g., ",(0,r.jsx)(s.code,{children:"Core.AOS"}),") mean the default depends on your configured expansion."]}),"\n",(0,r.jsx)(s.h3,{id:"movement",children:"Movement"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movement.delay.runFoot"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"200"})}),(0,r.jsx)(s.td,{children:"Run speed on foot (ms)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movement.delay.runMount"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"100"})}),(0,r.jsx)(s.td,{children:"Run speed while mounted (ms)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movement.delay.walkFoot"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"400"})}),(0,r.jsx)(s.td,{children:"Walk speed on foot (ms)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movement.delay.walkMount"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"200"})}),(0,r.jsx)(s.td,{children:"Walk speed while mounted (ms)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movement.delay.turn"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"0"})}),(0,r.jsx)(s.td,{children:"Delay for turning in place (ms)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movement.delay.npcMinIdle"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"15"})}),(0,r.jsx)(s.td,{children:"Minimum idle time for NPCs (seconds)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movement.delay.npcMaxIdle"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"25"})}),(0,r.jsx)(s.td,{children:"Maximum idle time for NPCs (seconds)"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"movement-throttling",children:"Movement Throttling"}),"\n",(0,r.jsx)(s.p,{children:"The movement throttle system uses RTT-based credit buffering to absorb network jitter while detecting speed hacks through movement rate analysis."}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movementThrottle.debugLogging"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Enable debug logging for movement throttle decisions"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movementThrottle.maxCredit"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"200"})}),(0,r.jsx)(s.td,{children:"Maximum credit buffer for timing jitter (ms)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movementThrottle.hardQueueLimit"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"10"})}),(0,r.jsx)(s.td,{children:"Reject and clear movement queue at this depth"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movementThrottle.movementHistorySize"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"20"})}),(0,r.jsx)(s.td,{children:"Circular buffer size for rate analysis"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movementThrottle.minSamplesForRate"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"8"})}),(0,r.jsx)(s.td,{children:"Minimum movements before calculating speed"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movementThrottle.suspiciousRateThreshold"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"1.05"})}),(0,r.jsx)(s.td,{children:"Flag as suspicious at 5% over expected speed"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"movementThrottle.definiteRateThreshold"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"1.10"})}),(0,r.jsx)(s.td,{children:"Flag as definite hack at 10% over expected speed"})]})]})]}),"\n",(0,r.jsx)(s.admonition,{type:"note",children:(0,r.jsxs)(s.p,{children:["Most movement throttle settings are auto-tuned and rarely need manual adjustment. The ",(0,r.jsx)(s.code,{children:"debugLogging"})," flag is useful for diagnosing false positives."]})}),"\n",(0,r.jsx)(s.h3,{id:"client-verification",children:"Client Verification"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"clientVerification.enable"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Enable client version verification"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"clientVerification.ageLeniency"})}),(0,r.jsxs)(s.td,{children:[(0,r.jsx)(s.code,{children:"10.00:00:00"})," (10 days)"]}),(0,r.jsx)(s.td,{children:"Grace period for new accounts before enforcing version checks"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"clientVerification.gameTimeLeniency"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"1.01:00:00"})}),(0,r.jsx)(s.td,{children:"Grace period based on game time played"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"clientVerification.invalidClientResponse"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Kick"})}),(0,r.jsxs)(s.td,{children:["Action on invalid client: ",(0,r.jsx)(s.code,{children:"Kick"}),", ",(0,r.jsx)(s.code,{children:"LenientKick"}),", ",(0,r.jsx)(s.code,{children:"Annoy"}),", or ",(0,r.jsx)(s.code,{children:"None"})]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"clientVerification.kickDelay"})}),(0,r.jsxs)(s.td,{children:[(0,r.jsx)(s.code,{children:"00:00:20"})," (20s)"]}),(0,r.jsx)(s.td,{children:"Delay before kicking an invalid client"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"clientVerification.minRequired"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"null"})}),(0,r.jsxs)(s.td,{children:["Minimum allowed client version (e.g., ",(0,r.jsx)(s.code,{children:"7.0.0.0"}),")"]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"clientVerification.maxRequired"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"null"})}),(0,r.jsx)(s.td,{children:"Maximum allowed client version"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"clientVerification.allowedClientTypes"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Classic | SA"})}),(0,r.jsx)(s.td,{children:"Allowed client types bitmask"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"clientData.clientVersion"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"null"})}),(0,r.jsx)(s.td,{children:"Override the expected client version"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"accounts-and-security",children:"Accounts and Security"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"accountHandler.enableAutoAccountCreation"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Create accounts automatically on first login"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"accountHandler.enablePlayerPasswordCommand"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Allow players to change password via in-game command"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"accountHandler.maxAccountsPerIP"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"1"})}),(0,r.jsx)(s.td,{children:"Maximum accounts allowed per IP address"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"accountSecurity.encryptionAlgorithm"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Argon2"})}),(0,r.jsxs)(s.td,{children:["Password hashing algorithm (",(0,r.jsx)(s.code,{children:"SHA2"}),", ",(0,r.jsx)(s.code,{children:"PBKDF2"}),", or ",(0,r.jsx)(s.code,{children:"Argon2"}),")"]})]})]})]}),"\n",(0,r.jsx)(s.admonition,{type:"note",children:(0,r.jsxs)(s.p,{children:["Algorithms below ",(0,r.jsx)(s.code,{children:"SHA2"})," (such as ",(0,r.jsx)(s.code,{children:"MD5"}),", ",(0,r.jsx)(s.code,{children:"SHA1"}),", ",(0,r.jsx)(s.code,{children:"None"}),") are rejected at startup. They exist only for automatic password migration from legacy RunUO/ServUO databases."]})}),"\n",(0,r.jsx)(s.h3,{id:"world-saves",children:"World Saves"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"world.savePath"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Saves"})}),(0,r.jsx)(s.td,{children:"Directory for world save files (relative to Distribution)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"world.tempSavePath"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"temp"})}),(0,r.jsx)(s.td,{children:"Temporary directory during save operations"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"world.useMultithreadedSaves"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Use background threads for serialization during saves"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"world.enableAutoRestart"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Automatically restart the server after a crash or shutdown"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autosave.enabled"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Enable automatic world saves"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autosave.saveDelay"})}),(0,r.jsxs)(s.td,{children:[(0,r.jsx)(s.code,{children:"00:05:00"})," (5 min)"]}),(0,r.jsx)(s.td,{children:"Interval between automatic saves"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autosave.warningDelay"})}),(0,r.jsxs)(s.td,{children:[(0,r.jsx)(s.code,{children:"00:00:00"})," (0)"]}),(0,r.jsx)(s.td,{children:"Broadcast a warning this long before each save (0 = no warning)"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"archives-and-backups",children:"Archives and Backups"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.archiveLocally"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Archive saves to a local directory"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.archivePath"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Archives"})}),(0,r.jsx)(s.td,{children:"Directory for compressed save archives"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.backupPath"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Backups"})}),(0,r.jsx)(s.td,{children:"Directory for backup copies"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.compressionLevel"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"3"})}),(0,r.jsx)(s.td,{children:"Zstd compression level (1-19)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.enableArchivePruning"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Automatically prune old archives based on retention policy"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.verifyArchives"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Verify archive integrity after creation"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.retryCount"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"3"})}),(0,r.jsx)(s.td,{children:"Number of retries on archive failure"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.retryDelayMs"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"500"})}),(0,r.jsx)(s.td,{children:"Delay between retries (ms)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.backupMaxAge"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"30"})}),(0,r.jsx)(s.td,{children:"Maximum age of backup files in days"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.hourlyRetention"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"24"})}),(0,r.jsx)(s.td,{children:"Number of hourly archives to keep"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.dailyRetention"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"30"})}),(0,r.jsx)(s.td,{children:"Number of daily archives to keep"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"autoArchive.monthlyRetention"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"12"})}),(0,r.jsx)(s.td,{children:"Number of monthly archives to keep"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"crash-guard",children:"Crash Guard"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"crashGuard.enabled"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Enable the crash guard system"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"crashGuard.saveBackup"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Save a backup on crash"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"crashGuard.restartServer"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Attempt to restart after a crash"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"crashGuard.generateReport"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Generate a crash report file"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"stats-and-stamina",children:"Stats and Stamina"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Stat Gain:"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stats.statMax"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.LBR ? 125 : 100"})}),(0,r.jsx)(s.td,{children:"Maximum value for a single stat"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stats.gainChanceMultiplier"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"1.0"})}),(0,r.jsx)(s.td,{children:"Multiplier for stat gain chance"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stats.primaryStatGainChance"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"0.75"})}),(0,r.jsx)(s.td,{children:"Chance to gain in the primary stat"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stats.gainDelay"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.ML ? 0.05m : 10m"})}),(0,r.jsx)(s.td,{children:"Cooldown between stat gain checks"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stats.petGainDelay"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"5m"})}),(0,r.jsx)(s.td,{children:"Cooldown between pet stat gain checks"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stats.usePub45StatGain"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.ML"})}),(0,r.jsx)(s.td,{children:"Use Publish 45 stat gain system"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Stamina System:"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stamina.cannotRunWhenFatigued"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"!Core.AOS"})}),(0,r.jsx)(s.td,{children:"Prevent running at zero stamina"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stamina.cannotWalkWhenFatigued"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Prevent walking at zero stamina"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stamina.stonesPerOverweightLoss"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"25"})}),(0,r.jsx)(s.td,{children:"Stones of weight per stamina loss tick"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stamina.stonesOverweightAllowance"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"4"})}),(0,r.jsx)(s.td,{children:"Extra stones allowed before overweight penalty"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stamina.baseOverweightLoss"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"5"})}),(0,r.jsx)(s.td,{children:"Base stamina loss per overweight tick"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stamina.additionalLossWhenBelow"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"0.10"})}),(0,r.jsx)(s.td,{children:"Extra loss rate when stamina is below this fraction"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stamina.enableMountStamina"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Enable stamina drain while mounted"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stamina.useMountStaminaOnlyWhenOverloaded"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.SA"})}),(0,r.jsx)(s.td,{children:"Only drain mount stamina when overloaded"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stamina.globalEtherealMountStamina"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.ML"})}),(0,r.jsx)(s.td,{children:"Apply stamina drain to ethereal mounts"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"combat-and-systems",children:"Combat and Systems"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"melee.enableInstaHit"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"!Core.UOR"})}),(0,r.jsx)(s.td,{children:"Enable instant first melee hit on target switch"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"spellCasting.disableCastParalyze"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Prevent casting while paralyzed"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"actionDelay"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.AOS ? 1000 : 500"})}),(0,r.jsx)(s.td,{children:"Global action delay in milliseconds"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"visibleDamage"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.AOS"})}),(0,r.jsx)(s.td,{children:"Show damage numbers above targets"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"insurance.enable"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.AOS"})}),(0,r.jsx)(s.td,{children:"Enable the item insurance system"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"player-systems",children:"Player Systems"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Murder System:"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"murderSystem.shortTermMurderDuration"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"8h"})}),(0,r.jsx)(s.td,{children:"Duration of a short-term murder count"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"murderSystem.longTermMurderDuration"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"40h"})}),(0,r.jsx)(s.td,{children:"Duration of a long-term murder count"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"murderSystem.bountiesEnabled"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"!Core.LBR"})}),(0,r.jsx)(s.td,{children:"Enable the bounty system"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"murderSystem.recentlyReportedDelay"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"10m"})}),(0,r.jsx)(s.td,{children:"Cooldown before a victim can report the same murderer"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"murderSystem.bountyExpiry"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"14d"})}),(0,r.jsx)(s.td,{children:"Time before an uncollected bounty expires"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Stealing:"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stealing.classicMode"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"!Core.AOS"})}),(0,r.jsx)(s.td,{children:"Use classic (pre-AOS) stealing mechanics"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stealing.suspendOnMurder"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"!Core.AOS"})}),(0,r.jsx)(s.td,{children:"Suspend stealing perma-flag on murder"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stealing.canStealContainers"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"!Core.AOS"})}),(0,r.jsx)(s.td,{children:"Allow stealing entire containers"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"stealing.maxWeightToSteal"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"10"})}),(0,r.jsx)(s.td,{children:"Maximum weight of an item that can be stolen (stones)"})]})]})]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Taming:"})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsx)(s.tbody,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"taming.enableBonding"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.LBR"})}),(0,r.jsx)(s.td,{children:"Enable pet bonding"})]})})]}),"\n",(0,r.jsx)(s.h3,{id:"game-systems",children:"Game Systems"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"opl.enable"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.AOS"})}),(0,r.jsx)(s.td,{children:"Enable Object Property Lists (item tooltips)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"opl.enableForVendorBuy"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Show property lists in vendor buy menus"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"vendor.isInvulnerable"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.LBR"})}),(0,r.jsx)(s.td,{children:"Make NPC vendors invulnerable"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"guards.instantKill"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Guards instantly kill criminals (vs. fighting them)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"factions.enabled"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Enable the factions system"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"ethics.enable"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Enable the ethics (Hero/Evil) system"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"questSystem.enableMLQuests"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.ML"})}),(0,r.jsx)(s.td,{children:"Enable Mondain's Legacy quest system"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"vetRewards.enable"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Enable veteran rewards"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"vetRewards.skillCapRewards"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Enable skill cap increase rewards"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"vetRewards.rewardInterval"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"30d"})}),(0,r.jsx)(s.td,{children:"Time between reward tiers"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"testCenter.enable"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Enable test center mode (free skills, items, etc.)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"chat.enabled"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Enable the built-in chat system"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"buffIcons.enable"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Core.ML"})}),(0,r.jsx)(s.td,{children:"Enable buff/debuff icons on the client UI"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"houseDecay.enable"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Enable house decay over time"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"pathfinding.enable"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Enable NPC pathfinding"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"network",children:"Network"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"pingServer.enabled"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Enable the UDP ping server (used by server browsers)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"pingServer.port"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"12000"})}),(0,r.jsx)(s.td,{children:"UDP port for the ping server"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"pingServer.maxConnections"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"2048"})}),(0,r.jsx)(s.td,{children:"Maximum queued ping connections"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"network.encryptionMode"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Both"})}),(0,r.jsxs)(s.td,{children:["Encryption mode: ",(0,r.jsx)(s.code,{children:"None"}),", ",(0,r.jsx)(s.code,{children:"Login"}),", ",(0,r.jsx)(s.code,{children:"Game"}),", or ",(0,r.jsx)(s.code,{children:"Both"})]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"network.encryptionDebug"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Enable debug logging for encryption negotiation"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"netstate.packetLoggingPath"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Packets"})}),(0,r.jsx)(s.td,{children:"Directory for per-client packet logs"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"uogateway.enabled"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Enable the UO Gateway protocol"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"assistants.enableNegotiation"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Enable Razor-style assistant protocol negotiation"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"server-listing",children:"Server Listing"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"serverListing.serverName"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"ModernUO"})}),(0,r.jsx)(s.td,{children:"Server name shown in the server list"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"serverListing.address"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"null"})}),(0,r.jsx)(s.td,{children:"Public IP address override for the server list"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"serverListing.autoDetect"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"true"})}),(0,r.jsx)(s.td,{children:"Auto-detect public IP via external service"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"maps-and-client-data",children:"Maps and Client Data"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"maps.enablePre6000Trammel"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Use pre-client-6000 Trammel map format"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"maps.enableMapDiffPatches"})}),(0,r.jsx)(s.td,{children:"auto"}),(0,r.jsx)(s.td,{children:"Enable map diff patches"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"maps.enableStaticsDiffPatches"})}),(0,r.jsx)(s.td,{children:"auto"}),(0,r.jsx)(s.td,{children:"Enable statics diff patches"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"maps.enablePostHSMultiComponentFormat"})}),(0,r.jsx)(s.td,{children:"auto"}),(0,r.jsx)(s.td,{children:"Use post-High Seas multi component format"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"expansion.forceOldAnimations"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Force pre-expansion animation set"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"miscellaneous",children:"Miscellaneous"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Key"}),(0,r.jsx)(s.th,{children:"Default"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"commandsystem.prefix"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"["})}),(0,r.jsxs)(s.td,{children:["Command prefix character (e.g., ",(0,r.jsx)(s.code,{children:"["})," for ",(0,r.jsx)(s.code,{children:"[command"}),")"]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"profanityProtection.enabled"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"false"})}),(0,r.jsx)(s.td,{children:"Enable profanity filter"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"profanityProtection.action"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"Disallow"})}),(0,r.jsxs)(s.td,{children:["Profanity action: ",(0,r.jsx)(s.code,{children:"Disallow"}),", ",(0,r.jsx)(s.code,{children:"Criminal"}),", ",(0,r.jsx)(s.code,{children:"None"})]})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"system.localTimeZone"})}),(0,r.jsx)(s.td,{children:"system default"}),(0,r.jsx)(s.td,{children:"Override the server's time zone (IANA or Windows ID)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"pages.discordWebhookUrl"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"null"})}),(0,r.jsx)(s.td,{children:"Discord webhook URL for GM page notifications"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"guildClickMessage"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"!Core.AOS"})}),(0,r.jsx)(s.td,{children:"Show guild abbreviation on single-click"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"asciiClickMessage"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"!Core.AOS"})}),(0,r.jsx)(s.td,{children:"Use ASCII (not Unicode) for single-click messages"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"bulletinboards.creationTimeDelay"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"2m"})}),(0,r.jsx)(s.td,{children:"Cooldown between creating bulletin board threads"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"bulletinboards.expireDuration"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"6h"})}),(0,r.jsx)(s.td,{children:"Time before bulletin board threads expire"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"bulletinboards.replyDelay"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"30s"})}),(0,r.jsx)(s.td,{children:"Cooldown between bulletin board replies"})]})]})]}),"\n",(0,r.jsx)(s.h2,{id:"other-configuration-files",children:"Other Configuration Files"}),"\n",(0,r.jsx)(s.h3,{id:"expansionjson",children:"expansion.json"}),"\n",(0,r.jsx)(s.p,{children:"Controls which expansion the server emulates and which maps are active."}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:'{\n "id": 7,\n "name": "Mondain\\u0027s Legacy",\n "mapSelectionFlags": "Felucca, Trammel, Ilshenar, Malas, Tokuno"\n}\n'})}),"\n",(0,r.jsxs)(s.p,{children:["The ",(0,r.jsx)(s.code,{children:"id"})," corresponds to the ",(0,r.jsx)(s.code,{children:"Expansion"})," enum (0 = None, 1 = T2A, 2 = UOR, 3 = UOTD, 4 = LBR, 5 = AOS, 6 = SE, 7 = ML, 8 = SA, 9 = HS, 10 = TOL, 11 = EJ). The ",(0,r.jsx)(s.code,{children:"mapSelectionFlags"})," field controls which maps are loaded."]}),"\n",(0,r.jsx)(s.h3,{id:"antimacrojson",children:"antimacro.json"}),"\n",(0,r.jsx)(s.p,{children:"Configures per-skill anti-macro rules to prevent automated skill gain."}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:'{\n "allowance": 3,\n "locationSize": 5,\n "enabled": true,\n "skillTriggers": {\n "Anatomy": true,\n "AnimalLore": true,\n "Blacksmith": false,\n "Magery": true\n },\n "expire": "00:05:00"\n}\n'})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Field"}),(0,r.jsx)(s.th,{children:"Description"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"allowance"})}),(0,r.jsx)(s.td,{children:"Number of allowed skill uses per location before throttling"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"locationSize"})}),(0,r.jsx)(s.td,{children:'Tile radius that defines a "location" for anti-macro purposes'})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"enabled"})}),(0,r.jsx)(s.td,{children:"Master toggle for the anti-macro system"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"skillTriggers"})}),(0,r.jsx)(s.td,{children:"Per-skill toggle (true = anti-macro enforced for this skill)"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"expire"})}),(0,r.jsx)(s.td,{children:"How long before location-based counters reset"})]})]})]}),"\n",(0,r.jsx)(s.h3,{id:"email-settingsjson",children:"email-settings.json"}),"\n",(0,r.jsx)(s.p,{children:"SMTP configuration for crash reports and support emails. Created with defaults on first launch if not present."}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:'{\n "enabled": false,\n "fromAddress": "support@example.com",\n "fromName": "ModernUO Team",\n "crashAddress": "crashes@example.com",\n "crashName": "Crash Log",\n "speechLogPageAddress": "support@example.com",\n "speechLogPageName": "GM Support Conversation",\n "emailServer": "smtp.gmail.com",\n "emailPort": 465,\n "emailUsername": "support@example.com",\n "emailPassword": "your-app-password",\n "emailSendRetryCount": 5,\n "emailSendRetryDelay": 3\n}\n'})}),"\n",(0,r.jsx)(s.admonition,{type:"tip",children:(0,r.jsxs)(s.p,{children:["Set ",(0,r.jsx)(s.code,{children:'"enabled": true'})," and configure your SMTP credentials to receive crash reports by email. For Gmail, use an ",(0,r.jsx)(s.a,{href:"https://support.google.com/accounts/answer/185833",children:"App Password"}),"."]})}),"\n",(0,r.jsx)(s.h3,{id:"server-accessjson",children:"server-access.json"}),"\n",(0,r.jsxs)(s.p,{children:["Defines protected accounts that cannot be permanently locked out. If a protected account is banned or has its access level lowered, it automatically resets to ",(0,r.jsx)(s.code,{children:"Owner"})," on the next successful login."]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:'{\n "protectedAccounts": ["admin", "owner"]\n}\n'})}),"\n",(0,r.jsx)(s.admonition,{type:"note",children:(0,r.jsx)(s.p,{children:"Account names are case-insensitive. This is a safety net for server owners -- it ensures you can always regain access to your server even if another admin modifies your account."})}),"\n",(0,r.jsx)(s.h3,{id:"throttlesjson",children:"throttles.json"}),"\n",(0,r.jsx)(s.p,{children:"Maps packet IDs to throttle delays in milliseconds. Packets sent faster than the configured delay are dropped for players (staff is exempt)."}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-json",children:'{\n "0x03": 25,\n "0x12": 25,\n "0x75": 500,\n "0xAD": 25\n}\n'})}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Packet"}),(0,r.jsx)(s.th,{children:"Delay"}),(0,r.jsx)(s.th,{children:"Purpose"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"0x03"})}),(0,r.jsx)(s.td,{children:"25ms"}),(0,r.jsx)(s.td,{children:"Speech"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"0xAD"})}),(0,r.jsx)(s.td,{children:"25ms"}),(0,r.jsx)(s.td,{children:"Unicode speech"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"0x12"})}),(0,r.jsx)(s.td,{children:"25ms"}),(0,r.jsx)(s.td,{children:"Text commands"})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"0x75"})}),(0,r.jsx)(s.td,{children:"500ms"}),(0,r.jsx)(s.td,{children:"Rename request"})]})]})]}),"\n",(0,r.jsxs)(s.p,{children:["You can modify throttles at runtime using the ",(0,r.jsx)(s.code,{children:"[SetThrottle"})," and ",(0,r.jsx)(s.code,{children:"[GetThrottle"})," admin commands."]}),"\n",(0,r.jsx)(s.h2,{id:"custom-configuration",children:"Custom Configuration"}),"\n",(0,r.jsxs)(s.p,{children:["Developers can create custom JSON configuration files using the ",(0,r.jsx)(s.code,{children:"JsonConfig"})," utility:"]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-csharp",children:'var mySettings = JsonConfig.Deserialize<MySettings>(\n Path.Combine(Core.BaseDirectory, "Configuration/my-settings.json")\n);\n'})}),"\n",(0,r.jsxs)(s.p,{children:["Files are read from the ",(0,r.jsx)(s.code,{children:"Configuration/"})," directory and support comments, trailing commas, and all standard JSON converters (enums, TimeSpan, IPEndPoint, etc.) automatically."]})]})}function a(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(o,{...e})}):o(e)}}}]); |