SBGItemFramework
Shared backbone for custom item mods. Register an ItemType and a use-handler; it owns the Harmony plumbing for inventory injection, localized names, hotkey labels, tooltips, and pool-spawn injection. Required by dependent mods.
| Date uploaded | 15 hours ago |
| Version | 0.1.0 |
| Download link | Cray-SBGItemFramework-0.1.0.zip |
| Downloads | 8 |
| Dependency string | Cray-SBGItemFramework-0.1.0 |
This mod requires the following mods to function
BepInEx-BepInExPack
BepInEx pack for Mono Unity games. Preconfigured and ready to use.
Preferred version: 5.4.2305README
SBGItemFramework
Shared backbone for Super Battle Golf custom-item mods. Each consumer mod hands the
framework a RegisteredItem description and an IItemHandler that owns the gameplay; the
framework deals with everything that would otherwise force every item mod to write the same
~300 lines of ItemCollection / PlayerInventory / LocalizedString / HotkeyUi plumbing
and to coordinate that plumbing pairwise with every other custom-item mod the user has
installed.
Not a gameplay mod. It does nothing on its own — install it because something else lists it as a dependency.
Consumer flow
public sealed class MyItemPlugin : BaseUnityPlugin
{
private void Awake()
{
ItemKit.Register(RegisteredItem.Define((ItemType)1234, "My Item")
.WithHandler(new MyItemHandler())
.WithIconFromVanillaItem(ItemType.OrbitalLaser)
.WithIconTint(new Color(0.65f, 0.85f, 1.0f))
.WithMaxUses(2)
.WithTooltip("One-line description shown in the pause-menu probability grid.")
.WithConfigBindings(Config, bindMaxUses: true, bindSpawnWeights: true)
.Done());
}
}
public sealed class MyItemHandler : ItemHandlerBase
{
public override void OnUse(PlayerInventory inventory)
{
// Server-authoritative work goes through a Mirror Cmd; client-only fizz can run here.
}
}
The framework picks a non-conflicting integer for the ItemType is the consumer's
responsibility. Use anything >= 1000 to stay clear of the vanilla enum range; the
framework rejects ids <= 0 and warns when two mods claim the same id (second registration
loses).
What the framework owns
| Concern | Patch / mechanism |
|---|---|
Count / GetItemAtIndex |
Idempotent ItemCollection.items[] extension |
TryGetItemData |
Dictionary rebuilt by vanilla Initialize |
TryUseItem |
Prefix → Handler.OnUse(inventory) |
| Vanilla swing eligibility | GetEffectivelyEquippedItem(false) postfix → None |
| Item name in chat / pause / hotkey bar | LocalizedString.GetLocalizedString postfix |
| Probability-grid tooltip | PauseMenu.UpdateItemProbabilites postfix |
| Spawn-pool participation | ItemSpawnerSettings.ResetRuntimeData postfix |
| Localization-table seeding | First-frame retry on LocalizationSettings |
What the framework deliberately does not own (yet)
- Held-model prefab in the right hand. If a future item needs a custom mesh visible while equipped, that landed in v0.2.x of the framework.
- Animator pose mapping for the upper body. Same v0.2 scope.
- Custom drop visuals — vanilla pickup mesh works for sprite-based items.
- Network helpers for cross-client gameplay events. Consumer mods register their own Mirror message handlers.
Build / deploy / release
dotnet build -c Release
pwsh tools/package.ps1
gh release create vX.Y.Z artifacts/Cray-SBGItemFramework-<ver>.zip --notes-file CHANGELOG.md
CHANGELOG
Changelog
v0.1.0
- Initial release. Provides the
Cray.SBGItemFrameworklibrary used by other custom-item mods. Surface:ItemKit.Register(RegisteredItem)— entry point, takes a builder-built immutable item description.RegisteredItem.Define(id, displayName)— fluent builder. Optional knobs:WithIconFromVanillaItem,WithIconOverride,WithIconTint,WithMaxUses,WithTooltip,WithSpawnWeight(poolIndex, weight),WithConfigBindings(consumerConfig, bindMaxUses, bindSpawnWeights),AllowVanillaSwingEligibility.IItemHandler/ItemHandlerBasefor the consumer to implement gameplay callbacks (OnUse, optionalOnEquip/OnUnequip).
- Framework-owned Harmony patches:
ItemCollection.Initialize/OnEnableextend the privateitems[]array idempotently so vanillaCount/GetItemAtIndex/TryGetItemDatasee custom items natively, with no per-mod prefix coordination.PlayerInventory.TryUseItemdispatches to the registered handler.PlayerInventory.GetEffectivelyEquippedItem(false)masks custom items toNoneso vanilla swing/aim eligibility doesn't get confused by an unknown ItemType.LocalizedString.GetLocalizedStringrewritesITEM_<rawId>keys to the registered display name.PauseMenu.UpdateItemProbabilitesappends the optional tooltip text alongside the vanilla per-pool weight rows.ItemSpawnerSettings.ResetRuntimeDatainjects custom items into the requested pools'spawnChancesarrays and recalculates the totals.
- Icon tinting goes through a CPU-pixel path on readable source textures and falls back to
a
Graphics.Blitthrough a temporaryRenderTexturefor unreadable ones, with results cached by(textureInstanceId, packedRgba). - Localization-table seeding runs once a frame from a hidden host until the
Datatable finishes loading, so vanilla code that bypasses the LocalizedString postfix still resolves the same display names.