Bring Citizens NPCs to life with intelligent item pickup and thief mechanics.
Virtual inventories, death drops, item filtering, and container stealing.
NPC PickUp is an open-source Citizens2 enhancement plugin that brings NPCs to life through intelligent item interaction. NPCs automatically scan their surroundings for dropped items, pathfind toward them, and collect them into persistent virtual inventories. When an NPC dies, their full inventory scatters to the ground with configurable drop patterns and drop chance. A dedicated thief mode enables specialized NPCs to steal items directly from nearby chests, barrels, and other containers. Every behavior - pickup radius, movement speed, drop chance, container scanning, and item filtering - is configurable globally via config.yml, and pickup mode and thief mode can be toggled independently per NPC at runtime using commands.
- Intelligent Item Detection: NPCs automatically scan their surroundings for dropped items within a configurable detection radius and pathfind toward them before collecting
- Virtual Inventory Management: Each NPC maintains an in-memory inventory with full item stacking, holding up to
max_itemsitem stacks (default: 256) - Death Drop Mechanics: When an NPC is killed, their entire inventory is dropped at the death location with a configurable scatter radius, random velocity, and per-drop chance
- Thief Mode: Designated NPCs steal items directly from chests, barrels, trapped chests, hoppers, dispensers, droppers, and all shulker box colors within a configurable radius
- Item Filtering: Whitelist or blacklist controls determine exactly which material types NPCs are allowed to collect - configure per server needs
- Per-NPC Control: Pickup mode and thief mode can be enabled or disabled independently for any individual NPC by ID or name, persisted across restarts in
config.yml - NPC Pickup Priority: When an NPC is within range and eligible to collect an item, the item pickup delay is briefly extended to give the NPC a fair chance before players can grab it
- Sound Feedback: A pickup sound plays at the NPC location each time an item is collected; a chest sound plays softly during container theft
- Performance Optimized: Configurable tick delays for both the pickup scan task and the theft scan task minimize server impact when running many NPCs
- Admin Management Tools: 9 subcommands for real-time monitoring, inventory inspection, inventory clearing, and per-NPC mode toggling
- Debug Logging: Optional detailed console output for pickup, drop, and theft events to help with setup and troubleshooting
- No Setup Required: The plugin works immediately after installation with sensible defaults - no manual configuration needed before first use
- Server Software:
Spigot,Paper,Purpur,CraftBukkit - Minecraft Versions:
1.20and higher - Java Requirements:
Java 17+ - Required Dependency: Citizens2 - must be installed and running
- Getting Started
- Third-Party Libraries
- Configuration
- How It Works
- Commands
- Permissions
- Building from Source
- License
- Screenshots
Before installing NPC PickUp, confirm the following requirements are met:
- A Minecraft server running Spigot, Paper, Purpur, or any compatible fork
- Server version 1.20 or higher (
api-version: 1.20is the minimum) - Java 17 or newer installed on the machine running the server
- Citizens2 installed and running on the server - this is a hard dependency and the plugin will not load without it
- Operator or console access to install plugin files
- Download and install Citizens2 if not already present on your server
- Download the latest
NPCItemPickup-x.x.x.jarfrom the Releases page - Stop your server completely before placing any files
- Copy the
.jarinto your server'splugins/directory - Start the server -
plugins/NPCItemPickup/config.ymlis generated automatically with all defaults on first boot - Edit
config.ymlto adjust behavior for your server, then run/npcpickup reloadto apply changes
On the first server start after installation, NPC PickUp creates the following structure:
plugins/
└── NPCItemPickup/
└── config.yml - All plugin settings with their defaults
The plugin starts running immediately with default settings. NPCs will begin scanning for dropped items and collecting them right away - no additional setup is required. If you want to change radii, drop behavior, or item filtering, edit config.yml and run /npcpickup reload.
To designate an NPC as a thief (container stealer), use /npcpickup thief <npc_name> at runtime - no manual config editing is needed. The NPC ID is written to config.yml automatically.
- Run
/pluginsin-game -NPCItemPickupshould appear green in the list - Run
/npcpickup statusto confirm the plugin is active and view its current settings - Drop an item near a Citizens NPC - the NPC should pathfind toward it and collect it (listen for the pickup sound)
- Run
/npcpickup infowhile standing within 5 blocks of an NPC to inspect its current inventory contents - If the plugin fails to load, check the server console for
NPCItemPickuperror messages (most common cause: Citizens2 is not installed or failed to load before this plugin)
NPC PickUp depends on one external Minecraft plugin to manage NPC entities and behavior: Citizens 2. It is a required hard dependency — the plugin will not load without it.
Citizens 2 is the leading NPC framework for Bukkit-based Minecraft servers. NPC PickUp uses Citizens to identify and interact with NPC entities in the world, and to hook into NPC lifecycle events for item pickup, drop, and carrying behavior. All NPC entities managed by this plugin exist as Citizens NPCs backed by standard Minecraft mobs.
- Website: Citizens2 SpigotMC Resource
- GitHub: CitizensDev/Citizens2
- License: Citizens 2 is licensed under the Apache License 2.0.
For more details about Citizens, including setup guides and configuration references, check the official documentation:
- Citizens Documentation: Citizens Wiki
If you have questions or issues related to this dependency, please open an issue on GitHub.
enabled: true
pickup:
radius: 5.0
delay: 20
max_items: 256
move_to_items: true
movement_speed: 1.2
drop:
enabled: true
drop_chance: 1.0
scatter_items: true
scatter_radius: 2.0
item_filter:
use_whitelist: false
whitelist:
- "DIAMOND"
- "GOLD_INGOT"
- "IRON_INGOT"
blacklist:
- "BEDROCK"
npc_settings:
disabled_pickup: []
thief_mode:
enabled: true
chest_radius: 5.0
items_per_tick: 1
theft_delay: 10
move_to_chests: true
theft_distance: 4.0
thief_npcs: []
debug:
enabled: false
log_pickups: true
log_drops: true
log_theft: trueGeneral
| Key | Default | Description |
|---|---|---|
enabled |
true |
Master switch - disabling this stops all plugin activity globally without unloading the plugin |
Pickup Settings (pickup.*)
| Key | Default | Description |
|---|---|---|
pickup.radius |
5.0 |
Detection radius in blocks - NPCs scan this area for dropped items on every cycle |
pickup.delay |
20 |
Ticks between pickup scan attempts (20 = 1 second) - lower values are more responsive but cost more performance |
pickup.max_items |
256 |
Maximum total item count an NPC can hold - once full, the NPC stops collecting until items are cleared or dropped on death |
pickup.move_to_items |
true |
Whether NPCs pathfind toward detected items - if false, NPCs only collect items that land within 1.5 blocks of them |
pickup.movement_speed |
1.2 |
NPC movement speed multiplier when walking toward an item (1.0 = default Citizens speed) |
Drop Settings (drop.*)
| Key | Default | Description |
|---|---|---|
drop.enabled |
true |
Whether NPCs drop their inventory when they die - disable to make NPCs permanently retain items across deaths |
drop.drop_chance |
1.0 |
Probability (0.0-1.0) that the inventory is dropped on death - 1.0 always drops, 0.5 drops half the time |
drop.scatter_items |
true |
If true, items land at random positions around the death point; if false, all items drop at the exact death location |
drop.scatter_radius |
2.0 |
Maximum scatter distance in blocks from the death location when scatter_items is enabled |
Item Filter Settings (item_filter.*)
| Key | Default | Description |
|---|---|---|
item_filter.use_whitelist |
false |
If true, only items listed in whitelist can be picked up; if false, everything except blacklist items is collected |
item_filter.whitelist |
[DIAMOND, GOLD_INGOT, IRON_INGOT] |
Materials NPCs are allowed to collect when use_whitelist is true - use Bukkit material names in UPPER_CASE |
item_filter.blacklist |
[BEDROCK] |
Materials NPCs will never collect when use_whitelist is false - use Bukkit material names in UPPER_CASE |
NPC-Specific Settings (npc_settings.*)
| Key | Default | Description |
|---|---|---|
npc_settings.disabled_pickup |
[] |
List of NPC IDs with pickup disabled - managed automatically via /npcpickup disable, do not edit manually |
Thief Mode Settings (thief_mode.*)
| Key | Default | Description |
|---|---|---|
thief_mode.enabled |
true |
Whether the thief mode system is active at all - disabling this prevents any NPC from stealing regardless of their thief flag |
thief_mode.chest_radius |
5.0 |
Detection radius in blocks for container scanning - the plugin checks a sphere of this radius around each thief NPC |
thief_mode.items_per_tick |
1 |
Number of items stolen per theft cycle - increase for faster stealing, decrease for slower more subtle theft |
thief_mode.theft_delay |
10 |
Ticks between theft scan attempts (10 = 0.5 seconds) |
thief_mode.move_to_chests |
true |
Whether thief NPCs pathfind toward detected containers before stealing |
thief_mode.theft_distance |
4.0 |
Maximum distance in blocks from which a thief NPC can actually steal - the NPC must be within this range to take items |
thief_mode.thief_npcs |
[] |
List of NPC IDs currently in thief mode - managed automatically via /npcpickup thief, do not edit manually |
Debug Settings (debug.*)
| Key | Default | Description |
|---|---|---|
debug.enabled |
false |
Enable verbose console output for all plugin events |
debug.log_pickups |
true |
Log item pickup events to console when debug mode is on |
debug.log_drops |
true |
Log item drop events to console when debug mode is on |
debug.log_theft |
true |
Log theft events to console when debug mode is on |
Item names: All values in
whitelistandblacklistmust use Bukkit material names in UPPER_CASE with underscores, for exampleDIAMOND_SWORD,OAK_LOG,GOLDEN_APPLE. The full list of material names is available in the Bukkit Material documentation.
Item pickup runs on a repeating background task that fires every pickup.delay ticks (default: every second). Here is what happens on each cycle:
- Every spawned NPC in the Citizens registry is iterated
- For each NPC, all entities within a sphere of
pickup.radiusblocks are checked - Items with a pickup delay greater than 0 are ignored - items that were just dropped have a short protection window
- Each item is checked against the item filter (whitelist or blacklist) and the NPC's personal pickup enabled state
- If the NPC is within 1.5 blocks of the item, the item is collected immediately - it is removed from the world, added to the NPC's virtual inventory, and the pickup sound plays at the NPC's location
- If the NPC is further than 1.5 blocks but still within
pickup.radius, andmove_to_itemsis enabled, the NPC receives a velocity nudge toward the item and turns to face it
Each NPC has a separate virtual inventory stored in memory as a list of item stacks, keyed by the NPC's UUID. Items stack automatically against existing stacks of the same type up to the vanilla maximum stack size. When the total item count reaches max_items, the NPC stops collecting until space becomes available through a death drop or an admin clear command.
Important: Virtual inventories are stored in memory only and are not written to disk. They reset when the server restarts or the plugin reloads. This is by design - NPCs are not meant to permanently accumulate items between sessions.
Death drops are triggered by two events: the Citizens2 NPCDeathEvent and the standard Bukkit EntityDeathEvent as a backup in case the Citizens event does not fire. Here is the full drop sequence:
- The plugin checks whether
drop.enabledistrue - If the NPC's inventory is empty, nothing happens and the event is ignored
- A random roll is compared against
drop.drop_chance- if the roll fails, the inventory is cleared silently with no drops - All items from the NPC's virtual inventory are retrieved and the inventory is cleared
- Each item is dropped at the NPC's death location using
world.dropItemNaturally() - If
scatter_itemsis enabled, each item receives a random positional offset withinscatter_radiusblocks and a small random upward velocity for a natural explosion of drops - Each dropped item receives a 2-second pickup delay (40 ticks) to prevent the NPC's own pickup task from immediately recollecting the items
Thief mode is a secondary behavior layer running on its own repeating task, completely separate from the item pickup task. The theft task fires every theft_delay ticks (default: every 0.5 seconds). The container types supported for theft are:
- Standard containers:
CHEST,TRAPPED_CHEST,BARREL - Shulker boxes: all 16 color variants
- Redstone containers:
HOPPER,DISPENSER,DROPPER
For each NPC flagged as a thief, the plugin scans a cubic volume of chest_radius blocks for any of the above block types. When a container is found within range:
- If the NPC is within
theft_distanceblocks of the container, it steals up toitems_per_tickitems per cycle. Each stolen item is moved one at a time from the container's inventory into the NPC's virtual inventory. A soft chest open sound plays at the NPC's location. - If the NPC is further than
theft_distancebut still withinchest_radius, andmove_to_chestsis enabled, the NPC moves toward the container.
Item filter rules apply to theft exactly as they do to ground pickup - thief NPCs will not steal items they are not allowed to collect based on the whitelist or blacklist.
The filter system has two modes controlled by item_filter.use_whitelist:
- Blacklist mode (
use_whitelist: false, default): NPCs collect all items except those listed inblacklist. Use this when you want NPCs to pick up almost everything but exclude a few specific materials. - Whitelist mode (
use_whitelist: true): NPCs collect only items listed inwhitelist. Use this for specialized collector NPCs that should only gather specific valuable items.
Both lists use Bukkit material name strings in UPPER_CASE. The filter applies equally to ground item pickup and thief mode container stealing.
All commands require the npcpickup.admin permission node, which defaults to server operators.
| Command | Description |
|---|---|
/npcpickup reload |
Reload config.yml and restart all plugin tasks with the new settings |
/npcpickup toggle |
Enable or disable all plugin functionality globally - state is saved to config.yml |
/npcpickup status |
Show plugin status: enabled state, pickup radius, max items, drop mode, and total items held across all NPCs |
/npcpickup info [npc_name] |
Show the inventory of the nearest NPC within 5 blocks, or a named NPC |
/npcpickup clear <npc_name|all> |
Clear the inventory of a specific NPC by name, or all NPC inventories at once with all |
/npcpickup disable <npc_id|npc_name> |
Disable item pickup for a specific NPC - saved to config.yml under npc_settings.disabled_pickup |
/npcpickup enable <npc_id|npc_name> |
Re-enable item pickup for a previously disabled NPC |
/npcpickup thief <npc_id|npc_name> |
Enable thief mode for an NPC - it will begin stealing from nearby containers |
/npcpickup unthief <npc_id|npc_name> |
Disable thief mode for a specific NPC |
Aliases: None - use the full /npcpickup command
Console support: All subcommands except info work from the server console. info requires a player because it uses proximity detection.
/npcpickup status
Displays a summary of the current plugin state - whether it is globally enabled, the configured pickup radius and item cap, whether death drops are active, how many NPCs are currently holding items, and the total item count across all NPC inventories.
/npcpickup status
/npcpickup info [npc_name]
Shows the full inventory contents of a specific NPC. Without a name, the nearest NPC within 5 blocks of the player is used. The output lists each item type with its quantity and shows how full the inventory is against the configured maximum.
/npcpickup info # Inspect the nearest NPC within 5 blocks
/npcpickup info "Town Guard" # Inspect a named NPC
/npcpickup info Merchant # NPC names without spaces need no quotes
/npcpickup clear <npc_name|all>
Removes all items from one or all NPC inventories instantly. Items are deleted - they are not dropped to the ground. Use all to wipe every NPC inventory at once.
/npcpickup clear "Town Guard" # Clear one NPC by name
/npcpickup clear all # Clear every NPC's inventory
/npcpickup disable <npc_id|npc_name>
Prevents a specific NPC from picking up any items. The NPC ID is written to npc_settings.disabled_pickup in config.yml and survives restarts and reloads. Use either the numeric NPC ID or the exact NPC name.
/npcpickup disable 42 # Disable pickup by NPC ID
/npcpickup disable "Town Guard" # Disable pickup by NPC name
/npcpickup enable <npc_id|npc_name>
Re-enables item pickup for an NPC that was previously disabled. The NPC ID is removed from npc_settings.disabled_pickup in config.yml.
/npcpickup enable 42
/npcpickup enable "Town Guard"
/npcpickup thief <npc_id|npc_name>
Puts an NPC into thief mode. The NPC will start scanning nearby containers and stealing items from them on every theft cycle. The NPC ID is written to thief_mode.thief_npcs in config.yml and persists across restarts.
/npcpickup thief "Sneaky Pete" # Enable thief mode by name
/npcpickup thief 7 # Enable thief mode by NPC ID
/npcpickup unthief <npc_id|npc_name>
Removes an NPC from thief mode. The NPC stops stealing from containers but keeps any items already collected in its virtual inventory. The NPC ID is removed from thief_mode.thief_npcs in config.yml.
/npcpickup unthief "Sneaky Pete"
/npcpickup unthief 7
/npcpickup reload
Reloads config.yml from disk and restarts both the pickup task and the theft task with the updated settings. Use this after directly editing the config file. Per-NPC states (disabled_pickup, thief_npcs) are re-read from the reloaded config.
/npcpickup reload
/npcpickup toggle
Toggles the entire plugin on or off globally. When disabled, no pickup scans, theft scans, or death drop handling run at all. The new state is saved to config.yml. Useful for temporarily suspending all NPC item activity without removing the plugin.
/npcpickup toggle
Full tab completion is provided for all subcommands and NPC names. Typing /npcpickup and pressing Tab shows all available subcommands. For commands that accept an NPC name, pressing Tab suggests NPC names from the Citizens registry.
| Subcommand | Argument |
|---|---|
reload, toggle, status |
(no arguments) |
info |
NPC name (optional) |
clear |
NPC name or all |
disable, enable |
NPC ID or NPC name |
thief, unthief |
NPC ID or NPC name |
| Permission | Description | Default |
|---|---|---|
npcpickup.admin |
Access to all /npcpickup commands |
op |
By default only server operators can use the plugin commands. Grant access to specific groups using your permission manager. Example using LuckPerms:
/lp group admin permission set npcpickup.admin true
/lp group moderator permission set npcpickup.admin true
NPC PickUp uses Apache Maven as its build system. Citizens2 is a provided dependency - it must be present at runtime but is not bundled into the output JAR.
Requirements:
- Java 17 or newer
- Apache Maven 3.6 or newer
Steps:
# Clone the repository
git clone https://github.com/Cobbleworks/NPC-PickUp-Plugin.git
cd NPC-PickUp-Plugin
# Compile and package
mvn clean packageThe output JAR is written to target/NPCItemPickup-x.x.x.jar. Copy it into your server's plugins/ folder as described in the Installation Steps section.
Project Structure:
src/main/
├── java/com/example/npcitempickup/
│ ├── NPCItemPickupPlugin.java - Plugin entry point (onEnable / onDisable)
│ ├── commands/
│ │ └── NPCPickupCommand.java - All /npcpickup subcommands + tab completion
│ ├── listeners/
│ │ ├── ItemPickupListener.java - NPC pickup priority and player drop handling
│ │ └── NPCDeathListener.java - Death drop handling via NPCDeathEvent and EntityDeathEvent
│ ├── managers/
│ │ └── NPCInventoryManager.java - Virtual inventory storage, item filtering, per-NPC state
│ └── tasks/
│ ├── ItemPickupTask.java - Repeating task for NPC item detection and collection
│ └── ChestTheftTask.java - Repeating task for thief NPC container scanning and stealing
└── resources/
├── config.yml - Default configuration with all settings and comments
└── plugin.yml - Plugin metadata, commands, permissions, Citizens dependency
This project is licensed under the MIT License - see the LICENSE file for details.
The screenshots below demonstrate NPC PickUp Plugin across several scenarios, including container theft, passive item spotting, death drops, and NPC behavior in different environments.
| NPC PickUp - Chest Pickup | NPC PickUp - Barrel Steal |
|---|---|
![]() |
![]() |
| NPC PickUp - Item Spotting | NPC PickUp - Death Drop |
![]() |
![]() |
| NPC PickUp - NPC Eating | NPC PickUp - Chest Item Retrieval |
![]() |
![]() |






