diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0331d89 --- /dev/null +++ b/pom.xml @@ -0,0 +1,62 @@ + + 4.0.0 + + com.zivilon + AdminTools + 1.4 + jar + + AdminTools + + + UTF-8 + 1.7 + 1.7 + + + + + + org.bukkit + bukkit + 1.7.10-R0.1-SNAPSHOT + provided + + + com.github.flinbein + PowerNBT + 0.8.9.2 + + + com.sk89q + worldguard + 6.1.2 + + + com.comphenix.protocol + ProtocolLib + 3.6.5 + provided + + + + package + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + + + diff --git a/src/main/java/com/zivilon/admintools/AdminTools.java b/src/main/java/com/zivilon/admintools/AdminTools.java new file mode 100644 index 0000000..fd02619 --- /dev/null +++ b/src/main/java/com/zivilon/admintools/AdminTools.java @@ -0,0 +1,90 @@ +package com.zivilon.admintools; + +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; + +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.ProtocolLibrary; + +import com.zivilon.admintools.commands.clean_entities_command; +import com.zivilon.admintools.commands.count_units_command; +import com.zivilon.admintools.commands.chunkloader_command; +import com.zivilon.admintools.commands.block_swap_command; +import com.zivilon.admintools.commands.world_summon_command; +import com.zivilon.admintools.commands.world_setblock_command; +import com.zivilon.admintools.commands.set_login_location_command; +import com.zivilon.admintools.commands.area_message_command; +import com.zivilon.admintools.commands.areaeffect_command; +import com.zivilon.admintools.commands.effect_command; +import com.zivilon.admintools.commands.check_players_command; +import com.zivilon.admintools.commands.region_teleport_command; +import com.zivilon.admintools.commands.entity_effect_command; +import com.zivilon.admintools.listeners.ranged_immunity_listener; + +public class AdminTools extends JavaPlugin { + private ProtocolManager protocolManager; + private FileConfiguration unitNamesConfig; + private FileConfiguration chunkLoaderConfig; + + @Override + public void onEnable() { + saveDefaultConfig(); + this.unitNamesConfig = loadConfigFile("unit_names.yml"); + this.chunkLoaderConfig = loadConfigFile("chunkloaders.yml"); + + protocolManager = ProtocolLibrary.getProtocolManager(); + + // Register the /clean_entities command + this.getCommand("clean_entities").setExecutor(new clean_entities_command()); + // Register the /count_units command + this.getCommand("count_units").setExecutor(new count_units_command(this)); + // Register the /chunkloader command + this.getCommand("chunkloader").setExecutor(new chunkloader_command(this)); + // Register the /block_swap command + this.getCommand("block_swap").setExecutor(new block_swap_command(protocolManager)); + // Register the /wsummon command + this.getCommand("wsummon").setExecutor(new world_summon_command()); + // Register the /wsetblock command + this.getCommand("wsetblock").setExecutor(new world_setblock_command()); + // Register the /set_login_location command + this.getCommand("set_login_location").setExecutor(new set_login_location_command()); + // Register the /area_message command + this.getCommand("area_message").setExecutor(new area_message_command()); + // Register the /areaeffect command + this.getCommand("areaeffect").setExecutor(new areaeffect_command()); + // Register the /effect command + this.getCommand("effect").setExecutor(new effect_command()); + // Register the /check_players command + this.getCommand("check_players").setExecutor(new check_players_command(this)); + // Register the /check_players command + this.getCommand("region_tp").setExecutor(new region_teleport_command(this)); + // Register the /entityeffect command + this.getCommand("entityeffect").setExecutor(new entity_effect_command()); + + + getServer().getPluginManager().registerEvents(new ranged_immunity_listener(this), this); + } + + @Override + public void onDisable() { + } + + public FileConfiguration getUnitNamesConfig() { + return this.unitNamesConfig; + } + + public FileConfiguration getChunkLoaderConfig() { + return this.chunkLoaderConfig; + } + + private FileConfiguration loadConfigFile(String fileName) { + File file = new File(getDataFolder(), fileName); + if (!file.exists()) { + saveResource(fileName, false); + } + return YamlConfiguration.loadConfiguration(file); + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/area_message_command.java b/src/main/java/com/zivilon/admintools/commands/area_message_command.java new file mode 100644 index 0000000..29863ac --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/area_message_command.java @@ -0,0 +1,91 @@ +package com.zivilon.admintools.commands; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class area_message_command implements CommandExecutor { + + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.hasPermission("admintools.area_message")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + double x, y, z, radius; + if (args.length < 6) { + sender.sendMessage("Usage: /area_message [-d -s] "); + return false; + + } + + boolean debug_flag = false; + boolean silent_flag = false; + int argument_offset = 0; // this offset helps us handle the arguments correctly + + // Iterate over flags + for (; argument_offset < args.length; argument_offset++) { + if (args[argument_offset].startsWith("-")) { + debug_flag |= args[argument_offset].contains("d"); + silent_flag |= args[argument_offset].contains("s"); + } else { + break; + } + } + + if (args.length - argument_offset < 6) { + if (debug_flag) sender.sendMessage("Failed at args.length - argument_offset < 6 with args.length " + args.length + " and argument_offset " + argument_offset); + sender.sendMessage(ChatColor.RED + "Usage: /area_message [-d -s] "); + return false; + } + + World world = Bukkit.getWorld(args[0 + argument_offset]); + + try { + x = Double.parseDouble(args[1 + argument_offset]); + y = Double.parseDouble(args[2 + argument_offset]); + z = Double.parseDouble(args[3 + argument_offset]); + radius = Double.parseDouble(args[4 + argument_offset]); + } catch (NumberFormatException e) { + sender.sendMessage(ChatColor.RED + "Coordinates and radius need to be numbers."); + return true; + } + + if (world == null) { + sender.sendMessage(ChatColor.RED + String.format("There is no such world with name %s.", args[0 + argument_offset])); + return true; + } + + // Construct the location object + Location target_location = new Location(world, x, y, z); + + // Construct the message from the remaining arguments + StringBuilder message_builder = new StringBuilder(); + for (int i = 5 + argument_offset; i < args.length; i++) { + message_builder.append(args[i]); + if (i != args.length - 1) { + message_builder.append(" "); + } + } + String message = message_builder.toString(); + String coloredMessage = ChatColor.translateAlternateColorCodes('&', message); + + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getWorld().equals(world) && player.getLocation().distanceSquared(target_location) <= Math.pow(radius, 2)) { + player.sendMessage(coloredMessage); + } + } + + + // If the command is not silent, inform the command sender + if (!silent_flag) { + sender.sendMessage(ChatColor.GREEN + "Message has been sent."); + } + + return true; + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/areaeffect_command.java b/src/main/java/com/zivilon/admintools/commands/areaeffect_command.java new file mode 100644 index 0000000..d1d89bb --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/areaeffect_command.java @@ -0,0 +1,88 @@ +package com.zivilon.admintools.commands; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionEffect; + + +public class areaeffect_command implements CommandExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.hasPermission("admintools.areaeffect")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + + if (args.length < 8) { + sender.sendMessage("Incorrect arguments. Usage: /areaeffect [-d -s] "); + return true; + } + + boolean debug_flag = false; + boolean silent_flag = false; + int argument_offset = 0; // this offset helps us handle the arguments correctly + + // Iterate over flags + for (; argument_offset < args.length; argument_offset++) { + if (args[argument_offset].startsWith("-")) { + debug_flag |= args[argument_offset].contains("d"); + silent_flag |= args[argument_offset].contains("s"); + } else { + break; + } + } + + if (args.length < (8 + argument_offset)) { + sender.sendMessage("Incorrect arguments. Usage: /areaeffect [-d -s] "); + return true; + } + + try { + String worldName = args[0 + argument_offset]; // Get the world name from the arguments + int x = Integer.parseInt(args[1 + argument_offset]); + int y = Integer.parseInt(args[2 + argument_offset]); + int z = Integer.parseInt(args[3 + argument_offset]); + int radius = Integer.parseInt(args[4 + argument_offset]); + String effectName = args[5 + argument_offset]; + int duration = Integer.parseInt(args[6 + argument_offset]) * 20; // Convert duration from seconds to ticks + int level = Integer.parseInt(args[7 + argument_offset]); + + PotionEffectType effectType = PotionEffectType.getByName(effectName); + if (effectType == null) { + sender.sendMessage("Invalid effect name!"); + return true; + } + + World world = Bukkit.getServer().getWorld(worldName); + if (world == null) { + sender.sendMessage("World " + worldName + " not found!"); + return true; + } + + Location center = new Location(world, x, y, z); + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + if (player.getWorld().equals(world) && player.getLocation().distance(center) <= radius) { + if(level == 0){ + if(player.hasPotionEffect(effectType)){ + player.removePotionEffect(effectType); + if (!silent_flag) sender.sendMessage("Removed " + effectName + " from " + player.getName()); + } + }else{ + player.addPotionEffect(new PotionEffect(effectType, duration, level - 1, false), true); + if (!silent_flag) sender.sendMessage("Added " + effectName + " level " + level + " to " + player.getName()); + } + } + } + } catch (NumberFormatException e) { + sender.sendMessage("Invalid number format!"); + } + return true; + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/block_swap_command.java b/src/main/java/com/zivilon/admintools/commands/block_swap_command.java new file mode 100644 index 0000000..260f1ec --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/block_swap_command.java @@ -0,0 +1,100 @@ +package com.zivilon.admintools.commands; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.ChatColor; +import org.bukkit.material.MaterialData; +import org.bukkit.entity.Player; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketContainer; + +import java.lang.reflect.InvocationTargetException; + +public class block_swap_command implements CommandExecutor { + private ProtocolManager protocolManager; + + public block_swap_command(ProtocolManager protocolManager) { + this.protocolManager = protocolManager; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.hasPermission("admintools.block_swap")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + if(args.length != 4){ + sender.sendMessage("Incorrect command format! Use: /block_swap "); + return true; + } + + String[] corner1 = args[0].split(","); + String[] corner2 = args[1].split(","); + String[] materialDataArg = args[2].split(":"); + String playerName = args[3]; + + if (corner1.length != 3 || corner2.length != 3 || materialDataArg.length != 2) { + sender.sendMessage("Incorrect command format! Use: /block_swap "); + return true; + } + + try { + int x1 = Integer.parseInt(corner1[0]); + int y1 = Integer.parseInt(corner1[1]); + int z1 = Integer.parseInt(corner1[2]); + + int x2 = Integer.parseInt(corner2[0]); + int y2 = Integer.parseInt(corner2[1]); + int z2 = Integer.parseInt(corner2[2]); + + Material material = Material.getMaterial(materialDataArg[0].toUpperCase()); + if (material == null) { + sender.sendMessage("Invalid material: " + materialDataArg[0]); + return true; + } + + int data = Integer.parseInt(materialDataArg[1]); + + Player targetPlayer = Bukkit.getServer().getPlayer(playerName); + if (targetPlayer == null) { + sender.sendMessage("Could not find player: " + playerName); + return true; + } + + MaterialData materialData = new MaterialData(material, (byte) data); + + for (int x = Math.min(x1, x2); x <= Math.max(x1, x2); x++) { + for (int y = Math.min(y1, y2); y <= Math.max(y1, y2); y++) { + for (int z = Math.min(z1, z2); z <= Math.max(z1, z2); z++) { + Location location = new Location(targetPlayer.getWorld(), x, y, z); + PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.BLOCK_CHANGE); + packet.getIntegers() + .write(0, location.getBlockX()) + .write(1, location.getBlockY()) + .write(2, location.getBlockZ()); + packet.getBlocks().write(0, materialData.getItemType()); + packet.getIntegers().write(3, (int) materialData.getData()); + + try { + protocolManager.sendServerPacket(targetPlayer, packet); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } + } + + } catch (NumberFormatException e){ + sender.sendMessage("The coordinates and data must be integers!"); + return true; + } + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/zivilon/admintools/commands/check_players_command.java b/src/main/java/com/zivilon/admintools/commands/check_players_command.java new file mode 100644 index 0000000..64118fd --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/check_players_command.java @@ -0,0 +1,97 @@ +package com.zivilon.admintools.commands; + +import org.bukkit.Location; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.Location; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.managers.RegionManager; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; + +import com.zivilon.admintools.AdminTools; + +public class check_players_command implements CommandExecutor { + + private final AdminTools plugin; + private WorldGuardPlugin worldGuardPlugin; + + public check_players_command(AdminTools plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { + if (!sender.hasPermission("admintools.check_players")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + + if (args.length < 3) { + sender.sendMessage("Usage: /check_players "); + return true; + } + + // Logic to join arguments for command-if-empty + StringBuilder commandIfEmpty = new StringBuilder(); + int i = 1; + while (i < args.length && !args[i].endsWith("\"")) { + commandIfEmpty.append(args[i]).append(" "); + i++; + } + commandIfEmpty.append(args[i]); + + String emptyCommand = commandIfEmpty.toString().replaceAll("\"", "").trim(); + + // Logic to join arguments for command-if-players + StringBuilder commandIfPlayers = new StringBuilder(); + i++; + while (i < args.length && !args[i].endsWith("\"")) { + commandIfPlayers.append(args[i]).append(" "); + i++; + } + commandIfPlayers.append(args[i]); + + String playersCommand = commandIfPlayers.toString().replaceAll("\"", "").trim(); + + Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin("WorldGuard"); + if (plugin instanceof WorldGuardPlugin) { + worldGuardPlugin = (WorldGuardPlugin) plugin; + } + + World dim100World = Bukkit.getWorld("DIM100"); + if (dim100World == null) { + plugin.getLogger().warning("World DIM100 not found! Ensure the world name is correct."); + return true; + } + + RegionManager regionManager = worldGuardPlugin.getRegionManager(dim100World); + + boolean playersFound = false; + + String[] regionNames = args[0].split(","); // Split region names by comma + + for (Player player : Bukkit.getOnlinePlayers()) { + for (String regionName : regionNames) { + ProtectedRegion region = regionManager.getRegion(regionName); + if (region != null && region.contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ())) { + playersFound = true; + break; + } + } + if (playersFound) break; // Break outer loop if players are found in any of the specified regions + } + + // Execute the appropriate command based on player presence + String commandToExecute = playersFound ? playersCommand : emptyCommand; + plugin.getServer().dispatchCommand(sender, commandToExecute); + return true; + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/chunkloader_command.java b/src/main/java/com/zivilon/admintools/commands/chunkloader_command.java new file mode 100644 index 0000000..d4fd0d4 --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/chunkloader_command.java @@ -0,0 +1,268 @@ +package com.zivilon.admintools.commands; + +import com.zivilon.admintools.AdminTools; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static java.lang.Math.abs; + +public class chunkloader_command implements CommandExecutor { + + private final AdminTools plugin; + private final Map chunkLoaders = new HashMap<>(); + private final FileConfiguration chunkLoaderConfig; + + public chunkloader_command(AdminTools plugin) { + this.plugin = plugin; + this.chunkLoaderConfig = plugin.getChunkLoaderConfig(); + loadChunkLoaders(); + } + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { + if (!sender.hasPermission("admintools.chunkloader")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + + Player player = null; + if (sender instanceof Player) { + player = (Player) sender; + } + + if (cmd.getName().equalsIgnoreCase("chunkloader")) { + if (args.length == 0) { + sender.sendMessage(ChatColor.YELLOW + "Usage: /chunkloader create [ ]"); + sender.sendMessage(ChatColor.YELLOW + " /chunkloader load "); + sender.sendMessage(ChatColor.YELLOW + " /chunkloader delete "); + sender.sendMessage(ChatColor.YELLOW + " /chunkloader isloaded "); + return true; + } + + if (args[0].equalsIgnoreCase("create")) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "This command can only be run by a player!"); + return true; + } + + if (args.length < 3 || args.length > 5) { + sender.sendMessage(ChatColor.RED + "Usage: /chunkloader create [ ]"); + return true; + } + + String name = args[1]; + int radius = Integer.parseInt(args[2]); + Location location = args.length == 5 ? + new Location(player.getWorld(), Double.parseDouble(args[3]), 0.0, Double.parseDouble(args[4])) : + player.getLocation(); + + ChunkLoader loader = new ChunkLoader(name, location, radius); + chunkLoaders.put(name, loader); + loader.saveChunkLoader(loader); + saveConfig(); + + sender.sendMessage(ChatColor.GREEN + "Chunk loader " + name + " created!"); + return true; + } + + if (args[0].equalsIgnoreCase("load")) { + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Usage: /chunkloader load "); + return true; + } + + String name = args[1]; + ChunkLoader loader = chunkLoaders.get(name); + + if (loader == null) { + sender.sendMessage(ChatColor.RED + "Chunk loader " + name + " not found!"); + return true; + } + + loader.loadChunk(); + sender.sendMessage(ChatColor.GREEN + "Chunk loader " + name + " loaded!"); + return true; + } + + if (args[0].equalsIgnoreCase("delete")) { + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Usage: /chunkloader delete "); + return true; + } + + String name = args[1]; + ChunkLoader loader = chunkLoaders.get(name); + + if (loader == null) { + sender.sendMessage(ChatColor.RED + "Chunk loader " + name + " not found!"); + return true; + } + + chunkLoaders.remove(name); + chunkLoaderConfig.set(name, null); + saveConfig(); + + sender.sendMessage(ChatColor.GREEN + "Chunk loader " + name + " deleted!"); + return true; + } + + if (args[0].equalsIgnoreCase("isloaded")) { + if (args.length != 3) { + sender.sendMessage(ChatColor.RED + "Usage: /chunkloader isloaded "); + return true; + } + + int x = Integer.parseInt(args[1]); + int z = Integer.parseInt(args[2]); + World world = player.getWorld(); + Location location = new Location(world, x, 0, z); + + if (isChunkLoaded(location)) { + sender.sendMessage(ChatColor.GREEN + "Chunk is loaded!"); + } else { + sender.sendMessage(ChatColor.RED + "Chunk is not loaded!"); + } + return true; + } + } + + return false; + } + + public boolean isChunkLoaded(Location location) { + int chunkX = location.getBlockX() >> 4; + int chunkZ = location.getBlockZ() >> 4; + World world = location.getWorld(); + return world.isChunkLoaded(chunkX, chunkZ); + } + + public class ChunkLoader { + private String name; + private Location location; + private int radius; + + public ChunkLoader(String name, Location location, int radius) { + this.name = name; + this.location = location; + this.radius = radius; + } + + public ChunkLoader(ConfigurationSection config) { + this.name = config.getName(); + this.location = new Location( + Bukkit.getWorld(config.getString("world")), + config.getDouble("x"), + config.getDouble("y"), + config.getDouble("z")); + this.radius = config.getInt("radius"); + } + + public String getName() { + return this.name; + } + + public Location getLocation() { + return this.location; + } + + public int getRadius() { + return this.radius; + } + + public void saveChunkLoader(ChunkLoader loader) { + String name = loader.getName(); + Location location = loader.getLocation(); + int radius = loader.getRadius(); + + ConfigurationSection loaderSection = chunkLoaderConfig.createSection("chunkloaders." + name); + + loaderSection.set("world", location.getWorld().getName()); + loaderSection.set("x", location.getX()); + loaderSection.set("y", location.getY()); + loaderSection.set("z", location.getZ()); + loaderSection.set("radius", radius); + } + + + public boolean containsChunk(Chunk chunk) { + int chunkX = chunk.getX(); + int chunkZ = chunk.getZ(); + int centerChunkX = location.getBlockX() >> 4; + int centerChunkZ = location.getBlockZ() >> 4; + return abs(chunkX - centerChunkX) <= radius && abs(chunkZ - centerChunkZ) <= radius; + } + + public void loadChunk() { + // Load all chunks within the radius + World world = location.getWorld(); + int centerChunkX = location.getBlockX() >> 4; + int centerChunkZ = location.getBlockZ() >> 4; + int radiusChunks = (radius >> 4) + 1; + for (int dx = -radiusChunks; dx <= radiusChunks; dx++) { + for (int dz = -radiusChunks; dz <= radiusChunks; dz++) { + int chunkX = centerChunkX + dx; + int chunkZ = centerChunkZ + dz; + Chunk chunk = world.getChunkAt(chunkX, chunkZ); + chunk.load(); + } + } + } + + private boolean chunkInUse(Chunk chunk) { + return Bukkit.getOnlinePlayers().stream() + .anyMatch(player -> player.getWorld().equals(chunk.getWorld()) + && player.getLocation().getBlockX() >> 4 == chunk.getX() + && player.getLocation().getBlockZ() >> 4 == chunk.getZ()); + } + } + + private void loadChunkLoaders() { + if (chunkLoaderConfig.isConfigurationSection("chunkloaders")) { + ConfigurationSection loaderSection = chunkLoaderConfig.getConfigurationSection("chunkloaders"); + for (String key : loaderSection.getKeys(false)) { + ConfigurationSection loaderConfig = loaderSection.getConfigurationSection(key); + + String name = key; + String worldName = loaderConfig.getString("world"); + double x = loaderConfig.getDouble("x"); + double y = loaderConfig.getDouble("y"); + double z = loaderConfig.getDouble("z"); + int radius = loaderConfig.getInt("radius"); + + World world = Bukkit.getServer().getWorld(worldName); + + if (world != null) { + // Create a new ChunkLoader object and add it to the map + ChunkLoader loader = new ChunkLoader(name, new Location(world, x, y, z), radius); + chunkLoaders.put(name, loader); + } else { + Bukkit.getLogger().warning("Could not load chunkloader " + name + ": World " + worldName + " not found"); + } + } + } + } + + + + private void saveConfig() { + try { + chunkLoaderConfig.save(new File(plugin.getDataFolder(), "chunkloaders.yml")); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/clean_entities_command.java b/src/main/java/com/zivilon/admintools/commands/clean_entities_command.java new file mode 100644 index 0000000..92b8882 --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/clean_entities_command.java @@ -0,0 +1,98 @@ +package com.zivilon.admintools.commands; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +import me.dpohvar.powernbt.api.NBTCompound; +import me.dpohvar.powernbt.api.NBTManager; + +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +public class clean_entities_command implements CommandExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + + if (!sender.hasPermission("admintools.clean_entities")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + + if(args.length != 6){ + sender.sendMessage("Incorrect command format! Use: /cleanentities "); + return true; + } + + int x, y, z, radius; + try { + x = Integer.parseInt(args[0]); + y = Integer.parseInt(args[1]); + z = Integer.parseInt(args[2]); + radius = Integer.parseInt(args[4]); + } catch (NumberFormatException e){ + sender.sendMessage("The coordinates and radius must be integers!"); + return true; + } + + World world = Bukkit.getWorld(args[3]); + if (world == null) { + sender.sendMessage("Invalid world: " + args[3]); + return true; + } + + String targetEntityId = args[5]; + if (!targetEntityId.equals("ALL") && targetEntityId.isEmpty()) { + sender.sendMessage("Invalid entity ID: " + args[5]); + return true; + } + + Location center = new Location(world, x, y, z); + + // Convert wildcard format to regex + String regex = targetEntityId.replaceAll("\\*", ".*"); + + // Obtain an instance of NBTManager + NBTManager nbtManager = me.dpohvar.powernbt.PowerNBT.getApi(); + + // List of entities to exclude from deletion + List excludeEntityIds = Arrays.asList("lotr.WallBanner", "lotr.Banner", "ItemFrame"); + + for (Entity entity : world.getEntities()) { + if (entity != null && entity.getLocation().distance(center) <= radius) { + // Skip if the entity is a player + if (entity instanceof Player) { + continue; + } + + // Get NBT data of entity + NBTCompound nbtData = nbtManager.read(entity); + + String entityId = (String) nbtData.get("id"); + if (entityId == null) { + continue; + } + + if (excludeEntityIds.contains(entityId)) { + continue; + } + + // If a specific entityId is provided, only delete entities that match the pattern + if (!targetEntityId.equals("ALL") && !Pattern.matches(regex, entityId)) { + continue; + } + + // Delete the entity if not excluded + entity.remove(); + } + } + return true; + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/count_units_command.java b/src/main/java/com/zivilon/admintools/commands/count_units_command.java new file mode 100644 index 0000000..b4e6431 --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/count_units_command.java @@ -0,0 +1,131 @@ +package com.zivilon.admintools.commands; + +import me.dpohvar.powernbt.api.NBTCompound; +import me.dpohvar.powernbt.api.NBTManager; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import com.zivilon.admintools.AdminTools; + +public class count_units_command implements CommandExecutor { + private final AdminTools plugin; + + public count_units_command(AdminTools plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + + if (!sender.hasPermission("admintools.count_units")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + + FileConfiguration unitNamesConfig = plugin.getUnitNamesConfig(); + + if(args.length < 1 || args.length > 3){ + sender.sendMessage("Incorrect command format! Use: /count_units [-d] [radius]"); + return true; + } + + boolean debug = false; + String playerName; + int radius = 100; + + if(args[0].equals("-d")){ + debug = true; + playerName = args[1]; + if(args.length == 3){ + try { + radius = Integer.parseInt(args[2]); + } catch (NumberFormatException e) { + sender.sendMessage("The radius must be an integer!"); + return true; + } + } + } + else{ + playerName = args[0]; + if(args.length == 2){ + try { + radius = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + sender.sendMessage("The radius must be an integer!"); + return true; + } + } + } + + Player targetPlayer = Bukkit.getPlayer(playerName); + if (targetPlayer == null) { + sender.sendMessage("Invalid player: " + playerName); + return true; + } + + if(debug) { + sender.sendMessage("Passed argument check"); + } + Location playerLoc = targetPlayer.getLocation(); + UUID playerUUID = targetPlayer.getUniqueId(); + if (debug) {sender.sendMessage("Passed coordinate retrieval");} + + NBTManager nbtManager = me.dpohvar.powernbt.PowerNBT.getApi(); + + // Use a map to keep count of the different types of entities + Map entityCounts = new HashMap<>(); + + for (Entity entity : playerLoc.getWorld().getEntities()) { + if (entity.getLocation().distance(playerLoc) <= radius) { + if (debug) {sender.sendMessage("FOR LOOP: Passed distance check");} + + // Get NBT data of entity + NBTCompound nbtData = nbtManager.read(entity); + NBTCompound hiredNPCInfo = (NBTCompound) nbtData.get("HiredNPCInfo"); + + if (debug) {sender.sendMessage("FOR LOOP: Started HiredNPCInfo null check on " + nbtData.get("id"));} + if (hiredNPCInfo == null) { + if (debug) {sender.sendMessage("FOR LOOP: Is null");} + continue; + } + + if (debug) {sender.sendMessage("FOR LOOP: Started HiringPlayerUUID null check");} + String hiringPlayerUUID = (String) hiredNPCInfo.get("HiringPlayerUUID"); + if (hiringPlayerUUID == null) { + if (debug) {sender.sendMessage("FOR LOOP: Is null");} + continue; + } + if (debug) {sender.sendMessage("FOR LOOP: Passed HiredNPCInfo null check");} + + if (hiringPlayerUUID.equals(playerUUID.toString())) { + if (debug) {sender.sendMessage("FOR LOOP: Started HiredNPCInfo value check");} + String entityType = (String) nbtData.get("id"); + if (debug) {sender.sendMessage("FOR LOOP: Got HiredNPCInfo value");} + + // Increment the count for this entity type + entityCounts.put(entityType, entityCounts.getOrDefault(entityType, 0) + 1); + if (debug) {sender.sendMessage("FOR LOOP: Added to entity count");} + } + } + } + if (debug) {sender.sendMessage("FOR LOOP: Ended loop");} + sender.sendMessage(ChatColor.GRAY + "Player " + playerName + "'s units:"); + for (Map.Entry entry : entityCounts.entrySet()) { + String friendlyName = unitNamesConfig.getString(entry.getKey(), entry.getKey()); + sender.sendMessage(ChatColor.DARK_AQUA + "[" + ChatColor.AQUA + "x" + entry.getValue() + ChatColor.DARK_AQUA + "] " + ChatColor.GRAY + friendlyName); + } + + return true; + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/effect_command.java b/src/main/java/com/zivilon/admintools/commands/effect_command.java new file mode 100644 index 0000000..63518d3 --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/effect_command.java @@ -0,0 +1,83 @@ +package com.zivilon.admintools.commands; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionEffect; + +public class effect_command implements CommandExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.hasPermission("admintools.effect")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + + if (args.length < 2) { + sender.sendMessage(ChatColor.RED + "Usage: /effect [-d -s] [seconds] [amplifier]"); + return false; + } + + boolean debug_flag = false; + boolean silent_flag = false; + int argument_offset = 0; + + // Iterate over flags + for (; argument_offset < args.length; argument_offset++) { + if (args[argument_offset].startsWith("-")) { + debug_flag |= args[argument_offset].contains("d"); + silent_flag |= args[argument_offset].contains("s"); + } else { + break; + } + } + + if (args.length < (2 + argument_offset)) { + sender.sendMessage(ChatColor.RED + "Usage: /effect [-d -s] [seconds] [amplifier]"); + return false; + } + + + Player targetPlayer = Bukkit.getPlayerExact(args[0 + argument_offset]); + if (targetPlayer == null) { + sender.sendMessage(ChatColor.RED + "Could not find player: " + args[0 + argument_offset]); + return true; + } + + if ("clear".equalsIgnoreCase(args[1 + argument_offset])) { + targetPlayer.getActivePotionEffects().forEach(effect -> targetPlayer.removePotionEffect(effect.getType())); + if (!silent_flag) { + sender.sendMessage("Effect has been removed from " + targetPlayer.getName()); + } + return true; + } + + PotionEffectType effectType = findPotionEffectType(args[1 + argument_offset]); + if (effectType == null) { + sender.sendMessage(ChatColor.RED + "Invalid effect: " + args[1 + argument_offset]); + return true; + } + + int duration = (args.length > argument_offset + 2) ? Integer.parseInt(args[2 + argument_offset]) * 20 : 60 * 20; + int amplifier = (args.length > argument_offset + 3) ? Integer.parseInt(args[3 + argument_offset]) : 0; + + targetPlayer.addPotionEffect(new PotionEffect(effectType, duration, amplifier, false), true); + if (!silent_flag) { + targetPlayer.sendMessage("You have been given " + effectType.getName() + "."); + } + + return true; + } + + private PotionEffectType findPotionEffectType(String nameOrId) { + try { + return PotionEffectType.getById(Integer.parseInt(nameOrId)); + } catch (NumberFormatException e) { + return PotionEffectType.getByName(nameOrId.toUpperCase()); + } + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/entity_effect_command.java b/src/main/java/com/zivilon/admintools/commands/entity_effect_command.java new file mode 100644 index 0000000..24990b2 --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/entity_effect_command.java @@ -0,0 +1,116 @@ +package com.zivilon.admintools.commands; + +import me.dpohvar.powernbt.api.NBTCompound; +import me.dpohvar.powernbt.api.NBTList; +import me.dpohvar.powernbt.utils.EntityUtils; +import me.dpohvar.powernbt.utils.NBTParser; +import me.dpohvar.powernbt.utils.NBTUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionEffect; + +import java.util.List; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; +import java.util.Arrays; +import java.util.stream.Collectors; + +public class entity_effect_command implements CommandExecutor { + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "Only players can use this command."); + return true; + } + if (!sender.hasPermission("admintools.entity_effect")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + + Player player = (Player) sender; + + if (args.length < 5) { + player.sendMessage(ChatColor.RED + "Usage: /command "); + return true; + } + + PotionEffectType effectType = PotionEffectType.getByName(args[0].toUpperCase()); + if (effectType == null) { + player.sendMessage(ChatColor.RED + "Invalid effect type."); + return true; + } + + int radius; + try { + radius = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + player.sendMessage(ChatColor.RED + "Invalid radius."); + return true; + } + + int duration; + int amplifier; + + try { + duration = Integer.parseInt(args[3]) * 20; // Convert seconds to game ticks + amplifier = Integer.parseInt(args[4]) - 1; // Subtract 1 because amplifiers are zero-indexed (0 is level 1) + } catch (NumberFormatException e) { + player.sendMessage(ChatColor.RED + "Invalid duration or amplifier."); + return true; + } + + List includeTargets = new ArrayList<>(); + Set excludeTargets = new HashSet<>(); + + List targets = Arrays.asList(args[2].split(",")); + for (String target : targets) { + if (target.startsWith("!")) { + // If it starts with "!", it's an exclusion, so remove the "!" and add it to the excludeTargets + excludeTargets.add(target.substring(1).toLowerCase()); // Convert to lower case for consistency + } else { + // Otherwise, it's an inclusion + includeTargets.add(target.toLowerCase()); // Convert to lower case for consistency + } + } + + Location loc = player.getLocation(); + World world = loc.getWorld(); + if (world == null) { + return false; + } + + List nearbyEntities = loc.getWorld().getEntitiesByClass(Entity.class).stream() + .filter(e -> e.getLocation().distance(loc) <= radius) + .collect(Collectors.toList()); + for (Entity entity : nearbyEntities) { + String entityType = entity.getType().toString().toLowerCase(); // Get the entity type as a string in lower case + // Check if this entity type is excluded + if (excludeTargets.contains(entityType.toLowerCase())) { // Ensure checking against lower case + continue; // Skip this entity as it's excluded + } + + // Check if "all" is in the includeTargets or if this specific type is included + if (includeTargets.contains("all") || includeTargets.contains(entityType)) { + // Apply the potion effect if entity is a LivingEntity + if (entity instanceof LivingEntity) { + LivingEntity livingEntity = (LivingEntity) entity; + livingEntity.addPotionEffect(new PotionEffect(effectType, duration, amplifier)); + } + } + } + + player.sendMessage(ChatColor.GREEN + "Effect applied."); + return true; + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/region_teleport_command.java b/src/main/java/com/zivilon/admintools/commands/region_teleport_command.java new file mode 100644 index 0000000..5de3ca5 --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/region_teleport_command.java @@ -0,0 +1,78 @@ +package com.zivilon.admintools.commands; + +import org.bukkit.Location; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.Location; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.managers.RegionManager; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; + +import com.zivilon.admintools.AdminTools; + +public class region_teleport_command implements CommandExecutor { + + private final AdminTools plugin; + private WorldGuardPlugin worldGuardPlugin; + + public region_teleport_command(AdminTools plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { + if (!sender.hasPermission("admintools.region_tp")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + + if (args.length != 4) { + sender.sendMessage("Usage: /region_tp "); + return true; + } + + Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin("WorldGuard"); + if (plugin instanceof WorldGuardPlugin) { + worldGuardPlugin = (WorldGuardPlugin) plugin; + } + + World dim100World = Bukkit.getWorld("DIM100"); + if (dim100World == null) { + plugin.getLogger().warning("World DIM100 not found! Ensure the world name is correct."); + return true; + } + + int x, y, z; + try { + x = Integer.parseInt(args[1]); + y = Integer.parseInt(args[2]); + z = Integer.parseInt(args[3]); + } catch (NumberFormatException e){ + sender.sendMessage("The coordinates must be integers!"); + return true; + } + + RegionManager regionManager = worldGuardPlugin.getRegionManager(dim100World); + Location location = new Location(dim100World, (double) x, (double) y, (double) z); + + String[] regionNames = args[0].split(","); // Split region names by comma + + for (Player player : Bukkit.getOnlinePlayers()) { + for (String regionName : regionNames) { + ProtectedRegion region = regionManager.getRegion(regionName); + if (region != null && region.contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ())) { + player.teleport(location); + } + } + } + return true; + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/set_login_location_command.java b/src/main/java/com/zivilon/admintools/commands/set_login_location_command.java new file mode 100644 index 0000000..ed12eae --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/set_login_location_command.java @@ -0,0 +1,76 @@ +package com.zivilon.admintools.commands; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; + +import java.util.HashMap; +import java.util.Map; + +public class set_login_location_command implements CommandExecutor, Listener { + // Map to store player names and their login locations. + private Map login_locations = new HashMap<>(); + + public set_login_location_command() { + Bukkit.getPluginManager().registerEvents(this, Bukkit.getPluginManager().getPlugin("AdminTools")); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.hasPermission("admintools.set_login_location")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + if (command.getName().equalsIgnoreCase("set_login_location")) { + if (args.length < 4) { + sender.sendMessage("Usage: /set_login_location "); + return true; + } + + String playerName = args[0]; + World world = Bukkit.getWorld(args[1]); + if (world == null) { + sender.sendMessage("World not found: " + args[1]); + return true; + } + + double x; + double y; + double z; + try { + x = Double.parseDouble(args[2]); + y = Double.parseDouble(args[3]); + z = Double.parseDouble(args[4]); + } catch (NumberFormatException e) { + sender.sendMessage("Coordinates must be numbers."); + return true; + } + + Location location = new Location(world, x, y, z); + + login_locations.put(playerName, location); + sender.sendMessage("Login location set for " + playerName); + return true; + } + + return false; + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + if (login_locations.containsKey(player.getName())) { + player.teleport(login_locations.get(player.getName())); + login_locations.remove(player.getName()); + } + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/world_setblock_command.java b/src/main/java/com/zivilon/admintools/commands/world_setblock_command.java new file mode 100644 index 0000000..0fcbe07 --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/world_setblock_command.java @@ -0,0 +1,115 @@ +package com.zivilon.admintools.commands; + +import java.util.Objects; +import me.dpohvar.powernbt.utils.NBTBlockUtils; +import me.dpohvar.powernbt.utils.NBTParser; +import me.dpohvar.powernbt.utils.NBTUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; + +public class world_setblock_command implements CommandExecutor { + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.hasPermission("admintools.world_setblock")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + int x, y, z; + if (args.length < 5) { + sender.sendMessage("Usage: /wsetblock [data] [oldBlockHandling] [dataTag]"); + return false; + } + + boolean debug_flag = false; + boolean silent_flag = false; + int argument_offset = 0; // This offset helps us handle the arguments correctly + + // Iterate over flags + for (; argument_offset < args.length; argument_offset++) { + if (args[argument_offset].startsWith("-")) { + debug_flag |= args[argument_offset].contains("d"); + silent_flag |= args[argument_offset].contains("s"); + } else { + break; + } + } + + if (args.length - argument_offset < 5) { + if (debug_flag) sender.sendMessage("Failed at args.length - argument_offset < 5 with args.length " + args.length + " and argument_offset " + argument_offset); + sender.sendMessage(ChatColor.RED + "Usage: /wsetblock [-s] [data] [oldBlockHandling] [dataTag]"); + return false; + } + + World world = Bukkit.getWorld(args[0 + argument_offset]); + try { + x = Integer.parseInt(args[1 + argument_offset]); + y = Integer.parseInt(args[2 + argument_offset]); + z = Integer.parseInt(args[3 + argument_offset]); + } catch (NumberFormatException e) { + sender.sendMessage(ChatColor.RED + "Coordinates need to be numbers."); + return true; + } + if (world == null) { + sender.sendMessage(ChatColor.RED + String.format("There is no such world with name %s.", new Object[] { args[1 + argument_offset] })); + return true; + } + Material material = Material.matchMaterial(args[4 + argument_offset]); + if (material == null) { + sender.sendMessage(ChatColor.RED + String.format("There is no such block with ID/name %s.", new Object[] { args[4 + argument_offset] })); + return true; + } + int data = 0; + if (args.length > (5 + argument_offset)) + try { + data = Integer.parseInt(args[5 + argument_offset]); + if (data < 0 || data > 15) { + sender.sendMessage(ChatColor.RED + "Data must be between 0 and 15."); + return true; + } + } catch (NumberFormatException e) { + sender.sendMessage(ChatColor.RED + "Data must to be a numbers."); + return true; + } + Block block = world.getBlockAt(x, y, z); + Object handle = NBTUtils.nbtUtils.createTagCompound(); + boolean hasNBT = false; + if (args.length >= (8 + argument_offset)) + try { + StringBuilder builder = new StringBuilder(); + for (int i = (7 + argument_offset); i < args.length; i++) + builder.append(args[i]).append(" "); + handle = NBTParser.parser("tag", builder.toString()).parse(); + hasNBT = true; + } catch (Exception e) { + sender.sendMessage(ChatColor.RED + String.format("Data tag parsing failed: %s", new Object[] { e.getMessage() })); + return true; + } + if (args.length >= (7 + argument_offset)) { + String handleMethod = args[6 + argument_offset]; + if (Objects.equals(handleMethod, "destroy")) { + block.setTypeId(0, true); + } else if (Objects.equals(handleMethod, "keep") && !block.isEmpty()) { + if (!silent_flag) sender.sendMessage(ChatColor.RED + "The block couldn't be placed"); + return true; + } + } + if (!block.setTypeIdAndData(material.getId(), (byte)data, true)) { + if (!silent_flag) sender.sendMessage(ChatColor.RED + "The block couldn't be placed"); + return true; + } + if (hasNBT) + try { + NBTBlockUtils.nbtBlockUtils.setTag(block, handle); + } catch (Exception e) { + sender.sendMessage(ChatColor.RED + String.format("Data tag parsing failed: %s", new Object[] { e.getMessage() })); + return true; + } + if (!silent_flag) sender.sendMessage(ChatColor.GREEN + "Block placed"); + return true; + } +} diff --git a/src/main/java/com/zivilon/admintools/commands/world_summon_command.java b/src/main/java/com/zivilon/admintools/commands/world_summon_command.java new file mode 100644 index 0000000..01bcd4c --- /dev/null +++ b/src/main/java/com/zivilon/admintools/commands/world_summon_command.java @@ -0,0 +1,102 @@ +package com.zivilon.admintools.commands; + +import me.dpohvar.powernbt.api.NBTCompound; +import me.dpohvar.powernbt.api.NBTList; +import me.dpohvar.powernbt.utils.EntityUtils; +import me.dpohvar.powernbt.utils.NBTParser; +import me.dpohvar.powernbt.utils.NBTUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; + +import java.util.Arrays; + +public class world_summon_command implements CommandExecutor { + + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.hasPermission("admintools.world_summon")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return true; + } + double x, y, z; + if (args.length < 5) { + sender.sendMessage("Usage: /wsummon [NBT]"); + return false; + + } + + boolean debug_flag = false; + boolean silent_flag = false; + int argument_offset = 0; // This offset helps us handle the arguments correctly + + // Iterate over flags + for (; argument_offset < args.length; argument_offset++) { + if (args[argument_offset].startsWith("-")) { + debug_flag |= args[argument_offset].contains("d"); + silent_flag |= args[argument_offset].contains("s"); + } else { + break; + } + } + + if (args.length - argument_offset < 5) { + if (debug_flag) sender.sendMessage("Failed at args.length - argument_offset < 5 with args.length " + args.length + " and argument_offset " + argument_offset); + sender.sendMessage(ChatColor.RED + "Usage: /wsummon [-s] [NBT]"); + return false; + } + + World world = Bukkit.getWorld(args[0 + argument_offset]); + + try { + x = Double.parseDouble(args[1 + argument_offset]); + y = Double.parseDouble(args[2 + argument_offset]); + z = Double.parseDouble(args[3 + argument_offset]); + } catch (NumberFormatException e) { + sender.sendMessage(ChatColor.RED + "Coordinates need to be numbers."); + return true; + } + + if (world == null) { + sender.sendMessage(ChatColor.RED + String.format("There is no such world with name %s.", args[1 + argument_offset])); + return true; + } + + if (!world.isChunkLoaded((int)x >> 4, (int)z >> 4)) + world.loadChunk((int)x >> 4, (int)z >> 4); + + Object handle = NBTUtils.nbtUtils.createTagCompound(); + + if (args.length >= (6 + argument_offset)) { + try { + StringBuilder builder = new StringBuilder(); + for (int i = 5; i < (args.length - argument_offset); i++) + builder.append(args[i + argument_offset]).append(" "); + + handle = NBTParser.parser("tag", builder.toString()).parse(); + } catch (IllegalArgumentException e) { + sender.sendMessage(ChatColor.RED + String.format("Data tag parsing failed: %s", args[5 + argument_offset])); + return true; + } + } + + NBTCompound nbtCompound = NBTCompound.forNBT(handle); + nbtCompound.put("id", args[4 + argument_offset]); + + nbtCompound.put("Pos", new NBTList(Arrays.asList(x, y, z))); + + Entity entity = EntityUtils.entityUtils.spawnEntity(nbtCompound.getHandle(), world); + + if (entity != null) { + if (!silent_flag) sender.sendMessage(ChatColor.GREEN + "Object successfully summoned"); + } else { + sender.sendMessage(ChatColor.RED + "Unable to summon object."); + } + + return true; + } +} diff --git a/src/main/java/com/zivilon/admintools/listeners/ranged_immunity_listener.java b/src/main/java/com/zivilon/admintools/listeners/ranged_immunity_listener.java new file mode 100644 index 0000000..467329c --- /dev/null +++ b/src/main/java/com/zivilon/admintools/listeners/ranged_immunity_listener.java @@ -0,0 +1,47 @@ +package com.zivilon.admintools.listeners; + +import me.dpohvar.powernbt.api.NBTCompound; +import me.dpohvar.powernbt.api.NBTManager; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Projectile; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; + +import com.zivilon.admintools.AdminTools; + +public class ranged_immunity_listener implements Listener { + + private final AdminTools plugin; + + public ranged_immunity_listener(AdminTools plugin) { + this.plugin = plugin; + } + + // DEPRECATED + // Use the DamageModifiers plugin instead + // It lets you create immunities and damage multipliers to all damage types + + @EventHandler + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + Entity damager = event.getDamager(); + Entity entity = event.getEntity(); + + // Check if damage source is a projectile + if (!(damager instanceof Projectile)) { + return; + } + + // Obtain an instance of NBTManager + NBTManager nbtManager = me.dpohvar.powernbt.PowerNBT.getApi(); + + // Get NBT data of the entity + NBTCompound nbtData = nbtManager.read(entity); + NBTCompound forgeData = (NBTCompound) nbtData.get("ForgeData"); + + // Check if the entity has RangedImmune = 1 + if (forgeData != null && forgeData.getByte("RangedImmune") == 1) { + event.setCancelled(true); + } + } +} diff --git a/src/main/resources/chunkloaders.yml b/src/main/resources/chunkloaders.yml new file mode 100644 index 0000000..6694142 --- /dev/null +++ b/src/main/resources/chunkloaders.yml @@ -0,0 +1,11 @@ +chunkloaders: + chunkloader1: + world: "world" + x: 100 + y: 64 + z: 200 + chunkloader2: + world: "world_nether" + x: -100 + y: 64 + z: -200 diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..71f2d59 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,42 @@ +main: com.zivilon.admintools.AdminTools +name: AdminTools +author: Shinare +version: 1.3 +depend: [WorldGuard] +load: POSTWORLD +commands: + clean_entities: + description: "Removes entities of the specified type within the given radius" + count_units: + description: "Counts the hired units of a specified player" + chunkloader: + description: "Main command for creating chunk loaders" + aliases: [chl] + block_swap: + description: "Sets an area of blocks client-side only to the specified player" + usage: "Usage: /block_swap " + wsummon: + description: "Usage: /wsummon [-d -s] [entity] []" + wsetblock: + description: "Usage: /wsetblock [-d -s] [dataValue] [oldBlockHandling] [dataTag]]" + set_login_location: + description: "Sets player's login location for when they log in again. Needs to be during current server session, is not persistent over restarts." + usage: "Usage: /set_login_location [dataValue] [oldBlockHandling] [dataTag]]" + area_message: + description: "Usage: /area_message [-d -s] " + areaeffect: + description: "Usage: /areaeffect " + effect: + description: "Applies an effect to a player with optional silence and debug flags." + usage: "/ [-d -s] [seconds] [amplifier]" + check_players: + description: "Runs a command depending on if players are in specified WorldGuard regions." + usage: "Usage: /check_players " + region_tp: + description: "Teleports all players within given WorldGuard regions to coordinates." + usage: "Usage: /region_tp " + aliases: [region_teleport, rtp, rgtp] + entityeffect: + description: "Applies given potion effect to all listed entity types nearby." + usage: "Usage: /entityeffect " + diff --git a/src/main/resources/unit_names.yml b/src/main/resources/unit_names.yml new file mode 100644 index 0000000..d84cb43 --- /dev/null +++ b/src/main/resources/unit_names.yml @@ -0,0 +1,3 @@ +EntityNames: + lotr.NearHaradrimWarrior: 'Coast Southron Warrior' + lotr.SomeOtherEntity: 'Friendly name'