FrameworkVersion class
Single source of truth for the framework’s version string. Lives in Abstractions so every layer (Host’s BepInPlugin manifest, Infrastructure’s AboutPanel, and any plugin that wants to gate behaviour on a particular framework release) can read the same constant without re-declaring it. Bump this on each user-visible release; Host’s BootstrapPlugin.PluginVersion forwards to it so the BepInEx plugin manifest stays in lockstep.
public static class FrameworkVersionPublic Members
Section titled “Public Members”| name | description |
|---|---|
| const Value | Current framework version. Plain SemVer (no pre-release suffix) keeps the BepInEx chainloader happy. 2.11.0 adds player spec from talent root buffs: ICombatSpec.TryGetTalentSpec, CombatEvent.SpecChanged and CombatEvent.EntityBuffsSeeded (a player’s full buff set when they appear). Additive only. 2.10.0 adds ILoadoutSave (IPluginServices.LoadoutSave): SaveCurrentToAsync(index) saves the WORN setup into another saved loadout through the game’s own AsyncSaveRolePlan wrapper (refused without dispatch for the worn / unknown loadout or while a switch or save is in flight), and HasUnsavedChanges — the game’s own CheckRolePlanIsChange, cached and re-evaluated on the container-merge event, the loadout-list re-read and after a save (never on a timer). Additive only. 2.8.3 adds IEntityPortrait.ShowWeapon (hide the subject’s weapon in the 3D portrait) and IEntityPortrait.LightPreset (-1 = Scene/dynamic, 0..4 = custom, environment-independent creature-light profiles rebased on the real HDR scene scale), with the camera controls (Orbit/Zoom/Pan/SetViewport) factored onto a new base IEntityPortraitView (IEntityPortrait : IEntityPortraitView) so each interface stays under the STELLAR0005 8-member cap. The portrait’s custom creature light is world-isolated: the five shared creature-light shader globals are captured before the portrait’s CommandBuffer draw and restored byte-identical after, so in-world characters are unaffected regardless of frame timing. Also adds BarElement.LabelColor (ColorRgba?) — a per-bar override for the inside label colour that wins over the theme’s muted tone (default null keeps every existing bar byte-identical). Additive members + a new base interface; binary-compatible with plugins built against ≤2.8.2 EXCEPT a plugin that CALLS the camera methods moved onto IEntityPortraitView must be recompiled (only EntityInspector consumes them, rebuilt in tandem). Consumed by StellarEntityInspectorPlugin. 2.8.2 is a fix: a player-stats sampling pass in which NO attribute read is no longer allowed to mark those attributes permanently unreadable. The local-player entity exists for several ticks before its attribute sheet is populated, so a pass taken inside that login window missed every subscribed id and latched them all for the life of the process — Stat Inspector then showed “—” for every tracked stat until the client was relaunched (owner report 2026-09-21). The decision moved out of the reflection probe into the pure, unit-pinned AttrReadabilityMemo: a pass may condemn its misses only once the attribute sheet is known populated — a live read in the same pass, or the caller’s explicit readiness signal — so the anti-spam for genuinely absent ids such as 11760 / 11980 is unchanged. The verdict itself now EXPIRES after 60 s and the id is probed once more, so an attribute the game publishes late (11951 on a test client) appears within a minute instead of dashing for the session; re-subscribing an attribute re-probes it at once, and a logout forgets every verdict. Infrastructure/Application only — no API change, binary-compatible with all existing plugins. 2.8.0 adds MeterRowData.LabelStyle (MeterLabelStyle Plain / Outline / Shadow): how the two values drawn on a meter row’s bar stay readable over the fill — CombatMeter 2.10.0 can paint the bar with the class crest colour (yellow / green / orange), where plain white text had a contrast of 1.4–2.0 (owner 2026-09-09: “text on meter is barely readable” → “it should be option for players”). Outline = the stat HUD’s readability halo (UGuiPrimitives.AddReadabilityOutline, 1.1 px); Shadow = a soft dark shade under the value whose strength follows the fill’s luminance. Default Plain keeps every pre-2.8 plugin’s rows byte-identical. Additive API; binary-compatible. 2.8.1 is a fix: the Steam Class::Init injection guard (Il2CppClassInitFix.EnsureSeeded) is now armed BEFORE user plugins load, not only inside the tick host’s install (which ran AFTER plugin construction). A plugin that injects an IL2CPP type in its constructor (e.g. an enabled overlay like Minimal Nameplate) previously crashed the Steam StarSEA_STEAM build at boot because the guard wasn’t seeded yet. Infrastructure/boot-order only — no API change, binary-compatible with all existing plugins. 2.7.4 is a fix: repairs Il2CppInterop’s IL2CPP type injector on game builds whose GameAssembly.dll codegen defeats InjectorHelpers.FindClassInit()’s hardcoded Class::Init byte-signature scan — it mis-resolves to a bad pointer and hard-crashes the CLR (0x80131506) at the FIRST ClassInjector.RegisterTypeInIl2Cpp. Observed on the Steam StarSEA_STEAM build (separate SKU compile; the standalone StarSEA resolves fine). The framework now pre-seeds the process-global InjectorHelpers.ClassInit with Il2CppInterop’s own documented substitute (il2cpp_class_has_references) before its first injection, so the broken scan is skipped; harmless on builds where the scan already worked (the substitute is the library’s own fallback). Infrastructure-only (Il2CppClassInitFix) — no API change, binary-compatible with all existing plugins. See docs/recon/steam-client-classinit-injection.md. 2.7.3 is the STABLE release of the 2.7 line: same code as the 2.7.2 testing build, promoted to the stable channel (2.7.2’s version number was already taken by that testing release, and a taken version is never re-minted — the promotion rides a patch bump). No API change. 2.7.2 carries the 2.6.3 native-UI layout fixes and the 2.6.4 IPlayerIdentity.CharId API into the 2.7.x (rDPS groundwork) line — additive, binary-compatible with ≤2.7.1. 2.7.1 carries the 2.6.2 Deep-Slumber loadout hotfix into the 2.7.0 (rDPS groundwork) line — no API change. 2.6.4 adds IPlayerIdentity.CharId — the local character’s stable id (char-record-backed, known before the world entity syncs; 0 when unknown), so plugins can key per-character storage instead of colliding across characters on one account. Additive (a new interface member + getter): binary-compatible with plugins built against ≤2.6.3, but a plugin that CALLS CharId needs this framework (LoadoutSwitcher/Wardrobe bump their min to 2.6.4). Abstractions/Application surface only; built on v2.6.3 (native-UI layout fixes + the 2.6.2 Deep-Slumber cross-loadout factor-move fix). 2.6.3 is a fix: native game-UI elements you have repositioned (quest tracker, boss HP bar, etc.) survive a resolution round-trip, no longer ratchet on repeated hide/show, and fall back to the game’s default pose at an unconfigured resolution. The SetRect idempotent guard now keys on (target, anchoredPosition, curatedSize) equality; adds INativeUiAdapter.RestoreOriginalPose. Infrastructure/Application-only (native-UI positioning) — no plugin API change, binary-compatible. 2.6.1 is a fix: IWardrobe.GetWornWeaponSkin reports “no weapon skin” as SkinId 0 again. The Wardrobe’s ⊘ tile is not skin 0 — the game stores the current weapon’s ORIGIN row id (a concrete WeaponSkinTable row per weapon family), so capture saved a specific skin and re-applying the outfit forced that look. Infrastructure-only (capture chunk) — no API change, binary-compatible. 2.4.1 is a fix: the framework-only “Cannot perform this action during combat” toast (~every 5s in sustained open-world combat) is gone. Root cause: every CharSerialize merge re-armed the loadout refresh, whose weapon-VM SyncProjectList RPC the server rejects in combat (ErrStateIllegal 3202) and the game’s own wrapper toasts. PandaLoadoutProbe.DecideRefresh now defers ONLY that RPC while the local player is in combat (game’s own check), keeping the pending/first-refresh state armed so exactly one refresh fires at combat end; the RPC-free live-state re-read keeps running in combat. Infrastructure-only — no API change, binary-compatible with all existing plugins. (2.4.0 shipped the Wardrobe surface but did not bump this constant; 2.4.1 realigns it.) 2.2.0 is the live-build release. Adds ILoadout.LiveState (LiveLoadoutState — the live class + talents, never a saved plan), ILoadout.LiveStateChanged (ONE game-tick event covering the whole build: equipped gear/module slots, class, talent stage/nodes, the equipped Battle Imagine pair, and Deep-Slumber — raised only after the framework’s re-read actually changed what it serves, so a consumer may treat it as “the setup I can read right now is the new one”), and IPluginServices.DeepSlumber (IDeepSlumber) — the live Deep-Slumber Psychoscope (season cultivate) state: season levels, lines, areas, socketed cards and node levels, read live per call. IInventory.SelfGearChanged widens from gear-only to the local player’s BUILD-state signal (it now also fires on talent field-61 and season-cultivate field-101 dirty deltas). IResonanceState.Installed keeps its shape but changes SOURCE and id space: the equipped Battle Imagines are now read from the skill hotbar’s aoyi slots 7/8 as aoyi SKILL ids (resolve via IGameDataResonance.GetImagineForSkill) because CharSerialize.resonance (wire field 28) is never re-serialized on an in-session swap. Internally the framework’s last per-tick game reads are gone — live-state capture and the dungeon defeated count are both event-driven now (container-merge / scene-attr sync). New members + a new service only — additive, binary-compatible with plugins built against ≤2.1.0. 2.1.0 adds IPluginServices.Localization (ILocalization) — a plugin-scoped UI-text localizer. A plugin ships four embedded Lang/{en,ja,th,id}.json catalogs and calls Localization.T(key) / TFormat(key, args), resolved to the active language (English fallback, then the key literal). The framework auto-discovers each plugin’s catalogs at load, and Stellar’s own settings UI is now localized in English / 日本語 / ไทย / Bahasa Indonesia (Settings → Themes → Language, defaulting to Follow-game-client). Adds ILocalizationControl (Settings-facing, NOT on IPluginServices). New service only — additive, binary-compatible with plugins built against ≤2.0.3. 1.18.1 is a fix: game-region detection matches the running executable by name PREFIX (StarSEA = SEA, StarASIA = JP) rather than exact filename, so the Steam build’s StarSEA_STEAM.exe resolves to SEA instead of Unknown (which had made upload plugins withhold every run). Detection-logic only — no API change, binary-compatible with all existing plugins. 1.18.0 adds SliderElement.SquareHandle, an OPT-IN knob that is exactly HandleSize square. Unity’s Slider drives the handle’s cross-axis anchors to full stretch every frame, so by default HandleSize ADDS to the row height instead of setting the knob’s height — a 13px handle in a 16px row draws a 13×29 capsule (measured 2026-07-30). The stretched shape stays the default on purpose: every existing slider already renders that way, and correcting it globally would restyle every plugin’s sliders at once. Additive only — no existing slider changes appearance, and drag behaviour is identical (the value maps from the container’s width, which is untouched). 1.17.0 adds ActorState and CombatEvent.EntityStateChanged (2026-07-28 entity-state-death-signal spec): the client’s own entity state-machine transitions (death, break phase), surfaced on the existing ICombatEvents stream — no service interface gains a member, so the STELLAR0005 8-member ceiling is untouched. Lets plugins (e.g. the CombatMeter’s BossKill) know an entity died without inferring it from HP reaching zero, which scripted kills never do. Field-proven sourcing, after three recon rounds (see recon/entity-state-death-signal-notes.md): Panda.ZGame.ZStateDead.OnEnter fired for all ten deaths in the owner’s confirming run and is the sole installed death source; Panda.ZGame.ZStateBreaking.OnEnter (untested, not disproven — no break phase occurred in that run) is its kept sibling. The originally-spec’d EntityCtrlDead.OnEnter stayed silent across those same ten deaths (disproven) and the wider ZStateMachine.onStateChanged/EnterState hooks tried in between were dropped for cost, not correctness — EnterState also resolved every one of the ten deaths correctly and remains a documented, field-proven fallback if ZStateDead is ever removed/renamed, just not installed by default because it fires on every actor’s every transition rather than only the one that matters. New enum + new discriminated-union case only — additive, binary-compatible with plugins built against ≤1.16.1. 1.15.0 adds IPluginServices.Data — an IPluginDataStore giving each plugin its own binary file storage (Write/Read/Delete/List, never-throws, path-traversal-safe) for data too large/opaque for IConfigSection; rooted OUTSIDE the plugin-scan dir. New service only — additive, binary-compatible with plugins built against ≤1.14.0. 1.14.0 adds EntityVitals.HasHpObservation (MaxHp-only observations no longer read as dead; init-prop, binary-compatible), AOI-appear vitals seeding, PartyMember.FastSyncState (raw TeamMemberFastSyncData.state transport; init-prop), and IDungeonState.CurrentFlowState/FlowStateVersion (EDungeonState surfaced with a poll-friendly transition counter) — all additive, binary-compatible with plugins built against ≤1.13.0. 1.13.0 adds IExchange.GetStallSubcategoryMap (live StallDetailTable membership). 1.12.0 adds IGameEnvironment — region (SEA/JP/Unknown) + installed game version, detected once at boot from install markers with a framework-config override; additive, binary-compatible with plugins built against ≤1.11.0. 1.11.0 consolidates the portraits/replay line: IDungeonState (settlement + outcome + achieved score), IEntityTransforms (live entity transforms for position/replay capture), IEntityDetail.RefreshSocialSnapshot (self social-data refresh), IGameDataWorld.GetMonsterByEntity, SocialSnapshot.MasterScore, GearInstance.BreakThroughTime, skill-phase CombatEvents — all additive (new services / init-props / defaulted params), binary-compatible with plugins built against 1.10.0. 1.10.0 adds additive window-framework support behind the CooldownBar overlay: WindowSpec.BackgroundOpacity (poll-diffed backdrop on the borderless root that expands on height resize), ColumnElement.Padding, RowElement.Justify + RowJustify (with a compat overload), BackdropElement, VirtualListElement.ResetScroll, and CooldownTileElement.OnClick — all init-props / new records / defaulted params, so binary-compatible. Infrastructure: atomic game-asset icon rebind via a WindowToken binding (no scroll blink), buff icons as atlas Sprites, a ConditionalElement flex clamp, and a VirtualList viewport inset. (#32) 1.9.1 is a fix: PandaMenuStateProbe now also detects NPC dialogue, loading screens, the dungeon-enter confirm popup (team_copy_popup on UILayerFuncPopup), the line-selector panel, and story cutscenes as full-screen menu states, so AutoHideBehindGameMenus windows hide in all those cases. 1.9.0 adds IWindowControl.BringToFront() (a ZFront counter that sorts above category so explicit fronting works cross-category, with a pending flag so SetVisible(true) + BringToFront() works on a still-hidden window), a front-window interaction pass-through guard, and a restyled dropdown item to match SelectableElement. 1.8.0 adds DropdownElement — a reusable compact dropdown (trigger caption + ▾ that opens a themed floating option list above the window’s scroll clip; dismiss on pick, outside-click, or Escape). The Settings → Performance per-plugin Self-rate control now uses it in place of the click-to-cycle button. 1.7.1 was a binary-compatibility hotfix: SliderElement’s Width/HandleSize moved off the record primary constructor (added in 1.7.0, which broke the old positional ctor) to init-only properties, so plugins compiled against ≤1.6.0 (e.g. AutoFishing) load again. 1.7.0 adds per-plugin & dynamic update-rate control: each plugin’s IFramework.Update ticks at its own rate (user-configurable in Settings → Performance), and a plugin may temporarily ramp its own rate via IFramework.RequestUpdateRate (returns an IUpdateRateScope), gated by a per-plugin user permission. The framework tick became a single variable-speed clock at max(global, all active rates), with the Lua-bridge probe drains riding it so RPC latency falls with the rate. Also adds SliderElement.Width/HandleSize and honors ToggleElement.Enabled. 1.6.0 adds IExchange (player Trading-Center query + buy via the game’s own trade flow, exposed as IPluginServices.Market) and the extensible INotifications.Create() toast builder (custom-icon support). 1.5.0 added team-voice mic status + dungeon ready-check on the meter row (IPartyEvents/IPartyRoster) plus the click-away popup / PanelElement / z-ordering UI primitives. 1.4.2 was a hotfix for non-ASCII (e.g. Thai) text input truncated in uGUI fields (onValidateInput → onValueChanged); 1.4.1 scoped the rail-button template lookup (periodic freeze); 1.4.0 added IWindowControl.SetVisiblePersist plus the native-UI grab-box / cutscene-reposition fixes. |
Remarks
Section titled “Remarks”BepInEx parses Value with SemVer semantics — it rejects trailing letters like 0.9.0a (“Skipping type because its version is invalid”). Use SemVer pre-release suffix syntax (0.9.0-alpha) so the chainloader accepts the manifest.
See Also
Section titled “See Also”- namespace Stellar.Abstractions.Domain