Clipboard
public static class ClipboardNamespace Clipwise.Api
Clipwise’s modder API. Reference Clipwise.Api.dll OR drop this single file into your mod.
The management clipboard shows every selectable item of a field in one flat, unscrollable icon grid. Clipwise replaces that with a searchable, tabbed picker. Tell it which category your items belong to and they get their own tab instead of being mixed into the vanilla ones.
Every call is a zero-overhead no-op when Clipwise is not installed and lights up automatically when it is, so this can ship unconditionally with no hard dependency. Registration order does not matter: calls made before Clipwise loads are queued and replayed on bind.
using Clipwise.Api;Clipboard.Category("doodesch.breedtoseed", "tier-1", "Bred - Tier 1", sortOrder: 100) .Item("headband", "b2s_headband_seed", sortKey: "Headband", tags: new[] { "doodesch.breedtoseed:tier/1" });Tip: a class named ClipwiseProbe with a static Register() is auto-discovered and called on bind (see AutoRegister), so a mod’s Core does not have to wire anything.
Identifiers: source is the reverse-DNS id of the registering mod ("doodesch.breedtoseed"). A category’s canonical key is "source:id". Tags MUST be namespaced the same way ("doodesch.breedtoseed:tier/1") - bare tags are rejected by the host so two unrelated mods cannot fight over a name like “tier3”. The clipwise: namespace is reserved for the host.
All calls MUST be made from the Unity main thread.
Properties
Section titled “Properties”Available
Section titled “Available”public static bool Available { get; }True only when the Clipwise host is installed AND bound. Rarely needed - the API is a safe no-op when absent.
AbiVersion
Section titled “AbiVersion”public static int AbiVersion { get; }The host’s ABI version: 0 when Clipwise is absent, 1 for the initial contract. Use this only to gate on capabilities added in a later ABI; everything below degrades to a no-op on its own.
Methods
Section titled “Methods”Category
Section titled “Category”public static CategoryRef Category( string source, string id, string label, int sortOrder = 0, string iconItemId = null)Declare a category - one tab in the picker. sortOrder orders the tabs (lower first; vanilla sits at 0). iconItemId optionally names an item whose icon represents the tab. Returns a fluent builder for the items in it. Load-order-proof.
RegisterCategory
Section titled “RegisterCategory”public static void RegisterCategory( string source, string id, string label, int sortOrder = 0, string iconItemId = null)Same as Category without the builder, for callers that keep their own loop.
RegisterItem
Section titled “RegisterItem”public static void RegisterItem( string source, string id, string itemId, string category, string[] tags = null, int sortOrder = 0, string sortKey = null, string description = null, int precedence = 0)Place one item in a category. id is this mod’s own stable key for the entry, unique within source; itemId is the game’s ItemDefinition.ID the entry stands for; category is a canonical category key ("source:id"). sortKey orders entries inside the category (falls back to the item’s display name); description shows up in the tooltip; precedence breaks ties when several sources claim the same item (higher wins).
Returns nothing on purpose: a call queued before Clipwise loaded cannot know whether the future host accepts it. Re-registering the same (source, id) is an idempotent upsert, so calling this twice is safe. Load-order-proof.
RegisterTagLabel
Section titled “RegisterTagLabel”public static void RegisterTagLabel(string tag, string label)Give a tag a human-readable label for its filter chip, e.g. "mymod:tier/1" -> "Tier 1". Without this the chip shows the tag’s last path segment. Load-order-proof.
public static void Facts(string source, Func<string, string> provider)Answer for your own items with extra rows on the picker’s detail card.
provider is handed one ItemDefinition.ID and returns one "LABEL value" line per row, separated by newlines. An empty answer, a blank value or a missing line simply leaves that row OUT - never show a label with nothing under it.
Clipboard.Facts("doodesch.breedtoseed", itemId =>{ StrainDef s = StrainTable.BySeedId(itemId); if (s == null) return null; string who = Register.ShownName(s); // live, and never the raw Steam name return who == null ? null : "DISCOVERED BY " + who;});ASKED EVERY TIME THE PICKER OPENS, never cached. That is why this takes a callback rather than a string: a name that resolves against a live register has to be read live, or a player who renames themselves keeps seeing the old name here after every other surface has caught up.
Only the source that registered an item is asked about it. Load-order-proof; no-op without Clipwise; needs host ABI 2.
AutoRegister
Section titled “AutoRegister”public static void AutoRegister()Discover a convention type named ClipwiseProbe with a static Register() in THIS mod’s own assembly and invoke it once - so a mod never has to wire a Register() call into its Core. Drive it from a [ModuleInitializer] in the probe file. No-op + load-order-proof.