Developer API - Arnuh/EchoPet GitHub Wiki

As A Maven Dependency

If you're familiar with Maven, you'll be able to automatically download EchoPet as a dependency using the following setup.

<repository>
    <id>arnah-group</id>
    <url>https://repo.arnah.ca/repository/maven-group/</url>
</repository>
<dependency>
    <groupId>com.dsh105<groupId>
    <artifactId>EchoPet-API</artifactId>
    <version>1.3.0-SNAPSHOT</version>
    <scope>provided</scope>
</dependency>

Note: Change the version to whatever you require.

Accessing The API

The EchoPet Developer API can be accessed used the following method.

public EchoPetAPI getEchoPetAPI() {
    return EchoPetAPI.getAPI();
}

Using The API

The EchoPet Developer API allows developers access to a wide range of utilities that can be used to control Pets initiated using the plugin.

List Of Methods

Method Name Description/Function
givePet(Player.class, IPetType.class, Boolean.class) Gives a Pet to the specified player. If the third parameter is true, the player will also be notified of their new Pet.
removePet(Player.class, Boolean.class Removes any Pet a player has.
hasPet(Player.class) Checks whether a Player has a Pet. Returns a boolean value depending on the result.
getPet(Player.class) Gets a Player's Pet. Will return null if the Player does not have a Pet.
getAllPets() Returns an Array of all active Pets.
teleportPet(IPet.class, Location.class) Teleport's a Pet to a certain Location. The Pet's owner can be retrieved using pet.getOwner()
setData(IPet.class, PetData.class) Sets the specified data to for a Pet.
removeData(IPet.class, PetData.class) Removes/deactivates a data option for a Pet.
hasData(IPet.class, PetData.class) Checks whether a Pet has a data option enabled.
addGoal(IPet.class, Integer.class, PetGoal.class) Adds a Goal to a Pet's AI.
removeGoal(IPet.class, String.class) Removes a Goal from a Pet's AI by its Identifier
removeGoal(IPet.class, PetGoal.class) Removes a Goal instance from a Pet's AI

Referenced Classes:

  • Player.class: Player object from the Bukkit API
  • PetType.class: API Enumeration, representing all available Pet Types (com.github.dsh105.echopet.data.PetData)
  • Pet.class: Represents a Pet object (com.github.dsh105.echopet.entity.pet.Pet)
  • Location.class: Location object from the Bukkit API
  • PetData.class: API Enumeration of all valid Data options for all Pets. Note that only some data types may be applied to certain Pets. Use pet.getPetType() (com.github.dsh105.echopet.data.PetType) to check Entity Types
  • LivingEntity.class: Represents a Living Entity (org.bukkit.entity.LivingEntity)
  • GoalType.class: API Enumeration of already included Goals to add to a Pet's AI
  • PetGoal.class: API Super class representing all PetGoals. A tutorial for extending this can be found below.

Accessing EchoPetPlugin

Not everything is provided in the EchoPetAPI class so you may be interested in accessing EchoPet and IEchoPetPlugin.

EchoPet can be accessed anywhere, but IEchoPetPlugin requires you to call EchoPet.getPlugin() Accessing these provides you with things like the following:

  • IPetManager: The internal methods of most methods in EchoPetAPI
  • IStorageManager: EchoPets internal saving & loading methods.
  • IPetRegistry: EchoPets internal spawning & registering of Pets.
  • YamlConfig: Access to EchoPets configs
  • ISpawnUtil: Internal NMS helper methods
  • ICraftBukkitUtil: Internal craftbukkit helper methods

Using EchoPet implementations

Sometimes you want to expand onto EchoPet in cases where the EchoPet API doesn't allow you. You can instead depend directly on EchoPet itself in this case.

Change your dependency to the following:

<dependency>
    <groupId>com.dsh105<groupId>
    <artifactId>EchoPet</artifactId>
    <version>1.3.0-SNAPSHOT</version>
    <scope>provided</scope>
</dependency>

This opens up the ability to extend off the code of EchoPet, like what is used in the Model Engine Extension to avoid the need to duplicate the code in the Pet class when adding additional pets.

Custom Events

Event Name Function
PetAttackEvent Called when a Pet attempts to damage a target. Cancelling this event will not cancel the animation, only the damage dealt.
PetDamageEvent Called when a Pet is damaged.
PetInteractEvent Called when a Player interacts (right or left click) with a Pet.
PetMenuOpenEvent Called when a Pet's Owner opens the PetMenu for their Pet.
PetMoveEvent Called when a Pet moves while following it's Owner or riding.
PetPreSpawnEvent Called when a Pet is attempting to be spawned.
PetRideJumpEvent Called when a Player attempts to jump while riding their Pet.
PetRideMoveEvent Called when a Player moves while riding their Pet.
PetSpawnEvent Called when a Pet spawns.
PetTeleportEvent Called when a Pet teleports.

Creating PetGoals

Custom AI Goals can be created and applied to Pets through the Developer API. For this tutorial, a simple goal (floating in water) is used.

First, create a class that extends PetGoal.

public class TestPetGoal extends PetGoal {
    private final IEntityPet pet;

    public TestPetGoal(IEntityPet pet) {
        this.pet = pet;
        this.setFlags(EnumSet.of(PetGoal.Flag.MOVE));
    }
}

There are five important methods that can be accessed inside this class now:

  • setFlags(EnumSet<PetGoal.Flag>) - Determines what type of action the PetGoal does, used to disable certain actions.
  • getIdentifier() - String identifier for the Goal.
  • canUse() - Called to check whether the method should start.
  • canContinueToUse() - Called to check whether the Goal should continue ticking.
  • start() - Called when the Goal starts executing.
  • stop() - Called when the Goal finished executing.
  • tick() - Called every tick if the Goal has started.

Goals have a couple additional methods:

  • isInterruptable() - Determines if it can be replaced by a higher priority Goal.

In this example, it checks if the Pet is currently in liquid, and teleports it to its owner.

@Override
public boolean canUse(){
    Location location = pet.getPet().getLocation();
    World world = location.getWorld();
    if(world == null) return false;
    return world.getBlockAt(location).isLiquid();
}

@Override
public void tick(){
    pet.getEntity().teleport(pet.getOwner().getLocation());
}

The final class looks like this:

public class TestPetGoal extends PetGoal{

    private final IEntityPet pet;

    public TestPetGoal(IEntityPet pet){
        this.pet = pet;
        this.setFlags(EnumSet.of(PetGoal.Flag.JUMP));
    }

    @Override
    public String getIdentifier(){
        return "TestGoal";
    }

    @Override
    public boolean canUse(){
        Location location = pet.getPet().getLocation();
        World world = location.getWorld();
        if(world == null) return false;
        return world.getBlockAt(location).isLiquid();
    }

    // By default, canContinueToUse uses canUse. Don't need any extra checks so it is not included.

    @Override
    public void tick(){
        pet.getEntity().teleport(pet.getOwner().getLocation());
    }
}

Now add this goal to your pet.

EchoPetAPI.getAPI().addGoal(pet, new TestPetGoal(pet.getEntityPet()), 0);

And you're done! Any pet with this goal will now teleport to you when it touches a liquid.

Detecting Pets

Using NamespacedKey

If you have access to IEchoPetPlugin, you can grab the getPetNamespacedKey and check the PDC of any entity for a byte boolean.

Without access to IEchoPetPlugin, you can make a NamespacedKey using new NamespacedKey("echopet", "pet") and check with the type PersistentDataType.BYTE like normal.

Using the API

Basic idea is you just check if the NMS entity is an instanceof IEntityPet

IEchoPetPlugin#getCraftBukkitUtil#getEntityHandle(Entity) Can be used to achieve this, and you can see an example used in EchoPet

Other Examples

You can see other examples of the API maintained by the Developer of EchoPet in the readme.

An example is the Model Engine Extension which adds completely custom Pets by integrating with the Model Engine API.

⚠️ **GitHub.com Fallback** ⚠️