Skip to content

Registry Reference

ModularShoot stores all definitions in 10 dynamic registries (DataPackRegistry). All support /reload hot-reload and client sync.

Registry Overview

Registry IDPurposeValue Type
modularshoot:gunsGun definitionsGunDefinition
modularshoot:pluginsPlugin definitionsPluginDefinition
modularshoot:plugin_typesPlugin type (category) definitionsPluginTypeDefinition
modularshoot:traitsBoolean trait definitionsTrait
modularshoot:attribute_metaAttribute metadataAttributeMeta
modularshoot:statesPersistent state definitionsStateDefinition
modularshoot:variantsRandom variant definitionsVariantDefinition
modularshoot:shootersShooter definitions (independent-firing config templates)ShooterDefinition
modularshoot:gun_itemsItem → gun bindingsGunItemBinding
modularshoot:plugin_itemsItem → plugin bindingsPluginItemBinding

Attribute bodies (Attribute instances) are not in these dynamic registries — register them using vanilla DeferredRegister into BuiltInRegistries.ATTRIBUTE. The metadata table stores only defaults, display info, and bindings.

Gun Definition (GunDefinition)

Registry: modularshoot:guns

FieldTypeRequiredDefaultDescription
nameOptional text stringNoNone (falls back to gun ID path)Display name. Supports § color codes and lang: translation key prefix
textureResource pathYesGun base texture path, rendered using vanilla item pipeline with 3D-ification
shootTextureOptional resource pathNoNone (always uses base texture)Texture swapped to while firing
shootTextureModeEnumNoPER_SHOTTexture swap timing. Only effective when shootTexture is specified
textureScaleEnumNoAUTOWhether the render geometry scales with the texture resolution. AUTO (16 px = 1 grid cell; a 32×32 texture renders 2× larger) / FIXED (fixed 16×16 unit grid). Base and shoot textures scale independently by their own size
attributeMountEnumNoITEMAttribute mount (JSON key attribute_mount): ITEM (default; item-side, the framework writes the main-hand attribute modifier component as usual) / PLAYER (player-side; the framework does not write an item attribute modifier component for this gun, transferring mounting responsibility to the declaring side, e.g. mounting modifiers directly on a player entity)
statsAttribute ID → decimal mapNoEmpty mapAttribute base values. Keys are the logical ids of attribute_meta-registered entries; bare keys (no colon) auto-resolve to the modularshoot namespace (e.g. hit_damagemodularshoot:hit_damage), and an explicit minecraft: prefix is normalised to modularshoot as well; other explicit namespaces pass through verbatim. Unspecified attributes use the metadata table default. Any registered entry is supported (beyond the 10 preset attributes): adding an attribute_meta entry makes stats support that key automatically
traitsTrait ID → boolean mapNoEmpty mapGun inherent trait overrides. Gun-declared traits always override all plugins
variantsVariant ID → decimal mapNoEmpty mapVariant pool base weights: variant ID → base weight. The pool is assembled fresh for every shot, summed with plugins' addsVariants per variant, adjusted by contributor weight modifiers, then rolled weighted-random (see "Variant Definition (VariantDefinition)")
extraValuesNamespaced-number mapNoEmpty mapExtension numeric fields: keys are ResourceLocations (must be namespaced), values are numbers. The framework only carries and sums them per key without interpreting their meaning; getExtraValueSums / getExtraValue return them summed with installed plugins' accumulated values (the gun definition provides the base)
slotsPlugin type ID → integer mapNoEmpty mapPlugin slot configuration. Key is plugin type ID, value is slot count
soundsString → resource path mapNoEmpty mapSound bindings. Predefined slot: shoot (firing sound). Custom slot names supported
soundRangeOptional decimalNoNone (uses the sound event's own range, default 16 blocks)Audible radius override in blocks for the firing sound. JSON key sound_range; when absent, the sound event's own range (default 16) is used
bulletStyleOptional bullet styleNoNone (falls back to framework default appearance ComposedBulletStyle.FALLBACK_BASE, billboard + default texture)Bullet visual appearance config

BulletStyle

v2 structure (modifier stacking): the legacy model map + renderMode structure is replaced by base + modifiers. Modifiers from multiple sources (gun / plugins / traits / state conditions) stack instead of being fully replaced.

FieldTypeRequiredDefaultDescription
baseOptional objectNoNone (framework fallback base used at compose time)Base appearance. renderMode is required (BILLBOARD / THREE_D); texture (billboard texture) and model (3d model) are optional, exactly one of them used per mode
modifiersOptional list of modifiersNoEmpty listStacking visual modifiers, dispatched by "type": scale / tint / attach_layer. An unrecognised "type" decodes to an UnsupportedModifier sentinel (skipped with a WARN) rather than failing the whole list

ShootTextureMode

Enum ValueDescription
PER_SHOTSwap to shoot texture on every shot, snap back immediately after. High-rate weapons will flicker
WHILE_FIRINGHold shoot texture while trigger is pressed, revert on release. Best for full-auto to avoid flicker

Plugin Definition (PluginDefinition)

Registry: modularshoot:plugins

Registration (since 0.3.0): datapack JSON (data/<namespace>/modularshoot/plugins/<id>.json) or the Java API (ModularShootAPI.registerPlugin, which takes priority over a same-id datapack entry and survives /reload), plus a dynamic definition provider (registerPluginDefinitionProvider, computed at query time — fits random loot / dynamic affixes). See API Reference → Registration API.

FieldTypeRequiredDefaultDescription
tagsList of resource pathsNoEmpty listMatching tags. Install requires intersection with a type's tags. Empty list prevents installation (logs WARN)
priorityIntegerNo0Trait conflict priority, higher wins. Does not inherit type priority
visualPriorityOptional integerNoNone (falls back to priority)Visual base-election priority; JSON key visual_priority. Consulted only when this plugin's bullet style base competes in the visual composition election — it never affects trait-conflict resolution. When absent, falls back to priority
itemIconResource pathYesPlugin icon texture shown in inventory/hotbar
textureScaleEnumNoAUTOWhether the icon geometry scales with the texture resolution; same semantics as the gun's textureScale (AUTO / FIXED)
modifiersList of modifiersNoEmpty listAttribute modifier array. Applied to gun on installation
traitsTrait ID → boolean mapNoEmpty mapTrait overrides provided after installation
addsVariantsVariant ID → decimal mapNoEmpty mapBase weights appended to the gun's variant pool. Summed with the gun-declared weight of the same variant once installed (see "Variant Definition (VariantDefinition)")
addsSlotsCategory ID → integer mapNoEmpty mapSlot extension (JSON key adds_slots): increases the count of specified slot types on install, or creates slot types the gun never declared. Effective key set = gun slots ∪ installed plugins' adds_slots keys; effective capacity = gun base + sum of installed plugins' contributions. Values are arbitrary integers (negative values occupy slots; a capacity ≤ installed count can no longer accept new plugins for that type). Keys must reference the plugin_types registry; bare keys auto-complete to the modularshoot namespace (same rule as the gun's slots). Install matching and the tooltip plugin bar both use the effective slot configuration; the uninstall overflow pre-check is documented in the API doc
exclusiveGroupOptional text stringNoNoneMutual exclusion group ID. Two plugins with the same group ID cannot coexist on the same gun
bulletStyleOptional bullet styleNoNoneBullet style contribution. Stacks: base candidates are elected by visual_priority (falling back to priority when absent; equal values: later-installed wins; when no candidate, the framework fallback appearance is used); all modifiers stack (scale multiplies, tint multiplies channel-wise, attach layers are all kept)
textureOverlayOptional texture overlayNoNoneTexture overlay info. Layers stacked over the gun's base texture after install
gunOutlineOptional outline specNoNoneWhole-gun outline spec (see "Outline Spec (OutlineSpec)" below). Strokes the silhouette of the final composited gun texture; multiple plugins nest concentrically, widest first
extraValuesNamespaced-number mapNoEmpty mapExtension numeric fields: keys are ResourceLocations, values are numbers. The framework only carries and sums them per key (read via ModularShootAPI.getExtraValueSums / getExtraValue) without interpreting their meaning — integration mods use them to carry custom values (e.g. rarity) and accumulate them onto the gun in plugin install/uninstall events
nameOptional text stringNoNonePlugin display name. Supports § color codes
briefOptional text stringNoNoneOne-line summary. Shown in default tooltip level
descriptionOptional text stringNoNoneMulti-line detailed description. Shown in Shift tooltip level
colorOptional text stringNoNonePlugin name color (e.g. #FF4444)

Modifier (PluginModifier)

FieldTypeRequiredDefaultDescription
attributeText stringYesTarget attribute name. If no namespace, defaults to modularshoot namespace
operationEnumYesOperation type: ADD (additive), MULTIPLY (base multiplier), MULTIPLY_TOTAL (final multiplier)
valueDecimal numberYesModifier numeric value

Texture Overlay (TextureOverlay)

FieldTypeRequiredDefaultDescription
textureResource pathYesOverlay texture path layered onto the gun texture
layerIntegerYesZ-order, higher renders on top. Same layer: later-installed covers earlier
alignmentEnumNoTOP_LEFTNine-grid alignment: TOP_LEFT / TOP_CENTER / TOP_RIGHT / CENTER_LEFT / CENTER / CENTER_RIGHT / BOTTOM_LEFT / BOTTOM_CENTER / BOTTOM_RIGHT. Only effective when fit is NONE
fitEnumNoNONEFit mode: NONE (no resampling, blended at the aligned position, parts beyond the canvas are clipped with a WARN) / FILL (bilinearly stretched to cover the whole canvas; distorted when aspect ratios differ) / CONTAIN (uniformly scaled to be fully visible, centred with transparent margins)
tint4-element float arrayNoWhite [1,1,1,1] (identity)Per-channel RGBA multiplier applied to the overlay's pixels before blending. White is the identity
blendEnumNoNORMALColour mixing mode against the underlying pixels: NORMAL (ordinary source-over compositing — opaque pixels replace the base, translucent ones blend) / MULTIPLY (multiplies, darkens) / SCREEN (inverse-multiplies, brightens) / ADD (adds, clamped to 1, brightens). Only colour channels are affected; alpha always uses ordinary over compositing
outlineOptional outline specNoNoneStroke painted along the overlay's own alpha silhouette; same format as the outline spec (OutlineSpec). Applied after the tint, so it is never tinted

Outline Spec (OutlineSpec)

FieldTypeRequiredDefaultDescription
colorRGB float arrayYesOutline colour, three 0-1 floats (e.g. [1.0, 0.2, 0.1])
alphaDecimal numberNo1.0Outline opacity
widthIntegerNo1Outline width (pixels). Multiple plugin outlines nest concentrically, widest first; ties broken by installation order (later install paints over earlier)

Dynamic outlines (per-frame colour): outline colours are baked statically at composite time by default. An integration mod that needs a per-frame colour shift can register a GunOutlineTintProvider (functional interface (ItemStack, float partialTick) → Vector4f RGBA) in DynamicOutlineTintRegistry, keyed by the plugin id, during client initialisation:

java
// Client initialisation (e.g. @Mod(Dist.CLIENT) constructor)
DynamicOutlineTintRegistry.register(
    ResourceLocation.parse("examplemod:prismatic_core"),
    (stack, partialTick) -> /* per-frame colour, e.g. a rainbow hue rotating over time */);

Every gun with that plugin installed then renders its outline with the provider's per-frame colour (white outline mask × per-frame tint; cached textures are never rebuilt). Outlines without a registered provider keep their static baked colour. The built-in demo plugins with gun_outline are modularshoot:fragment_guard (guardian blue) and modularshoot:fragment_shining (golden holy light), both statically baked; the framework ships no dynamic-outline demo plugin — per-frame recolouring requires an integration mod to register a provider via DynamicOutlineTintRegistry as shown above.

Plugin Type Definition (PluginTypeDefinition)

Registry: modularshoot:plugin_types

FieldTypeRequiredDefaultDescription
tagsList of resource pathsNoEmpty listMatching tags. Install requires intersection with a plugin's tags. Empty list matches nothing (logs WARN)
priorityIntegerNo0Display priority (tooltip sort order) + install auto-select secondary sort key. Does not affect plugin trait conflict priority
nameOptional text stringNoNoneType display name
colorOptional text stringNoNoneType name color (e.g. #FFAA00)

Trait Definition (Trait)

Registry: modularshoot:traits

FieldTypeRequiredDefaultDescription
defaultValueBooleanYesDefault trait value when not declared by the gun
descriptionText stringNo"" (empty string)Description text
nameOptional text stringNoNone (falls back to trait ID path)Trait display name. Supports § color codes and lang: translation key prefix
colorOptional text stringNoNoneTrait name color (e.g. #FF8800)
briefOptional text stringNoNoneOne-line summary. Shown in Alt tooltip level
forceShowBooleanNofalseForce display. When true, shown in tooltip regardless of value
priorityIntegerNo0Display priority, higher sorts first
visualModifiersList of modifiersNoEmpty listStacking visual modifiers. Stacked into the composed bullet style when the trait is active

Runtime behavior (hook callbacks) is not stored in the Trait definition. Register it separately via registerTraitHook API.

Attribute Metadata (AttributeMeta)

Registry: modularshoot:attribute_meta

FieldTypeRequiredDefaultDescription
bindsResource pathYesPoints to a registered vanilla Attribute ID. Framework resolves the Attribute holder through this field at runtime. Shared by all three paths (mount / resolve / display all resolve through binds); may be rebound to any registered vanilla attribute. Preset attributes have logical ID = body ID, binds points to self
defaultValueDecimal numberYesGun base value when not declared by the gun (participates in ADD_VALUE calculation). Hot-reloadable. Not the vanilla Attribute's base (which is always 0)
entityTypesEntity type ID listNo[PLAYER] (player only)Read-effect whitelist (JSON key entity_types, default ["minecraft:player"]): only entity types in this list have their attribute values read by the framework; types outside read 0.0. The mounting side pre-mounts the framework's 10 preset attributes onto every entity type (lazily instantiated), so this field controls only "whose value takes effect" — a datapack-only change switches the effect scope. The attribute_binds of shooters are subject to the same whitelist
descriptionText stringNo"" (empty string)Description text
colorText stringNo"" (empty string)Attribute name color (e.g. #FF4444)
priorityIntegerNo0Display priority, higher sorts first
forceShowBooleanNofalseForce display. When true, shown in tooltip even if value equals default
unitOptional text stringNoNone (no unit shown)Translation key for the value's display unit (e.g. modularshoot.unit.per_second), rendered after the numeric value in the tooltip. When absent, no unit is shown

If the binds target attribute is not registered: metadata entry is retained but modifier won't mount, tooltip won't show, reads return 0.

Datapacks may rebind binds to any registered vanilla attribute (incl. minecraft:*), e.g. rebind modularshoot:hit_damage to minecraft:attack_damage. The three-path (mount / resolve / display) semantics plus the base-offset and syncable conventions are described in the datapack format doc.

Shooter Definition (ShooterDefinition)

Registry: modularshoot:shooters

The config template for independent firing (non-player sources: turrets, traps, boss attacks, scripted scenarios, ...): it provides a numeric template, and at firing time live attribute values read from a source entity are overlaid to produce a snapshot handed to ModularShootAPI.fireBullet. The registry key (the shooter id, e.g. modularshoot:bone_shooter) is supplied by the registry itself; it is not a record field.

FieldTypeRequiredDefaultDescription
statsAttribute ID → decimal mapYes— (non-empty)The snapshot's numeric template. JSON keys must be fully namespaced (e.g. "modularshoot:hit_damage"); the modularshoot namespace is NOT auto-completed; an empty template fails the entry load
traitsTrait ID → boolean mapNoEmpty mapInherent trait flags on the snapshot
bulletStyleOptional bullet styleNoNoneIndependent-firing visual style (JSON key bullet_style, same structure as a gun's); absent → framework default appearance
shootSoundOptional shoot soundNoNoneShoot sound (JSON key shoot_sound: id required, volume/pitch default 1.0); absent → silent
attributeBindsResource path listNoEmpty listAttribute binds (JSON key attribute_binds): at snapshot time each id is read live from the source entity and overrides the template entry (new keys allowed); on an empty read (null source / unregistered WARN / whitelist miss) the template value is kept

createSnapshot(LivingEntity source, RegistryAccess registryAccess) produces a snapshot following the independent-firing convention (gunId/gunInstanceUuid/shooter all null); the damage type is left null and patched by the fireBullet facade. The sound is not played automatically — call playShootSound(Level, Vec3). Entries registered via the Java API (registerShooter) take priority over same-ID datapack entries. Full JSON field documentation in the datapack format doc.

Variant Definition (VariantDefinition)

Registry: modularshoot:variants

FieldTypeRequiredDefaultDescription
baseWeightDecimal numberNo0.0Base weight fallback; JSON key base_weight. Used only when no gun/plugin declares this variant in its pool (typical for variants introduced solely via registerVariantContributor); declared gun/plugin weights are authoritative
traitsTrait ID → boolean mapNoEmpty mapMerged into the snapshot when selected: declared trait values are written, unlisted keys are kept
statsAttribute ID → decimal mapNoEmpty mapWhen selected, overrides only the declared keys (does not replace the whole snapshot stat table)
damageTypeOptional resource pathNoNoneWhen present, overrides the ammo_damage_type preset (variant takes precedence)
bulletStyleOverrideOptional bullet styleNoNoneVisual override, same format as bulletStyle (base + modifiers). Its base participates in the visual composition election with the highest priority (beats gun / plugins / traits / state conditions); modifiers stack as usual. Read by server-side compose only; never serialised to clients

Weight semantics (three sources): the variant pool is assembled fresh for every shot (never persisted). After merging the three sources below, one variant is rolled weighted-random:

  1. Base weights declared by the gun definition (variants)
  2. Installed plugins' addsVariantssummed with the gun's weight of the same variant
  3. Weight modifiers contributed via registerVariantContributor — vanilla AttributeModifier three-stage semantics: ADD_VALUE (flat add) → ADD_MULTIPLIED_BASE (multiplies only the base weight) → ADD_MULTIPLIED_TOTAL (scales the whole). A zero base with no ADD_VALUE modifier always resolves to 0 — "a fire trinket is useless on a non-fire gun"

Normal-bullet fallback: when the gun declares no variants, the pool implicitly contains a "normal bullet" candidate with weight 1.0 (not written into any JSON); guns that declare variants get no fallback. Probability math: P(variant X) = X's final weight ÷ pool total weight (pool total = the sum of the final weights of all positive-weight candidates, including the fallback 1.0); equal weights in a two-candidate pool give 50% each, and a variant hits 50% ⟺ its weight equals the sum of the other candidates' weights. Example: a normal gun + fireball plugin adds_variants: 1.0 → pool {fireball 1.0, normal bullet 1.0} → exactly 50%.

Per-pellet semantics: the variant is rolled independently per pellet (one election affects only that pellet), so a shotgun blast can mix different variants or normal pellets; an all-zero-weight or empty pool silently yields a normal pellet. Mutually-exclusive single-value fields (damageType / visual base) must go through the variant pool; stackable effects should use registerShootEffect.

State Definition (StateDefinition)

Registry: modularshoot:states

FieldTypeRequiredDefaultDescription
domainEnumYesOwnership domain. GUN (per-gun, persisted in gun NBT), PLAYER (per-player, persisted via AttachmentType), BULLET (per-bullet, lifetime only, not persisted)
valueTypeEnumYesValue type. INT / LONG / DOUBLE / FLOAT / BOOLEAN / STRING / UUID
defaultValueObjectNoZero value for the typeInitial value. Type must match valueType. Used when per-gun/per-player first accessed
displayState displayYesDisplay metadata object
visualModifiersList of state visual modifiersNoEmpty listConditional visual modifier batches: each entry pairs a condition (state / domain / op / value) with a modifiers list, stacked into the composed bullet style when the condition holds at bullet creation time

State Display (StateDisplay)

FieldTypeRequiredDefaultDescription
nameText stringYesState name in tooltip. Supports § color codes and lang: translation key prefix
colorOptional text stringNoNone (default tooltip color)Name color (e.g. #FFAA00). When omitted, the default tooltip color is used
formatText stringNo"{value}"Display template with {value} placeholder. E.g. "{value} kills" → tooltip shows Kill Count: 3 kills
priorityIntegerNo0Tooltip sort order, higher sorts first
hideDefaultBooleanNofalseWhen true, the line is hidden if the value equals the default

Item Binding Definition (GunItemBinding / PluginItemBinding)

Registry: modularshoot:gun_items / modularshoot:plugin_items

Binds other mods' items as guns/plugins — once bound, every instance of that item ID is treated as a framework gun/plugin, without replacing the original item (model / texture / acquisition paths are all preserved — no "counterfeit" problem). The entry key (JSON filename) is an arbitrary id; the content declares the binding target.

FieldTypeRequiredDescription
itemResource pathYesThe bound item ID (e.g. minecraft:diamond_sword)
gunResource pathYes (gun_items)Target gun definition ID (an entry in the modularshoot:guns registry)
pluginResource pathYes (plugin_items)Target plugin definition ID (an entry in the modularshoot:plugins registry)

Behavior semantics:

  • Converts upon entering the inventory: within 1 tick of a bound item entering the player's inventory (36 main slots + offhand), the server automatically attaches the gun_data component (instance UUID, base attribute modifiers). After that it is fully runtime-isomorphic with native guns — plugin installation, locking, state persistence, bullet backtracking and anti-cheat version numbers all behave identically.
  • Plugin bindings attach no component: bound plugins are consumed on install; the pluginId is resolved directly through the binding table.
  • Full conversion: on bound guns, left-click melee is replaced by shooting, vanilla enchantments are nullified, and shooting does not consume durability.
  • Visual tier 1: bound items keep their original item model rendering; the framework's dynamic texture pipeline (recoloring / overlays / outlines / shoot-texture swapping) serves native guns only.
  • Identity hint: an unconverted (component-less) bound gun shows a grey identifier line Gun: <id> in its tooltip plus the base attribute/slot preview registered in the gun definition; visible in JEI, the creative inventory and inventory hover.
  • Post-load validation (WARN degrade, never rejected): item must exist in the item registry; gun/plugin must exist in the corresponding definition registry; duplicate bindings of the same item ID → the lexicographically smallest entry key wins, the rest WARN.
  • Java API priority: bindings registered via registerGunItem/registerPluginItem take precedence over datapack entries; datapack entries conflicting with the Java API WARN at load time.
  • Main menu limitation: datapack bindings show no hint in the main-menu creative inventory (registry not loaded); Java API bindings are exempt.

Released under the MIT License