--- /dev/null
+#!/bin/bash
+if [ -d bin/no ]; then
+ rm -r bin/no 2>/dev/null
+fi
+
+if [ ! -d bin/ ]; then
+ mkdir bin 2>/dev/null
+fi
+
+rm YAVote*.jar 2>/dev/null
+
+javac -Werror -Xlint -d bin -s src -sourcepath src -cp .:src:bukkit-1.2.3-R0.2.jar src/no/defcon/yavote/YAVote.java
+EX=$?
+if [ $EX -ne 0 ]; then
+ echo Error in build.
+ exit $EX
+fi
+jar -cf YAVote.jar -C bin . plugin.yml todo.txt
--- /dev/null
+name: YAVote\r
+main: no.defcon.yavote.YAVote\r
+version: 1.4\r
+description: Yet Another Vote plugin for Bukkit\r
+website: http://minecraft.defcon.no/yavote\r
+authors:\r
+ - Jon Langseth\r
+commands:\r
+ vote:\r
+ description: Start or take part in a vote\r
+ usage: |\r
+ /<command> [parameter]\r
+ /<command> sun - Vote for fine weather\r
+ /<command> rain - Vote for rainy weather\r
+ /<command> day - Vote to set the time to morning\r
+ /<command> night - Vote to set the time to night\r
+ /<command> yes|no - Respond positive or negative to current vote\r
+ /<command> status - Return status of current vote\r
+ /<command> cancel - Cancel a running vote.\r
+permissions:\r
+ vote.weather.start:\r
+ description: Gives access to starting new votes for sun/rain\r
+ vote.weather.respond:\r
+ description: Gives access to responding to a started sun/rain vote\r
+ vote.time.start:\r
+ description: Gives access to starting a vote for day/night\r
+ vote.time.respond:\r
+ description: Gives access to responding to a started nay/night vote\r
+ vote.cancel:\r
+ description: Gives access to immediately canceling a running vote\r
+ vote.status:\r
+ description: Gives access to information on running vote\r
+ vote.weather.*:\r
+ description: Gives vote.weather.start and .respond\r
+ children:\r
+ vote.weather.start: true \r
+ vote.weather.respond: true \r
+ vote.time.*:\r
+ description: Gives vote.time.start and .respond \r
+ children:\r
+ vote.time.start: true \r
+ vote.time.respond: true \r
+ vote.*:\r
+ description: Gives access to all vote commands/options.\r
+ children:\r
+ vote.time.*: true\r
+ vote.weather.*: true\r
+ vote.cancel: true\r
+ vote.status: true
\ No newline at end of file
--- /dev/null
+package no.defcon.yavote;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.bukkit.World;\r
+import org.bukkit.entity.Player;\r
+import org.bukkit.plugin.java.JavaPlugin;\r
+\r
+public class Votemanager {\r
+ private JavaPlugin plugin;\r
+ private boolean voteRunning;\r
+ private String voteType;\r
+ private int expireTask;\r
+ private List<String> yesVoters;\r
+ private List<String> noVoters;\r
+ \r
+ \r
+ public Votemanager(JavaPlugin plugin) {\r
+ super();\r
+ this.plugin = plugin;\r
+ this.voteRunning = false;\r
+ }\r
+ \r
+ public boolean cancelVote( )\r
+ {\r
+ if ( voteRunning )\r
+ {\r
+ plugin.getServer().broadcastMessage("Currently running vote is being canceled."); \r
+ plugin.getServer().getScheduler().cancelTask(expireTask);\r
+ clearState();\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public boolean startVote( String type, Player p )\r
+ {\r
+ if ( this.voteRunning )\r
+ return false;\r
+ \r
+ if ( ! (type.equalsIgnoreCase("sun") ||\r
+ type.equalsIgnoreCase("rain") ||\r
+ type.equalsIgnoreCase("day") ||\r
+ type.equalsIgnoreCase("night") ))\r
+ {\r
+ plugin.getLogger().info("Tried to start a vote of invalid type. Code error!");\r
+ return false;\r
+ }\r
+ \r
+ voteType = type;\r
+ voteRunning = true;\r
+ \r
+ if ( yesVoters == null )\r
+ yesVoters = new ArrayList<String>();\r
+ else\r
+ yesVoters.clear();\r
+\r
+ if ( noVoters == null )\r
+ noVoters = new ArrayList<String>();\r
+ else\r
+ noVoters.clear();\r
+\r
+ yesVoters.add(p.getName());\r
+\r
+ if ( checkRatio( ) )\r
+ {\r
+ applyVote( voteType );\r
+ return true;\r
+ }\r
+ \r
+ expireTask = plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, new Runnable(){\r
+ @Override\r
+ public void run()\r
+ {\r
+ if ( voteRunning )\r
+ {\r
+ plugin.getServer().broadcastMessage("Time expired for voting on " + ((voteType != null) ? voteType : " .. uhm *blush*"));\r
+ clearState();\r
+ }\r
+ else\r
+ {\r
+ plugin.getLogger().info("Timer expired but vote was not running :S");\r
+ clearState();\r
+ }\r
+ }\r
+ }, plugin.getConfig().getLong("vote.timeoutSeconds")*20L );\r
+ \r
+ plugin.getServer().broadcastMessage("A vote has started for " + voteType.toLowerCase() );\r
+ return true;\r
+ }\r
+\r
+ public boolean isVoteRunning()\r
+ {\r
+ return voteRunning;\r
+ }\r
+ \r
+ public String getVoteType ()\r
+ {\r
+ return voteType;\r
+ }\r
+\r
+ public boolean addVote(Player player, boolean yes) \r
+ {\r
+ if ( ! voteRunning || (voteType == null ) )\r
+ return false;\r
+\r
+ if( yesVoters.contains(player.getName()) || noVoters.contains(player.getName()) )\r
+ {\r
+ player.sendMessage("You have already cast your vote");\r
+ return true;\r
+ }\r
+ if (yes == true) yesVoters.add(player.getName());\r
+ else noVoters.add(player.getName());\r
+ \r
+ if ( (yes == true) && checkRatio( ) )\r
+ {\r
+ applyVote( voteType );\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ if ( yesVoters.size() + noVoters.size() >= plugin.getServer().getOnlinePlayers().length )\r
+ {\r
+ plugin.getServer().broadcastMessage("Vote failed for " + voteType);\r
+ plugin.getServer().getScheduler().cancelTask(expireTask);\r
+ clearState();\r
+ return true;\r
+ }\r
+ player.sendMessage("Vote counted. Thank you.");\r
+ return true;\r
+ }\r
+ }\r
+\r
+ private void applyVote(String type)\r
+ {\r
+ plugin.getServer().getScheduler().cancelTask(expireTask);\r
+ if ( ! voteRunning || (voteType == null ) )\r
+ {\r
+ plugin.getLogger().info("No vote running, but I was told to apply one. ERRR");\r
+ return;\r
+ }\r
+ \r
+ List<World> worlds = plugin.getServer().getWorlds();\r
+ for ( World w : worlds)\r
+ {\r
+ if ( voteType.equalsIgnoreCase("sun"))\r
+ w.setStorm(false);\r
+ else if ( voteType.equalsIgnoreCase("rain"))\r
+ w.setStorm(true);\r
+ else if ( voteType.equalsIgnoreCase("day"))\r
+ w.setTime( plugin.getConfig().getInt("vote.time.dayStart") );\r
+ else if ( voteType.equalsIgnoreCase("night"))\r
+ w.setTime( plugin.getConfig().getInt("vote.time.nightStart") );\r
+ }\r
+ plugin.getServer().broadcastMessage("Vote succeeded for " + ((voteType != null) ? voteType : " .. uhm *blush*"));\r
+ clearState();\r
+ }\r
+ \r
+ private boolean checkRatio( )\r
+ {\r
+ float required = 0.5F;\r
+ if ( voteType.equalsIgnoreCase("sun") || voteType.equalsIgnoreCase("rain") )\r
+ required = (float)plugin.getConfig().getInt("vote.weather.requiredPercent") / 100.0F;\r
+ else if ( voteType.equalsIgnoreCase("day") || voteType.equalsIgnoreCase("night") )\r
+ required = (float)plugin.getConfig().getInt("vote.time.requiredPercent") / 100.0F;\r
+ \r
+ float ratio = (float) yesVoters.size() / (float) plugin.getServer().getOnlinePlayers().length;\r
+ if ( ratio > required ) return true;\r
+ return false;\r
+ }\r
+ \r
+ private void clearState()\r
+ {\r
+ voteRunning = false;\r
+ voteType = null;\r
+ yesVoters.clear();\r
+ noVoters.clear();\r
+ }\r
+\r
+}\r
--- /dev/null
+package no.defcon.yavote;\r
+\r
+import java.io.File;\r
+\r
+import org.bukkit.ChatColor;\r
+import org.bukkit.command.Command;\r
+import org.bukkit.command.CommandSender;\r
+import org.bukkit.entity.Player;\r
+import org.bukkit.plugin.java.JavaPlugin;\r
+\r
+import org.bukkit.plugin.PluginLogger;\r
+\r
+public class YAVote extends JavaPlugin {\r
+ public PluginLogger logger;\r
+ private Votemanager manager;\r
+ \r
+ public void onDisable() {\r
+ // TODO: Stub.\r
+ }\r
+ \r
+ public void onEnable() {\r
+ logger = new PluginLogger(this);\r
+ manager = new Votemanager(this);\r
+ \r
+ // Set up default values for all missing config variables.\r
+ if ( ! getConfig().isSet("vote.timeoutSeconds") )\r
+ getConfig().set("vote.timeoutSeconds", 15*60L);\r
+ \r
+ if ( ! getConfig().isSet("vote.weather.requiredPercent") )\r
+ getConfig().set("vote.weather.requiredPercent", 33);\r
+\r
+ if ( ! getConfig().isSet("vote.time.requiredPercent") )\r
+ getConfig().set("vote.time.requiredPercent", 33);\r
+\r
+ if ( ! getConfig().isSet("vote.time.dayStart") )\r
+ getConfig().set("vote.time.dayStart", 23500);\r
+ \r
+ if ( ! getConfig().isSet("vote.time.nightStart") )\r
+ getConfig().set("vote.time.nightStart", 12500);\r
+\r
+ // Create config plugin data-dir if missing...\r
+ if(!getDataFolder().exists())\r
+ {\r
+ logger.info("Creating configuration directory");\r
+ getDataFolder().mkdirs();\r
+ }\r
+ \r
+ // If config.yml is missing, create it by writing out defaults.\r
+ if(!new File(getDataFolder(), "config.yml").exists())\r
+ {\r
+ logger.info("Creating configuration file");\r
+ saveConfig();\r
+ }\r
+ logger.info("Version " + getDescription().getVersion() + " is enabled!");\r
+ }\r
+ \r
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){\r
+ if(cmd.getName().equalsIgnoreCase("vote")){\r
+ if (!(sender instanceof Player)) {\r
+ sender.sendMessage(ChatColor.RED + "You must be an online player!");\r
+ return true;\r
+ }\r
+ Player player = (Player) sender; \r
+\r
+ // TODO: Add check to verify that only one option is given.\r
+ \r
+ String voteCmd = args[0];\r
+ \r
+ if ( voteCmd.equalsIgnoreCase("status") )\r
+ {\r
+ if ( ! player.hasPermission("vote.status"))\r
+ return noPermissionsMessage(player);\r
+\r
+ if ( ! manager.isVoteRunning() )\r
+ {\r
+ sender.sendMessage("No vote is currently running.");\r
+ return true;\r
+ }\r
+ \r
+ return notImplemented(player);\r
+ }\r
+ \r
+ else if ( voteCmd.equalsIgnoreCase("cancel") )\r
+ {\r
+ if ( ! player.hasPermission("vote.cancel"))\r
+ return noPermissionsMessage(player);\r
+\r
+ if ( ! manager.isVoteRunning() )\r
+ {\r
+ if (! manager.cancelVote() )\r
+ player.sendMessage("I'm sorry, unable to cancel at this time.");\r
+ \r
+ return true;\r
+ }\r
+\r
+ return notImplemented(player);\r
+ }\r
+ else if ( voteCmd.equalsIgnoreCase("sun") || voteCmd.equalsIgnoreCase("rain") || \r
+ voteCmd.equalsIgnoreCase("day") || voteCmd.equalsIgnoreCase("night") ) \r
+ {\r
+ if ( ! manager.isVoteRunning() )\r
+ {\r
+ if ( ! testPermission(voteCmd, "start", player ))\r
+ return noPermissionsMessage(player);\r
+ \r
+ manager.startVote( voteCmd.toLowerCase(), player );\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ if ( ! manager.getVoteType().equalsIgnoreCase( voteCmd ) )\r
+ {\r
+ player.sendMessage("A vote for " + manager.getVoteType() + " is already running.");\r
+ return true;\r
+ }\r
+ \r
+ else if ( ! testPermission(voteCmd, "respond", player ))\r
+ return noPermissionsMessage(player);\r
+ \r
+ else if ( ! manager.addVote( player, true ) )\r
+ {\r
+ player.sendMessage("Oops, I was unable to count your vote!");\r
+ return true;\r
+ }\r
+ return true;\r
+ }\r
+ }\r
+ \r
+ else if ( voteCmd.equalsIgnoreCase("yes") || voteCmd.equalsIgnoreCase("no") )\r
+ {\r
+ if ( ! manager.isVoteRunning() )\r
+ {\r
+ sender.sendMessage("No vote running. Perhaps you want to start a new one?");\r
+ return true;\r
+ }\r
+ if ( ! testPermission(manager.getVoteType(), "respond", player ))\r
+ return noPermissionsMessage(player);\r
+ \r
+ if ( ! manager.addVote( player, (voteCmd.equalsIgnoreCase("yes")?true:false)) )\r
+ {\r
+ player.sendMessage("Oops, I was unable to count your vote!");\r
+ return true;\r
+ }\r
+ return true;\r
+ }\r
+ \r
+\r
+\r
+ return notImplemented(player);\r
+ }\r
+ return false; \r
+ }\r
+ \r
+ private boolean notImplemented(Player p) {\r
+ p.sendMessage("It seems I do not know how to do that yet...");\r
+ return true;\r
+ }\r
+\r
+ private boolean noPermissionsMessage( Player p ){\r
+ p.sendMessage("I'm sorry, " + p.getDisplayName() + ", I'm afraid I can't do that.");\r
+ return true;\r
+ }\r
+ \r
+ private boolean testPermission (String cmd, String action, Player p)\r
+ {\r
+ if ( ( cmd.equalsIgnoreCase("sun") ) || cmd.equalsIgnoreCase("rain") )\r
+ {\r
+ if ( p.hasPermission("vote.weather." + action ) ) return true;\r
+ else return false;\r
+ }\r
+ if ( ( cmd.equalsIgnoreCase("day") ) || cmd.equalsIgnoreCase("night") )\r
+ {\r
+ if ( p.hasPermission("vote.time." + action ) ) return true;\r
+ else return false;\r
+ }\r
+ return false;\r
+ }\r
+}\r
--- /dev/null
+Cooldown on commands?\r
+Minimum votes?\r
+Text strings in config or custom-config?\r
+Per-world voting?
\ No newline at end of file