diff --git a/config.yml b/config.yml index 8c86157..dfcdd81 100644 --- a/config.yml +++ b/config.yml @@ -1,3 +1,22 @@ +messages: + player_cleared: "Player {player} cleared!" + players_cleared: "Players cleared!" + reload_start: "Starting reloading..." + reload_complete: "Configuration reloaded!" + reload_pastebin_start: "Starting loading from pastebin..." + reload_pastebin_complete: "Rules was loaded!" + insufficient_permissions: "§cInsufficient permissions!" + player_not_found: "§cPlayer {player} not found" + invalid_sound_name: "Sound {sound} is invalid..." + wrong_usage: "Open rules - /rules " + wrong_usage_accept: "§cWrong usage: /rules -accept " + wrong_usage_status: "§cWrong usage: /rules -status " + prevent_while_sleeping: "§cYou cannot use this while sleeping." + player_accept_added: "§aPlayer {player} has been added to people having accepted the rules!" + player_accept_already: "§cPlayer {player} has already accepted the rules!" + player_status_accepted: "§6Player {player} has §a§laccepted§6 the rules." + player_status_not_yet: "§6Player {player} has §lnot yet§6 accepted the rules." + items: '1': id: BOOK @@ -49,8 +68,6 @@ items: - 'pastebin: pLgFRfeG' # Item will be enchanted ench: true - - inventory: name: '&0Rules' @@ -64,18 +81,27 @@ accept: slot: 21 id: EMERALD_BLOCK name: '&aAgree' + lore: + - '&eClick to accept' # Deny button deny: slot: 23 id: REDSTONE_BLOCK name: '&cDisagree' - + lore: + - '&eClick to refuse' # When player joins the server, he must click 'Agree' in rules inventory # He will not be able to close menu and play on server until he accept the rules useConfirmation: true +# When player refuses the server rules... +kickPlayerWhenRefuse: true +closeInventoryWhenRefuse: false +# (Could be useful, for example, for plugins implementing the Rules' events +# to put the player in a jail, and give him the exempt permission) + # If true, menu will be opened not on join but on login or register authmeHook: true @@ -87,14 +113,13 @@ kickMessage: '&cYou must agree with terms!' # For 1.8: LEVEL_UP acceptSound: ENTITY_PLAYER_LEVELUP +acceptSoundVolume: 1.0 +acceptSoundPitch: 1.0 + +denySound: ENTITY_BAT_DEATH +denySoundVolume: 1.0 +denySoundPitch: 0.2 # Which commands player can use when he has not agree with rules # It makes no sense because he unable to close inventory, but still allowedCommands: [] - - - - - - - diff --git a/plugin.yml b/plugin.yml index b2b7779..5aab25f 100644 --- a/plugin.yml +++ b/plugin.yml @@ -1,6 +1,43 @@ name: Rules -main: clusterstorm.rules.Rules -version: 1.0 +description: Agree with rules before playing on server. +version: 1.1 + author: ClusterStorm +contributors: [ arboriginal ] +website: https://www.spigotmc.org/resources/rules.56584/ +dev-url: https://github.com/KlasterStormInc/Rules + +main: clusterstorm.rules.Rules +depend: [ ] +softdepend: [ authme ] + commands: - rules: \ No newline at end of file + rules: + description: Main command of Rules plugin + permission: rules.rules + +permissions: + rules.*: + description: Gives all plugin permissions + default: op + children: + rules.rules: true + rules.rules.others: true + rules.rules.options: true + rules.rules.exempt: true + + rules.rules: + description: Open rules menu + default: true + + rules.rules.others: + description: Open rules menu for other player + default: op + + rules.rules.options: + description: Allows to use reload and clear options + default: op + + rules.rules.exempt: + description: Be exempted to accept the rules to play + default: op diff --git a/src/clusterstorm/rules/MenuManager.java b/src/clusterstorm/rules/MenuManager.java index 218966b..020790f 100644 --- a/src/clusterstorm/rules/MenuManager.java +++ b/src/clusterstorm/rules/MenuManager.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; - import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -19,25 +18,25 @@ public class MenuManager { Inventory i, c; int accept, deny; - - String kickMessage; + public MenuManager() { reload(); } public void reload() { - if(i != null) i.clear(); - if(c != null) c.clear(); - - FileConfiguration c = Rules.getInstance().getConfig(); - String name = c.getString("inventory.name", "Rules").replace("&", "§"); - kickMessage = c.getString("kickMessage", "Disconnected").replace("&", "§"); - - this.i = Bukkit.createInventory(null, c.getInt("inventory.simpleMenuRows") * 9, name); - this.c = Bukkit.createInventory(null, c.getInt("inventory.comfirmMenuRows") * 9, name); + FileConfiguration config = Rules.getInstance().getConfig(); + String name = config.getString("inventory.name", "Rules").replace("&", "§"); + // Only recreate the inventory if not already set, prevent existing opened inventory to be empty after reload + if (i == null) + i = Bukkit.createInventory(null, config.getInt("inventory.simpleMenuRows") * 9, name); + else i.clear(); + // Only recreate the inventory if not already set, prevent existing opened inventory to be empty after reload + if (c == null) + c = Bukkit.createInventory(null, config.getInt("inventory.comfirmMenuRows") * 9, name); + else c.clear(); - ConfigurationSection sec = c.getConfigurationSection("items"); + ConfigurationSection sec = config.getConfigurationSection("items"); if(sec != null) { Set keys = sec.getKeys(false); @@ -46,9 +45,9 @@ public void reload() { int lastSlot = 0; for (String key : keys) { - ItemStack item = deserialize(c, "items." + key); + ItemStack item = deserialize(config, "items." + key); if(item == null) continue; - int slot = c.getInt("items." + key + ".slot", lastSlot++); + int slot = config.getInt("items." + key + ".slot", lastSlot++); this.i.setItem(slot, item); this.c.setItem(slot, item); @@ -56,13 +55,13 @@ public void reload() { } } - ItemStack a = deserialize(c, "accept"); - accept = c.getInt("accept.slot", 21); - this.c.setItem(accept, a); + ItemStack a = deserialize(config, "accept"); + accept = config.getInt("accept.slot", config.getInt("accept.slot")); + c.setItem(accept, a); - a = deserialize(c, "deny"); - deny = c.getInt("accept.deny", 23); - this.c.setItem(deny, a); + a = deserialize(config, "deny"); + deny = config.getInt("accept.deny", config.getInt("deny.slot")); + c.setItem(deny, a); } @@ -78,24 +77,41 @@ public void accept(Player p) { String player = p.getName(); if(Rules.players().hasPlayer(player)) return; - Rules.players().writePlayer(player); - if(Rules.sound != null) p.playSound(p.getLocation(), Rules.sound, 1, 1); - p.closeInventory(); + RulesConfirmedEvent event = new RulesConfirmedEvent(p); + Bukkit.getPluginManager().callEvent(event); - Bukkit.getPluginManager().callEvent(new RulesConfirmedEvent(p)); + if (event.isCancelled()) return; + + Rules.players().writePlayer(player); + Rules.getInstance().playSound(p, "accept"); + p.closeInventory(); } public void deny(Player p) { String player = p.getName(); if(Rules.players().hasPlayer(player)) return; + + RulesRefusedEvent event = new RulesRefusedEvent(p); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) return; - Bukkit.getScheduler().scheduleSyncDelayedTask(Rules.getInstance(), new Runnable() { - - @Override - public void run() { - p.kickPlayer(kickMessage); - } - }); + if (Rules.getInstance().getConfig().getBoolean("kickPlayerWhenRefuse")) { + Bukkit.getScheduler().scheduleSyncDelayedTask(Rules.getInstance(), new Runnable() { + @Override + public void run() { + p.kickPlayer(Rules.getInstance().getConfig().getString("kickMessage", "Disconnected").replace("&", "§")); + } + }); + + return; + } + + Rules.getInstance().playSound(p, "deny"); + + if (Rules.getInstance().getConfig().getBoolean("closeInventoryWhenRefuse")) { + p.closeInventory(); // Because a plugin using the API can have given the permission exempt (and place the user in a jail) + } } @@ -133,7 +149,7 @@ private ItemStack deserialize(FileConfiguration c, String section) { try { List payload = Rules.pastebin().getList(pastebin); for (String p : payload) { - lorez.add("§7" + p.replace("&", "\u00a7")); + lorez.add("§7" + p.replace("&", "\u00a7")); } continue; } catch (Exception e) { @@ -142,7 +158,7 @@ private ItemStack deserialize(FileConfiguration c, String section) { } } - lorez.add("§7" + l.replace("&", "\u00a7")); + lorez.add("§7" + l.replace("&", "\u00a7")); } meta.setLore(lorez); } diff --git a/src/clusterstorm/rules/Players.java b/src/clusterstorm/rules/Players.java index 7a028f2..44fbce3 100644 --- a/src/clusterstorm/rules/Players.java +++ b/src/clusterstorm/rules/Players.java @@ -41,12 +41,21 @@ public void writePlayer(String player) { c.set("players", players); save(); } - - public void clear() { - players.clear(); - c.set("players", null); - save(); - } + + public void clear() { + players.clear(); + c.set("players", null); + save(); + } + + public boolean clear(String player) { + player = player.toLowerCase(); + if(!players.contains(player)) return false; + players.remove(player); + c.set("players", players); + save(); + return true; + } private void save() { try { diff --git a/src/clusterstorm/rules/Rules.java b/src/clusterstorm/rules/Rules.java index 6f6ff06..bb2e878 100644 --- a/src/clusterstorm/rules/Rules.java +++ b/src/clusterstorm/rules/Rules.java @@ -2,8 +2,9 @@ import java.io.File; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; - +import java.util.Map; import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.command.PluginCommand; @@ -28,7 +29,6 @@ public class Rules extends JavaPlugin implements Listener { private static Rules instance; - public static Sound sound; private MenuManager menu; private Pastebin pastebin; private Players players; @@ -36,6 +36,7 @@ public class Rules extends JavaPlugin implements Listener { private boolean useConfirmation; private List allowedCommands; + private Map sounds = new HashMap(); @Override public void onEnable() { @@ -49,11 +50,10 @@ public void onEnable() { useConfirmation = getConfig().getBoolean("useConfirmation", true); allowedCommands = getConfig().getStringList("allowedCommands"); - try { - sound = Sound.valueOf(getConfig().getString("acceptSound")); - } catch (Exception e) { - sound = null; - } + + registerSound("accept"); + registerSound("deny"); + if(allowedCommands == null) allowedCommands = new ArrayList<>(); pastebin = new Pastebin(); @@ -86,11 +86,8 @@ public void reload() { useConfirmation = getConfig().getBoolean("useConfirmation", true); allowedCommands = getConfig().getStringList("allowedCommands"); if(allowedCommands == null) allowedCommands = new ArrayList<>(); - try { - sound = Sound.valueOf(getConfig().getString("acceptSound")); - } catch (Exception e) { - sound = null; - } + registerSound("accept"); + registerSound("deny"); reloadConfig(); menu.reload(); } @@ -154,9 +151,7 @@ public void run() { } public void performJoin(Player p) { - if(!useConfirmation) return; - - if(players.hasPlayer(p.getName())) return; + if(!useConfirmation || !shouldCancel(p)) return; Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { @@ -171,7 +166,7 @@ public void run() { @EventHandler public void onClose(InventoryCloseEvent e) { if(e.getInventory() == null) return; - if(e.getInventory().equals(menu.c) && !players.hasPlayer(e.getPlayer().getName())) { + if(e.getInventory().equals(menu.c) && shouldCancel((Player) e.getPlayer())) { Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { @Override @@ -200,12 +195,39 @@ public static Players players() { return instance.players; } + private void registerSound(String key) { + key += "Sound"; + + if (sounds.containsKey(key)) sounds.remove(key); + + String soundName = getConfig().getString(key); + + if (soundName.isEmpty()) return; + + try { + sounds.put(key, Sound.valueOf(soundName)); + } + catch (Exception e) { + getLogger().warning(getConfig().getString("messages.invalid_sound_name").replace("{sound}", soundName)); + } + } + + public void playSound(Player player, String key) { + key += "Sound"; + + if(!sounds.containsKey(key)) return; + + player.playSound(player.getLocation(), sounds.get(key), + (float) getConfig().getDouble(key + "Volume"), + (float) getConfig().getDouble(key + "Pitch")); + } + private boolean shouldCancel(Player p) { - return !players.hasPlayer(p.getName()); + return !p.hasPermission("rules.exempt") && !players.hasPlayer(p.getName()); } diff --git a/src/clusterstorm/rules/RulesCommand.java b/src/clusterstorm/rules/RulesCommand.java index ff59e23..d49edc5 100644 --- a/src/clusterstorm/rules/RulesCommand.java +++ b/src/clusterstorm/rules/RulesCommand.java @@ -4,27 +4,80 @@ 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.Player; public class RulesCommand implements CommandExecutor { - public static final String prefix = "§2§lRules §3> §f"; + public static final String prefix = "§2§lRules §3> §f"; @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { + FileConfiguration config = Rules.getInstance().getConfig(); + if(args.length > 0 && sender.hasPermission("rules.options")) { - if(args[0].equalsIgnoreCase("-rl")) { - sender.sendMessage(prefix + "Starting reloading..."); - Rules.getInstance().reload(); - sender.sendMessage(prefix + "Configuration reloaded!"); - return true; - } + if(args[0].equalsIgnoreCase("-rl")) { + sender.sendMessage(prefix + config.getString("messages.reload_start")); + Rules.getInstance().reload(); + sender.sendMessage(prefix + config.getString("messages.reload_complete")); + return true; + } + + if(args[0].equalsIgnoreCase("-status")) { + if (args.length == 2) { + sender.sendMessage(prefix + config.getString("messages.player_status_" + (Rules.players().hasPlayer(args[1])? "accepted": "not_yet")).replace("{player}", args[1])); + return true; + } + + sender.sendMessage(prefix + config.getString("messages.wrong_usage_status")); + return false; + } + + if(args[0].equalsIgnoreCase("-accept")) { + if (args.length == 2) { + if (Rules.players().hasPlayer(args[1])) { + sender.sendMessage(prefix + config.getString("messages.player_accept_already").replace("{player}", args[1])); + return false; + } + + Rules.players().writePlayer(args[1]); + sender.sendMessage(prefix + config.getString("messages.player_accept_added").replace("{player}", args[1])); + return true; + } + + sender.sendMessage(prefix + config.getString("messages.wrong_usage_accept")); + return false; + } if(args[0].equalsIgnoreCase("-clear")) { - Rules.players().clear(); - sender.sendMessage(prefix + "Players cleared!"); - return true; + if (args.length == 2) { + if (Rules.players().hasPlayer(args[1])) { + Rules.players().clear(args[1]); + sender.sendMessage(prefix + config.getString("messages.player_cleared").replace("{player}", args[1])); + + Player p = Bukkit.getPlayerExact(args[1]); + if (p != null && p.isOnline()) { + Rules.menu().openConfirm(p); + } + + return true; + }; + + sender.sendMessage(prefix + config.getString("messages.player_status_not_yet").replace("{player}", args[1])); + return false; + } + else { + Rules.players().clear(); + sender.sendMessage(prefix + config.getString("messages.players_cleared")); + + for (Player p:Bukkit.getOnlinePlayers()) { + if (!Rules.players().hasPlayer(p.getName())) { + Rules.menu().openConfirm(p); + } + } + return true; + } } if(args[0].equalsIgnoreCase("-reload")) { @@ -32,10 +85,10 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String @Override public void run() { - sender.sendMessage(prefix + "Starting loading from pastebin..."); + sender.sendMessage(prefix + config.getString("messages.reload_pastebin_start")); Rules.pastebin().reload(); Rules.getInstance().reload(); - sender.sendMessage(prefix + "Rules was loaded!"); + sender.sendMessage(prefix + config.getString("messages.reload_pastebin_complete")); } }); return true; @@ -43,7 +96,7 @@ public void run() { } if(!sender.hasPermission("rules.rules")) { - sender.sendMessage("§cInsufficient permissions!"); + sender.sendMessage(config.getString("messages.insufficient_permissions")); return true; } @@ -52,15 +105,20 @@ public void run() { { p = Bukkit.getPlayerExact(args[0]); if(p == null) { - sender.sendMessage(prefix + "Player " + args[0] + " not found"); + sender.sendMessage(prefix + config.getString("messages.player_not_found").replace("{player}", args[0])); return true; } } else { if(sender instanceof Player) p = (Player) sender; else { - sender.sendMessage(prefix + "Open rules - /rules "); + sender.sendMessage(prefix + config.getString("messages.wrong_usage")); return true; } + // Because if in a bed the player can drag and drop items into his inventory... + if (p.isSleeping()) { + sender.sendMessage(config.getString("messages.prevent_while_sleeping")); + return false; + } } Rules.menu().openRules(p); diff --git a/src/clusterstorm/rules/RulesConfirmedEvent.java b/src/clusterstorm/rules/RulesConfirmedEvent.java index 5ff7a01..c3c004e 100644 --- a/src/clusterstorm/rules/RulesConfirmedEvent.java +++ b/src/clusterstorm/rules/RulesConfirmedEvent.java @@ -1,12 +1,14 @@ package clusterstorm.rules; import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -public final class RulesConfirmedEvent extends Event { +public final class RulesConfirmedEvent extends Event implements Cancellable { private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; private Player player; public RulesConfirmedEvent(Player player) { @@ -24,4 +26,14 @@ public HandlerList getHandlers() { public static HandlerList getHandlerList() { return handlers; } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } } diff --git a/src/clusterstorm/rules/RulesRefusedEvent.java b/src/clusterstorm/rules/RulesRefusedEvent.java new file mode 100644 index 0000000..1bfc155 --- /dev/null +++ b/src/clusterstorm/rules/RulesRefusedEvent.java @@ -0,0 +1,39 @@ +package clusterstorm.rules; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public final class RulesRefusedEvent extends Event implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private Player player; + + public RulesRefusedEvent(Player player) { + this.player = player; + } + + public Player getPlayer() { + return player; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } +}