Repository navigation
Home
Welcome to the official documentation for the VirtualShulker plugin. Here you'll find setup instructions, usage guides, command references, and customization tips for VirtualShulker.
- Getting Started
- How It Works
- Commands
- Permissions
- Configuration
- Anti-Duplication System
- Advanced Features
- FAQ
- Troubleshooting
- Contributing
- Support
VirtualShulker allows Minecraft players to access shulker box inventories directly from their inventory without needing to place them in the world. The plugin features a cutting-edge anti-duplication system with multiple security layers.
- Minecraft Version: 1.21.8+
- Server Software: Paper/Purpur (recommended) or Spigot
- Java Version: 21+
- Download the latest release from GitHub Releases
- Place the
vshulker.jarfile in your server'spluginsfolder - Restart your Minecraft server
- The plugin will automatically create a
VirtualShulkerfolder withconfig.yml - (Optional) Customize the configuration and reload with
/vs reload
- Get a shulker box (any color)
- Hold it in your main hand or off hand
- Shift + Right Click to open the virtual inventory
- Modify contents as needed
- Close the inventory (ESC) to save changes
Method: Hold a shulker box and press Shift + Right Click
The plugin will:
- Validate the shulker box and its contents (NBT validation)
- Create a snapshot of your inventory state
- Open a virtual inventory with the shulker's contents
- Start continuous session validation (every tick)
The virtual shulker will automatically close when:
- You take damage
- You teleport or change worlds
- You disconnect from the server
- You die
- The system detects manipulation attempts
Auto-save triggers:
- Every inventory modification (2-tick delay for batching)
- When closing the inventory
- During session validation checks
Security checks before saving:
- Transaction pattern analysis
- Inventory snapshot comparison
- NBT validation
- Impossible modification detection
⚠️ Important: If the anti-duplication system detects suspicious activity, changes will NOT be saved and you'll receive a notification.
All commands support the /vs alias as a shortcut for /virtualshulker.
| Command | Permission Required | Description |
|---|---|---|
| /vs help | virtualshulker.command.help | Display all available commands |
| /vs reload | virtualshulker.command.reload | Reload plugin configuration |
| /vs debug [player] | virtualshulker.command.debug | Show debug information for a player |
| /vs cleanup [player] | virtualshulker.command.cleanup | Force cleanup player session state |
| /vs stats | virtualshulker.command.stats | Display system statistics |
Examples:
# Give admin group full access
/lp group admin permission set virtualshulker.* true
Give moderator group all commands but not use
/lp group moderator permission set virtualshulker.command.* true
Give specific player full access
/lp user Steve permission set virtualshulker.* true
Grant to Groups:
# Everyone can use virtual shulkers
/lp group default permission set virtualshulker.use true
Admins get full access
/lp group admin permission set virtualshulker.* true
Moderators get all commands
/lp group moderator permission set virtualshulker.command.* true
Grant to Players:
# Give player ability to use virtual shulkers
/lp user PlayerName permission set virtualshulker.use true
Give player full access
/lp user PlayerName permission set virtualshulker.* true
Give player specific command
/lp user PlayerName permission set virtualshulker.command.debug true
Remove Permissions:
# Remove from player
/lp user PlayerName permission unset virtualshulker.use
Remove from group
/lp group default permission unset virtualshulker.use
Problem: Player can't open virtual shulkers
Solutions:
- Check
config.yml- ifuse: "virtualshulker.use", player needs the permission - Grant permission:
/lp user PlayerName permission set virtualshulker.use true - Or set
use: ""in config to allow everyone
Problem: Admin can't use commands
Solutions:
- Make sure they're OP:
/op PlayerName - Or grant specific permission:
/lp user PlayerName permission set virtualshulker.command.reload true - Or grant all:
/lp user PlayerName permission set virtualshulker.* true
Problem: Commands work but can't open shulkers
Solution: The use permission is separate from command permissions. Grant virtualshulker.use.
The legacy virtualshulker.admin permission from older versions is still supported but deprecated.
Old way (still works):
/lp group admin permission set virtualshulker.admin true
New way (recommended):
/lp group admin permission set virtualshulker.* true
# or for specific commands:
/lp group admin permission set virtualshulker.command.* true
ℹ️ Note: The new permission system provides better control. We recommend migrating to the new permissions for more flexibility.
The configuration file is located at plugins/VirtualShulker/config.yml.
# VirtualShulker Configuration
shulker:
Inventory size (must be multiple of 9: 9, 18, 27, 36, 45, 54)
size: 27
Inventory title (supports MiniMessage format)
title: "<gold><bold>Virtual Shulker"
Messages (support MiniMessage and legacy color codes)
messages:
opened: "<green>Shulker opened!"
closed: "<red>Shulker closed!"
closed-damage: "<red>Shulker automatically closed due to damage!"
no-permission: "<red>You don't have permission to use this command!"
reload: "<green>Plugin reloaded successfully!"
Permissions
permissions:
Permission to use virtual shulkers (shift + right-click)
Options:
"" or "*" = Everyone can use (no permission required)
"virtualshulker.use" = Requires specific permission
use: ""
Permission for admin commands (always required)
admin: "virtualshulker.admin"
The number of slots in the virtual inventory.
- Valid values: 9, 18, 27, 36, 45, 54 (multiples of 9)
- Default: 27 (same as standard shulker box)
- Note: This only affects the GUI size, not the actual storage capacity
The title displayed at the top of the virtual inventory.
- Format: MiniMessage or legacy color codes
-
Default:
<gold><bold>Virtual Shulker -
Examples:
title: "<gradient:red:blue>Rainbow Shulker"title: "<green>✦ Storage Box ✦"title: "§6§lShulker Box"
Customizable messages shown to players.
-
Format: MiniMessage (
<color>) or legacy codes (§,&) - Default: Italian messages (can be changed to any language)
Controls who can open virtual shulkers.
-
""or"*"= No permission required (everyone) -
"virtualshulker.use"= Requires specific permission
Controls access to admin commands.
- Always required regardless of use permission
-
Default:
virtualshulker.admin
The plugin uses MiniMessage for text formatting:
Colors:
"<black>Black"
"<dark_blue>Dark Blue"
"<dark_green>Dark Green"
"<dark_aqua>Dark Aqua"
"<dark_red>Dark Red"
"<dark_purple>Dark Purple"
"<gold>Gold"
"<gray>Gray"
"<dark_gray>Dark Gray"
"<blue>Blue"
"<green>Green"
"<aqua>Aqua"
"<red>Red"
"<light_purple>Light Purple"
"<yellow>Yellow"
"<white>White"
Formatting:
"<bold>Bold Text"
"<italic>Italic Text"
"<underline>Underlined Text"
"<strikethrough>Strikethrough"
"<obfuscated>Obfuscated"
Combined:
"<gold><bold>Golden Bold"
"<red><italic>Red Italic"
"<gradient:red:blue>Rainbow Gradient"
"<rainbow>Rainbow Text"
Also supports legacy § and & color codes:
"§6§lGolden Bold"
"&c&oRed Italic"
VirtualShulker features one of the most advanced anti-duplication systems available for Minecraft plugins, with 6 independent security layers.
┌─────────────────────────────────────┐
│ Layer 1: Transaction Tracking │ ← Records every action
├─────────────────────────────────────┤
│ Layer 2: NBT Validation │ ← Validates item data
├─────────────────────────────────────┤
│ Layer 3: Inventory Snapshot │ ← SHA-256 hashing
├─────────────────────────────────────┤
│ Layer 4: Continuous Validation │ ← Every tick (20Hz)
├─────────────────────────────────────┤
│ Layer 5: Session Integrity │ ← Slot tracking
├─────────────────────────────────────┤
│ Layer 6: Multi-Point Saving │ ← Checkpoint system
└─────────────────────────────────────┘
Purpose: Monitor all player interactions with the inventory
Features:
- Records every click, drag, shift-click, hotkey swap
- Transaction timestamp tracking
- Rate limiting: max 50 transactions per second
- Pattern analysis for suspicious behavior
Detects:
- Rapid-fire clicking (bot-like behavior)
- Impossible transaction sequences
- Packet flooding attacks
Purpose: Ensure all items have valid data structures
Validates:
- Display name length (max 256 characters)
- Lore lines (max 50 lines, 256 chars each)
- Nested shulker boxes (blocked)
- Malformed NBT data
Prevents:
- NBT size exploits
- Crash items
- Nested shulker duplication
Purpose: Detect inventory state manipulation
How it works:
- Creates SHA-256 hash of inventory on open
- Tracks player inventory, shulker contents, ender chest
- Maintains history of last 10 states
- Compares current state against snapshot
Detects:
- Inventory rollback exploits
- Copy-paste manipulation (UIUtils)
- Item count increases
- Partial inventory restoration
- Identical state repetition (>2 times)
Purpose: Real-time monitoring during session
Frequency: Every tick (20 times per second)
Checks:
- Shulker still exists in original slot
- Shulker hasn't been replaced
- Shulker matches original metadata
- Session integrity maintained
Action on failure:
- Immediate session termination
- No save performed
- Player notification
- Admin alert
- Detailed logging
Purpose: Prevent session hijacking and slot swapping
Tracks:
- Original slot location (main hand, off hand, inventory, ender chest)
- Original shulker metadata (type, display name, lore, enchantments)
- Session start timestamp
- Player UUID
Features:
- 200ms cooldown between opens
- Prevents concurrent sessions
- Slot verification on every save
Purpose: Ensure data consistency across saves
Save Points:
- Auto-save after modifications (2-tick delay)
- Manual save on inventory close
- Emergency save on damage/teleport
- Checkpoint before any modification
Rollback Capability:
- Original contents checkpoint created on open
- Rollback to checkpoint if validation fails
- No data loss on legitimate use
Player: Steve
Action: Used UIUtils to copy items
Detection: Inventory snapshot comparison
├─ Before: 64 diamonds
├─ After: 128 diamonds (inventory + shulker)
├─ Total items increased from 1,234 to 1,298
└─ Result: BLOCKED - Changes not saved
Player: Alex
Action: Swapped shulker during session
Detection: Continuous validation (tick 450)
├─ Original: Blue Shulker Box
├─ Current: Red Shulker Box
├─ Session age: 22,500ms
└─ Result: BLOCKED - Session terminated
Player: Mike
Action: Delayed packet sending via mod
Detection: Transaction tracking + session integrity
├─ 73 transactions in 1000ms (suspicious rate)
├─ Shulker not in expected slot
└─ Result: BLOCKED - Pattern flagged
Step-by-step:
-
Immediate Block
- Save operation cancelled instantly
- No data written to shulker NBT
-
Session Termination
- Active session removed from memory
- Inventory closed for player
-
Detailed Logging
═══════════════════════════════════════════════ ANTI-DUPE SYSTEM TRIGGERED ═══════════════════════════════════════════════ Player: Steve (UUID: xxx-xxx-xxx) Reason: Inventory manipulation detected Detection: Snapshot validation failed Details: Item count increased by 64 Slot Type: MAIN_HAND Session Age: 15234ms Location: 100, 64, 200 (world) ═══════════════════════════════════════════════ ACTION: Save blocked, session terminated ═══════════════════════════════════════════════ -
Admin Notification All online players with
virtualshulker.adminpermission receive:[ANTI-DUPE] Steve attempted duplication! Reason: Item count increased by 64 -
Player Notification The player sees:
ANTI-DUPE: Manipulation detected! Reason: Item count increased by 64 Changes NOT saved!
✅ UIUtils copy-paste exploits
✅ Packet delay manipulation
✅ Inventory rollback attacks
✅ Shulker swapping during session
✅ Nested shulker duplication
✅ NBT size exploits
✅ Concurrent session abuse
✅ Client-server desynchronization
✅ Crash items and malformed NBT
✅ Rapid transaction flooding
- Validation overhead: < 0.1ms per tick
- Memory usage: ~500 bytes per active session
- CPU impact: Negligible (<0.5% on average servers)
VirtualShulker uses a pure NBT storage system:
Benefits:
- ✅ No database required
- ✅ No external dependencies
- ✅ No data migration needed
- ✅ Portable between servers
- ✅ Backup-friendly (standard world saves)
- ✅ Zero data loss risk
How it works:
- Contents stored directly in shulker box item metadata
- Uses Minecraft's native BlockStateMeta API
- Full compatibility with vanilla mechanics
- Instant read/write operations
The plugin tracks shulker boxes placed in the world:
Protected actions:
- Cannot be moved by pistons
- Cannot have items piped in/out via hoppers
- Contents preserved during explosions
- Proper NBT saving when broken
Implementation:
- Location-based tracking registry
- Automatic cleanup on break
- Explosion handling with NBT preservation
Supports shulker boxes from any inventory:
- ✅ Main hand
- ✅ Off hand
- ✅ Player inventory
- ✅ Ender chest
Automatic slot detection and saving to correct location.
Blocked actions during virtual session:
- ❌ Moving the opened shulker
- ❌ Dropping the opened shulker
- ❌ Swapping hands with opened shulker
- ❌ Hotkey swapping with opened shulker
- ❌ Placing shulker boxes inside virtual inventory
- ❌ Shift-clicking shulker boxes
- ❌ Double-clicking with shulker boxes
- ❌ Number key swaps involving shulkers
Automatic closing triggers:
- Taking damage
- Teleportation
- World change
- Player death
- Server shutdown
- Disconnect
Validation frequency: Every tick (50ms)
Validates:
- Shulker still in original slot
- Shulker hasn't been modified externally
- Session integrity maintained
- No suspicious patterns
Benefits:
- Immediate exploit detection
- Zero-tolerance policy
- Sub-second response time
Q: Does this plugin require a database?
A: No! VirtualShulker uses NBT-only storage. Everything is saved directly in the item data.
Q: Can I use this with other shulker plugins?
A: Generally yes, but test compatibility. VirtualShulker handles its own shulker boxes independently.
Q: Does this work in creative mode?
A: Yes, fully compatible with all game modes.
Q: What happens if the server crashes?
A: Contents are saved on every modification (2-tick delay). At most, you lose the last 0.1 seconds of changes.
Q: Can I open a shulker while another is open?
A: No, only one virtual shulker per player at a time.
Q: Can I place shulker boxes inside the virtual inventory?
A: No, this is blocked to prevent nested shulker exploits.
Q: What happens if I drop the opened shulker?
A: The action is blocked. You must close the inventory first.
Q: Can I use this with ender chests?
A: Yes, shulker boxes in ender chests work perfectly.
Q: How do I let everyone use virtual shulkers?
A: Set permissions.use: "" in config.yml.
Q: Can I restrict usage to specific worlds?
A: Use your permission plugin's world-specific permissions or install a world guard plugin.
Q: How do I give admin permissions?
A: Grant virtualshulker.admin permission via your permission plugin.
Q: Will legitimate players be flagged?
A: No. The system is designed to only flag impossible actions (item count increases, inventory rollbacks, etc.).
Q: What if I'm falsely flagged?
A: Report it as a bug with logs. The system is extensively tested but we continuously improve detection accuracy.
Q: Can I disable anti-duplication?
A: No, it's a core feature and cannot be disabled. However, it doesn't interfere with normal gameplay.
Q: Does this prevent ALL duplication methods?
A: It prevents all known client-side methods (UIUtils, packet delay, etc.). Server-side duplication bugs in Paper/Spigot are out of scope.
Q: What's the performance impact?
A: Minimal. < 0.1ms validation per tick, negligible CPU usage.
Q: How much RAM does this use?
A: About 500 bytes per active session. With 100 concurrent sessions, that's ~50KB.
Q: Can this cause lag?
A: No. All operations are optimized and asynchronous where possible.
Q: Is the source code available?
A: Yes, it's open source on GitHub.
Cause: Permission not granted or misconfigured
Solution:
- Check
config.yml- ifpermissions.useis set to a permission node, you need to grant it - Grant the permission via your permission plugin:
/lp user YourName permission set virtualshulker.use true - Or set
permissions.use: ""in config to allow everyone
Possible causes:
- Not holding a shulker box - Make sure it's in main hand or off hand
- Not shift-clicking - You must hold shift while right-clicking
- Clicking on a block - Try clicking in the air or on a non-interactive block
- Permission issue - See above
- Cooldown - Wait 200ms between opens
Debug steps:
/vs debug YourName
Check if "Loading: true" - if stuck, use /vs cleanup YourName
Possible causes:
- Anti-duplication triggered - Check console for logs
- Shulker moved/replaced - Don't move the shulker while it's open
- Server crash - At most 0.1 seconds of changes can be lost
Check logs for:
ANTI-DUPE SYSTEM TRIGGERED
This is intentional! You cannot move a shulker while it's open.
Solution: Close the inventory first (ESC), then move it.
Solution:
/vs cleanup PlayerName
This force-closes the session and cleans up the player's state.
Before reporting a bug:
- Check console for errors
- Try
/vs cleanupfor stuck sessions - Verify configuration is correct
- Test with minimal plugins to rule out conflicts
Include in bug reports:
- Full server log (use pastebin)
- VirtualShulker version
- Server software and version (Paper 1.21.8, etc.)
- Steps to reproduce
- Output of
/vs debug
Enable debug logging:
Add to bukkit.yml:
settings:
plugin-logging:
VirtualShulker: FINE
This will log all operations to console.
Check session state:
/vs debug PlayerName
View statistics:
/vs stats
Force cleanup:
/vs cleanup PlayerName
If experiencing lag with VirtualShulker:
-
Check active sessions:
/vs stats- Normal: < 20 active sessions per 100 players
- High: > 50 active sessions per 100 players
-
Check console for spam:
- If seeing constant validation failures, investigate player behavior
-
Monitor server TPS:
/tpsVirtualShulker should not significantly impact TPS
-
Check plugin conflicts:
- Try disabling other inventory plugins temporarily
We welcome contributions to VirtualShulker!
- Fork the repository on GitHub
-
Create a feature branch from
maingit checkout -b feature/your-feature-name - Make your changes and test thoroughly
-
Commit with clear messages
git commit -m "Add: Description of your feature" -
Push to your fork
git push origin feature/your-feature-name - Submit a Pull Request with detailed description
- Follow existing code style
- Add comments for complex logic
- Test all changes thoroughly
- Update documentation if needed
- One feature per pull request
Create an issue on GitHub with:
- Clear title describing the bug
- Steps to reproduce
- Expected behavior vs actual behavior
- Server version and plugin version
- Full error logs (use pastebin)
- Any relevant screenshots
Create an issue on GitHub with:
- Clear description of the feature
- Use case / why it's needed
- Possible implementation approach
- Any mockups or examples
- Be respectful and constructive
- Help others when possible
- Follow the contribution guidelines
- No spam or self-promotion
For help and support:
- Read this wiki - Most questions are answered here
- Check FAQ section - Common issues and solutions
- Search existing issues on GitHub
- Create a new issue if your problem isn't covered
Report bugs and request features on GitHub:
https://github.com/MathsAnalysis/VirtualShulker/issues
- GitHub Discussions: Ask questions and share configurations
- Issue Tracker: Report bugs and request features
- Pull Requests: Contribute code and improvements
For commercial support, server setup assistance, or custom modifications, contact the author via GitHub.
- GitHub Repository: https://github.com/MathsAnalysis/VirtualShulker
- Issue Tracker: https://github.com/MathsAnalysis/VirtualShulker/issues
- Latest Release: https://github.com/MathsAnalysis/VirtualShulker/releases/latest
Thank you for using VirtualShulker!
Last updated: December 2024
# VirtualShulker WikiWelcome to the official documentation for the VirtualShulker plugin. Here you'll find setup instructions, usage guides, command references, and customization tips for VirtualShulker.
- [Getting Started](#getting-started)
- [How It Works](#how-it-works)
- [Commands](#commands)
- [Permissions](#permissions)
- [Configuration](#configuration)
- [Anti-Duplication System](#anti-duplication-system)
- [Advanced Features](#advanced-features)
- [FAQ](#faq)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [Support](#support)
VirtualShulker allows Minecraft players to access shulker box inventories directly from their inventory without needing to place them in the world. The plugin features a cutting-edge anti-duplication system with multiple security layers.
- Minecraft Version: 1.21.8+
- Server Software: Paper/Purpur (recommended) or Spigot
- Java Version: 21+
- Download the latest release from [GitHub Releases](https://github.com/MathsAnalysis/VirtualShulker/releases)
- Place the
vshulker.jarfile in your server'spluginsfolder - Restart your Minecraft server
- The plugin will automatically create a
VirtualShulkerfolder withconfig.yml - (Optional) Customize the configuration and reload with
/vs reload
- Get a shulker box (any color)
- Hold it in your main hand or off hand
- Shift + Right Click to open the virtual inventory
- Modify contents as needed
- Close the inventory (ESC) to save changes
Method: Hold a shulker box and press Shift + Right Click
The plugin will:
- Validate the shulker box and its contents (NBT validation)
- Create a snapshot of your inventory state
- Open a virtual inventory with the shulker's contents
- Start continuous session validation (every tick)
The virtual shulker will automatically close when:
- You take damage
- You teleport or change worlds
- You disconnect from the server
- You die
- The system detects manipulation attempts
Auto-save triggers:
- Every inventory modification (2-tick delay for batching)
- When closing the inventory
- During session validation checks
Security checks before saving:
- Transaction pattern analysis
- Inventory snapshot comparison
- NBT validation
- Impossible modification detection
⚠️ Important: If the anti-duplication system detects suspicious activity, changes will NOT be saved and you'll receive a notification.
All commands support the /vs alias as a shortcut for /virtualshulker.
| Command | Permission Required | Description |
|---|---|---|
/vs help |
virtualshulker.command.help |
Display all available commands |
/vs reload |
virtualshulker.command.reload |
Reload plugin configuration |
/vs debug [player] |
virtualshulker.command.debug |
Show debug information for a player |
/vs cleanup [player] |
virtualshulker.command.cleanup |
Force cleanup player session state |
/vs stats |
virtualshulker.command.stats |
Display system statistics |
Note: All admin commands (
reload,debug,cleanup,stats) default to OP-only unless explicitly granted.
# View server statistics
/vs stats
# Debug your own session
/vs debug
# Debug another player's session
/vs debug Steve
# Force cleanup if a player is stuck
/vs cleanup Steve
# Reload configuration after editing config.yml
/vs reload/vs stats output:
╔═══════════════════════════════════════╗
║ VIRTUALSHULKER STATISTICS ║
╠═══════════════════════════════════════╣
Online players: 5
Active sessions: 2
System: NBT-ONLY (Direct Save)
Database: NONE
Cache: NONE
╚═══════════════════════════════════════╝
/vs debug Steve output:
╔═══════════════════════════════════════╗
║ DEBUG INFO: Steve ║
╠═══════════════════════════════════════╣
Shulker open: true
Loading: false
╚═══════════════════════════════════════╝
VirtualShulker uses a granular permission system that allows fine-tuned control over who can access which features.
| Permission | Description | Default |
|---|---|---|
| Core Permissions | ||
virtualshulker.use |
Open virtual shulker boxes (Shift + Right Click) | Configurable |
| Command Permissions | ||
virtualshulker.command.use |
Access to base /vs command |
Everyone |
virtualshulker.command.help |
Access to /vs help command |
Everyone |
virtualshulker.command.reload |
Access to /vs reload command |
OP only |
virtualshulker.command.debug |
Access to /vs debug command |
OP only |
virtualshulker.command.cleanup |
Access to /vs cleanup command |
OP only |
virtualshulker.command.stats |
Access to /vs stats command |
OP only |
| Wildcard Permissions | ||
virtualshulker.* |
All permissions (core + commands) | OP only |
virtualshulker.command.* |
All command permissions | OP only |
The virtualshulker.use permission controls who can open virtual shulker boxes.
Configuration in config.yml:
permissions:
use: "" # Empty = everyone can use (no permission required)
# OR
use: "virtualshulker.use" # Specific permission requiredOption 1: Allow Everyone (Recommended for most servers)
permissions:
use: ""No permission management needed - all players can use virtual shulkers.
Option 2: Permission-Based Access
permissions:
use: "virtualshulker.use"Then grant the permission:
# LuckPerms
/lp group default permission set virtualshulker.use true
# PermissionsEx
/pex group default add virtualshulker.useEach command has its own permission for granular access control.
These commands are accessible to everyone by default:
-
virtualshulker.command.use- Base command access -
virtualshulker.command.help- View help menu
These commands require explicit permission (OP by default):
-
virtualshulker.command.reload- Reload plugin configuration -
virtualshulker.command.debug- View player debug information -
virtualshulker.command.cleanup- Force cleanup player sessions -
virtualshulker.command.stats- View system statistics
# config.yml
permissions:
use: ""# No additional permissions needed!✅ Result: All players can open virtual shulkers, only OPs can use admin commands.
# Everyone can use virtual shulkers
/lp group default permission set virtualshulker.use true
# Moderators can view stats and debug
/lp group moderator permission set virtualshulker.command.stats true
/lp group moderator permission set virtualshulker.command.debug true
# Admins get full access
/lp group admin permission set virtualshulker.* true✅ Result:
- Default players: Can use virtual shulkers
- Moderators: Can use + view stats/debug
- Admins: Full access to everything
# Helper staff can only cleanup stuck players
/lp group helper permission set virtualshulker.command.cleanup true
# Moderators get stats + debug
/lp group moderator permission set virtualshulker.command.stats true
/lp group moderator permission set virtualshulker.command.debug true
# Senior mods can reload config
/lp group seniormod permission set virtualshulker.command.reload true
# Admins get everything
/lp group admin permission set virtualshulker.* true✅ Result: Each rank has exactly the permissions they need.
Use wildcards for easier permission management:
| Wildcard | Grants | Use Case |
|---|---|---|
virtualshulker.* |
Everything (use + all commands) | Admin groups |
virtualshulker.command.* |
All commands (but not use) | Command-only access |
Examples:
# Give admin group full access
/lp group admin permission set virtualshulker.* true
# Give moderator group all commands but not use
/lp group moderator permission set virtualshulker.command.* true
# Give specific player full access
/lp user Steve permission set virtualshulker.* trueGrant to Groups:
# Everyone can use virtual shulkers
/lp group default permission set virtualshulker.use true
# Admins get full access
/lp group admin permission set virtualshulker.* true
# Moderators get all commands
/lp group moderator permission set virtualshulker.command.* trueGrant to Players:
# Give player ability to use virtual shulkers
/lp user PlayerName permission set virtualshulker.use true
# Give player full access
/lp user PlayerName permission set virtualshulker.* true
# Give player specific command
/lp user PlayerName permission set virtualshulker.command.debug trueRemove Permissions:
# Remove from player
/lp user PlayerName permission unset virtualshulker.use
# Remove from group
/lp group default permission unset virtualshulker.useProblem: Player can't open virtual shulkers
Solutions:
- Check
config.yml- ifuse: "virtualshulker.use", player needs the permission - Grant permission:
/lp user PlayerName permission set virtualshulker.use true - Or set
use: ""in config to allow everyone
Problem: Admin can't use commands
Solutions:
- Make sure they're OP:
/op PlayerName - Or grant specific permission:
/lp user PlayerName permission set virtualshulker.command.reload true - Or grant all:
/lp user PlayerName permission set virtualshulker.* true
Problem: Commands work but can't open shulkers
Solution: The use permission is separate from command permissions. Grant virtualshulker.use.
The legacy virtualshulker.admin permission from older versions is still supported but deprecated.
Old way (still works):
/lp group admin permission set virtualshulker.admin trueNew way (recommended):
/lp group admin permission set virtualshulker.* true
# or for specific commands:
/lp group admin permission set virtualshulker.command.* trueℹ️ Note: The new permission system provides better control. We recommend migrating to the new permissions for more flexibility.
The configuration file is located at plugins/VirtualShulker/config.yml.
# VirtualShulker Configuration
shulker:
# Inventory size (must be multiple of 9: 9, 18, 27, 36, 45, 54)
size: 27
# Inventory title (supports [MiniMessage](https://docs.advntr.dev/minimessage/format.html) format)
title: "<gold><bold>Virtual Shulker"
# Messages (support MiniMessage and legacy color codes)
messages:
opened: "<green>Shulker opened!"
closed: "<red>Shulker closed!"
closed-damage: "<red>Shulker automatically closed due to damage!"
no-permission: "<red>You don't have permission to use this command!"
reload: "<green>Plugin reloaded successfully!"
# Permissions
permissions:
# Permission to use virtual shulkers (shift + right-click)
# Options:
# "" or "*" = Everyone can use (no permission required)
# "virtualshulker.use" = Requires specific permission
use: ""
# Permission for admin commands (always required)
admin: "virtualshulker.admin"The number of slots in the virtual inventory.
- Valid values: 9, 18, 27, 36, 45, 54 (multiples of 9)
- Default: 27 (same as standard shulker box)
- Note: This only affects the GUI size, not the actual storage capacity
The title displayed at the top of the virtual inventory.
- Format: MiniMessage or legacy color codes
-
Default:
<gold><bold>Virtual Shulker -
Examples:
title: "<gradient:red:blue>Rainbow Shulker" title: "<green>✦ Storage Box ✦" title: "§6§lShulker Box"
Customizable messages shown to players.
-
Format: MiniMessage (
<color>) or legacy codes (§,&) - Default: Italian messages (can be changed to any language)
Controls who can open virtual shulkers.
-
""or"*"= No permission required (everyone) -
"virtualshulker.use"= Requires specific permission
Controls access to admin commands.
- Always required regardless of use permission
-
Default:
virtualshulker.admin
The plugin uses MiniMessage for text formatting:
Colors:
"<black>Black"
"<dark_blue>Dark Blue"
"<dark_green>Dark Green"
"<dark_aqua>Dark Aqua"
"<dark_red>Dark Red"
"<dark_purple>Dark Purple"
"<gold>Gold"
"<gray>Gray"
"<dark_gray>Dark Gray"
"<blue>Blue"
"<green>Green"
"<aqua>Aqua"
"<red>Red"
"<light_purple>Light Purple"
"<yellow>Yellow"
"<white>White"Formatting:
"<bold>Bold Text"
"<italic>Italic Text"
"<underline>Underlined Text"
"<strikethrough>Strikethrough"
"<obfuscated>Obfuscated"Combined:
"<gold><bold>Golden Bold"
"<red><italic>Red Italic"
"<gradient:red:blue>Rainbow Gradient"
"<rainbow>Rainbow Text"Also supports legacy § and & color codes:
"§6§lGolden Bold"
"&c&oRed Italic"VirtualShulker features one of the most advanced anti-duplication systems available for Minecraft plugins, with 6 independent security layers.
┌─────────────────────────────────────┐
│ Layer 1: Transaction Tracking │ ← Records every action
├─────────────────────────────────────┤
│ Layer 2: NBT Validation │ ← Validates item data
├─────────────────────────────────────┤
│ Layer 3: Inventory Snapshot │ ← SHA-256 hashing
├─────────────────────────────────────┤
│ Layer 4: Continuous Validation │ ← Every tick (20Hz)
├─────────────────────────────────────┤
│ Layer 5: Session Integrity │ ← Slot tracking
├─────────────────────────────────────┤
│ Layer 6: Multi-Point Saving │ ← Checkpoint system
└─────────────────────────────────────┘
Purpose: Monitor all player interactions with the inventory
Features:
- Records every click, drag, shift-click, hotkey swap
- Transaction timestamp tracking
- Rate limiting: max 50 transactions per second
- Pattern analysis for suspicious behavior
Detects:
- Rapid-fire clicking (bot-like behavior)
- Impossible transaction sequences
- Packet flooding attacks
Purpose: Ensure all items have valid data structures
Validates:
- Display name length (max 256 characters)
- Lore lines (max 50 lines, 256 chars each)
- Nested shulker boxes (blocked)
- Malformed NBT data
Prevents:
- NBT size exploits
- Crash items
- Nested shulker duplication
Purpose: Detect inventory state manipulation
How it works:
- Creates SHA-256 hash of inventory on open
- Tracks player inventory, shulker contents, ender chest
- Maintains history of last 10 states
- Compares current state against snapshot
Detects:
- Inventory rollback exploits
- Copy-paste manipulation (UIUtils)
- Item count increases
- Partial inventory restoration
- Identical state repetition (>2 times)
Purpose: Real-time monitoring during session
Frequency: Every tick (20 times per second)
Checks:
- Shulker still exists in original slot
- Shulker hasn't been replaced
- Shulker matches original metadata
- Session integrity maintained
Action on failure:
- Immediate session termination
- No save performed
- Player notification
- Admin alert
- Detailed logging
Purpose: Prevent session hijacking and slot swapping
Tracks:
- Original slot location (main hand, off hand, inventory, ender chest)
- Original shulker metadata (type, display name, lore, enchantments)
- Session start timestamp
- Player UUID
Features:
- 200ms cooldown between opens
- Prevents concurrent sessions
- Slot verification on every save
Purpose: Ensure data consistency across saves
Save Points:
- Auto-save after modifications (2-tick delay)
- Manual save on inventory close
- Emergency save on damage/teleport
- Checkpoint before any modification
Rollback Capability:
- Original contents checkpoint created on open
- Rollback to checkpoint if validation fails
- No data loss on legitimate use
Player: Steve
Action: Used UIUtils to copy items
Detection: Inventory snapshot comparison
├─ Before: 64 diamonds
├─ After: 128 diamonds (inventory + shulker)
├─ Total items increased from 1,234 to 1,298
└─ Result: BLOCKED - Changes not saved
Player: Alex
Action: Swapped shulker during session
Detection: Continuous validation (tick 450)
├─ Original: Blue Shulker Box
├─ Current: Red Shulker Box
├─ Session age: 22,500ms
└─ Result: BLOCKED - Session terminated
Player: Mike
Action: Delayed packet sending via mod
Detection: Transaction tracking + session integrity
├─ 73 transactions in 1000ms (suspicious rate)
├─ Shulker not in expected slot
└─ Result: BLOCKED - Pattern flagged
Step-by-step:
-
Immediate Block
- Save operation cancelled instantly
- No data written to shulker NBT
-
Session Termination
- Active session removed from memory
- Inventory closed for player
-
Detailed Logging
═══════════════════════════════════════════════ ANTI-DUPE SYSTEM TRIGGERED ═══════════════════════════════════════════════ Player: Steve (UUID: xxx-xxx-xxx) Reason: Inventory manipulation detected Detection: Snapshot validation failed Details: Item count increased by 64 Slot Type: MAIN_HAND Session Age: 15234ms Location: 100, 64, 200 (world) ═══════════════════════════════════════════════ ACTION: Save blocked, session terminated ═══════════════════════════════════════════════ -
Admin Notification All online players with
virtualshulker.adminpermission receive:[ANTI-DUPE] Steve attempted duplication! Reason: Item count increased by 64 -
Player Notification The player sees:
ANTI-DUPE: Manipulation detected! Reason: Item count increased by 64 Changes NOT saved!
✅ UIUtils copy-paste exploits
✅ Packet delay manipulation
✅ Inventory rollback attacks
✅ Shulker swapping during session
✅ Nested shulker duplication
✅ NBT size exploits
✅ Concurrent session abuse
✅ Client-server desynchronization
✅ Crash items and malformed NBT
✅ Rapid transaction flooding
- Validation overhead: < 0.1ms per tick
- Memory usage: ~500 bytes per active session
- CPU impact: Negligible (<0.5% on average servers)
VirtualShulker uses a pure NBT storage system:
Benefits:
- ✅ No database required
- ✅ No external dependencies
- ✅ No data migration needed
- ✅ Portable between servers
- ✅ Backup-friendly (standard world saves)
- ✅ Zero data loss risk
How it works:
- Contents stored directly in shulker box item metadata
- Uses Minecraft's native BlockStateMeta API
- Full compatibility with vanilla mechanics
- Instant read/write operations
The plugin tracks shulker boxes placed in the world:
Protected actions:
- Cannot be moved by pistons
- Cannot have items piped in/out via hoppers
- Contents preserved during explosions
- Proper NBT saving when broken
Implementation:
- Location-based tracking registry
- Automatic cleanup on break
- Explosion handling with NBT preservation
Supports shulker boxes from any inventory:
- ✅ Main hand
- ✅ Off hand
- ✅ Player inventory
- ✅ Ender chest
Automatic slot detection and saving to correct location.
Blocked actions during virtual session:
- ❌ Moving the opened shulker
- ❌ Dropping the opened shulker
- ❌ Swapping hands with opened shulker
- ❌ Hotkey swapping with opened shulker
- ❌ Placing shulker boxes inside virtual inventory
- ❌ Shift-clicking shulker boxes
- ❌ Double-clicking with shulker boxes
- ❌ Number key swaps involving shulkers
Automatic closing triggers:
- Taking damage
- Teleportation
- World change
- Player death
- Server shutdown
- Disconnect
Validation frequency: Every tick (50ms)
Validates:
- Shulker still in original slot
- Shulker hasn't been modified externally
- Session integrity maintained
- No suspicious patterns
Benefits:
- Immediate exploit detection
- Zero-tolerance policy
- Sub-second response time
Q: Does this plugin require a database?
A: No! VirtualShulker uses NBT-only storage. Everything is saved directly in the item data.
Q: Can I use this with other shulker plugins?
A: Generally yes, but test compatibility. VirtualShulker handles its own shulker boxes independently.
Q: Does this work in creative mode?
A: Yes, fully compatible with all game modes.
Q: What happens if the server crashes?
A: Contents are saved on every modification (2-tick delay). At most, you lose the last 0.1 seconds of changes.
Q: Can I open a shulker while another is open?
A: No, only one virtual shulker per player at a time.
Q: Can I place shulker boxes inside the virtual inventory?
A: No, this is blocked to prevent nested shulker exploits.
Q: What happens if I drop the opened shulker?
A: The action is blocked. You must close the inventory first.
Q: Can I use this with ender chests?
A: Yes, shulker boxes in ender chests work perfectly.
Q: How do I let everyone use virtual shulkers?
A: Set permissions.use: "" in config.yml.
Q: Can I restrict usage to specific worlds?
A: Use your permission plugin's world-specific permissions or install a world guard plugin.
Q: How do I give admin permissions?
A: Grant virtualshulker.admin permission via your permission plugin.
Q: Will legitimate players be flagged?
A: No. The system is designed to only flag impossible actions (item count increases, inventory rollbacks, etc.).
Q: What if I'm falsely flagged?
A: Report it as a bug with logs. The system is extensively tested but we continuously improve detection accuracy.
Q: Can I disable anti-duplication?
A: No, it's a core feature and cannot be disabled. However, it doesn't interfere with normal gameplay.
Q: Does this prevent ALL duplication methods?
A: It prevents all known client-side methods (UIUtils, packet delay, etc.). Server-side duplication bugs in Paper/Spigot are out of scope.
Q: What's the performance impact?
A: Minimal. < 0.1ms validation per tick, negligible CPU usage.
Q: How much RAM does this use?
A: About 500 bytes per active session. With 100 concurrent sessions, that's ~50KB.
Q: Can this cause lag?
A: No. All operations are optimized and asynchronous where possible.
Q: Is the source code available?
A: Yes, it's open source on GitHub.
Cause: Permission not granted or misconfigured
Solution:
- Check
config.yml- ifpermissions.useis set to a permission node, you need to grant it - Grant the permission via your permission plugin:
/lp user YourName permission set virtualshulker.use true
- Or set
permissions.use: ""in config to allow everyone
Possible causes:
- Not holding a shulker box - Make sure it's in main hand or off hand
- Not shift-clicking - You must hold shift while right-clicking
- Clicking on a block - Try clicking in the air or on a non-interactive block
- Permission issue - See above
- Cooldown - Wait 200ms between opens
Debug steps:
/vs debug YourNameCheck if "Loading: true" - if stuck, use /vs cleanup YourName
Possible causes:
- Anti-duplication triggered - Check console for logs
- Shulker moved/replaced - Don't move the shulker while it's open
- Server crash - At most 0.1 seconds of changes can be lost
Check logs for:
ANTI-DUPE SYSTEM TRIGGERED
This is intentional! You cannot move a shulker while it's open.
Solution: Close the inventory first (ESC), then move it.
Solution:
/vs cleanup PlayerNameThis force-closes the session and cleans up the player's state.
Before reporting a bug:
- Check console for errors
- Try
/vs cleanupfor stuck sessions - Verify configuration is correct
- Test with minimal plugins to rule out conflicts
Include in bug reports:
- Full server log (use pastebin)
- VirtualShulker version
- Server software and version (Paper 1.21.8, etc.)
- Steps to reproduce
- Output of
/vs debug
Enable debug logging:
Add to bukkit.yml:
settings:
plugin-logging:
VirtualShulker: FINEThis will log all operations to console.
Check session state:
/vs debug PlayerNameView statistics:
/vs statsForce cleanup:
/vs cleanup PlayerNameIf experiencing lag with VirtualShulker:
-
Check active sessions:
/vs stats- Normal: < 20 active sessions per 100 players
- High: > 50 active sessions per 100 players
-
Check console for spam:
- If seeing constant validation failures, investigate player behavior
-
Monitor server TPS:
/tps
VirtualShulker should not significantly impact TPS
-
Check plugin conflicts:
- Try disabling other inventory plugins temporarily
We welcome contributions to VirtualShulker!
- Fork the repository on GitHub
-
Create a feature branch from
maingit checkout -b feature/your-feature-name
- Make your changes and test thoroughly
-
Commit with clear messages
git commit -m "Add: Description of your feature" -
Push to your fork
git push origin feature/your-feature-name
- Submit a Pull Request with detailed description
- Follow existing code style
- Add comments for complex logic
- Test all changes thoroughly
- Update documentation if needed
- One feature per pull request
Create an issue on GitHub with:
- Clear title describing the bug
- Steps to reproduce
- Expected behavior vs actual behavior
- Server version and plugin version
- Full error logs (use pastebin)
- Any relevant screenshots
Create an issue on GitHub with:
- Clear description of the feature
- Use case / why it's needed
- Possible implementation approach
- Any mockups or examples
- Be respectful and constructive
- Help others when possible
- Follow the contribution guidelines
- No spam or self-promotion
For help and support:
- Read this wiki - Most questions are answered here
- Check FAQ section - Common issues and solutions
- Search existing issues on GitHub
- Create a new issue if your problem isn't covered
Report bugs and request features on GitHub:
https://github.com/MathsAnalysis/VirtualShulker/issues
- GitHub Discussions: Ask questions and share configurations
- Issue Tracker: Report bugs and request features
- Pull Requests: Contribute code and improvements
For commercial support, server setup assistance, or custom modifications, contact the author via GitHub.
- GitHub Repository: https://github.com/MathsAnalysis/VirtualShulker
- Issue Tracker: https://github.com/MathsAnalysis/VirtualShulker/issues
- Latest Release: https://github.com/MathsAnalysis/VirtualShulker/releases/latest
- [MiniMessage Format](https://docs.advntr.dev/minimessage/format.html)
- [Paper API Documentation](https://papermc.io/javadocs)
- [Spigot API Reference](https://hub.spigotmc.org/javadocs/spigot/)
Thank you for using VirtualShulker!
Last updated: December 2024