Burnsies HideoutDocsBurnsie.Common

Burnsie.Common — Feature Documentation

One document per feature, written for plugin developers building on the library. Each doc covers what the feature does, why it exists, how to use it, and the rules you must follow. For the end-to-end plugin skeleton and setup, start with the Developer Guide.

Both assemblies target .NET Framework 4.8, x64, against RagePluginHook 1.124+ and LSPDFR 0.4.9+.

Core library — Burnsie.Common.dll (needs RPH only)

DocTypesWhat it gives you
LoggingLogPrefixed, leveled logging to RagePluginHook.log plus an optional diagnostics file sink
ConfigurationConfigSchema, IniFileDeclarative INI schema: one table drives values, the default file, and generated docs
Threading & fibersFiberRegistry, CancellationFlag, OffThreadException-fenced fiber loops, cooperative cancellation, background threads for blocking IO
Notifications & textNotifier, Palette, CaptionsRate-limited toast queue, persistent live-status HUD line, color conventions, subtitles
AudioWavPlayer, FrontendSoundsPreloaded async WAV playback (RPH has no sound API) and fail-soft frontend cues
Entities & blipsEntityBag, BlipsLifetime-scoped entity/blip ownership with one-call cleanup; standard-color blip factory
KeybindsKeybindKeyboard/controller chords with correct modifier semantics and input suppression
Safe nativesSafeNatives, CrowdNativesPinned-hash native calls behind a self-disabling fence — a bad native never crashes the plugin
World & positionsPositionsStreet names, water checks, road-reachability heuristic for dispatch decisions
Diagnostics & updatesDependencyReport, UpdateChecker, LcpdfrVersionChecker, LibraryInfoInstall validation with correct version semantics; daily update checks; library identity

LSPDFR layer — Burnsie.Common.Lspdfr.dll (needs RPH + LSPDFR)

DocTypesWhat it gives you
Duty stateDutyStateServiceCached on-duty state (LSPDFR has no duty query API) with idempotent attach/detach
Scanner audioScannerAudioCrash-proof police scanner playback: per-install token validation and a busy-gated queue
Backup dispatcherBackupDispatcher, Wave, UnitOrder, TrackedUnit, DispatchOptionsWave-based backup with honest unit tracking, arrival detection and incident-scoped cancellation
Callout base classBurnsieCalloutHardened LSPDFR callout lifecycle: automatic teardown, route blips, leash, death guard
Timer barsTimerBarHud, ITextTimerBar, IProgressTimerBarHUD timer bars over LSPDFR's undocumented engine UI, self-disabling on failure
LSPDFR helpersZoneInfo, Officers, Pursuits, RadioAnimation, LspdfrRuntimeZone names, officer personas, pursuit-safe helpers, radio animation, plugin coexistence checks
Crowd engineCrowd, CrowdSpawner, HostilityMeter, FactionManager, EscalationLadder, RoadClosure, CrowdArsenal, CrowdEngineOptionsCivil-disorder scenes: budget-disciplined crowds, faction combat, escalation waves, road closures

The ground rules (apply to everything)

These are the library-wide invariants every doc assumes. Violating them produces the classic plugin bugs.

  1. Natives and entities only on GameFibers. Anything touching the game world must run on a GameFiber, never a CLR thread.
  2. Yield every loop iteration. Use GameFiber.Sleep for pacing (real time); GameFiber.Wait is scaled by Game.TimeScale and is only for deliberate slow-motion stretching.
  3. LSPDFR event handlers: copy args, hand off, return. Events arrive on LSPDFR's fibers — do the real work on your own fiber.
  4. Re-validate every entity with .Exists() after any yield. Handles die at any time.
  5. Timers on Game.TickCount or DateTime.UtcNow, never Game.GameTime (time dilation stretches it).
  6. Blocking IO off-thread, always (OffThread.Run) — a fiber that blocks on disk or network stalls the game.
  7. Everything you set, you restore — on off-duty, plugin reload and unload.
  8. Versions are System.Version, never floats (as floats, 1.124 < 1.98).
  9. Degrade per-subsystem. One broken asset, native or service never takes the whole plugin down.
  10. Log decisions, not noise — and prefix every line.