Modular Items
IModularItem
IModularItem is a capability that can be attached to item stacks.
Its recommended implementation is ModularItemStack, which can be attached to a stack
in an AttachCapabilitiesEvent<ItemStack> listener, or attached as an item component
to a ComponentItem using ModularItemComponent. Note that if it is attached not as
a component, module-related tooltips won't be displayed, and onUse and related methods won't work.
Attaching a ModularItemStack using an event
@Mod.EventBusSubscriber(modid = "your_mod_id", bus = Mod.EventBusSubscriber.Bus.FORGE)
public static class ExampleEventListener {
@SubscribeEvent
public static void onAttachCapabilities(AttachCapabilitiesEvent<ItemStack> event) {
ItemStack stack = event.getObject();
if (stack.is(Items.DIAMOND_CHESTPLATE)) {
int slots = 5, maxTier = GTValues.HV;
List<ItemModuleSlot> defaultSlots = new ArrayList<>();
for (int i = 0; i < slots; i++) defaultSlots.add(GTItemModules.TIERED_SLOTS[maxTier]);
// ModularItemStack accepts a Function<ItemStack, List<ItemModuleSlot>> in the constructor
// The stack provided to that function is the same stack as here, so we can ignore it
event.addCapability(GTCEu.id("modular"), new ModularItemStack(stack, ignored -> defaultSlots));
}
}
}
Attaching a ModularItemComponent to a ComponentItem
ItemModuleSlot
An ItemModuleSlot is basically a Predicate<ItemModule> (a function that accepts an ItemModule and returns a boolean) with some other methods.
It has 3 abstract methods for your subclasses to implement:
acceptsModule(ItemModule)->booleanreturns whether the provided module can be put into this slotgetDisplayName()->Componentreturns the text to be displayed as part of the tooltipgetSlotTexture()->IDrawable(returnsnullby default) returns the texture to use for this slot in the equipment foundry UI,nullmeans to use the default
Tiered slot implementation
public class TieredItemModuleSlot extends ItemModuleSlot {
@Getter
private final int tier;
public TieredItemModuleSlot(ResourceLocation id, int tier) {
super(id);
this.tier = tier;
}
@Override
public boolean acceptsModule(ItemModule module) {
return !(module instanceof ITieredItemModule tieredModule) || tieredModule.getTier() <= getTier();
}
@Override
public Component getDisplayName() {
return Component.translatable("gui.gtceu.module_slot.tiered", GTValues.VNF[getTier()]);
}
}
ItemModule
ItemModule is an NBT-serializable object that can be attached to modular items.
AppliedItemModule is an object that contains info about the module itself, the item
it is applied to, and the module's NBT.
List of all overridable methods in ItemModule
getInfo()->Component(override required)
returns the info about this module to display in XEIonAttach(AppliedItemModule)->void
called when this module is attached to a modular itemonRemove(AppliedItemModule)->void
called when this module is removed from a modular itemonEquip(LivingEntity, AppliedItemModule)->void
called when the armor piece this module is attached to is equippedonUnequip(LivingEntity, AppliedItemModule)->void
called when the armor piece this module is attached to is unequippedonArmorTick(LivingEntity, AppliedItemModule)->void
called each tick while the armor piece this module is attached to is equippedonInventoryTick(Player, AppliedItemModule)->void
called each tick while the item this module is attached to is in a player's inventoryappendHoverText(Level, TooltipFlag, List<Component>, AppliedItemModule)->void
called to insert lines into the modular item's tooltipuseEnergyInInventory(LivingEntity, AppliedItemModule)->boolean(defaulttrue)
returns whether to consume energy while the item is in a player's inventory, iffalse, the item consumes energy only in armor slotsenergyUsagePerTick(LivingEntity, AppliedItemModule)->long(default0)
returns the amount of energy to consume this tick (called every tick)changeDamage(LivingEntity, AppliedItemModule, float damage, DamageSource)->float(returnsdamageby default)
returns the amount of damage to actually inflict, called each time the entity wearing the armor piece is damagedcanRemove(AppliedItemModule)->boolean(defaulttrue)
returns whether this module can be removed from the item in an equipment foundryisPPE(AppliedItemModule)->boolean(defaultfalse)
returns whether armor pieces with this module should be considered personal protection equipment (hazmat)canApplyTo(ItemStack)->boolean
returns whether this module can be attached to the provided stack, by default returns whether a module of this type is already attached to the stack (blocking more than one module of the same type)isEnabled(AppliedItemModule)->boolean(defaulttrue)
returns whether this module is enabled (all other methods, such asonInventoryTickwon't be calld if it's disabled)setEnabled(AppliedItemModule, boolean)->void
by default, sets the return value ofisEnabledby modifying this module's NBT; this method is not required to actually enable/disable this moduleuse(AppliedItemModule, Level, Player, InteractionHand)->InteractionResultHolder<ItemStack>
called when the item this module is attached to is useduseOn(AppliedItemModule, UseOnContext)->InteractionResult
called when the item this module is attached to is used on a block
Example of an energy shield module
public class EnergyShieldItemModule extends TieredItemModule {
public EnergyShieldItemModule(ResourceLocation id, int tier) {
super(id, tier);
}
@Override
public Component getInfo() {
return Component.literal("Makes you invulnerable and consumes 1A " + GTValues.VNF[getTier()]);
}
@Override
public long energyUsagePerTick(LivingEntity entity, AppliedItemModule module) {
return GTValues.V[getTier()];
}
@Override
public float changeDamage(LivingEntity entity, AppliedItemModule module, float amount, DamageSource source) {
return 0;
}
@Override
public void appendHoverText(Level level, TooltipFlag isAdvanced, List<Component> tooltips,
AppliedItemModule module) {
super.appendHoverText(level, isAdvanced, tooltips, module);
tooltips.add(Component.literal("Energy shield (" + GTValues.VNF[getTier()] + ")"));
}
}