### Minimal NPC Spawning Example in Java Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Provides a basic Java example of setting up the BukkitPlatform and spawning an NPC. This example utilizes the default action controller, which automatically manages NPC visibility and tracking within a specified range after building. ```java public final class TestPlugin extends JavaPlugin { private final Platform platform = BukkitPlatform .bukkitNpcPlatformBuilder() .extension(this) .actionController(builder -> {}) // enable action controller without changing the default config .build(); public void spawnNpc(Location location) { this.platform.newNpcBuilder() .position(BukkitPlatformUtil.positionFromBukkitLegacy(location)) .profile(Profile.unresolved("derklaro")) .thenAccept(builder -> { var npc = builder.buildAndTrack(); // continue using the npc... npc.unlink(); // when the npc is no longer needed it can be completely removed using this method }); } } ``` -------------------------------- ### Implement NPC-Lib Plugin for Bukkit Source: https://context7.com/juliarn/npc-lib/llms.txt A comprehensive example showing the setup of a BukkitPlugin that initializes the NPC platform and registers listeners for NPC interactions, attacks, and post-spawn events. It includes logic for spawning, removing, and configuring NPC behaviors. ```java import com.github.juliarn.npclib.bukkit.BukkitPlatform; import com.github.juliarn.npclib.api.*; import com.github.juliarn.npclib.api.event.*; import com.github.juliarn.npclib.api.profile.Profile; import com.github.juliarn.npclib.api.protocol.enums.EntityAnimation; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import java.util.HashMap; import java.util.Map; public class NpcPlugin extends JavaPlugin { private Platform platform; private final Map> activeNpcs = new HashMap<>(); @Override public void onEnable() { initializePlatform(); registerEventHandlers(); } private void initializePlatform() { platform = BukkitPlatform.bukkitNpcPlatformBuilder() .extension(this) .actionController(builder -> builder .flag(NpcActionController.SPAWN_DISTANCE, 60) .flag(NpcActionController.AUTO_SYNC_POSITION_ON_SPAWN, true)) .build(); } private void registerEventHandlers() { var eventManager = platform.eventManager(); eventManager.registerEventHandler(InteractNpcEvent.class, event -> { event.npc().playAnimation(EntityAnimation.SWING_MAIN_ARM).schedule(event.npc().trackedPlayers()); }); } private void spawnNpc(Location location, String name) { Position position = Position.position(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch(), location.getWorld().getName()); platform.newNpcBuilder() .position(position) .profile(Profile.unresolved(name)) .thenAccept(builder -> { Npc npc = builder.buildAndTrack(); activeNpcs.put(name, npc); }); } @Override public void onDisable() { activeNpcs.values().forEach(Npc::unlink); } } ``` -------------------------------- ### Create and Spawn NPCs Source: https://context7.com/juliarn/npc-lib/llms.txt Shows how to create NPC instances using the platform builder. These examples cover spawning with name-based profiles, UUID profiles, and setting custom entity IDs for tracking. ```java import com.github.juliarn.npclib.api.Npc; import com.github.juliarn.npclib.api.Position; import com.github.juliarn.npclib.api.profile.Profile; import org.bukkit.Location; public void spawnBasicNpc(Location location) { Position position = Position.position( location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch(), location.getWorld().getName() ); platform.newNpcBuilder() .position(position) .profile(Profile.unresolved("Notch")) .thenAccept(builder -> { Npc npc = builder.buildAndTrack(); getLogger().info("NPC spawned with entity ID: " + npc.entityId()); }) .exceptionally(throwable -> { getLogger().severe("Failed to spawn NPC: " + throwable.getMessage()); return null; }); } ``` ```java import java.util.UUID; public void spawnNpcWithUuid(Location location, UUID playerUuid) { Position position = Position.position( location.getX(), location.getY(), location.getZ(), location.getWorld().getName() ); platform.newNpcBuilder() .entityId(12345) .position(position) .profile(Profile.unresolved(playerUuid)) .thenAccept(builder -> { Npc npc = builder.buildAndTrack(); npc.flagValue(Npc.LOOK_AT_PLAYER).ifPresent(lookAtPlayer -> getLogger().info("NPC look-at-player: " + lookAtPlayer) ); }); } ``` -------------------------------- ### Initialize NPC Platform on Minestom Source: https://github.com/juliarn/npc-lib/blob/v3/README.md This snippet shows how to get a builder for the NPC platform specifically for the Minestom server implementation. It's the starting point for integrating NPC functionality within a Minestom environment. ```java MinestomPlatform.minestomNpcPlatformBuilder() ``` -------------------------------- ### Configure NPC Action Controller Distances in Java Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Illustrates how to customize the action controller for NPCs in Java. This example sets specific distances for when NPCs are spawned to players (SPAWN_DISTANCE) and when NPC imitation starts (IMITATE_DISTANCE). ```java public final class TestPlugin extends JavaPlugin { private final Platform platform = BukkitPlatform .bukkitNpcPlatformBuilder() .extension(this) .actionController(builder -> builder .flag(NpcActionController.SPAWN_DISTANCE, 100) .flag(NpcActionController.IMITATE_DISTANCE, 50)) .build(); } ``` -------------------------------- ### Include NPC-Lib as Dependency Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Configuration examples for adding NPC-Lib modules to your project using Maven or Gradle build systems. ```xml io.github.juliarn (module name from the list above) (latest version) compile ``` ```kotlin implementation("io.github.juliarn", "(module name from the list above)", "(latest version)") ``` -------------------------------- ### Configure Bukkit NPC Platform Source: https://github.com/juliarn/npc-lib/blob/v3/README.md This extensive Java code example illustrates the configuration of the NPC platform for the Bukkit server implementation. It covers numerous options including debug logging, extension, logger, event manager, NPC tracker, task manager, profile resolver, world accessor, version accessor, packet factory, and action controller settings. It demonstrates how to customize the platform's behavior and integration with the Bukkit environment. ```java BukkitPlatform.bukkitNpcPlatformBuilder() // enables debug logging in the platform. this mostly enables errors // to be printed into the console directly instead of being held back // to prevent spamming the console. // Defaults to false (debug disabled). .debug() // sets the extension of the platform, which is usually the plugin that // uses the plugin. on bukkit this is for example used to schedule sync // tasks using the bukkit scheduler. // This option has no default and must be set. .extension() // the logger to use for internal logging of the library. while this logger // has the possibility to log info messages, the level won't be used unless // information relevant to the user are being printed. // Defaults to a platform-specific logger instance, on bukkit it uses an // implementation which is backed by the plugin logger. .logger() // the event manager to use for the platform. all events, such as npc interacts // or spawns are propagated using this event manager. // Defaults to an internal default implementation. .eventManager() // the tracker for npcs that are created by this library. as explained below // a spawned npc can either be tracked or kept untracked if not needed. // the tracker is used to store all spawned npcs and automatically execute // actions on them, for example automatic spawning when a player moves into // their spawn distance. it's also used to fire npc events such as interact when // an interact packet is received. // Defaults to an internal default implementation. .npcTracker() // a scheduler for tasks that need to be executed either sync or async. the // implementation depends on the platform, for bukkit it's backed by the bukkit // scheduler, on minestom the minestom scheduler is used. // Defaults to a platform-specific implementation. .taskManager() // the resolver to use for npc profiles. the resolver is given an unresolved // version of a profile (for example only an uuid or name) and completes the // profile data (name, uuid, textures). // see BukkitProfileResolver for the available resolvers on bukkit (paper or spigot) // Defaults to a platform-specific implementation. .profileResolver() // the resolver for worlds of npcs. each npc position contains a world identifier // which is resolved using this resolver. the resolver can also provide the // identifier of a world using the world instance. // see BukkitWorldAccessor for the available resolvers on bukkit (name or key based) // see MinestomWorldAccessor for the available resolver on minestom (uuid based) // Defaults to a platform-specific implementation. .worldAccessor() // the provider for version information about the current platform. it's internally // used to determine which features can be used. an example is the profile resolver: // when on paper 1.12 or later the paper profile resolver is used, when on spigot // 1.18.2 or later the spigot profile resolver is used, else a fallback mojang api // based access is used. // see BukkitVersionAccessor for the bukkit implementation // see MinestomVersionAccessor for the minestom implementation // Defaults to a platform-specific implementation. .versionAccessor() // the factory for packets that need to be sent in order to spawn and manage npcs. // see BukkitProtocolAdapter for the available options on Bukkit (ProtocolLib or PacketEvents) // see MinestomProtocolAdapter for the minestom implementation // Defaults to a platform-specific implementation. .packetFactory() // configures the default action controller for the platform. if this method isn't called // during the build process, the default action controller is disabled. the method provides // a builder which can be used to modify the settings of the action controller. if the default // values should be used, don't call any methods and just provide an empty lambda. .actionController(builder -> builder .flag(NpcActionController.SPAWN_DISTANCE, 5)) // builds the final platform object which can then be used to spawn and manage npcs .build(); ``` -------------------------------- ### Manual NPC Tracking and Visibility Control (Java) Source: https://context7.com/juliarn/npc-lib/llms.txt Provides examples for manually controlling which players can see an NPC. This includes checking tracking rules, forcing tracking, and stopping tracking for specific players, as well as managing inclusion lists. ```java public void manualTrackingExample(Npc npc) { // Check if NPC should include a player based on tracking rules Player player = Bukkit.getPlayer("PlayerName"); if (npc.shouldIncludePlayer(player)) { // Track player (respects tracking rules) npc.trackPlayer(player); } // Force track player (ignores tracking rules) npc.forceTrackPlayer(player); // Check if player is currently tracked if (npc.tracksPlayer(player)) { getLogger().info("NPC is visible to " + player.getName()); } // Stop tracking player npc.stopTrackingPlayer(player); // Get all tracked players Collection trackedPlayers = npc.trackedPlayers(); getLogger().info("NPC visible to " + trackedPlayers.size() + " players"); } ``` ```java public void controlNpcVisibility(Npc npc) { // Add player to included list Player player = Bukkit.getPlayer("SpecialPlayer"); npc.addIncludedPlayer(player); // Check inclusion status if (npc.includesPlayer(player)) { getLogger().info(player.getName() + " is included in NPC visibility"); } // Get all included players Collection includedPlayers = npc.includedPlayers(); // Remove player from included list npc.removeIncludedPlayer(player); // Completely remove NPC and untrack from all players npc.unlink(); } ``` -------------------------------- ### Spawn NPC with Custom Tracking Rules (Java) Source: https://context7.com/juliarn/npc-lib/llms.txt Spawns an NPC with a custom tracking rule, allowing fine-grained control over which players can see the NPC. The example shows a rule that grants visibility only to players with a specific permission and a minimum level. Dependencies include the platform, Location, Position, Profile, and NPC settings for tracking rules. ```java public void spawnNpcWithTrackingRule(Location location) { Position position = Position.position( location.getX(), location.getY(), location.getZ(), location.getWorld().getName() ); platform.newNpcBuilder() .position(position) .npcSettings(settings -> settings .trackingRule((npc, player) -> { // Only show NPC to players with permission return player.hasPermission("mynpc.see") && player.getLevel() >= 10; })) .profile(Profile.unresolved("Guardian")) .thenAccept(builder -> { Npc npc = builder.buildAndTrack(); getLogger().info("NPC with custom tracking rule spawned"); }); } ``` -------------------------------- ### Spawn Imitating NPC with Flags (Java) Source: https://context7.com/juliarn/npc-lib/llms.txt Spawns an NPC that imitates player actions like looking, getting hit, and sneaking. This is configured using specific NPC flags. The NPC is automatically tracked after creation. Dependencies include the platform, Location, Position, Profile, and Npc flags. ```java public void spawnImitatingNpc(Location location) { Position position = Position.position( location.getX(), location.getY(), location.getZ(), location.getWorld().getName() ); platform.newNpcBuilder() .position(position) .flag(Npc.LOOK_AT_PLAYER, true) .flag(Npc.HIT_WHEN_PLAYER_HITS, true) .flag(Npc.SNEAK_WHEN_PLAYER_SNEAKS, true) .profile(Profile.unresolved("Herobrine")) .thenAccept(builder -> { Npc npc = builder.buildAndTrack(); getLogger().info("Imitative NPC spawned - will mimic player actions"); }); } ``` -------------------------------- ### Add Items to NPC Inventory Slots in Java Source: https://github.com/juliarn/npc-lib/blob/v3/README.md This Java code snippet shows how to add items to an NPC's inventory slots, specifically the main hand, off hand, and armor slots. The example demonstrates placing a `DRAGON_EGG` item into the NPC's main hand using the `changeItem` method upon the `ShowNpcEvent.Post`. ```java public final class TestPlugin extends JavaPlugin { private final Platform platform = BukkitPlatform .bukkitNpcPlatformBuilder() .extension(this) .actionController(builder -> {}) // enable action controller without changing the default config .build(); public void registerNpcListeners() { var eventManager = this.platform.eventManager(); eventManager.registerEventHandler(ShowNpcEvent.Post.class, showEvent -> { var npc = showEvent.npc(); Player player = showEvent.player(); // puts a dragon egg into the main hand of the npc var dragonEggItem = new ItemStack(Material.DRAGON_EGG); npc.changeItem(ItemSlot.MAIN_HAND, dragonEggItem).schedule(player); }); } } ``` -------------------------------- ### Initialize NPC-Lib Platform Instance Source: https://context7.com/juliarn/npc-lib/llms.txt Demonstrates how to initialize the NPC platform builder for specific server environments. These snippets configure the library with the host plugin or server instance and set initial action controller flags. ```java import com.github.juliarn.npclib.bukkit.BukkitPlatform; import com.github.juliarn.npclib.api.Platform; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; public class MyPlugin extends JavaPlugin { private Platform platform; @Override public void onEnable() { platform = BukkitPlatform.bukkitNpcPlatformBuilder() .extension(this) .debug(false) .actionController(builder -> builder .flag(NpcActionController.SPAWN_DISTANCE, 50) .flag(NpcActionController.IMITATE_DISTANCE, 20) .flag(NpcActionController.AUTO_SYNC_POSITION_ON_SPAWN, true)) .build(); getLogger().info("NPC-Lib platform initialized successfully"); } } ``` ```java import com.github.juliarn.npclib.minestom.MinestomPlatform; import com.github.juliarn.npclib.api.Platform; import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Player; import net.minestom.server.instance.Instance; import net.minestom.server.item.ItemStack; public class NpcManager { private final Platform platform; public NpcManager(MinecraftServer server) { platform = MinestomPlatform.minestomNpcPlatformBuilder() .extension(server) .actionController(builder -> {}) .build(); } } ``` ```java import com.github.juliarn.npclib.fabric.FabricPlatform; import com.github.juliarn.npclib.api.Platform; import net.minecraft.server.world.ServerWorld; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.item.ItemStack; public class FabricNpcMod { private Platform platform; public void initialize() { platform = FabricPlatform.fabricNpcPlatformBuilder() .extension(new Object()) .actionController(builder -> {}) .build(); } } ``` -------------------------------- ### Configure Bukkit platform adapters Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Demonstrates how to explicitly set the protocol adapter to use PacketEvents and the world resolver to use name-based accessors, ensuring consistent behavior across different server environments. ```java public final class TestPlugin extends JavaPlugin { private final Platform platform = BukkitPlatform .bukkitNpcPlatformBuilder() .extension(this) .packetFactory(BukkitProtocolAdapter.packetEvents()) .worldAccessor(BukkitWorldAccessor.nameBasedAccessor()) .build(); } ``` -------------------------------- ### Configuring Advanced Platform Components Source: https://context7.com/juliarn/npc-lib/llms.txt Covers advanced platform customization, including setting packet factories, world accessors, logging, and event managers for Bukkit environments. ```java public void configurePlatformComponents() { // Packet Adapter Platform platform = BukkitPlatform.bukkitNpcPlatformBuilder() .extension(this) .packetFactory(BukkitProtocolAdapter.packetEvents()) .build(); // World Accessor Platform platform2 = BukkitPlatform.bukkitNpcPlatformBuilder() .extension(this) .worldAccessor(BukkitWorldAccessor.nameBasedAccessor()) .build(); // Event Manager and Logger PlatformLogger customLogger = PlatformLogger.fromJul(getLogger()); NpcEventManager customEventManager = NpcEventManager.createDefault(true, customLogger); Platform platform3 = BukkitPlatform.bukkitNpcPlatformBuilder() .extension(this) .logger(customLogger) .eventManager(customEventManager) .build(); } ``` -------------------------------- ### Create and Use Custom NPC Flags in Java Source: https://context7.com/juliarn/npc-lib/llms.txt Illustrates defining and utilizing custom NPC flags with validation. It shows how to create flags for roles, levels (with range validation), and spawn times, and then apply and retrieve these flags when spawning and managing NPCs. Requires NPClib API and Java's `LocalDateTime`. ```java import com.github.juliarn.npclib.api.flag.NpcFlag; import java.time.LocalDateTime; public class CustomFlagExample { // Define custom flags private static final NpcFlag NPC_ROLE = NpcFlag.flag("custom_npc_role", "guard"); private static final NpcFlag NPC_LEVEL = NpcFlag.flag("custom_npc_level", 1, level -> level > 0 && level <= 100); private static final NpcFlag SPAWN_TIME = NpcFlag.flag("custom_spawn_time", (LocalDateTime) null); public void spawnNpcWithCustomFlags(Location location) { Position position = Position.position( location.getX(), location.getY(), location.getZ(), location.getWorld().getName() ); platform.newNpcBuilder() .position(position) .flag(NPC_ROLE, "merchant") .flag(NPC_LEVEL, 25) .flag(SPAWN_TIME, LocalDateTime.now()) .profile(Profile.unresolved("TraderJoe")) .thenAccept(builder -> { Npc npc = builder.buildAndTrack(); // Retrieve flag values String role = npc.flagValue(NPC_ROLE).orElse("unknown"); int level = npc.flagValue(NPC_LEVEL).orElse(1); LocalDateTime spawnTime = npc.flagValue(SPAWN_TIME).orElse(null); getLogger().info("Spawned " + role + " NPC at level " + level); }); } } ``` -------------------------------- ### Compile and Publish NPC-Lib Locally Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Provides shell commands to clone the NPC-Lib repository, navigate into the project directory, and publish the library to the local Maven repository using Gradle. ```shell git clone https://github.com/juliarn/npc-lib.git cd npc-lib gradlew publishToMavenLocal ``` -------------------------------- ### Spawning an NPC with Builder - Java Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Demonstrates how to use the `newNpcBuilder` method to customize and spawn an NPC. It covers setting entity IDs, positions, profiles, and additional NPC settings using flags. The builder allows for fine-grained control over NPC behavior and appearance before spawning. ```java platform.newNpcBuilder() // the id to use for the entity. if not provided a random integer is generated and used instead. .entityId() // the position where the npc should be spawned and located. // this option is required and must be set before spawning the npc. .position() // sets resolved or unresolved profile for the npc. if an unresolved profile is used the method // returns a future completed with the current build when the profile was resolved. a specific // profile resolver to use can be provided as well. .profile() // allows to add additional settings to the npc: // - a tracking rule to select the players which should be tracked automatically by the npc // - a profile resolver which can dynamically resolve the npc profile when it gets spawned // if no builder callback is provided default npc settings are applied. this means that the npc will be // spawned to all players in range and the skin (via the profile) provided to this builder will always be used. .npcSettings() // sets a value for a flag on the npc. .flag(); ``` -------------------------------- ### Initialize NPC Platform on Fabric Source: https://github.com/juliarn/npc-lib/blob/v3/README.md This snippet demonstrates how to obtain an NPC platform builder for the Fabric modding framework. This is used to set up NPC management within a Fabric-based Minecraft server. ```java FabricPlatform.fabricNpcPlatformBuilder() ``` -------------------------------- ### Initialize Bukkit NPC Platform Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Code snippet to initialize the NPC platform builder specifically for Bukkit server environments. This serves as the entry point for creating NPCs within a Bukkit-based project. ```java BukkitPlatform.bukkitNpcPlatformBuilder() ``` -------------------------------- ### Handle AttackNpcEvent in Java Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Demonstrates how to implement an event consumer to handle the AttackNpcEvent. It highlights the need to cast the player object to a specific type (e.g., Player) for proper usage, as the event provides a generic 'object' type. ```java public final class AttackEventConsumer implements NpcEventConsumer { @Override public void handle(AttackNpcEvent event) { var badPlayer = event.player(); // player type is object as the type couldn't be inferred Player goodPlayer = event.player(); // player type is Player, but it must be known at compile time } } ``` -------------------------------- ### Storing Configuration Data in Flags Source: https://context7.com/juliarn/npc-lib/llms.txt Demonstrates how to bind custom configuration objects to NPCs using the NpcFlag API. This allows developers to persist and retrieve arbitrary data directly from an NPC instance. ```java public class NpcConfigFlag { private static final NpcFlag CONFIG_FLAG = NpcFlag.flag("npc_config_data", (NpcConfiguration) null); public void spawnConfiguredNpc(NpcConfiguration config) { Position position = Position.position( config.getX(), config.getY(), config.getZ(), config.getWorldName() ); platform.newNpcBuilder() .position(position) .flag(CONFIG_FLAG, config) .profile(Profile.unresolved(config.getSkinName())) .thenAccept(builder -> { Npc npc = builder.buildAndTrack(); npc.flagValue(CONFIG_FLAG).ifPresent(storedConfig -> { getLogger().info("NPC loaded from config: " + storedConfig.getName()); }); }); } } ``` -------------------------------- ### Enable NPC behavioral imitation Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Explains how to use flags to enable interactive behaviors, such as looking at players and mimicking sneaking or hitting actions. ```java public final class TestPlugin extends JavaPlugin { public void spawnNpc(Location location) { this.platform.newNpcBuilder() .flag(Npc.LOOK_AT_PLAYER, true) .flag(Npc.HIT_WHEN_PLAYER_HITS, true) .flag(Npc.SNEAK_WHEN_PLAYER_SNEAKS, true) .position(BukkitPlatformUtil.positionFromBukkitLegacy(location)) .profile(Profile.unresolved("derklaro")) .thenAccept(builder -> { var npc = builder.buildAndTrack(); }); } } ``` -------------------------------- ### Register NPC Event Listeners in Java Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Demonstrates how to register event handlers for NPC-related events such as spawning. It shows how to make an NPC look at a specific location, play an animation, and rotate the player's head using the platform's event manager. ```java public final class TestPlugin extends JavaPlugin { private final Platform platform = BukkitPlatform .bukkitNpcPlatformBuilder() .extension(this) .actionController(builder -> {}) // enable action controller without changing the default config .build(); public void registerNpcListeners() { var eventManager = this.platform.eventManager(); eventManager.registerEventHandler(ShowNpcEvent.Post.class, showEvent -> { var npc = showEvent.npc(); Player player = showEvent.player(); // let the NPC look into the direction of 0, 50, 0 var spawnLocation = Position.position(0, 50, 0, npc.position().worldId()); npc.lookAt(spawnLocation).schedule(player); // lets the NPC swing his main arm npc.playAnimation(EntityAnimation.SWING_MAIN_ARM).schedule(player); // sets the player head rotation to yaw=0 & pitch=90 npc.rotate(0, 90).schedule(player); }); } } ``` -------------------------------- ### Implement NPC skin and tracking rules Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Shows how to configure an NPC to inherit the skin of the viewing player and restrict visibility to players with an experience level of at least 50. ```java public final class TestPlugin extends JavaPlugin { public void spawnNpc(Location location) { this.platform.newNpcBuilder() .position(BukkitPlatformUtil.positionFromBukkitLegacy(location)) .npcSettings(builder -> builder .profileResolver((player, npc) -> { var playerProfile = Profile.unresolved(player.getUniqueId()); return this.platform.profileResolver() .resolveProfile(playerProfile) .thenApply(profile -> npc.profile().withProperties(profile.properties())); }) .trackingRule((npc, player) -> player.getExp() >= 50)) .profile(Profile.unresolved("derklaro")) .thenAccept(builder -> { var npc = builder.buildAndTrack(); }); } } ``` -------------------------------- ### Handle NPC Interaction Events (Java) Source: https://context7.com/juliarn/npc-lib/llms.txt Demonstrates how to register event handlers for NPC interactions, such as right-clicking or attacking an NPC. This allows for custom responses to player interactions with NPCs. ```java import com.github.juliarn.npclib.api.event.InteractNpcEvent; import com.github.juliarn.npclib.api.event.AttackNpcEvent; import com.github.juliarn.npclib.api.event.manager.NpcEventManager; public void registerInteractionHandlers() { NpcEventManager eventManager = platform.eventManager(); // Handle right-click interactions eventManager.registerEventHandler(InteractNpcEvent.class, event -> { Npc npc = (Npc) event.npc(); Player player = (Player) event.player(); player.sendMessage("You interacted with " + npc.profile().name() + " using " + event.hand()); // Cancel the event to prevent further processing if (player.isSneaking()) { event.cancelled(true); } }); // Handle left-click attacks eventManager.registerEventHandler(AttackNpcEvent.class, event -> { Npc npc = (Npc) event.npc(); Player player = (Player) event.player(); player.sendMessage("You attacked " + npc.profile().name() + "!"); // Make NPC swing back npc.playAnimation(EntityAnimation.SWING_MAIN_ARM).schedule(player); }); } ``` -------------------------------- ### Handle NPC Spawn and Despawn Events in Java Source: https://context7.com/juliarn/npc-lib/llms.txt Registers handlers for NPC spawn and despawn events using NPClib's event manager. It demonstrates pre-spawn cancellation based on player bans, post-spawn appearance customization, and post-despawn notifications. Requires NPClib API and platform-specific event and player classes. ```java import com.github.juliarn.npclib.api.event.ShowNpcEvent; import com.github.juliarn.npclib.api.event.HideNpcEvent; public void registerSpawnHandlers() { NpcEventManager eventManager = platform.eventManager(); // Handle pre-spawn event (cancellable) eventManager.registerEventHandler(ShowNpcEvent.Pre.class, event -> { Npc npc = (Npc) event.npc(); Player player = (Player) event.player(); // Prevent NPC spawn for banned players if (isBanned(player)) { event.cancelled(true); return; } getLogger().info("About to show NPC " + npc.entityId() + " to " + player.getName()); }); // Handle post-spawn event eventManager.registerEventHandler(ShowNpcEvent.Post.class, event -> { Npc npc = (Npc) event.npc(); Player player = (Player) event.player(); // Customize NPC appearance for this player npc.changeMetadata(EntityMetadataFactory.skinLayerMetaFactory(), true) .schedule(player); player.sendMessage("A new NPC has appeared!"); }); // Handle despawn events eventManager.registerEventHandler(HideNpcEvent.Post.class, event -> { Player player = (Player) event.player(); player.sendMessage("NPC has disappeared!"); }); } private boolean isBanned(Player player) { return player.isBanned(); } ``` -------------------------------- ### Play LabyMod Emote for Player in Java Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Illustrates how to make a NPC play a LabyMod emote for a player using the LabyMod extension module. This requires NPCs to be spawned with a specific UUID configuration and is compatible with LabyMod version 4 (neo). ```java public final class TestPlugin extends JavaPlugin { public void playLabyModEmoteForPlayer(Npc npc, Player player, int... emoteIds) { LabyModExtension.createEmotePacket(npc.platform().packetFactory(), emoteIds).schedule(player, npc); } } ``` -------------------------------- ### Create Custom Resolved NPC Profiles (Java) Source: https://context7.com/juliarn/npc-lib/llms.txt Illustrates how to manually create a custom resolved NPC profile. This involves generating a UUID, defining texture properties (including optional signature), and then using this resolved profile when building a new NPC. This approach offers full control over the NPC's appearance and identity. ```java import com.github.juliarn.npclib.api.profile.ProfileProperty; import java.util.Set; import java.util.HashSet; public void createCustomProfile() { UUID npcUuid = UUID.randomUUID(); Set properties = new HashSet<>(); properties.add(ProfileProperty.property( "textures", "eyJ0aW1lc3RhbXAiOjE1OT...", // Base64 encoded texture data "signature" // Optional signature )); Profile.Resolved customProfile = Profile.resolved( "CustomNPC", npcUuid, properties ); platform.newNpcBuilder() .position(Position.position(0, 64, 0, "world")) .profile(customProfile) .thenAccept(builder -> { Npc npc = builder.buildAndTrack(); getLogger().info("NPC with custom profile spawned"); }); } ``` -------------------------------- ### Playing LabyMod Emotes on NPCs Source: https://context7.com/juliarn/npc-lib/llms.txt Explains how to use the LabyModExtension to trigger emotes on specific players or groups of tracked players by scheduling emote packets. ```java public void playLabyModEmote(Npc npc, Player player) { LabyModExtension.createEmotePacket(npc.platform().packetFactory(), 3) .schedule(player, npc); LabyModExtension.createEmotePacket(npc.platform().packetFactory(), 3, 5, 10) .schedule(npc.trackedPlayers(), npc); } ``` -------------------------------- ### Spawn NPC with Dynamic Player Skin (Java) Source: https://context7.com/juliarn/npc-lib/llms.txt Spawns an NPC whose skin is dynamically resolved based on the viewing player's skin. This utilizes a profile resolver to fetch and apply the player's profile properties to the NPC. Dependencies include the platform, Location, Position, Profile, and NPC settings for profile resolution. ```java public void spawnNpcWithDynamicSkin(Location location) { Position position = Position.position( location.getX(), location.getY(), location.getZ(), location.getWorld().getName() ); platform.newNpcBuilder() .position(position) .npcSettings(settings -> settings .profileResolver((player, npc) -> { // Use the player's own skin Profile playerProfile = Profile.unresolved(player.getUniqueId()); return platform.profileResolver() .resolveProfile(playerProfile) .thenApply(resolved -> npc.profile().withProperties(resolved.properties()) ); })) .profile(Profile.unresolved("MirrorNPC")) .thenAccept(builder -> { Npc npc = builder.buildAndTrack(); getLogger().info("NPC with dynamic player skin spawned"); }); } ``` -------------------------------- ### Enable Skin Layers and Change Entity Status for NPCs in Java Source: https://github.com/juliarn/npc-lib/blob/v3/README.md This Java code snippet demonstrates how to enable all skin layers and set the entity status for an NPC upon its appearance using `ShowNpcEvent.Post`. It shows how to apply the `skinLayerMetaFactory` and `entityStatusMetaFactory` to modify the NPC's appearance and status, such as setting it on fire. ```java public final class TestPlugin extends JavaPlugin { private final Platform platform = BukkitPlatform .bukkitNpcPlatformBuilder() .extension(this) .actionController(builder -> {}) // enable action controller without changing the default config .build(); public void registerNpcListeners() { var eventManager = this.platform.eventManager(); eventManager.registerEventHandler(ShowNpcEvent.Post.class, showEvent -> { var npc = showEvent.npc(); Player player = showEvent.player(); // enable all skin players npc.changeMetadata(EntityMetadataFactory.skinLayerMetaFactory(), true).schedule(player); // set the npc on fire // note: the glowing entity status must be sent in order for the entity to appear glowing. The logic of adding // the npc into a team and setting the glowing color must be handled by your plugin. var entityStatus = EnumSet.of(EntityStatus.ON_FIRE); npc.changeMetadata(EntityMetadataFactory.entityStatusMetaFactory(), entityStatus).schedule(player); }); } } ``` -------------------------------- ### Rotate NPC and Play Animations (Java) Source: https://context7.com/juliarn/npc-lib/llms.txt Demonstrates how to make an NPC rotate to face a specific direction or position, and how to play various animations like swinging arms. These actions can be scheduled for individual viewers or all tracked players. ```java import com.github.juliarn.npclib.api.protocol.enums.EntityAnimation; public void animateNpc(Npc npc, Player viewer) { // Rotate NPC to face a specific direction (yaw=90, pitch=0) npc.rotate(90.0f, 0.0f).schedule(viewer); // Make NPC look at a specific position Position targetPos = Position.position(100, 64, 200, npc.position().worldId()); npc.lookAt(targetPos).schedule(viewer); // Play swing animation npc.playAnimation(EntityAnimation.SWING_MAIN_ARM).schedule(viewer); // Schedule for all tracked players npc.playAnimation(EntityAnimation.SWING_OFF_ARM) .schedule(npc.trackedPlayers()); } ``` -------------------------------- ### Register Event Handlers with Priority in Java Source: https://context7.com/juliarn/npc-lib/llms.txt Demonstrates registering multiple event handlers for the same event with different priorities. Higher numerical values indicate higher priority, ensuring specific handlers execute before others. This is useful for creating ordered event processing logic. ```java public void registerPrioritizedHandlers() { NpcEventManager eventManager = platform.eventManager(); // High priority handler (executes first) eventManager.registerEventHandler( InteractNpcEvent.class, event -> { getLogger().info("High priority handler"); }, 100 ); // Normal priority handler eventManager.registerEventHandler( InteractNpcEvent.class, event -> { getLogger().info("Normal priority handler"); }, 50 ); // Low priority handler (executes last) eventManager.registerEventHandler( InteractNpcEvent.class, event -> { getLogger().info("Low priority handler"); }, 10 ); } ``` -------------------------------- ### Attach custom flags to NPCs Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Illustrates how to define and attach custom NpcFlags to store external data (like configuration entries) alongside an NPC, allowing for easy retrieval during interactions. ```java public final class TestPlugin extends JavaPlugin { private static final NpcFlag CONFIG_ENTRY_FLAG = NpcFlag.flag("npc_config_entry", null); public void spawnNpc(NpcEntry configEntry) { this.platform.newNpcBuilder() .flag(CONFIG_ENTRY_FLAG, configEntry) .position(BukkitPlatformUtil.positionFromBukkitLegacy(configEntry.location())) .profile(Profile.unresolved(configEntry.profileName())) .thenAccept(builder -> { var npc = builder.buildAndTrack(); var configEntry = npc.flagValue(CONFIG_ENTRY_FLAG).orElseThrow(); }); } } ``` -------------------------------- ### Manually Spawn and Remove NPCs for Players in Java Source: https://github.com/juliarn/npc-lib/blob/v3/README.md Provides methods for manually controlling the spawning and despawning of NPCs for specific players. It includes functions to track players, force-track players, and stop tracking players, with notes on event handling and player tracking conditions. ```java public final class TestPlugin extends JavaPlugin { public void spawnNpcToPlayer(Npc npc, Player player) { // use this method if you want to spawn the npc to the player, but only if all preconditions // (such as the player tracking rule) are met. You can manually check if a player would be // tracked by a npc by calling: `npc.shouldIncludePlayer(player)`. npc.trackPlayer(player); // Use this method if you want to spawn the npc to the player even is preconditions aren't met. // Note: this still calls the ShowNpc.Pre event which can still be cancelled by one of your event // listeners causing the npc to not get spawned for the player. npc.forceTrackPlayer(player); } public void removeNpcForPlayer(Npc npc, Player player) { // despawns the npc for the given player unless the npc is not spawned for the player. you can always // check the players for which a NPC is spawned by calling `npc.trackedPlayers()` or check for a // specific player by using `npc.tracksPlayer(player)`. // Note: this method calls the HideNpcEvent.Pre event which means that an event listener can // prevent the npc despawn process from being executed. npc.stopTrackingPlayer(player); } } ``` -------------------------------- ### Resolve NPC Profiles with Custom Bukkit Resolver (Java) Source: https://context7.com/juliarn/npc-lib/llms.txt Demonstrates how to use the BukkitProfileResolver to resolve NPC profiles. It takes an unresolved profile (identified by name) and asynchronously returns a resolved profile containing UUID and properties. This method relies on the Bukkit API and potentially PaperMC for efficient resolution. ```java import com.github.juliarn.npclib.api.profile.ProfileResolver; import com.github.juliarn.npclib.bukkit.BukkitProfileResolver; import java.util.concurrent.CompletableFuture; public void useCustomProfileResolver() { ProfileResolver paperResolver = BukkitProfileResolver.paperProfileResolver(); Profile unresolvedProfile = Profile.unresolved("jeb_"); CompletableFuture future = paperResolver.resolveProfile(unresolvedProfile); future.thenAccept(resolved -> { getLogger().info("Resolved profile for " + resolved.name()); getLogger().info("UUID: " + resolved.uniqueId()); getLogger().info("Properties: " + resolved.properties().size()); }); } ``` -------------------------------- ### Change NPC Equipment (Java) Source: https://context7.com/juliarn/npc-lib/llms.txt Equips an NPC with items in various slots, including the main hand, off-hand, helmet, chestplate, leggings, and boots. Each item change is scheduled to be applied for a specific viewer. Dependencies include the Npc object, Player viewer, ItemSlot enum, Material, and ItemStack. ```java import com.github.juliarn.npclib.api.protocol.enums.ItemSlot; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; public void equipNpc(Npc npc, Player viewer) { // Give the NPC a diamond sword in main hand ItemStack sword = new ItemStack(Material.DIAMOND_SWORD); npc.changeItem(ItemSlot.MAIN_HAND, sword).schedule(viewer); // Give the NPC a shield in off hand ItemStack shield = new ItemStack(Material.SHIELD); npc.changeItem(ItemSlot.OFF_HAND, shield).schedule(viewer); // Give the NPC diamond armor ItemStack helmet = new ItemStack(Material.DIAMOND_HELMET); ItemStack chestplate = new ItemStack(Material.DIAMOND_CHESTPLATE); ItemStack leggings = new ItemStack(Material.DIAMOND_LEGGINGS); ItemStack boots = new ItemStack(Material.DIAMOND_BOOTS); npc.changeItem(ItemSlot.HELMET, helmet).schedule(viewer); npc.changeItem(ItemSlot.CHESTPLATE, chestplate).schedule(viewer); npc.changeItem(ItemSlot.LEGGINGS, leggings).schedule(viewer); npc.changeItem(ItemSlot.BOOTS, boots).schedule(viewer); } ``` -------------------------------- ### Handle NPC Attack and Interaction Events in Java Source: https://github.com/juliarn/npc-lib/blob/v3/README.md This Java code registers event handlers for `AttackNpcEvent` and `InteractNpcEvent`. When an NPC is attacked or interacted with, it sends a message to the player indicating the action taken and the NPC's name. It utilizes the BukkitPlatform for NPC interactions. ```java public final class TestPlugin extends JavaPlugin { private final Platform platform = BukkitPlatform .bukkitNpcPlatformBuilder() .extension(this) .actionController(builder -> {}) // enable action controller without changing the default config .build(); public void registerNpcListeners() { var eventManager = this.platform.eventManager(); eventManager.registerEventHandler(AttackNpcEvent.class, attackEvent -> { var npc = attackEvent.npc(); Player player = attackEvent.player(); player.sendMessage("You attacked NPC " + npc.profile().name() + "! That's not nice!"); }); eventManager.registerEventHandler(InteractNpcEvent.class, interactEvent -> { var npc = interactEvent.npc(); Player player = interactEvent.player(); player.sendMessage("[" + npc.profile().name() + "]: Move along citizen!"); }); } } ``` -------------------------------- ### Spawn NPC without Automatic Tracking (Java) Source: https://context7.com/juliarn/npc-lib/llms.txt Spawns an NPC at a specified location without enabling automatic tracking. This method requires manual control after creation. It returns the spawned NPC object or null if creation fails. Dependencies include the platform, Location, Position, Profile, and CompletableFuture. ```java public Npc spawnUntrackedNpc(Location location) { Position position = Position.position( location.getX(), location.getY(), location.getZ(), location.getWorld().getName() ); CompletableFuture> future = platform.newNpcBuilder() .position(position) .profile(Profile.unresolved("Steve")) .thenApply(builder -> builder.build()); try { Npc npc = future.get(); getLogger().info("Created untracked NPC - manual control required"); return npc; } catch (Exception e) { getLogger().severe("Failed to create NPC: " + e.getMessage()); return null; } } ```