Skip to content

Perks (API)

Caltinor edited this page Dec 6, 2022 · 7 revisions

Perks are an extensible feature of Project MMMO that allows other mods and addons to register custom behavior that players can then configure.

NOTE: This is undergoing a major revision in 1.20

A Basic implementation

At its core, a perk is just a org.apache.commons.lang3.function.TriFunction that executes under a specific condition. The function is provided:

  • A net.minecraft.world.entity.player.Player for which the perk applies
  • A net.minecraft.nbt.CompoundTag of data inputs that certain events provide including the settings from the player's config
  • An Integer of the player's current level in the skill specified by the config.

and returns:

  • A CompoundTag of output data that certain events can use. A simplified example would be
public static final TriFunction<Player, CompoundTag, Integer, CompoundTag> EXAMPLE_PERK = (player, dataIn, level) -> {
    player.sendMessage(new TextComponent("My custom perk was activated!"), player.getUUID());
    return new CompoundTag();
};

Registering a Perk

in order for players to be able to use your perk in their configurations, you need to register your perk during FMLCommonSetupEvent using harmonised.pmmo.api.APIUtils.registerPerk. There are four parameters to this registration:

  • ResourceLocation a unique identifier for your perk. This will be used by players to reference your perk. eg "pmmo:jump_boost"
  • onExecute a perk implementation that fires in most cases
  • onTerminate a perk implementation called when the onExecute condition is no longer valid (see event spec) and in the DISABLE_PERK event as a means to undo changes made by perks such as attribute modifications.
  • PerkSide whether this should fire on the CLIENT, SERVER, BOTH. If your implementation will vary based on side, it might be good to register a perk for each side using the same identifier. a good example of a dual-implementation both-sided perk is the pmmo jump perk which does different things on each side, but both are needed for the perk to behave correctly.

Technical Notes

  1. Perks are skill agnostic: This means that you are not meant to know what skill your perk is being configured for. You may think this is a combat perk, but I want to use it with my custom zombie_hugging skill. Because of this, you are only given the level. There are some cases where you need to know the skill. In that case it is recommended you model the firework perk as this needs the skill name to know how to color the firework.
  2. Make your settings optional: you should assume that players won't look up your settings and you should have defaults built into your perk.
  3. Server Perks: Any perk you register only server-side does not need to be present on the client. This can allow you to have proprietary perks on your server that the client doesn't need. Note that there are limitations related to latency and rendering that you need to factor in.

XP Award Maps

Most events allow perks to set the initial values of the xp awards before other award logic is executed. to provide PMMO with a custom map, use the method APIUtils.serializeAwardMap(Map<String, Long> awardMap) to get a ListTag object representing your map and add that to your output CompoundTag using the key APIUtils.SERIALIZED_AWARD_MAP.

Event Reference

Except for the EventTypes listed below, all perk registrations call only the onExecute call, do not have any inputs, and only utilize xpAwardMap outputs. Only the config settings will be passed to your perk and outputs will be pointless.

Note: All tag keys are referenced in APIUtils.class

  • BREAK_SPEED
    • -> BREAK_SPEED_INPUT_VALUE = the original break speed
    • -> BLOCK_POS = the position of the block being broken
    • <- BREAK_SPEED_OUTPUT_VALUE = the new speed to be set.
  • DEAL_MELEE_DAMAGE, MELEE_TO_MOBS, MELEE_TO_ANIMALS, MELEE_TO_PLAYERS, DEAL_RANGED_DAMAGE, RANGED_TO_MOBS, RANGED_TO_ANIMALS, RANGED_TO_PLAYERS
    • -> DAMAGE_IN = the original damage supplied by the event
    • <- DAMAGE_OUT = the new damage to be applied
  • RECEIVE_DAMAGE, FROM_PLAYERS, FROM_ENVIRONMENT, FROM_IMPACT, FROM_MAGIC, FROM_MOBS, FROM_ANIMALS, FROM_PROJECTILES
    • -> DAMAGE_IN = the original damage supplied by the event
    • <- DAMAGE_OUT = the new damage to be applied
  • ENCHANT (server-side only)
    • -> STACK = the item being enchanted
    • -> PLAYER_ID = the UUID of the player enchanting
    • -> ENCHANT_LEVEL = the level of the enchantment
    • -> ENCHANT_NAME = the name of the enchantment
  • SMELT
    • -> STACK the serialized itemstack being smelted/cooked
  • JUMP, SPRINT_JUMP, CROUCH_JUMP
    • <- JUMP_OUT = an arbitrary value that the xp is scaled off of. does not actually affect jump height unless done in the perk itself.
  • DIABLE_PERK
    • no input/output, but it runs on player login.
  • SHIELD_BLOCK
    • -> DAMAGE_IN = damage that is being blocked

Note To Devs

It is incredibly easy to add extra inputs and outputs to this system and has negligible performance impacts. If there is anything you would like added to any event for a custom perk you are building, contact me on the discord or open an issue here. I will happily add them.

Clone this wiki locally