commit 69f7a6012064d79e4a9bc3cbfa4dfb6b814a8844 Author: Xelara Networks Date: Mon Jun 8 00:03:55 2026 -0400 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..986a728 --- /dev/null +++ b/pom.xml @@ -0,0 +1,47 @@ + + 4.0.0 + + com.bitnix + MyWorlds + 1.0 + jar + + MyWorlds + + + 21 + UTF-8 + + + + + papermc + https://repo.papermc.io/repository/maven-public/ + + + + + + io.papermc.paper + paper-api + 1.21.8-R0.1-SNAPSHOT + provided + + + + + MyWorlds + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 21 + + + + + diff --git a/src/main/java/com/bitnix/myworlds/MyWorldsPlugin.java b/src/main/java/com/bitnix/myworlds/MyWorldsPlugin.java new file mode 100644 index 0000000..7f0c7ab --- /dev/null +++ b/src/main/java/com/bitnix/myworlds/MyWorldsPlugin.java @@ -0,0 +1,1096 @@ +package com.bitnix.myworlds; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.WorldBorder; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +public final class MyWorldsPlugin extends JavaPlugin implements Listener { + + private File dataFile; + private FileConfiguration dataConfig; + + private String msgNoPermission; + private String msgPlayerOnly; + private String msgReloaded; + private String msgNoWorlds; + private String msgWorldLimitReached; + private String msgNoWorldLimit; + private String msgInvalidWorldType; + private String msgWorldCreating; + private String msgWorldCreated; + private String msgWorldFailed; + private String msgWorldNotFound; + private String msgTeleported; + private String msgOnlyOwnWorlds; + private String msgNoAccessWorld; + private String msgMultiverseMissing; + private String msgPlayerNotFound; + private String msgInvitedPlayer; + private String msgUninvitedPlayer; + private String msgYouWereInvited; + private String msgAlreadyInvited; + private String msgNotInvited; + private String msgPvpEnabled; + private String msgPvpDisabled; + private String msgInvalidPvpState; + private String msgWorldDeleted; + private String msgDeleteFailed; + private String msgConfirmDelete; + + private boolean quickTeleportSingleWorld; + private String worldNameFormat; + private int worldBorderSize; + private String defaultGamemode; + private int noLimitPermissionDefault; + + private String normalCommand; + private String flatCommand; + private String amplifiedCommand; + private String deleteCommand; + + private boolean allowNormal; + private boolean allowFlat; + private boolean allowAmplified; + + private String mainGuiTitle; + private int mainGuiSize; + private String listGuiTitle; + private int listGuiSize; + private String manageGuiTitle; + private int manageGuiSize; + + private final List permissionLimits = new ArrayList<>(); + private final Map openMenus = new HashMap<>(); + private final Map deleteConfirmations = new HashMap<>(); + + @Override + public void onEnable() { + saveDefaultConfig(); + NamespacedKeys.init(this); + createDataFile(); + loadSettings(); + + getServer().getPluginManager().registerEvents(this, this); + getLogger().info("MyWorlds enabled."); + } + + @Override + public void onDisable() { + openMenus.clear(); + deleteConfirmations.clear(); + saveDataConfig(); + } + + private void createDataFile() { + dataFile = new File(getDataFolder(), "data.yml"); + + if (!getDataFolder().exists()) { + getDataFolder().mkdirs(); + } + + if (!dataFile.exists()) { + try { + dataFile.createNewFile(); + } catch (IOException e) { + getLogger().severe("Could not create data.yml"); + e.printStackTrace(); + } + } + + dataConfig = YamlConfiguration.loadConfiguration(dataFile); + } + + private void saveDataConfig() { + if (dataConfig == null || dataFile == null) { + return; + } + + try { + dataConfig.save(dataFile); + } catch (IOException e) { + getLogger().severe("Could not save data.yml"); + e.printStackTrace(); + } + } + + private void loadSettings() { + reloadConfig(); + FileConfiguration config = getConfig(); + + quickTeleportSingleWorld = config.getBoolean("settings.quick-teleport-single-world", false); + worldNameFormat = config.getString("settings.world-name-format", "mw_%player%_%number%"); + worldBorderSize = config.getInt("settings.world-border-size", 10000); + defaultGamemode = config.getString("settings.default-gamemode", "SURVIVAL"); + noLimitPermissionDefault = config.getInt("settings.no-limit-permission-default", 0); + + normalCommand = config.getString("multiverse.normal-command", "mv create %world% normal"); + flatCommand = config.getString("multiverse.flat-command", "mv create %world% normal -t flat"); + amplifiedCommand = config.getString("multiverse.amplified-command", "mv create %world% normal -a true"); + deleteCommand = config.getString("multiverse.delete-command", "mv delete %world%"); + + allowNormal = config.getBoolean("world-types.normal", true); + allowFlat = config.getBoolean("world-types.flat", true); + allowAmplified = config.getBoolean("world-types.amplified", true); + + msgNoPermission = color(config.getString("messages.no-permission", "&cYou do not have permission.")); + msgPlayerOnly = color(config.getString("messages.player-only", "&cOnly players can use this command.")); + msgReloaded = color(config.getString("messages.reloaded", "&aMyWorlds config reloaded.")); + msgNoWorlds = color(config.getString("messages.no-worlds", "&cYou do not own any worlds yet.")); + msgWorldLimitReached = color(config.getString("messages.world-limit-reached", "&cYou have reached your world limit of &e%limit%&c.")); + msgNoWorldLimit = color(config.getString("messages.no-world-limit", "&cYou are not allowed to create any worlds.")); + msgInvalidWorldType = color(config.getString("messages.invalid-world-type", "&cInvalid world type.")); + msgWorldCreating = color(config.getString("messages.world-creating", "&eCreating your world: &f%world%&e...")); + msgWorldCreated = color(config.getString("messages.world-created", "&aWorld created: &e%world%&a.")); + msgWorldFailed = color(config.getString("messages.world-failed", "&cFailed to create world.")); + msgWorldNotFound = color(config.getString("messages.world-not-found", "&cThat world could not be found.")); + msgTeleported = color(config.getString("messages.teleported", "&aTeleported to &e%world%&a.")); + msgOnlyOwnWorlds = color(config.getString("messages.only-own-worlds", "&cYou can only manage your own worlds.")); + msgNoAccessWorld = color(config.getString("messages.no-access-world", "&cYou do not have access to that world.")); + msgMultiverseMissing = color(config.getString("messages.multiverse-missing", "&cMultiverse-Core was not found or is not enabled.")); + msgPlayerNotFound = color(config.getString("messages.player-not-found", "&cThat player is not online.")); + msgInvitedPlayer = color(config.getString("messages.invited-player", "&aInvited &e%player% &ato world &e%world%&a.")); + msgUninvitedPlayer = color(config.getString("messages.uninvited-player", "&e%player% &chas been removed from world &e%world%&c.")); + msgYouWereInvited = color(config.getString("messages.you-were-invited", "&aYou were invited to world &e%world% &aby &e%owner%&a.")); + msgAlreadyInvited = color(config.getString("messages.already-invited", "&e%player% &cis already invited to &e%world%&c.")); + msgNotInvited = color(config.getString("messages.not-invited", "&e%player% &cis not invited to &e%world%&c.")); + msgPvpEnabled = color(config.getString("messages.pvp-enabled", "&aPvP enabled for &e%world%&a.")); + msgPvpDisabled = color(config.getString("messages.pvp-disabled", "&cPvP disabled for &e%world%&c.")); + msgInvalidPvpState = color(config.getString("messages.invalid-pvp-state", "&cUse on/off.")); + msgWorldDeleted = color(config.getString("messages.world-deleted", "&cWorld deleted: &e%world%&c.")); + msgDeleteFailed = color(config.getString("messages.delete-failed", "&cFailed to delete world &e%world%&c.")); + msgConfirmDelete = color(config.getString("messages.confirm-delete", "&cClick again to confirm deletion of &e%world%&c.")); + + mainGuiTitle = color(config.getString("gui.main.title", "&8My Worlds")); + mainGuiSize = config.getInt("gui.main.size", 27); + listGuiTitle = color(config.getString("gui.list.title", "&8Your Worlds")); + listGuiSize = config.getInt("gui.list.size", 54); + manageGuiTitle = color(config.getString("gui.manage.title", "&8Manage World")); + manageGuiSize = config.getInt("gui.manage.size", 27); + + permissionLimits.clear(); + List> rawLimits = config.getMapList("limits"); + for (Map raw : rawLimits) { + Object permissionObj = raw.get("permission"); + Object amountObj = raw.get("amount"); + + if (permissionObj == null || amountObj == null) { + continue; + } + + String permission = String.valueOf(permissionObj).trim(); + int amount; + + try { + amount = Integer.parseInt(String.valueOf(amountObj)); + } catch (NumberFormatException e) { + continue; + } + + if (!permission.isBlank() && amount >= 0) { + permissionLimits.add(new LimitEntry(permission, amount)); + } + } + } + + private boolean hasMultiverse() { + Plugin mv = Bukkit.getPluginManager().getPlugin("Multiverse-Core"); + return mv != null && mv.isEnabled(); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player player)) { + if (args.length == 1 && args[0].equalsIgnoreCase("reload")) { + if (!sender.hasPermission("myworlds.admin")) { + sender.sendMessage(msgNoPermission); + return true; + } + + loadSettings(); + dataConfig = YamlConfiguration.loadConfiguration(dataFile); + sender.sendMessage(msgReloaded); + return true; + } + + sender.sendMessage(msgPlayerOnly); + return true; + } + + if (!player.hasPermission("myworlds.use")) { + player.sendMessage(msgNoPermission); + return true; + } + + if (args.length == 0) { + openMainGui(player); + return true; + } + + switch (args[0].toLowerCase()) { + case "help" -> sendHelp(player); + case "list" -> sendWorldList(player); + case "generate" -> { + if (args.length < 2) { + openMainGui(player); + return true; + } + generateWorld(player, args[1].toLowerCase()); + } + case "invite" -> { + if (!player.hasPermission("myworlds.invite")) { + player.sendMessage(msgNoPermission); + return true; + } + if (args.length < 3) { + player.sendMessage(color("&eUsage: /myworlds invite ")); + return true; + } + handleInvite(player, args[1], args[2]); + } + case "uninvite" -> { + if (!player.hasPermission("myworlds.invite")) { + player.sendMessage(msgNoPermission); + return true; + } + if (args.length < 3) { + player.sendMessage(color("&eUsage: /myworlds uninvite ")); + return true; + } + handleUninvite(player, args[1], args[2]); + } + case "pvp" -> { + if (!player.hasPermission("myworlds.pvp")) { + player.sendMessage(msgNoPermission); + return true; + } + if (args.length < 3) { + player.sendMessage(color("&eUsage: /myworlds pvp ")); + return true; + } + handlePvpToggle(player, args[1], args[2]); + } + case "reload" -> { + if (!player.hasPermission("myworlds.admin")) { + player.sendMessage(msgNoPermission); + return true; + } + loadSettings(); + dataConfig = YamlConfiguration.loadConfiguration(dataFile); + player.sendMessage(msgReloaded); + } + default -> openMainGui(player); + } + + return true; + } + + private void sendHelp(Player player) { + player.sendMessage(color("&6MyWorlds Help")); + player.sendMessage(color("&e/myworlds &7- Open menu")); + player.sendMessage(color("&e/myworlds help &7- Show help")); + player.sendMessage(color("&e/myworlds list &7- List your worlds")); + player.sendMessage(color("&e/myworlds generate &7- Generate a world")); + player.sendMessage(color("&e/myworlds invite &7- Invite a player")); + player.sendMessage(color("&e/myworlds uninvite &7- Remove invite")); + player.sendMessage(color("&e/myworlds pvp &7- Toggle world PvP")); + if (player.hasPermission("myworlds.admin")) { + player.sendMessage(color("&e/myworlds reload &7- Reload config")); + } + } + + private void sendWorldList(Player player) { + List owned = getOwnedWorlds(player.getUniqueId()); + List invited = getAccessibleInvitedWorlds(player.getUniqueId()); + + if (owned.isEmpty() && invited.isEmpty()) { + player.sendMessage(msgNoWorlds); + return; + } + + if (!owned.isEmpty()) { + player.sendMessage(color("&6Your Owned Worlds:")); + for (String world : owned) { + UUID owner = getOwnerOfWorld(world); + String type = owner != null ? getWorldType(owner, world) : "unknown"; + player.sendMessage(color("&e- &f" + world + " &7(" + type + ")")); + } + } + + if (!invited.isEmpty()) { + player.sendMessage(color("&6Worlds You Are Invited To:")); + for (String world : invited) { + player.sendMessage(color("&e- &f" + world)); + } + } + } + + private void openMainGui(Player player) { + Inventory inv = Bukkit.createInventory(null, normalizeSize(mainGuiSize), mainGuiTitle); + + setConfiguredItem(inv, "generate-normal", player, "GENERATE_NORMAL"); + setConfiguredItem(inv, "generate-flat", player, "GENERATE_FLAT"); + setConfiguredItem(inv, "generate-amplified", player, "GENERATE_AMPLIFIED"); + setConfiguredItem(inv, "list-worlds", player, "LIST_WORLDS"); + setConfiguredItem(inv, "info", player, "INFO"); + + openMenus.put(player.getUniqueId(), new GuiContext("MAIN", new HashMap<>())); + player.openInventory(inv); + } + + private void openListGui(Player player) { + Inventory inv = Bukkit.createInventory(null, normalizeSize(listGuiSize), listGuiTitle); + Map slotWorldMap = new HashMap<>(); + + int slot = 0; + + for (String world : getOwnedWorlds(player.getUniqueId())) { + if (slot >= inv.getSize()) { + break; + } + if (isReservedListSlot(slot, inv.getSize())) { + slot++; + } + if (slot >= inv.getSize()) { + break; + } + + inv.setItem(slot, buildWorldItem(world, true)); + slotWorldMap.put(slot, world); + slot++; + } + + for (String world : getAccessibleInvitedWorlds(player.getUniqueId())) { + if (slot >= inv.getSize()) { + break; + } + if (isReservedListSlot(slot, inv.getSize())) { + slot++; + } + if (slot >= inv.getSize()) { + break; + } + + inv.setItem(slot, buildWorldItem(world, false)); + slotWorldMap.put(slot, world); + slot++; + } + + setListBackButton(inv); + + openMenus.put(player.getUniqueId(), new GuiContext("LIST", slotWorldMap)); + player.openInventory(inv); + } + + private void openManageGui(Player player, String worldName) { + if (!ownsWorld(player.getUniqueId(), worldName)) { + player.sendMessage(msgOnlyOwnWorlds); + return; + } + + Inventory inv = Bukkit.createInventory(null, normalizeSize(manageGuiSize), manageGuiTitle + " - " + worldName); + + setManageItem(inv, "teleport", "TELEPORT:" + worldName, worldName); + setManageItem(inv, "toggle-pvp", "TOGGLE_PVP:" + worldName, worldName); + setManageItem(inv, "invited-info", "INFO:" + worldName, worldName); + setManageItem(inv, "delete-world", "DELETE_WORLD:" + worldName, worldName); + setManageItem(inv, "back", "BACK_TO_LIST", worldName); + + openMenus.put(player.getUniqueId(), new GuiContext("MANAGE", new HashMap<>())); + player.openInventory(inv); + } + + private boolean isReservedListSlot(int slot, int inventorySize) { + ConfigurationSection section = getConfig().getConfigurationSection("gui.list.back-button"); + if (section == null) { + return false; + } + + int backSlot = section.getInt("slot", inventorySize - 1); + return slot == backSlot; + } + + private void setListBackButton(Inventory inv) { + ConfigurationSection section = getConfig().getConfigurationSection("gui.list.back-button"); + if (section == null) { + return; + } + + Material material = Material.matchMaterial(section.getString("material", "ARROW")); + if (material == null) { + material = Material.ARROW; + } + + int slot = section.getInt("slot", inv.getSize() - 1); + if (slot < 0 || slot >= inv.getSize()) { + return; + } + + ItemStack item = new ItemStack(material); + ItemMeta meta = item.getItemMeta(); + + if (meta != null) { + meta.setDisplayName(color(section.getString("name", "&cBack"))); + + List lore = new ArrayList<>(); + for (String line : section.getStringList("lore")) { + lore.add(color(line)); + } + meta.setLore(lore); + meta.getPersistentDataContainer().set(NamespacedKeys.ACTION_KEY, PersistentDataType.STRING, "BACK_TO_MAIN"); + item.setItemMeta(meta); + } + + inv.setItem(slot, item); + } + + private ItemStack buildWorldItem(String worldName, boolean owned) { + Material material = owned ? Material.GRASS_BLOCK : Material.CHEST; + ItemStack item = new ItemStack(material); + ItemMeta meta = item.getItemMeta(); + + if (meta != null) { + UUID owner = getOwnerOfWorld(worldName); + String type = owner != null ? getWorldType(owner, worldName) : "unknown"; + boolean pvp = owner != null && isWorldPvpEnabled(owner, worldName); + + List lore = new ArrayList<>(); + lore.add(color("&7Type: &e" + type)); + lore.add(color("&7PvP: &e" + (pvp ? "ON" : "OFF"))); + lore.add(color(owned ? "&7Click to manage this world." : "&7Click to teleport to this world.")); + + meta.setDisplayName(color((owned ? "&a" : "&b") + worldName)); + meta.setLore(lore); + meta.getPersistentDataContainer().set( + NamespacedKeys.ACTION_KEY, + PersistentDataType.STRING, + owned ? "OPEN_MANAGE:" + worldName : "TELEPORT:" + worldName + ); + item.setItemMeta(meta); + } + + return item; + } + + private void setConfiguredItem(Inventory inv, String key, Player player, String action) { + ConfigurationSection section = getConfig().getConfigurationSection("gui.main.items." + key); + if (section == null) { + return; + } + + String materialName = section.getString("material", "STONE"); + int slot = section.getInt("slot", 0); + String name = section.getString("name", "&fItem"); + List lore = section.getStringList("lore"); + + Material material = Material.matchMaterial(materialName); + if (material == null) { + material = Material.STONE; + } + + ItemStack item = new ItemStack(material); + ItemMeta meta = item.getItemMeta(); + + if (meta != null) { + meta.setDisplayName(color(name)); + + List processedLore = new ArrayList<>(); + int owned = getOwnedWorlds(player.getUniqueId()).size(); + int limit = getWorldLimit(player); + + for (String line : lore) { + processedLore.add(color(line + .replace("%owned%", String.valueOf(owned)) + .replace("%limit%", String.valueOf(limit)))); + } + + meta.setLore(processedLore); + meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); + meta.getPersistentDataContainer().set(NamespacedKeys.ACTION_KEY, PersistentDataType.STRING, action); + item.setItemMeta(meta); + } + + if (slot >= 0 && slot < inv.getSize()) { + inv.setItem(slot, item); + } + } + + private void setManageItem(Inventory inv, String key, String action, String worldName) { + ConfigurationSection section = getConfig().getConfigurationSection("gui.manage.items." + key); + if (section == null) { + return; + } + + String materialName = section.getString("material", "STONE"); + int slot = section.getInt("slot", 0); + String name = section.getString("name", "&fItem"); + List lore = section.getStringList("lore"); + + Material material = Material.matchMaterial(materialName); + if (material == null) { + material = Material.STONE; + } + + UUID owner = getOwnerOfWorld(worldName); + List invites = owner != null ? getInvitedPlayers(owner, worldName) : new ArrayList<>(); + String invitesText = invites.isEmpty() ? "None" : String.join(", ", invites); + + ItemStack item = new ItemStack(material); + ItemMeta meta = item.getItemMeta(); + + if (meta != null) { + meta.setDisplayName(color(name)); + + List processedLore = new ArrayList<>(); + for (String line : lore) { + processedLore.add(color(line.replace("%invites%", invitesText))); + } + + meta.setLore(processedLore); + meta.getPersistentDataContainer().set(NamespacedKeys.ACTION_KEY, PersistentDataType.STRING, action); + item.setItemMeta(meta); + } + + if (slot >= 0 && slot < inv.getSize()) { + inv.setItem(slot, item); + } + } + + private void generateWorld(Player player, String type) { + if (!hasMultiverse()) { + player.sendMessage(msgMultiverseMissing); + return; + } + + if (!isTypeAllowed(type)) { + player.sendMessage(msgInvalidWorldType); + return; + } + + List ownedWorlds = getOwnedWorlds(player.getUniqueId()); + int limit = getWorldLimit(player); + + if (limit <= 0) { + player.sendMessage(msgNoWorldLimit); + return; + } + + if (ownedWorlds.size() >= limit) { + player.sendMessage(msgWorldLimitReached.replace("%limit%", String.valueOf(limit))); + return; + } + + String worldName = getNextWorldName(player, ownedWorlds.size() + 1); + player.sendMessage(msgWorldCreating.replace("%world%", worldName)); + + String command = switch (type) { + case "normal" -> normalCommand; + case "flat" -> flatCommand; + case "amplified" -> amplifiedCommand; + default -> null; + }; + + if (command == null) { + player.sendMessage(msgInvalidWorldType); + return; + } + + boolean success = Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.replace("%world%", worldName)); + + Bukkit.getScheduler().runTaskLater(this, () -> { + World world = Bukkit.getWorld(worldName); + + if (!success || world == null) { + player.sendMessage(msgWorldFailed); + return; + } + + registerOwnedWorld(player.getUniqueId(), worldName, type); + setWorldPvp(player.getUniqueId(), worldName, true); + applyWorldSettings(world, player.getUniqueId(), worldName); + teleportToWorld(player, worldName); + player.sendMessage(msgWorldCreated.replace("%world%", worldName)); + saveDataConfig(); + }, 40L); + } + + private void handleInvite(Player owner, String targetName, String worldName) { + if (!ownsWorld(owner.getUniqueId(), worldName)) { + owner.sendMessage(msgOnlyOwnWorlds); + return; + } + + Player target = Bukkit.getPlayerExact(targetName); + if (target == null) { + owner.sendMessage(msgPlayerNotFound); + return; + } + + if (isInvited(owner.getUniqueId(), worldName, target.getUniqueId())) { + owner.sendMessage(msgAlreadyInvited + .replace("%player%", target.getName()) + .replace("%world%", worldName)); + return; + } + + dataConfig.set("players." + owner.getUniqueId() + ".worlds." + worldName + ".invites." + target.getUniqueId(), target.getName()); + saveDataConfig(); + + owner.sendMessage(msgInvitedPlayer + .replace("%player%", target.getName()) + .replace("%world%", worldName)); + + target.sendMessage(msgYouWereInvited + .replace("%world%", worldName) + .replace("%owner%", owner.getName())); + } + + private void handleUninvite(Player owner, String targetName, String worldName) { + if (!ownsWorld(owner.getUniqueId(), worldName)) { + owner.sendMessage(msgOnlyOwnWorlds); + return; + } + + UUID targetUuid = getInvitedUuidByName(owner.getUniqueId(), worldName, targetName); + if (targetUuid == null) { + owner.sendMessage(msgNotInvited + .replace("%player%", targetName) + .replace("%world%", worldName)); + return; + } + + dataConfig.set("players." + owner.getUniqueId() + ".worlds." + worldName + ".invites." + targetUuid, null); + saveDataConfig(); + + owner.sendMessage(msgUninvitedPlayer + .replace("%player%", targetName) + .replace("%world%", worldName)); + } + + private void handlePvpToggle(Player owner, String worldName, String state) { + if (!ownsWorld(owner.getUniqueId(), worldName)) { + owner.sendMessage(msgOnlyOwnWorlds); + return; + } + + boolean pvp; + if (state.equalsIgnoreCase("on")) { + pvp = true; + } else if (state.equalsIgnoreCase("off")) { + pvp = false; + } else { + owner.sendMessage(msgInvalidPvpState); + return; + } + + setWorldPvp(owner.getUniqueId(), worldName, pvp); + World world = Bukkit.getWorld(worldName); + if (world != null) { + world.setPVP(pvp); + } + saveDataConfig(); + + owner.sendMessage((pvp ? msgPvpEnabled : msgPvpDisabled).replace("%world%", worldName)); + } + + private void handleDeleteWorld(Player owner, String worldName) { + if (!ownsWorld(owner.getUniqueId(), worldName)) { + owner.sendMessage(msgOnlyOwnWorlds); + return; + } + + long now = System.currentTimeMillis(); + long key = Objects.hash(owner.getUniqueId(), worldName); + + Long lastConfirm = deleteConfirmations.get(owner.getUniqueId()); + if (lastConfirm == null || lastConfirm != key) { + deleteConfirmations.put(owner.getUniqueId(), key); + owner.sendMessage(msgConfirmDelete.replace("%world%", worldName)); + return; + } + + deleteConfirmations.remove(owner.getUniqueId()); + + boolean success = Bukkit.dispatchCommand(Bukkit.getConsoleSender(), deleteCommand.replace("%world%", worldName)); + + Bukkit.getScheduler().runTaskLater(this, () -> { + dataConfig.set("players." + owner.getUniqueId() + ".worlds." + worldName, null); + saveDataConfig(); + + World world = Bukkit.getWorld(worldName); + if (world != null) { + Bukkit.unloadWorld(world, false); + } + + if (success) { + owner.sendMessage(msgWorldDeleted.replace("%world%", worldName)); + } else { + owner.sendMessage(msgDeleteFailed.replace("%world%", worldName)); + } + + openListGui(owner); + }, 20L); + } + + private void applyWorldSettings(World world, UUID owner, String worldName) { + WorldBorder border = world.getWorldBorder(); + border.setCenter(0.0, 0.0); + border.setSize(worldBorderSize); + + try { + GameMode.valueOf(defaultGamemode.toUpperCase()); + } catch (IllegalArgumentException ignored) { + } + + world.setGameRule(org.bukkit.GameRule.DO_DAYLIGHT_CYCLE, true); + world.setGameRule(org.bukkit.GameRule.DO_MOB_SPAWNING, true); + world.setGameRule(org.bukkit.GameRule.KEEP_INVENTORY, false); + world.setPVP(isWorldPvpEnabled(owner, worldName)); + + int y = world.getHighestBlockYAt(0, 0) + 1; + world.setSpawnLocation(0, y, 0); + } + + private void teleportToWorld(Player player, String worldName) { + if (!hasAccessToWorld(player.getUniqueId(), worldName)) { + player.sendMessage(msgNoAccessWorld); + return; + } + + World world = Bukkit.getWorld(worldName); + if (world == null) { + player.sendMessage(msgWorldNotFound); + return; + } + + player.teleport(world.getSpawnLocation()); + player.sendMessage(msgTeleported.replace("%world%", worldName)); + } + + private boolean hasAccessToWorld(UUID playerUuid, String worldName) { + UUID owner = getOwnerOfWorld(worldName); + if (owner == null) { + return false; + } + + if (owner.equals(playerUuid)) { + return true; + } + + return isInvited(owner, worldName, playerUuid); + } + + private boolean isTypeAllowed(String type) { + return switch (type.toLowerCase()) { + case "normal" -> allowNormal; + case "flat" -> allowFlat; + case "amplified" -> allowAmplified; + default -> false; + }; + } + + private int getWorldLimit(Player player) { + int highest = noLimitPermissionDefault; + + for (LimitEntry entry : permissionLimits) { + if (player.hasPermission(entry.permission)) { + highest = Math.max(highest, entry.amount); + } + } + + return highest; + } + + private String getNextWorldName(Player player, int number) { + return worldNameFormat + .replace("%player%", sanitizeName(player.getName().toLowerCase())) + .replace("%number%", String.valueOf(number)); + } + + private String sanitizeName(String input) { + return input.replaceAll("[^a-zA-Z0-9_\\-]", ""); + } + + private List getOwnedWorlds(UUID uuid) { + ConfigurationSection section = dataConfig.getConfigurationSection("players." + uuid + ".worlds"); + if (section == null) { + return new ArrayList<>(); + } + return new ArrayList<>(section.getKeys(false)); + } + + private List getAccessibleInvitedWorlds(UUID playerUuid) { + List worlds = new ArrayList<>(); + ConfigurationSection playersSection = dataConfig.getConfigurationSection("players"); + if (playersSection == null) { + return worlds; + } + + for (String ownerKey : playersSection.getKeys(false)) { + ConfigurationSection worldsSection = playersSection.getConfigurationSection(ownerKey + ".worlds"); + if (worldsSection == null) { + continue; + } + + for (String worldName : worldsSection.getKeys(false)) { + if (dataConfig.contains("players." + ownerKey + ".worlds." + worldName + ".invites." + playerUuid)) { + worlds.add(worldName); + } + } + } + + return worlds; + } + + private String getWorldType(UUID uuid, String worldName) { + return dataConfig.getString("players." + uuid + ".worlds." + worldName + ".type", "unknown"); + } + + private boolean ownsWorld(UUID uuid, String worldName) { + return dataConfig.contains("players." + uuid + ".worlds." + worldName); + } + + private void registerOwnedWorld(UUID uuid, String worldName, String type) { + dataConfig.set("players." + uuid + ".worlds." + worldName + ".type", type); + dataConfig.set("players." + uuid + ".worlds." + worldName + ".created-at", System.currentTimeMillis()); + } + + private void setWorldPvp(UUID uuid, String worldName, boolean enabled) { + dataConfig.set("players." + uuid + ".worlds." + worldName + ".pvp", enabled); + } + + private boolean isWorldPvpEnabled(UUID uuid, String worldName) { + return dataConfig.getBoolean("players." + uuid + ".worlds." + worldName + ".pvp", true); + } + + private boolean isInvited(UUID ownerUuid, String worldName, UUID targetUuid) { + return dataConfig.contains("players." + ownerUuid + ".worlds." + worldName + ".invites." + targetUuid); + } + + private UUID getInvitedUuidByName(UUID ownerUuid, String worldName, String playerName) { + ConfigurationSection section = dataConfig.getConfigurationSection("players." + ownerUuid + ".worlds." + worldName + ".invites"); + if (section == null) { + return null; + } + + for (String uuidString : section.getKeys(false)) { + String storedName = section.getString(uuidString, ""); + if (storedName.equalsIgnoreCase(playerName)) { + try { + return UUID.fromString(uuidString); + } catch (IllegalArgumentException ignored) { + } + } + } + + return null; + } + + private List getInvitedPlayers(UUID ownerUuid, String worldName) { + ConfigurationSection section = dataConfig.getConfigurationSection("players." + ownerUuid + ".worlds." + worldName + ".invites"); + if (section == null) { + return new ArrayList<>(); + } + + List names = new ArrayList<>(); + for (String uuid : section.getKeys(false)) { + names.add(section.getString(uuid, uuid)); + } + return names; + } + + private UUID getOwnerOfWorld(String worldName) { + ConfigurationSection playersSection = dataConfig.getConfigurationSection("players"); + if (playersSection == null) { + return null; + } + + for (String ownerKey : playersSection.getKeys(false)) { + if (dataConfig.contains("players." + ownerKey + ".worlds." + worldName)) { + try { + return UUID.fromString(ownerKey); + } catch (IllegalArgumentException ignored) { + return null; + } + } + } + + return null; + } + + private int normalizeSize(int size) { + if (size < 9) { + return 9; + } + if (size > 54) { + return 54; + } + return ((size + 8) / 9) * 9; + } + + private String color(String input) { + return input == null ? "" : ChatColor.translateAlternateColorCodes('&', input); + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + if (!(event.getWhoClicked() instanceof Player player)) { + return; + } + + GuiContext context = openMenus.get(player.getUniqueId()); + if (context == null) { + return; + } + + String title = event.getView().getTitle(); + if (!title.startsWith(mainGuiTitle) && !title.startsWith(listGuiTitle) && !title.startsWith(manageGuiTitle)) { + return; + } + + event.setCancelled(true); + + if (event.getCurrentItem() == null || !event.getCurrentItem().hasItemMeta()) { + return; + } + + ItemMeta meta = event.getCurrentItem().getItemMeta(); + if (meta == null) { + return; + } + + String action = meta.getPersistentDataContainer().get(NamespacedKeys.ACTION_KEY, PersistentDataType.STRING); + if (action == null) { + return; + } + + if (action.equals("GENERATE_NORMAL")) { + generateWorld(player, "normal"); + return; + } + + if (action.equals("GENERATE_FLAT")) { + generateWorld(player, "flat"); + return; + } + + if (action.equals("GENERATE_AMPLIFIED")) { + generateWorld(player, "amplified"); + return; + } + + if (action.equals("LIST_WORLDS")) { + openListGui(player); + return; + } + + if (action.equals("BACK_TO_MAIN")) { + openMainGui(player); + return; + } + + if (action.equals("BACK_TO_LIST")) { + openListGui(player); + return; + } + + if (action.startsWith("OPEN_MANAGE:")) { + openManageGui(player, action.substring("OPEN_MANAGE:".length())); + return; + } + + if (action.startsWith("TELEPORT:")) { + teleportToWorld(player, action.substring("TELEPORT:".length())); + player.closeInventory(); + return; + } + + if (action.startsWith("TOGGLE_PVP:")) { + String worldName = action.substring("TOGGLE_PVP:".length()); + + if (!player.hasPermission("myworlds.pvp")) { + player.sendMessage(msgNoPermission); + return; + } + + if (!ownsWorld(player.getUniqueId(), worldName)) { + player.sendMessage(msgOnlyOwnWorlds); + return; + } + + boolean newState = !isWorldPvpEnabled(player.getUniqueId(), worldName); + setWorldPvp(player.getUniqueId(), worldName, newState); + + World world = Bukkit.getWorld(worldName); + if (world != null) { + world.setPVP(newState); + } + + saveDataConfig(); + player.sendMessage((newState ? msgPvpEnabled : msgPvpDisabled).replace("%world%", worldName)); + openManageGui(player, worldName); + return; + } + + if (action.startsWith("DELETE_WORLD:")) { + handleDeleteWorld(player, action.substring("DELETE_WORLD:".length())); + } + } + + @EventHandler + public void onInventoryClose(InventoryCloseEvent event) { + if (event.getPlayer() instanceof Player player) { + Bukkit.getScheduler().runTaskLater(this, () -> { + String currentTitle = player.getOpenInventory().getTitle(); + if (!currentTitle.startsWith(mainGuiTitle) && + !currentTitle.startsWith(listGuiTitle) && + !currentTitle.startsWith(manageGuiTitle)) { + openMenus.remove(player.getUniqueId()); + } + }, 1L); + } + } + + private static final class GuiContext { + private final String menuType; + private final Map slotWorldMap; + + private GuiContext(String menuType, Map slotWorldMap) { + this.menuType = menuType; + this.slotWorldMap = slotWorldMap; + } + } + + private static final class LimitEntry { + private final String permission; + private final int amount; + + private LimitEntry(String permission, int amount) { + this.permission = permission; + this.amount = amount; + } + } +} diff --git a/src/main/java/com/bitnix/myworlds/NamespacedKeys.java b/src/main/java/com/bitnix/myworlds/NamespacedKeys.java new file mode 100644 index 0000000..9731dcd --- /dev/null +++ b/src/main/java/com/bitnix/myworlds/NamespacedKeys.java @@ -0,0 +1,16 @@ +package com.bitnix.myworlds; + +import org.bukkit.NamespacedKey; +import org.bukkit.plugin.java.JavaPlugin; + +public final class NamespacedKeys { + + public static NamespacedKey ACTION_KEY; + + private NamespacedKeys() { + } + + public static void init(JavaPlugin plugin) { + ACTION_KEY = new NamespacedKey(plugin, "action"); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..19643dc --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,152 @@ +settings: + quick-teleport-single-world: false + world-name-format: "mw_%player%_%number%" + world-border-size: 10000 + default-gamemode: SURVIVAL + no-limit-permission-default: 0 + +multiverse: + normal-command: "mv create %world% normal" + flat-command: "mv create %world% normal -t flat" + amplified-command: "mv create %world% normal -a true" + delete-command: "mv delete %world%" + +limits: + - permission: "myworlds.limit.1" + amount: 1 + - permission: "myworlds.limit.2" + amount: 2 + - permission: "myworlds.limit.3" + amount: 3 + - permission: "myworlds.limit.5" + amount: 5 + +world-types: + normal: true + flat: true + amplified: true + +messages: + no-permission: "&cYou do not have permission." + player-only: "&cOnly players can use this command." + reloaded: "&aMyWorlds config reloaded." + no-worlds: "&cYou do not own any worlds yet." + world-limit-reached: "&cYou have reached your world limit of &e%limit%&c." + no-world-limit: "&cYou are not allowed to create any worlds." + invalid-world-type: "&cInvalid world type." + world-creating: "&eCreating your world: &f%world%&e..." + world-created: "&aWorld created: &e%world%&a." + world-failed: "&cFailed to create world." + world-not-found: "&cThat world could not be found." + teleported: "&aTeleported to &e%world%&a." + only-own-worlds: "&cYou can only manage your own worlds." + no-access-world: "&cYou do not have access to that world." + multiverse-missing: "&cMultiverse-Core was not found or is not enabled." + player-not-found: "&cThat player is not online." + invited-player: "&aInvited &e%player% &ato world &e%world%&a." + uninvited-player: "&e%player% &chas been removed from world &e%world%&c." + you-were-invited: "&aYou were invited to world &e%world% &aby &e%owner%&a." + already-invited: "&e%player% &cis already invited to &e%world%&c." + not-invited: "&e%player% &cis not invited to &e%world%&c." + pvp-enabled: "&aPvP enabled for &e%world%&a." + pvp-disabled: "&cPvP disabled for &e%world%&c." + invalid-pvp-state: "&cUse on/off." + world-deleted: "&cWorld deleted: &e%world%&c." + delete-failed: "&cFailed to delete world &e%world%&c." + confirm-delete: "&cClick again to confirm deletion of &e%world%&c." + world-info-owner: "&7Owner: &e%owner%" + world-info-type: "&7Type: &e%type%" + world-info-pvp: "&7PvP: &e%pvp%" + world-info-invites: "&7Invited: &e%invites%" + +gui: + main: + title: "&8My Worlds" + size: 27 + items: + generate-normal: + material: GRASS_BLOCK + slot: 10 + name: "&aGenerate Normal World" + lore: + - "&7Create a standard world." + + generate-flat: + material: DIRT + slot: 12 + name: "&eGenerate Flat World" + lore: + - "&7Create a flat world." + + generate-amplified: + material: STONE + slot: 14 + name: "&bGenerate Amplified World" + lore: + - "&7Create an amplified world." + + list-worlds: + material: CHEST + slot: 16 + name: "&fYour Worlds" + lore: + - "&7Click to view your worlds." + + info: + material: BOOK + slot: 22 + name: "&6World Info" + lore: + - "&7Owned: &e%owned%" + - "&7Limit: &e%limit%" + + list: + title: "&8Your Worlds" + size: 54 + back-button: + material: ARROW + slot: 53 + name: "&cBack" + lore: + - "&7Return to main menu." + + manage: + title: "&8Manage World" + size: 27 + items: + teleport: + material: ENDER_PEARL + slot: 11 + name: "&aTeleport" + lore: + - "&7Teleport to this world." + + toggle-pvp: + material: DIAMOND_SWORD + slot: 13 + name: "&cToggle PvP" + lore: + - "&7Toggle PvP for this world." + + invited-info: + material: PLAYER_HEAD + slot: 15 + name: "&eInvites" + lore: + - "&7Invited players:" + - "&f%invites%" + + delete-world: + material: BARRIER + slot: 22 + name: "&4Delete World" + lore: + - "&7Delete this world." + - "&cThis cannot be undone." + + back: + material: ARROW + slot: 26 + name: "&cBack" + lore: + - "&7Return to world list." diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..0ea501b --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,20 @@ +name: MyWorlds +version: 1.1 +main: com.bitnix.myworlds.MyWorldsPlugin +api-version: '1.21' +author: bitnix +description: GUI-based personal world manager using Multiverse-Core. +commands: + myworlds: + description: Open your worlds GUI or manage your worlds + usage: /myworlds [help|list|generate|invite|uninvite|pvp|reload] + aliases: [myworld, mw] +permissions: + myworlds.use: + default: false + myworlds.admin: + default: op + myworlds.invite: + default: false + myworlds.pvp: + default: false diff --git a/target/MyWorlds.jar b/target/MyWorlds.jar new file mode 100644 index 0000000..02d8a1c Binary files /dev/null and b/target/MyWorlds.jar differ diff --git a/target/classes/com/bitnix/myworlds/MyWorldsPlugin$GuiContext.class b/target/classes/com/bitnix/myworlds/MyWorldsPlugin$GuiContext.class new file mode 100644 index 0000000..6dc764c Binary files /dev/null and b/target/classes/com/bitnix/myworlds/MyWorldsPlugin$GuiContext.class differ diff --git a/target/classes/com/bitnix/myworlds/MyWorldsPlugin$LimitEntry.class b/target/classes/com/bitnix/myworlds/MyWorldsPlugin$LimitEntry.class new file mode 100644 index 0000000..ebae9d4 Binary files /dev/null and b/target/classes/com/bitnix/myworlds/MyWorldsPlugin$LimitEntry.class differ diff --git a/target/classes/com/bitnix/myworlds/MyWorldsPlugin.class b/target/classes/com/bitnix/myworlds/MyWorldsPlugin.class new file mode 100644 index 0000000..650d7b2 Binary files /dev/null and b/target/classes/com/bitnix/myworlds/MyWorldsPlugin.class differ diff --git a/target/classes/com/bitnix/myworlds/NamespacedKeys.class b/target/classes/com/bitnix/myworlds/NamespacedKeys.class new file mode 100644 index 0000000..4a493c0 Binary files /dev/null and b/target/classes/com/bitnix/myworlds/NamespacedKeys.class differ diff --git a/target/classes/config.yml b/target/classes/config.yml new file mode 100644 index 0000000..19643dc --- /dev/null +++ b/target/classes/config.yml @@ -0,0 +1,152 @@ +settings: + quick-teleport-single-world: false + world-name-format: "mw_%player%_%number%" + world-border-size: 10000 + default-gamemode: SURVIVAL + no-limit-permission-default: 0 + +multiverse: + normal-command: "mv create %world% normal" + flat-command: "mv create %world% normal -t flat" + amplified-command: "mv create %world% normal -a true" + delete-command: "mv delete %world%" + +limits: + - permission: "myworlds.limit.1" + amount: 1 + - permission: "myworlds.limit.2" + amount: 2 + - permission: "myworlds.limit.3" + amount: 3 + - permission: "myworlds.limit.5" + amount: 5 + +world-types: + normal: true + flat: true + amplified: true + +messages: + no-permission: "&cYou do not have permission." + player-only: "&cOnly players can use this command." + reloaded: "&aMyWorlds config reloaded." + no-worlds: "&cYou do not own any worlds yet." + world-limit-reached: "&cYou have reached your world limit of &e%limit%&c." + no-world-limit: "&cYou are not allowed to create any worlds." + invalid-world-type: "&cInvalid world type." + world-creating: "&eCreating your world: &f%world%&e..." + world-created: "&aWorld created: &e%world%&a." + world-failed: "&cFailed to create world." + world-not-found: "&cThat world could not be found." + teleported: "&aTeleported to &e%world%&a." + only-own-worlds: "&cYou can only manage your own worlds." + no-access-world: "&cYou do not have access to that world." + multiverse-missing: "&cMultiverse-Core was not found or is not enabled." + player-not-found: "&cThat player is not online." + invited-player: "&aInvited &e%player% &ato world &e%world%&a." + uninvited-player: "&e%player% &chas been removed from world &e%world%&c." + you-were-invited: "&aYou were invited to world &e%world% &aby &e%owner%&a." + already-invited: "&e%player% &cis already invited to &e%world%&c." + not-invited: "&e%player% &cis not invited to &e%world%&c." + pvp-enabled: "&aPvP enabled for &e%world%&a." + pvp-disabled: "&cPvP disabled for &e%world%&c." + invalid-pvp-state: "&cUse on/off." + world-deleted: "&cWorld deleted: &e%world%&c." + delete-failed: "&cFailed to delete world &e%world%&c." + confirm-delete: "&cClick again to confirm deletion of &e%world%&c." + world-info-owner: "&7Owner: &e%owner%" + world-info-type: "&7Type: &e%type%" + world-info-pvp: "&7PvP: &e%pvp%" + world-info-invites: "&7Invited: &e%invites%" + +gui: + main: + title: "&8My Worlds" + size: 27 + items: + generate-normal: + material: GRASS_BLOCK + slot: 10 + name: "&aGenerate Normal World" + lore: + - "&7Create a standard world." + + generate-flat: + material: DIRT + slot: 12 + name: "&eGenerate Flat World" + lore: + - "&7Create a flat world." + + generate-amplified: + material: STONE + slot: 14 + name: "&bGenerate Amplified World" + lore: + - "&7Create an amplified world." + + list-worlds: + material: CHEST + slot: 16 + name: "&fYour Worlds" + lore: + - "&7Click to view your worlds." + + info: + material: BOOK + slot: 22 + name: "&6World Info" + lore: + - "&7Owned: &e%owned%" + - "&7Limit: &e%limit%" + + list: + title: "&8Your Worlds" + size: 54 + back-button: + material: ARROW + slot: 53 + name: "&cBack" + lore: + - "&7Return to main menu." + + manage: + title: "&8Manage World" + size: 27 + items: + teleport: + material: ENDER_PEARL + slot: 11 + name: "&aTeleport" + lore: + - "&7Teleport to this world." + + toggle-pvp: + material: DIAMOND_SWORD + slot: 13 + name: "&cToggle PvP" + lore: + - "&7Toggle PvP for this world." + + invited-info: + material: PLAYER_HEAD + slot: 15 + name: "&eInvites" + lore: + - "&7Invited players:" + - "&f%invites%" + + delete-world: + material: BARRIER + slot: 22 + name: "&4Delete World" + lore: + - "&7Delete this world." + - "&cThis cannot be undone." + + back: + material: ARROW + slot: 26 + name: "&cBack" + lore: + - "&7Return to world list." diff --git a/target/classes/plugin.yml b/target/classes/plugin.yml new file mode 100644 index 0000000..0ea501b --- /dev/null +++ b/target/classes/plugin.yml @@ -0,0 +1,20 @@ +name: MyWorlds +version: 1.1 +main: com.bitnix.myworlds.MyWorldsPlugin +api-version: '1.21' +author: bitnix +description: GUI-based personal world manager using Multiverse-Core. +commands: + myworlds: + description: Open your worlds GUI or manage your worlds + usage: /myworlds [help|list|generate|invite|uninvite|pvp|reload] + aliases: [myworld, mw] +permissions: + myworlds.use: + default: false + myworlds.admin: + default: op + myworlds.invite: + default: false + myworlds.pvp: + default: false diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties new file mode 100644 index 0000000..f71fb98 --- /dev/null +++ b/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Sun Jun 07 23:20:08 EDT 2026 +artifactId=MyWorlds +groupId=com.bitnix +version=1.0 diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..fff20d0 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,4 @@ +com/bitnix/myworlds/MyWorldsPlugin$GuiContext.class +com/bitnix/myworlds/MyWorldsPlugin$LimitEntry.class +com/bitnix/myworlds/MyWorldsPlugin.class +com/bitnix/myworlds/NamespacedKeys.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..d2c57ab --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,2 @@ +/home/bitnix/Desktop/MyWorlds/src/main/java/com/bitnix/myworlds/MyWorldsPlugin.java +/home/bitnix/Desktop/MyWorlds/src/main/java/com/bitnix/myworlds/NamespacedKeys.java