API - Pyrbu/ZNPCsPlus GitHub Wiki
To use the ZNPCsPlus API in your project, add the following Maven repository to your pom.xml
:
<repository>
<id>pyr-snapshots</id>
<name>Pyr's Repo</name>
<url>https://repo.pyr.lol/snapshots</url>
</repository>
Add the following Maven dependency to your pom.xml
:
<dependency>
<groupId>lol.pyr</groupId>
<artifactId>znpcsplus-api</artifactId>
<version>{version}</version>
<scope>provided</scope>
</dependency>
Replace {version}
with
For Gradle projects, add the following repository to your build.gradle
:
maven {
name "pyrSnapshots"
url "https://repo.pyr.lol/snapshots"
}
Add the following dependency to your build.gradle
:
compileOnly "lol.pyr:znpcsplus-api:{version}"
Replace {version}
with
Explore the API structure of ZNPCsPlus by referring to the concise JavaDoc here
To start working with the API, obtain an instance of NpcApi
:
NpcApi npcApi = NpcApiProvider.get();
Before creating an NPC, retrieve the desired NPC type:
NpcType playerNpcType = npcApi.getNpcTypeRegistry().getByName("player"); // Case-insensitive
if (playerNpcType == null) {
System.out.println("NPC type does not exist or is not available on this server version.");
return;
}
Create an NPC with the desired type, location, and settings:
NpcEntry playerNpc = npcApi.getNpcRegistry().create(
"npc1", // NPC ID
Bukkit.getWorlds().get(0), // World instance
playerNpcType, // NPC type
new NpcLocation(0, 100, 0, 0, 0) // x, y, z, yaw, pitch
);
// Enable the NPC to be processed by the plugin
playerNpc.setProcessed(true);
/*
* If you need custom logic for NPC visibility per player, keep "processed" disabled.
* Note: Disabling "processed" will prevent certain properties (e.g., look behavior,
* view distance, permission-based visibility, and knockback properties) from functioning.
*/
// Enable the NPC to be saved in the plugins storage
playerNpc.setSave(true);
// Enable the NPC to be modified by commands
playerNpc.setAllowCommandModification(true);
// Alternatively, you can use the following method to enable all of the above at once
playerNpc.enableEverything();
Retrieve an NPC that is already registered using its ID:
NpcEntry retrievedNpc = npcApi.getNpcRegistry().getById("npc1");
if (retrievedNpc != null) {
System.out.println("NPC found: " + retrievedNpc.getId());
}
Remove an NPC from the registry:
npcApi.getNpcRegistry().delete("npc1");
Customize an NPC by applying a property:
// Get the "dinnerbone" property (makes entities appear upside down)
EntityProperty<Boolean> dinnerboneProperty = npcApi.getPropertyRegistry().getByName("dinnerbone", Boolean.class);
// Apply the property to an NPC
NpcEntry zombieNpc = npcApi.getNpcRegistry().getById("zombie1");
if (zombieNpc != null) {
zombieNpc.getNpc().setProperty(dinnerboneProperty, true);
}
Register a dummy property for testing:
npcApi.getPropertyRegistry().registerDummy("my_property", Boolean.class);
Create a MessageAction
and assign it to an NPC:
// Create an action that sends a message when left-clicked
InteractionAction action = npcApi.getActionFactory().createMessageAction(
"Hello, world!", // Message
InteractionType.LEFT_CLICK, // Interaction type
5, // Cooldown in seconds
0 // Delay in ticks
);
// Assign the action to the NPC
zombieNpc.getNpc().addAction(action);
Skins are only available for player NPC types. Here's how to set different skin types:
SkinDescriptor mirrorDescriptor = npcApi.getSkinDescriptorFactory().createMirrorDescriptor();
SkinDescriptor staticSteveDescriptor = npcApi.getSkinDescriptorFactory().createStaticDescriptor("steve");
SkinDescriptor staticTextureDescriptor = npcAPI.getSkinDescriptorFactory().createStaticDescriptor("ewogICJ0aW1lc3RhbXAiIDogMTczNTExNzEzNzY0MSwKICAicHJvZmlsZUlkIiA6ICIxNmQ4NjI4NzYzMWY0NDY2OGQ0NDM2ZTJlY2IwNTllNSIsCiAgInByb2ZpbGVOYW1lIiA6ICJSZXphVG91cm5leSIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS81ODc0Nzk0OWMxOTUyMWEwYTAwOTgwYjNhMGVkODJjYzIzNmVkMjc5OWIzMGNiZDY4Nzk1ZGNiMDg5NTE5Y2NhIiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0=", "ZzIpWZCCCT6H95QQk0SCwF8hWjWL+J764KqH8hhpmTl5SfCHnoj8W4wZnPevrO+q213NgzGmZVEVucR16stX/39+H+NmLFILOBh+FDbRQgEhheyZGYEIj+25gvKRHddHW5eLIS+fOrXDXFffktLR8ImEtFQzFNWVQ8YHb6jmth2OUJgVTxz76UYZ0RVo/8dYbARijWyypTc95+8rOImoJl2f77qiIsPptxeorHdJ6+i0LfFQnbQzGO9GDVjShso/B1UMdoFEITO4MVG8RYpV7F1Awd7891N2vdhIAPWptIADAK/VFU6HG5dyOJoB8FEjPK5vpV/qaH5MQ5JqO2tjT6re1BEeKamymRX+LsgNJYq360gJAsf93tR1Q7oI8GtJ/6KGymGNRH5X6dPVNAgIx6yRvqbBDFW12bYlWFGvdY3kTYn50xe5oFtm6gas5CHJdnGL86m4iunNVtE7GKvYrXtxcAEP2HzfZ5b4eOyK5LOi8A55Z2rNmCKn/5YPX50OjpooNsZivrOvu4+qrs7EMa7JOqqKeq8WE+duLykJr1qXoURY4cz7JDGqHLJrE7E2FaQf4JoMdzdxNZIfvwFzhIh9TcQ/6iSOf439lc54d6vJuGcXLXBjmSq7GNAawxNTy7d3V/Bo0bnrQEh1EKE1LlkUP3ubnw+CW7jJcx9pPd8=");
SkinDescriptor dynamicSteveDescriptor = npcAPI.getSkinDescriptorFactory().createRefreshingDescriptor("Steve");
SkinDescriptor dynamicPlaceholderDescriptor = npcAPI.getSkinDescriptorFactory().createRefreshingDescriptor("%top_player_1_name%");
SkinDescriptor urlDescriptor = npcApi.getSkinDescriptorFactory().createUrlDescriptor(
"https://www.minecraftskins.com/uploads/skins/2024/12/24/iceman-22953593.png?v737",
"slim"
);
SkinDescriptor fileDescriptor = npcAPI.getSkinDescriptorFactory().createFileDescriptor("skin2.png");
Note: the file should be in the folder, ./plugins/ZNPCsPlus/skins
// Get the "skin" property
EntityProperty<SkinDescriptor> skinProperty = npcApi.getPropertyRegistry().getByName("skin", SkinDescriptor.class);
// Apply the skin to the NPC
playerNpc.getNpc().setProperty(skinProperty, staticSteveDescriptor);
Save an NPC to a YAML format:
NpcSerializer<YamlConfiguration> yamlSerializer = npcApi.getNpcSerializerRegistry().getSerializer(YamlConfiguration.class);
YamlConfiguration serializedPlayerNpc = yamlSerializer.serialize(playerNpc);
Load an NPC from YAML and register it:
NpcEntry deserializedPlayerNpc = yamlSerializer.deserialize(serializedPlayerNpc);
npcApi.getNpcRegistry().register(deserializedPlayerNpc);
For guidance, join our Discord community.