Start Coding

Transform into a mob!

  1. Api Levels
  2. Integrations
  3. Shape Events
  4. Every Day Use API
    1. PlayerShape
    2. PlayerAbilities
    3. PlayerShapeChanger
    4. PlayerHostility
    5. Flight Helper
  5. Tick Handler

This page describes most of the thinks you need to know when you’re trying to create an addon or any kind of other mod, that depends on Woodwalkers.

Api Levels

This logic is intended for mod creators, which want to use Woodwalkers as a library instead of a gameplay mod. You can set a new Api Level using this code:

ApiLevel.setApiLevel(apiLevel);

To invoke code once the Api Level is changed, use this code snippet:

ApiLevel.ON_API_LEVEL_CHANGE_EVENT.register(newLevel -> {
            LogUtils.getLogger().info("the api level was changed to " + newLevel);
        });

Note that Api Levels can be modified by server-side mods and will be send to the client once they join the world.

To check for the current Api Level use this code:

ApiLevel.getCurrentLevel(); // check for the current api level, that is loaded by the server
ApiLevel.getClientLevel(); // check for the current api level, that will be restored once the client leaves the server

Here are all Api Levels:

    /**
     * The players can't use Woodwalkers unlock method, can't open the variants menu and can't morph themselves but only via commands or code
     */
    API_ONLY,
    /**
     * The players can't open the variants menu and can't morph themselves but only via commands or code and can still use Woodwalkers unlock method to set their 2nd Shape
     */
 UNLOCK_ONLY,
    /**
     * The players can't use Woodwalkers unlock method, can't open the variants menu but can still morph freely
     */
 MORPHING_ONLY,
    /**
     * The players can't use Woodwalkers unlock method, but can open the variants menu and can morph freely
     */
 MORPHING_AND_VARIANTS_MENU_ONLY,
    /**
     * The players can use Woodwalkers without limitations
     */
 DEFAULT;

Integrations

This logic is meant to allow mod-compatible traits and abilities.

You have to register integrations during the initialization step of your mod:

register(ExampleIntegration.MODID, ExampleIntegration::new);

The integration will only be loaded, if a mod with the specified ModID was found and loaded. Here are the things you can do with Integrations:

public class ExampleIntegration extends AbstractIntegration {
    public static final String MODID = "example";

    /**
     * Called to load the integration (only when the required mod is loaded)
     */
    @Override
    public void initialize() {
        LogUtils.getLogger().info("Example Integration was loaded.");
    }

    /**
     * Called to add custom abilities via {@link AbilityRegistry}
     */
    public void registerAbilities() {
        AbilityRegistry.registerByClass(EnderDragon.class, new ShootDragonFireball<>());
    }

    /**
     * Called to add custom traits via {@link tocraft.walkers.traits.TraitRegistry TraitRegistry}
     */
    public void registerTraits() {
        TraitRegistry.registerByClass(Zombie.class, new BurnInDaylightTrait<>());
    }

    /**
     * Called to add custom variants via {@link tocraft.walkers.api.variant.TypeProviderRegistry TypeProviderRegistry}
     */
    public void registerTypeProvider() {
        TypeProviderRegistry.register(EntityType.WOLF, new WolfTypeProvider());
    }
    /**
     * Called to blacklist mods via {@link tocraft.walkers.api.blacklist.EntityBlacklist EntityBlacklist}
     */
    public void registerEntityBlacklist() {
        EntityBlacklist.registerByType(EntityType.WITHER);
    }


    /**
     * called to modify the way entities attack a morphed player
     *
     * @param mob the mob that wants to attack the player
     * @param target the player that is morphed
     * @return whether the mob can attack the morphed player
     */
    @SuppressWarnings("unused")
    public boolean mightAttackInnocent(Mob mob, Player target) {
        return mob.getTeam() == target.getTeam();
    }
}

Shape Events

These Events are based on CraftedCore Events. Here’s an example implementation to help you better understand each event:

@Override
public void initialize() {
    ShapeEvents.SWAP_SHAPE.register((player, to) -> {
        LogUtils.getLogger().info("player {} wants to morph into a {}", player.getDisplayName(), to != null ? to.getType().getDescriptionId() : "player");
        return InteractionResult.PASS; // PASS for continuing the event handling, success to force to morph into the mob, FAIL to fail morphing
    });
    ShapeEvents.UNLOCK_SHAPE.register((player, to) -> {
        LogUtils.getLogger().info("player {} wants to unlock a {}", player.getDisplayName(), to != null ? to.writeCompound().toString() : "player");
        return InteractionResult.PASS; // PASS for continuing the event handling, success to force the unlocking, FAIL to fail unlocking
    });
    ShapeEvents.USE_SHAPE_ABILITY.register((player, ability) -> {
        LogUtils.getLogger().info("player {} wants to use the ability {}", player.getDisplayName(), ability.getId());
        return InteractionResult.PASS; // PASS for continuing the event handling, success to force the usage of the ability, FAIL to not use the ability
    });
}

Every Day Use API

This section describes API that is the base for most of the mod.

PlayerShape

This class handles the most important game logic of the Woodwalkers mod: The current shape.

PlayerShape.getCurrentShape(player); // returns the current shape as LivingEntity
PlayerShape.updateShapes(player, shape); // updates the current shape to the specified shape or resets it if shape is null

PlayerAbilities

This class handles everything connected with using Abilities.

PlayerAbilities.getCooldown(player); // return the time in ticks the player has to wait until they can use another Ability
PlayerAbilities.canUseAbility(player); // whether the player can use another ability
PlayerAbilities.setCooldown(player); // overwrite the current Ability cooldown
PlayerAbilities.useAbility(player); // force the player to use their current ability

PlayerShapeChanger

This class changes the second shape of the player.

PlayerShapeChanger.change2ndShape(player, newShapeType);

PlayerHostility

This class handles the hostility logic, where e.g. a player morphed as Zombie can trigger other hostile mobs to attack him by right-clicking just one.

PlayerHostility.hasHostility(player) // whether other mobs attack the current player even if they are morphed as an Enemy
PlayerHostility.set(player, time); // overwrites the hostility time of the player

Flight Helper

If you need for some reason to modify the way Woodwalkers grants or revokes flying, you can use the FlightHelper class.

    @Override
public void initialize() {
    FlightHelper.GRANT.register(player -> {
        boolean bool = grantFlight(player); // custom method to handle the flight granting
        return bool ? InteractionResult.SUCCESS : InteractionResult.PASS; // success means, woodwalkers will skip it's built-in logic to grant flight
    });
    FlightHelper.REVOKE.register(player -> {
        boolean bool = revokeFlight(player); // custom method to handle the flight revoking
        return bool ? InteractionResult.SUCCESS : InteractionResult.PASS; // success means, woodwalkers will skip it's built-in logic to revoke flight
    });
}

Tick Handler

You can also register a custom Tick Handler, that is called each tick the player is morphed as a specific EntityType.

@Override
public void initialize() {
    WalkersTickHandlers.register(EntityType.WOLF, new WalkersTickHandler<Wolf>() {
        @Override
        public void tick(Player player, Wolf entity) {
            LogUtils.getLogger().info("the player - wolf tick is called.");
        }
    });
}