Bukkit API is the foundation for Minecraft server plugin development, enabling extensive customization and feature addition. This comprehensive guide covers plugin creation, event handling, world manipulation, and advanced server modifications.
Bukkit Architecture Overview
Bukkit Plugin Ecosystem: ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ Minecraft │ -> │ Bukkit API │ -> │ Your Plugin │ │ Server │ │ • Events │ │ • Listeners │ │ │ │ • Commands │ │ • Commands │ │ │ │ • Scheduler │ │ • Tasks │ └─────────────────┘ └──────────────────┘ └─────────────────┘ │ │ │ ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ World │ │ Entities │ │ Players │ │ Manipulation │ │ Management │ │ Interaction │ └─────────────────┘ └──────────────────┘ └─────────────────┘
Project Setup and Dependencies
1. Maven Configuration
<!-- pom.xml -->
<properties>
<bukkit.version>1.20.1-R0.1-SNAPSHOT</bukkit.version>
</properties>
<repositories>
<repository>
<id>spigotmc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<!-- Bukkit API -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>${bukkit.version}</version>
<scope>provided</scope>
</dependency>
<!-- Optional: WorldEdit for advanced world manipulation -->
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.2.9</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
2. Plugin Configuration File
# src/main/resources/plugin.yml name: MyAwesomePlugin version: 1.0.0 main: com.myplugin.MyAwesomePlugin api-version: 1.20 description: An awesome Minecraft plugin author: YourName website: https://yourwebsite.com commands: hello: description: Say hello to the player usage: /hello permission: myplugin.hello warp: description: Teleport to a warp location usage: /warp <name> permission: myplugin.warp kit: description: Get a kit of items usage: /kit <name> permission: myplugin.kit permissions: myplugin.*: description: All permissions for MyAwesomePlugin children: myplugin.hello: true myplugin.warp: true myplugin.kit: true myplugin.admin: true myplugin.hello: description: Allows using hello command default: true myplugin.warp: description: Allows using warp command default: true myplugin.kit: description: Allows using kit command default: op myplugin.admin: description: Admin permissions default: op
Core Plugin Implementation
1. Main Plugin Class
package com.myplugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.configuration.file.FileConfiguration;
import java.util.logging.Logger;
public class MyAwesomePlugin extends JavaPlugin {
private static MyAwesomePlugin instance;
private Logger logger;
private PluginManager pluginManager;
private DataManager dataManager;
@Override
public void onEnable() {
instance = this;
logger = getLogger();
pluginManager = new PluginManager(this);
dataManager = new DataManager(this);
// Load configuration
saveDefaultConfig();
reloadConfig();
// Initialize managers
pluginManager.initialize();
dataManager.initialize();
// Register events
registerEvents();
// Register commands
registerCommands();
// Start tasks
startTasks();
logger.info("MyAwesomePlugin has been enabled successfully!");
}
@Override
public void onDisable() {
// Save data
if (dataManager != null) {
dataManager.saveAll();
}
// Cancel tasks
getServer().getScheduler().cancelTasks(this);
logger.info("MyAwesomePlugin has been disabled.");
}
private void registerEvents() {
getServer().getPluginManager().registerEvents(new PlayerListener(), this);
getServer().getPluginManager().registerEvents(new WorldListener(), this);
getServer().getPluginManager().registerEvents(new EntityListener(), this);
}
private void registerCommands() {
getCommand("hello").setExecutor(new HelloCommand());
getCommand("warp").setExecutor(new WarpCommand());
getCommand("kit").setExecutor(new KitCommand());
getCommand("myplugin").setExecutor(new MainCommand());
}
private void startTasks() {
// Auto-save task every 5 minutes
getServer().getScheduler().scheduleSyncRepeatingTask(this, () -> {
dataManager.saveAll();
}, 6000L, 6000L); // 5 minutes * 60 seconds * 20 ticks
// Cleanup task every hour
getServer().getScheduler().scheduleSyncRepeatingTask(this, () -> {
pluginManager.cleanup();
}, 72000L, 72000L); // 1 hour * 60 minutes * 60 seconds * 20 ticks
}
public static MyAwesomePlugin getInstance() {
return instance;
}
public PluginManager getPluginManager() {
return pluginManager;
}
public DataManager getDataManager() {
return dataManager;
}
}
2. Plugin Manager
package com.myplugin;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.*;
public class PluginManager {
private final JavaPlugin plugin;
private final Map<String, Warp> warps;
private final Map<String, Kit> kits;
private final Set<UUID> hiddenPlayers;
public PluginManager(JavaPlugin plugin) {
this.plugin = plugin;
this.warps = new HashMap<>();
this.kits = new HashMap<>();
this.hiddenPlayers = new HashSet<>();
}
public void initialize() {
loadWarps();
loadKits();
}
public void cleanup() {
// Clean up expired data, remove unused warps, etc.
warps.entrySet().removeIf(entry -> !entry.getValue().isValid());
}
// Warp management
public void addWarp(String name, Warp warp) {
warps.put(name.toLowerCase(), warp);
}
public Warp getWarp(String name) {
return warps.get(name.toLowerCase());
}
public boolean removeWarp(String name) {
return warps.remove(name.toLowerCase()) != null;
}
public Set<String> getWarpNames() {
return Collections.unmodifiableSet(warps.keySet());
}
// Kit management
public void addKit(String name, Kit kit) {
kits.put(name.toLowerCase(), kit);
}
public Kit getKit(String name) {
return kits.get(name.toLowerCase());
}
public boolean removeKit(String name) {
return kits.remove(name.toLowerCase()) != null;
}
// Player visibility
public void hidePlayer(UUID playerId) {
hiddenPlayers.add(playerId);
}
public void showPlayer(UUID playerId) {
hiddenPlayers.remove(playerId);
}
public boolean isPlayerHidden(UUID playerId) {
return hiddenPlayers.contains(playerId);
}
private void loadWarps() {
// Load warps from configuration
// Implementation depends on storage method
}
private void loadKits() {
// Load kits from configuration
// Implementation depends on storage method
}
}
Event Handling System
1. Comprehensive Event Listeners
package com.myplugin.listeners;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.*;
import org.bukkit.event.entity.*;
import org.bukkit.event.block.*;
import org.bukkit.event.world.*;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.server.ServerListPingEvent;
import org.bukkit.ChatColor;
public class PlayerListener implements Listener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
// Custom join message
event.setJoinMessage(ChatColor.GREEN + "Welcome " + player.getName() + " to the server!");
// Send welcome title
player.sendTitle(
ChatColor.AQUA + "Welcome!",
ChatColor.YELLOW + "Enjoy your stay!",
10, 70, 20
);
// Give welcome items if first join
if (!player.hasPlayedBefore()) {
giveWelcomeKit(player);
}
// Update player stats
updatePlayerStats(player);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
// Custom quit message
event.setQuitMessage(ChatColor.RED + "Goodbye " + player.getName() + "!");
// Save player data
savePlayerData(player);
}
@EventHandler
public void onPlayerChat(AsyncPlayerChatEvent event) {
Player player = event.getPlayer();
String message = event.getMessage();
// Format chat message
String format = ChatColor.GRAY + "[%s] " + ChatColor.WHITE + "%s";
event.setFormat(format);
// Check for blocked words
if (containsBlockedWords(message)) {
event.setCancelled(true);
player.sendMessage(ChatColor.RED + "Your message contains blocked words!");
return;
}
// Log chat messages
logChatMessage(player, message);
}
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
Player player = event.getPlayer();
// Check if player is in a restricted area
if (isInRestrictedArea(player)) {
event.setCancelled(true);
player.sendMessage(ChatColor.RED + "You cannot enter this area!");
return;
}
// Update player location for tracking
updatePlayerLocation(player);
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
// Custom block interactions
switch (event.getAction()) {
case RIGHT_CLICK_BLOCK:
handleRightClick(player, event.getClickedBlock());
break;
case LEFT_CLICK_BLOCK:
handleLeftClick(player, event.getClickedBlock());
break;
}
}
@EventHandler
public void onPlayerDeath(PlayerDeathEvent event) {
Player player = event.getEntity();
// Custom death message
event.setDeathMessage(ChatColor.DARK_RED + player.getName() + " met their demise!");
// Handle death effects
handleDeathEffects(player);
}
@EventHandler
public void onPlayerRespawn(PlayerRespawnEvent event) {
Player player = event.getPlayer();
// Custom respawn location
if (hasCustomRespawnPoint(player)) {
event.setRespawnLocation(getCustomRespawnPoint(player));
}
// Give respawn items
giveRespawnItems(player);
}
@EventHandler
public void onPlayerTeleport(PlayerTeleportEvent event) {
Player player = event.getPlayer();
// Log teleportation
logTeleport(player, event.getFrom(), event.getTo());
// Check teleport permissions
if (!canTeleport(player, event.getTo())) {
event.setCancelled(true);
player.sendMessage(ChatColor.RED + "You cannot teleport to this location!");
}
}
// Helper methods
private void giveWelcomeKit(Player player) {
// Implementation for giving welcome items
}
private void updatePlayerStats(Player player) {
// Update player statistics
}
private void savePlayerData(Player player) {
// Save player data to file/database
}
private boolean containsBlockedWords(String message) {
// Check for inappropriate content
return false; // Implementation needed
}
private void logChatMessage(Player player, String message) {
// Log chat message for moderation
}
private boolean isInRestrictedArea(Player player) {
// Check if player is in restricted area
return false; // Implementation needed
}
private void updatePlayerLocation(Player player) {
// Update player location for tracking
}
private void handleRightClick(Player player, org.bukkit.block.Block block) {
// Handle right-click interactions
}
private void handleLeftClick(Player player, org.bukkit.block.Block block) {
// Handle left-click interactions
}
private void handleDeathEffects(Player player) {
// Handle death effects like sound, particles, etc.
}
private boolean hasCustomRespawnPoint(Player player) {
// Check if player has custom respawn point
return false; // Implementation needed
}
private org.bukkit.Location getCustomRespawnPoint(Player player) {
// Get custom respawn point
return player.getWorld().getSpawnLocation(); // Default
}
private void giveRespawnItems(Player player) {
// Give items on respawn
}
private void logTeleport(Player player, org.bukkit.Location from, org.bukkit.Location to) {
// Log teleport for admin purposes
}
private boolean canTeleport(Player player, org.bukkit.Location to) {
// Check teleport permissions
return true; // Implementation needed
}
}
2. World and Entity Listeners
package com.myplugin.listeners;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.*;
import org.bukkit.event.entity.*;
import org.bukkit.entity.*;
import org.bukkit.ChatColor;
public class WorldListener implements Listener {
@EventHandler
public void onEntitySpawn(EntitySpawnEvent event) {
Entity entity = event.getEntity();
// Limit mob spawning in certain areas
if (isInProtectedArea(entity.getLocation())) {
event.setCancelled(true);
return;
}
// Custom mob spawning logic
if (entity instanceof Monster) {
handleMonsterSpawning((Monster) entity);
}
}
@EventHandler
public void onCreatureSpawn(CreatureSpawnEvent event) {
Creature creature = event.getEntity();
// Modify spawn rates based on conditions
if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.NATURAL) {
if (shouldReduceSpawning(creature)) {
event.setCancelled(true);
}
}
}
@EventHandler
public void onEntityDamage(EntityDamageEvent event) {
Entity entity = event.getEntity();
// Protect certain entities from damage
if (isProtectedEntity(entity)) {
event.setCancelled(true);
return;
}
// Modify damage based on conditions
if (entity instanceof Player) {
handlePlayerDamage((Player) entity, event);
}
}
@EventHandler
public void onEntityDeath(EntityDeathEvent event) {
Entity entity = event.getEntity();
// Custom death drops
if (entity instanceof Monster) {
handleMonsterDeath((Monster) entity, event);
}
// Experience modification
if (shouldModifyExperience(entity)) {
event.setDroppedExp(calculateModifiedExperience(event.getDroppedExp()));
}
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
Player player = event.getPlayer();
// Check build permissions
if (!canBuild(player, event.getBlock().getLocation())) {
event.setCancelled(true);
player.sendMessage(ChatColor.RED + "You cannot break blocks here!");
return;
}
// Custom block break effects
handleBlockBreakEffects(event);
// Log block breaking for rollback systems
logBlockBreak(player, event.getBlock());
}
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
Player player = event.getPlayer();
// Check build permissions
if (!canBuild(player, event.getBlock().getLocation())) {
event.setCancelled(true);
player.sendMessage(ChatColor.RED + "You cannot place blocks here!");
return;
}
// Custom block placement logic
handleBlockPlacement(event);
}
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
org.bukkit.World world = event.getWorld();
// Apply world-specific settings
applyWorldSettings(world);
}
@EventHandler
public void onWorldSave(WorldSaveEvent event) {
org.bukkit.World world = event.getWorld();
// Perform custom save operations
performCustomSaveOperations(world);
}
// Helper methods
private boolean isInProtectedArea(org.bukkit.Location location) {
// Check if location is in protected area
return false; // Implementation needed
}
private void handleMonsterSpawning(Monster monster) {
// Custom monster spawning logic
}
private boolean shouldReduceSpawning(Creature creature) {
// Determine if spawning should be reduced
return false; // Implementation needed
}
private boolean isProtectedEntity(Entity entity) {
// Check if entity is protected
return false; // Implementation needed
}
private void handlePlayerDamage(Player player, EntityDamageEvent event) {
// Custom player damage handling
}
private void handleMonsterDeath(Monster monster, EntityDeathEvent event) {
// Custom monster death handling
}
private boolean shouldModifyExperience(Entity entity) {
// Check if experience should be modified
return false; // Implementation needed
}
private int calculateModifiedExperience(int originalExp) {
// Calculate modified experience
return originalExp; // Implementation needed
}
private boolean canBuild(Player player, org.bukkit.Location location) {
// Check build permissions
return true; // Implementation needed
}
private void handleBlockBreakEffects(BlockBreakEvent event) {
// Custom block break effects
}
private void logBlockBreak(Player player, org.bukkit.block.Block block) {
// Log block breaking
}
private void handleBlockPlacement(BlockPlaceEvent event) {
// Custom block placement handling
}
private void applyWorldSettings(org.bukkit.World world) {
// Apply custom world settings
}
private void performCustomSaveOperations(org.bukkit.World world) {
// Perform custom save operations
}
}
Command System Implementation
1. Command Executors
package com.myplugin.commands;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.ChatColor;
import java.util.*;
public class HelloCommand implements CommandExecutor, TabCompleter {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command can only be used by players!");
return true;
}
Player player = (Player) sender;
if (args.length == 0) {
// Basic hello command
player.sendMessage(ChatColor.GREEN + "Hello, " + player.getName() + "!");
player.sendMessage(ChatColor.YELLOW + "Welcome to the server!");
// Play sound effect
player.playSound(player.getLocation(),
org.bukkit.Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.0f);
// Spawn particles
player.spawnParticle(org.bukkit.Particle.HEART,
player.getLocation().add(0, 2, 0), 10);
} else if (args.length == 1) {
// Personalized hello
String targetName = args[0];
Player target = player.getServer().getPlayer(targetName);
if (target != null && target.isOnline()) {
player.sendMessage(ChatColor.GREEN + "You said hello to " + target.getName() + "!");
target.sendMessage(ChatColor.YELLOW + player.getName() + " says hello to you!");
} else {
player.sendMessage(ChatColor.RED + "Player not found or offline!");
}
} else {
player.sendMessage(ChatColor.RED + "Usage: /hello [player]");
}
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
List<String> completions = new ArrayList<>();
if (args.length == 1) {
// Tab complete player names
for (Player player : sender.getServer().getOnlinePlayers()) {
if (player.getName().toLowerCase().startsWith(args[0].toLowerCase())) {
completions.add(player.getName());
}
}
}
return completions;
}
}
public class WarpCommand implements CommandExecutor, TabCompleter {
private final com.myplugin.MyAwesomePlugin plugin;
public WarpCommand() {
this.plugin = com.myplugin.MyAwesomePlugin.getInstance();
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command can only be used by players!");
return true;
}
Player player = (Player) sender;
if (args.length == 0) {
// List available warps
Set<String> warpNames = plugin.getPluginManager().getWarpNames();
if (warpNames.isEmpty()) {
player.sendMessage(ChatColor.YELLOW + "No warps available.");
} else {
player.sendMessage(ChatColor.GREEN + "Available warps:");
for (String warpName : warpNames) {
player.sendMessage(ChatColor.WHITE + " - " + warpName);
}
}
return true;
}
String warpName = args[0].toLowerCase();
Warp warp = plugin.getPluginManager().getWarp(warpName);
if (warp == null) {
player.sendMessage(ChatColor.RED + "Warp '" + warpName + "' not found!");
return true;
}
// Check permissions
if (!player.hasPermission("myplugin.warp." + warpName) &&
!player.hasPermission("myplugin.warp.*")) {
player.sendMessage(ChatColor.RED + "You don't have permission to use this warp!");
return true;
}
// Teleport player with effects
player.sendMessage(ChatColor.GREEN + "Teleporting to " + warpName + "...");
// Delay teleport for effect
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {
if (player.isOnline()) {
player.teleport(warp.getLocation());
player.sendMessage(ChatColor.GREEN + "Welcome to " + warpName + "!");
player.playSound(player.getLocation(),
org.bukkit.Sound.ENTITY_ENDERMAN_TELEPORT, 1.0f, 1.0f);
}
}, 20L); // 1 second delay
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
List<String> completions = new ArrayList<>();
if (args.length == 1) {
// Tab complete warp names
Set<String> warpNames = plugin.getPluginManager().getWarpNames();
for (String warpName : warpNames) {
if (warpName.toLowerCase().startsWith(args[0].toLowerCase())) {
completions.add(warpName);
}
}
}
return completions;
}
}
public class KitCommand implements CommandExecutor, TabCompleter {
private final com.myplugin.MyAwesomePlugin plugin;
public KitCommand() {
this.plugin = com.myplugin.MyAwesomePlugin.getInstance();
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command can only be used by players!");
return true;
}
Player player = (Player) sender;
if (args.length == 0) {
// List available kits
// Implementation similar to warp list
return true;
}
String kitName = args[0].toLowerCase();
Kit kit = plugin.getPluginManager().getKit(kitName);
if (kit == null) {
player.sendMessage(ChatColor.RED + "Kit '" + kitName + "' not found!");
return true;
}
// Check cooldown
if (kit.hasCooldown(player)) {
player.sendMessage(ChatColor.RED + "This kit is on cooldown!");
return true;
}
// Give kit items
kit.giveToPlayer(player);
player.sendMessage(ChatColor.GREEN + "You received the " + kitName + " kit!");
// Set cooldown
kit.setCooldown(player);
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
// Implementation similar to WarpCommand
return new ArrayList<>();
}
}
2. Admin Command with Subcommands
package com.myplugin.commands;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.ChatColor;
import java.util.*;
public class MainCommand implements CommandExecutor, TabCompleter {
private final com.myplugin.MyAwesomePlugin plugin;
public MainCommand() {
this.plugin = com.myplugin.MyAwesomePlugin.getInstance();
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length == 0) {
sendHelp(sender);
return true;
}
String subCommand = args[0].toLowerCase();
switch (subCommand) {
case "reload":
return reloadCommand(sender);
case "save":
return saveCommand(sender);
case "info":
return infoCommand(sender);
case "setwarp":
return setWarpCommand(sender, args);
case "delwarp":
return delWarpCommand(sender, args);
default:
sender.sendMessage(ChatColor.RED + "Unknown subcommand!");
sendHelp(sender);
return true;
}
}
private boolean reloadCommand(CommandSender sender) {
if (!sender.hasPermission("myplugin.admin")) {
sender.sendMessage(ChatColor.RED + "You don't have permission to use this command!");
return true;
}
plugin.reloadConfig();
plugin.getPluginManager().initialize();
sender.sendMessage(ChatColor.GREEN + "Plugin configuration reloaded!");
return true;
}
private boolean saveCommand(CommandSender sender) {
if (!sender.hasPermission("myplugin.admin")) {
sender.sendMessage(ChatColor.RED + "You don't have permission to use this command!");
return true;
}
plugin.getDataManager().saveAll();
sender.sendMessage(ChatColor.GREEN + "All data saved!");
return true;
}
private boolean infoCommand(CommandSender sender) {
sender.sendMessage(ChatColor.GOLD + "=== MyAwesomePlugin Information ===");
sender.sendMessage(ChatColor.YELLOW + "Version: " + plugin.getDescription().getVersion());
sender.sendMessage(ChatColor.YELLOW + "Author: " + plugin.getDescription().getAuthors());
sender.sendMessage(ChatColor.YELLOW + "Warps: " + plugin.getPluginManager().getWarpNames().size());
sender.sendMessage(ChatColor.YELLOW + "Kits: " + "Implementation needed"); // Add kit count
return true;
}
private boolean setWarpCommand(CommandSender sender, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command can only be used by players!");
return true;
}
if (!sender.hasPermission("myplugin.admin")) {
sender.sendMessage(ChatColor.RED + "You don't have permission to use this command!");
return true;
}
if (args.length < 2) {
sender.sendMessage(ChatColor.RED + "Usage: /myplugin setwarp <name>");
return true;
}
Player player = (Player) sender;
String warpName = args[1].toLowerCase();
Warp warp = new Warp(warpName, player.getLocation());
plugin.getPluginManager().addWarp(warpName, warp);
player.sendMessage(ChatColor.GREEN + "Warp '" + warpName + "' set at your location!");
return true;
}
private boolean delWarpCommand(CommandSender sender, String[] args) {
if (!sender.hasPermission("myplugin.admin")) {
sender.sendMessage(ChatColor.RED + "You don't have permission to use this command!");
return true;
}
if (args.length < 2) {
sender.sendMessage(ChatColor.RED + "Usage: /myplugin delwarp <name>");
return true;
}
String warpName = args[1].toLowerCase();
if (plugin.getPluginManager().removeWarp(warpName)) {
sender.sendMessage(ChatColor.GREEN + "Warp '" + warpName + "' deleted!");
} else {
sender.sendMessage(ChatColor.RED + "Warp '" + warpName + "' not found!");
}
return true;
}
private void sendHelp(CommandSender sender) {
sender.sendMessage(ChatColor.GOLD + "=== MyAwesomePlugin Commands ===");
sender.sendMessage(ChatColor.YELLOW + "/myplugin reload - Reload plugin configuration");
sender.sendMessage(ChatColor.YELLOW + "/myplugin save - Save all plugin data");
sender.sendMessage(ChatColor.YELLOW + "/myplugin info - Show plugin information");
if (sender.hasPermission("myplugin.admin")) {
sender.sendMessage(ChatColor.YELLOW + "/myplugin setwarp <name> - Set a warp");
sender.sendMessage(ChatColor.YELLOW + "/myplugin delwarp <name> - Delete a warp");
}
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
List<String> completions = new ArrayList<>();
if (args.length == 1) {
String[] subCommands = {"reload", "save", "info"};
for (String subCommand : subCommands) {
if (subCommand.startsWith(args[0].toLowerCase())) {
completions.add(subCommand);
}
}
if (sender.hasPermission("myplugin.admin")) {
String[] adminCommands = {"setwarp", "delwarp"};
for (String adminCommand : adminCommands) {
if (adminCommand.startsWith(args[0].toLowerCase())) {
completions.add(adminCommand);
}
}
}
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("delwarp") && sender.hasPermission("myplugin.admin")) {
// Tab complete warp names for deletion
Set<String> warpNames = plugin.getPluginManager().getWarpNames();
for (String warpName : warpNames) {
if (warpName.toLowerCase().startsWith(args[1].toLowerCase())) {
completions.add(warpName);
}
}
}
}
return completions;
}
}
Data Management System
1. Configuration and Data Manager
```java
package com.myplugin;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.; import java.util.;
public class DataManager {
private final JavaPlugin plugin;
private FileConfiguration dataConfig;
private File dataFile;
public DataManager(JavaPlugin plugin) {
this.plugin = plugin;
this.dataFile = new File(plugin.getDataFolder(), "data.yml");
}
public void initialize() {
if (!plugin.getDataFolder().exists()) {
plugin.getDataFolder().mkdirs();
}
if (!dataFile.exists()) {
try {
dataFile.createNewFile();
} catch (IOException e) {
plugin.getLogger().severe("Could not create data.yml file!");
e.printStackTrace();
}
}
dataConfig = YamlConfiguration.loadConfiguration(dataFile);
}
public void saveAll() {
try {
dataConfig.save(dataFile);
plugin.getLogger().info("Data saved successfully!");
} catch (IOException e) {
plugin.getLogger().severe("Could not save data.yml file!");
e.printStackTrace();
}
}
// Warp data management
public void saveWarp(String name, Warp warp) {
String path = "warps." + name;
dataConfig.set(path + ".world", warp.getLocation().getWorld().getName());
dataConfig.set(path + ".x", warp.getLocation().getX());
dataConfig.set(path + ".y", warp.getLocation().getY());
dataConfig.set(path + ".z", warp.getLocation().getZ());
dataConfig.set(path + ".yaw", warp.getLocation().getYaw());
dataConfig.set(path + ".pitch", warp.getLocation().getPitch());
dataConfig.set(path + ".creator", warp.getCreator());
dataConfig.set(path + ".created", warp.getCreatedTimestamp());
}
public Warp loadWarp(String name) {
String path = "warps." + name;
if (!dataConfig.contains(path)) {
return null;
}
String worldName = dataConfig.getString(path + ".world");
double x = dataConfig.getDouble(path + ".x");
double y = dataConfig.getDouble(path + ".y");
double z = dataConfig.getDouble(path + ".z");
float yaw = (float) dataConfig.getDouble(path + ".yaw");
float pitch = (float) dataConfig.getDouble(path + ".pitch");
String creator = dataConfig.getString(path + ".creator");
long created = dataConfig.getLong(path + ".created");
org.bukkit.World world = plugin.getServer().getWorld(worldName);
if (world == null) {
plugin.getLogger().warning("World not found for warp: " + name);
return null;
}
org.bukkit.Location location = new org.b