diff --git a/com/nidefawl/Stats/ItemResolver/hModItemResolver.java b/com/nidefawl/Stats/ItemResolver/hModItemResolver.java new file mode 100755 index 0000000..0c3dbee --- /dev/null +++ b/com/nidefawl/Stats/ItemResolver/hModItemResolver.java @@ -0,0 +1,324 @@ +package com.nidefawl.Stats.ItemResolver; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class hModItemResolver implements itemResolver { + static final Logger log = Logger.getLogger("Minecraft"); + protected Map items; + String location = "items.txt"; + + public hModItemResolver(String itemsTxtLocation) { + loadItems(); + } + + /* + * (non-Javadoc) + * + * @see com.bukkit.nidefawl.Stats.itemResolver#loadItems() + */ + public void loadItems() { + if (!(new File(location).exists())) { + FileWriter writer = null; + try { + writer = new FileWriter(location); + writer.write("#Add your items in here (When adding your entry DO NOT include #!)\r\n"); + writer.write("#The format is:\r\n"); + writer.write("#NAME:ID\r\n"); + writer.write("#Default Items:\r\n"); + writer.write("air:0\r\n"); + writer.write("rock:1\r\n"); + writer.write("stone:1\r\n"); + writer.write("grass:2\r\n"); + writer.write("dirt:3\r\n"); + writer.write("cobblestone:4\r\n"); + writer.write("cobble:4\r\n"); + writer.write("wood:5\r\n"); + writer.write("sapling:6\r\n"); + writer.write("adminium:7\r\n"); + writer.write("bedrock:7\r\n"); + writer.write("water:8\r\n"); + writer.write("stillwater:9\r\n"); + writer.write("swater:9\r\n"); + writer.write("lava:10\r\n"); + writer.write("stilllava:11\r\n"); + writer.write("slava:11\r\n"); + writer.write("sand:12\r\n"); + writer.write("gravel:13\r\n"); + writer.write("goldore:14\r\n"); + writer.write("ironore:15\r\n"); + writer.write("coalore:16\r\n"); + writer.write("tree:17\r\n"); + writer.write("log:17\r\n"); + writer.write("leaves:18\r\n"); + writer.write("sponge:19\r\n"); + writer.write("glass:20\r\n"); + writer.write("lazuliore:21\r\n"); + writer.write("lapislazuliore:21\r\n"); + writer.write("lazuliblock:22\r\n"); + writer.write("lapislazuliblock:22\r\n"); + writer.write("dispenser:23\r\n"); + writer.write("sandstone:24\r\n"); + writer.write("musicblock:25\r\n"); + writer.write("noteblock:25\r\n"); + writer.write("wool:35\r\n"); + writer.write("cloth:35\r\n"); + writer.write("flower:37\r\n"); + writer.write("rose:38\r\n"); + writer.write("brownmushroom:39\r\n"); + writer.write("redmushroom:40\r\n"); + writer.write("gold:41\r\n"); + writer.write("goldblock:41\r\n"); + writer.write("iron:42\r\n"); + writer.write("ironblock:42\r\n"); + writer.write("doublestair:43\r\n"); + writer.write("stair:44\r\n"); + writer.write("step:44\r\n"); + writer.write("brickblock:45\r\n"); + writer.write("brickwall:45\r\n"); + writer.write("tnt:46\r\n"); + writer.write("bookshelf:47\r\n"); + writer.write("bookcase:47\r\n"); + writer.write("mossycobblestone:48\r\n"); + writer.write("mossy:48\r\n"); + writer.write("obsidian:49\r\n"); + writer.write("torch:50\r\n"); + writer.write("fire:51\r\n"); + writer.write("mobspawner:52\r\n"); + writer.write("woodstairs:53\r\n"); + writer.write("chest:54\r\n"); + writer.write("redstonedust:55\r\n"); + writer.write("redstonewire:55\r\n"); + writer.write("diamondore:56\r\n"); + writer.write("diamondblock:57\r\n"); + writer.write("workbench:58\r\n"); + writer.write("crop:59\r\n"); + writer.write("crops:59\r\n"); + writer.write("soil:60\r\n"); + writer.write("furnace:61\r\n"); + writer.write("litfurnace:62\r\n"); + writer.write("signblock:63\r\n"); + writer.write("wooddoorblock:64\r\n"); + writer.write("ladder:65\r\n"); + writer.write("rails:66\r\n"); + writer.write("rail:66\r\n"); + writer.write("track:66\r\n"); + writer.write("tracks:66\r\n"); + writer.write("cobblestonestairs:67\r\n"); + writer.write("stairs:67\r\n"); + writer.write("signblocktop:68\r\n"); + writer.write("wallsign:68\r\n"); + writer.write("lever:69\r\n"); + writer.write("rockplate:70\r\n"); + writer.write("stoneplate:70\r\n"); + writer.write("irondoorblock:71\r\n"); + writer.write("woodplate:72\r\n"); + writer.write("redstoneore:73\r\n"); + writer.write("redstoneorealt:74\r\n"); + writer.write("redstonetorchoff:75\r\n"); + writer.write("redstonetorchon:76\r\n"); + writer.write("button:77\r\n"); + writer.write("snow:78\r\n"); + writer.write("ice:79\r\n"); + writer.write("snowblock:80\r\n"); + writer.write("cactus:81\r\n"); + writer.write("clayblock:82\r\n"); + writer.write("reedblock:83\r\n"); + writer.write("jukebox:84\r\n"); + writer.write("fence:85\r\n"); + writer.write("pumpkin:86\r\n"); + writer.write("netherstone:87\r\n"); + writer.write("slowsand:88\r\n"); + writer.write("lightstone:89\r\n"); + writer.write("portal:90\r\n"); + writer.write("jackolantern:91\r\n"); + writer.write("jacko:91\r\n"); + writer.write("cakeblock:92\r\n"); + writer.write("ironshovel:256\r\n"); + writer.write("ironspade:256\r\n"); + writer.write("ironpickaxe:257\r\n"); + writer.write("ironpick:257\r\n"); + writer.write("ironaxe:258\r\n"); + writer.write("flintandsteel:259\r\n"); + writer.write("lighter:259\r\n"); + writer.write("apple:260\r\n"); + writer.write("bow:261\r\n"); + writer.write("arrow:262\r\n"); + writer.write("coal:263\r\n"); + writer.write("diamond:264\r\n"); + writer.write("ironbar:265\r\n"); + writer.write("goldbar:266\r\n"); + writer.write("ironsword:267\r\n"); + writer.write("woodsword:268\r\n"); + writer.write("woodshovel:269\r\n"); + writer.write("woodspade:269\r\n"); + writer.write("woodpickaxe:270\r\n"); + writer.write("woodpick:270\r\n"); + writer.write("woodaxe:271\r\n"); + writer.write("stonesword:272\r\n"); + writer.write("stoneshovel:273\r\n"); + writer.write("stonespade:273\r\n"); + writer.write("stonepickaxe:274\r\n"); + writer.write("stonepick:274\r\n"); + writer.write("stoneaxe:275\r\n"); + writer.write("diamondsword:276\r\n"); + writer.write("diamondshovel:277\r\n"); + writer.write("diamondspade:277\r\n"); + writer.write("diamondpickaxe:278\r\n"); + writer.write("diamondpick:278\r\n"); + writer.write("diamondaxe:279\r\n"); + writer.write("stick:280\r\n"); + writer.write("bowl:281\r\n"); + writer.write("bowlwithsoup:282\r\n"); + writer.write("soupbowl:282\r\n"); + writer.write("soup:282\r\n"); + writer.write("goldsword:283\r\n"); + writer.write("goldshovel:284\r\n"); + writer.write("goldspade:284\r\n"); + writer.write("goldpickaxe:285\r\n"); + writer.write("goldpick:285\r\n"); + writer.write("goldaxe:286\r\n"); + writer.write("string:287\r\n"); + writer.write("feather:288\r\n"); + writer.write("gunpowder:289\r\n"); + writer.write("woodhoe:290\r\n"); + writer.write("stonehoe:291\r\n"); + writer.write("ironhoe:292\r\n"); + writer.write("diamondhoe:293\r\n"); + writer.write("goldhoe:294\r\n"); + writer.write("seeds:295\r\n"); + writer.write("wheat:296\r\n"); + writer.write("bread:297\r\n"); + writer.write("leatherhelmet:298\r\n"); + writer.write("leatherchestplate:299\r\n"); + writer.write("leatherpants:300\r\n"); + writer.write("leatherboots:301\r\n"); + writer.write("chainmailhelmet:302\r\n"); + writer.write("chainmailchestplate:303\r\n"); + writer.write("chainmailpants:304\r\n"); + writer.write("chainmailboots:305\r\n"); + writer.write("ironhelmet:306\r\n"); + writer.write("ironchestplate:307\r\n"); + writer.write("ironpants:308\r\n"); + writer.write("ironboots:309\r\n"); + writer.write("diamondhelmet:310\r\n"); + writer.write("diamondchestplate:311\r\n"); + writer.write("diamondpants:312\r\n"); + writer.write("diamondboots:313\r\n"); + writer.write("goldhelmet:314\r\n"); + writer.write("goldchestplate:315\r\n"); + writer.write("goldpants:316\r\n"); + writer.write("goldboots:317\r\n"); + writer.write("flint:318\r\n"); + writer.write("meat:319\r\n"); + writer.write("pork:319\r\n"); + writer.write("cookedmeat:320\r\n"); + writer.write("cookedpork:320\r\n"); + writer.write("painting:321\r\n"); + writer.write("paintings:321\r\n"); + writer.write("goldenapple:322\r\n"); + writer.write("sign:323\r\n"); + writer.write("wooddoor:324\r\n"); + writer.write("bucket:325\r\n"); + writer.write("waterbucket:326\r\n"); + writer.write("lavabucket:327\r\n"); + writer.write("minecart:328\r\n"); + writer.write("saddle:329\r\n"); + writer.write("irondoor:330\r\n"); + writer.write("redstonedust:331\r\n"); + writer.write("snowball:332\r\n"); + writer.write("boat:333\r\n"); + writer.write("leather:334\r\n"); + writer.write("milkbucket:335\r\n"); + writer.write("brick:336\r\n"); + writer.write("clay:337\r\n"); + writer.write("reed:338\r\n"); + writer.write("paper:339\r\n"); + writer.write("book:340\r\n"); + writer.write("slimeorb:341\r\n"); + writer.write("storageminecart:342\r\n"); + writer.write("poweredminecart:343\r\n"); + writer.write("egg:344\r\n"); + writer.write("compass:345\r\n"); + writer.write("fishingrod:346\r\n"); + writer.write("watch:347\r\n"); + writer.write("lightstonedust:348\r\n"); + writer.write("lightdust:348\r\n"); + writer.write("rawfish:349\r\n"); + writer.write("fish:349\r\n"); + writer.write("cookedfish:350\r\n"); + writer.write("inksac:351\r\n"); + writer.write("bone:352\r\n"); + writer.write("sugar:353\r\n"); + writer.write("cake:354\r\n"); + writer.write("goldrecord:2256\r\n"); + writer.write("greenrecord:2257\r\n"); + } catch (Exception e) { + log.log(Level.SEVERE, "Exception while creating " + location, e); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + log.log(Level.SEVERE, "Exception while closing writer for " + location, e); + } + } + } + } + items = new HashMap(); + try { + Scanner scanner = new Scanner(new File(location)); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.startsWith("#")) { + continue; + } + if (line.equals("")) { + continue; + } + String[] split = line.split(":"); + String name = split[0]; + + this.items.put(name, Integer.parseInt(split[1])); + } + scanner.close(); + } catch (Exception e) { + log.log(Level.SEVERE, "Exception while reading " + location + " (Are you sure you formatted it correctly?)", e); + } + } + + /* + * (non-Javadoc) + * + * @see com.bukkit.nidefawl.Stats.itemResolver#getItem(java.lang.String) + */ + @Override + public int getItem(String name) { + if (items.containsKey(name)) { + return items.get(name); + } + return 0; + } + + /* + * (non-Javadoc) + * + * @see com.bukkit.nidefawl.Stats.itemResolver#getItem(int) + */ + @Override + public String getItem(int id) { + for (String name : items.keySet()) { + if (items.get(name) == id) { + return name; + } + } + return String.valueOf(id); + } + +} \ No newline at end of file diff --git a/com/nidefawl/Stats/ItemResolver/itemResolver.java b/com/nidefawl/Stats/ItemResolver/itemResolver.java new file mode 100755 index 0000000..b2904c5 --- /dev/null +++ b/com/nidefawl/Stats/ItemResolver/itemResolver.java @@ -0,0 +1,21 @@ +package com.nidefawl.Stats.ItemResolver; + +public interface itemResolver { + /** + * Returns item id corresponding to item name + * + * @param name + * @return item id + */ + public abstract int getItem(String name); + + /** + * Returns the name of the item corresponding to the ID + * + * @param id + * id of item + * @return name of item + */ + public abstract String getItem(int id); + +} \ No newline at end of file diff --git a/com/nidefawl/Stats/ItemResolver/myGeneralItemResolver.java b/com/nidefawl/Stats/ItemResolver/myGeneralItemResolver.java new file mode 100755 index 0000000..48e1a55 --- /dev/null +++ b/com/nidefawl/Stats/ItemResolver/myGeneralItemResolver.java @@ -0,0 +1,24 @@ +package com.nidefawl.Stats.ItemResolver; + +import org.bukkit.plugin.Plugin; + +import com.nidefawl.MyGeneral.MyGeneral; + +public class myGeneralItemResolver implements itemResolver { + public MyGeneral plugin; + + public myGeneralItemResolver(Plugin plugin) { + this.plugin = (MyGeneral) plugin; + } + + @Override + public int getItem(String name) { + return plugin.getDataSource().getItem(name); + } + + @Override + public String getItem(int id) { + return plugin.getDataSource().getItem(id); + } + +} diff --git a/com/nidefawl/Stats/Messaging.java b/com/nidefawl/Stats/Messaging.java new file mode 100755 index 0000000..bb2d759 --- /dev/null +++ b/com/nidefawl/Stats/Messaging.java @@ -0,0 +1,184 @@ +package com.nidefawl.Stats; + +import org.bukkit.Server; +import org.bukkit.entity.Player; + +/** + * General 1.1 & Code from iConomy 2.x + * Copyright (C) 2011 Nijikokun + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * Messaging.java
+ *
+ * Lets us do fancy pantsy things with colors, messages, and broadcasting :D! + * + * @author Nijikokun + */ +public class Messaging { + + public static Player player = null; + + /** + * Converts a list of arguments into points. + * + * @param original + * The original string necessary to convert inside of. + * @param arguments + * The list of arguments, multiple arguments are seperated by + * commas for a single point. + * @param points + * The point used to alter the argument. + * + * @return String - The parsed string after converting + * arguments to variables (points) + */ + public static String argument(String original, String[] arguments, String[] points) { + for (int i = 0; i < arguments.length; i++) { + if (arguments[i].contains(",")) { + for (String arg : arguments[i].split(",")) { + original = original.replace(arg, points[i]); + } + } else { + original = original.replace(arguments[i], points[i]); + } + } + + return original; + } + + /** + * Parses the original string against color specific codes. This one + * converts &[code] to §[code]
+ *
+ * Example:
+ * + *
+	 * Messaging.parse("Hello &2world!"); // returns: Hello §2world!
+	 * 
+ * + *
+ * + * @param original + * The original string used for conversions. + * + * @return String - The parsed string after conversion. + */ + public static String parse(String original) { + return colorize(original.replaceAll("(&([a-z0-9]))", "§$2").replace("\\\\\u00A7", "&")); + } + + /** + * Converts color codes into the simoleon code. Sort of a HTML format color + * code tag. + *

+ * Color codes allowed: black, navy, green, teal, red, purple, gold, silver, + * gray, blue, lime, aqua, rose, pink, yellow, white. + *

+ * Example:
+ * Messaging.colorize("Hello <green>world!"); // returns: Hello §2world! + * + * + *
+ * + * @param original + * Original string to be parsed against group of color names. + * + * @return String - The parsed string after conversion. + */ + public static String colorize(String original) { + return original.replace("", "§0").replace("", "§1").replace("", "§2").replace("", "§3").replace("", "§4").replace("", "§5").replace("", "§6").replace("", "§7").replace("", "§8").replace("", "§9").replace("", "§a").replace("", "§b") + .replace("", "§c").replace("", "§d").replace("", "§e").replace("", "§f"); + } + + /** + * Helper function to assist with making brackets. Why? Dunno, lazy. + * + * @param message + * The message inside of brackets. + * + * @return String - The message inside [brackets] + */ + public static String bracketize(String message) { + return "[" + message + "]"; + } + + /** + * Save the player to be sent messages later. Ease of use sending messages.
+ *
+ * Example:
+ * + *
+	 * Messaging.save(player);
+	 * Messaging.send("This will go to the player saved.");
+	 * 
+ * + *
+ * + * @param player + * The player we wish to save for later. + */ + public static void save(Player player) { + Messaging.player = player; + } + + /** + * Sends a message to a specific player.
+ *
+ * Example:
+ * + *
+	 * Messaging.send(player, "This will go to the player saved.");
+	 * 
+ * + *
+ * + * @param player + * Player we are sending the message to. + * @param message + * The message to be sent. + */ + public static void send(Player player, String message) { + String parsedMsg = parse(message); + player.sendMessage(parsedMsg); + } + + /** + * Sends a message to the stored player. + * + * @param message + * The message to be sent. + * @see Messaging#save(Player) + */ + public static void send(String message) { + if (Messaging.player != null) + player.sendMessage(parse(message)); + } + + /** + * Brodcast a message to every player online. + * + * @param message + * - The message to be sent. + */ + public static void broadcast(Server server, String message) { + for (Player p : server.getOnlinePlayers()) { + p.sendMessage(parse(message)); + } + } +} \ No newline at end of file diff --git a/com/nidefawl/Stats/MinecraftFontWidthCalculator.java b/com/nidefawl/Stats/MinecraftFontWidthCalculator.java new file mode 100755 index 0000000..6a32bb8 --- /dev/null +++ b/com/nidefawl/Stats/MinecraftFontWidthCalculator.java @@ -0,0 +1,30 @@ +package com.nidefawl.Stats; + +public class MinecraftFontWidthCalculator { + private static String charWidthIndexIndex = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~‚åÇ√á√º√©√¢√§√†√•√ß√™√´√®√Ø√Æ√¨√Ñ√Ö√â√¶√Ü√¥√∂√≤√ª√π√ø√ñ√ú√âˆ?£Ø×ƒáíóúñѪº¿®¬½¼¡«»"; + private static int[] charWidths = { 4, 2, 5, 6, 6, 6, 6, 3, 5, 5, 5, 6, 2, 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 5, 6, 5, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 4, 6, 6, 3, 6, 6, 6, 6, 6, 5, 6, 6, 2, 6, 5, 3, 6, 6, 6, 6, 6, 6, 6, 4, 6, 6, 6, 6, 6, 6, 5, 2, + 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 6, 3, 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 2, 6, 6, 8, 9, 9, 6, 6, 6, 8, 8, 6, 8, 8, 8, 8, 8, 6, 6, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 6, 9, 9, 9, 5, 9, 9, 8, 7, 7, + 8, 7, 8, 8, 8, 7, 8, 8, 7, 9, 9, 6, 7, 7, 7, 7, 7, 9, 6, 7, 8, 7, 6, 6, 9, 7, 6, 7, 1 }; + + public static int getStringWidth(String s) { + int i = 0; + if (s != null) + for (int j = 0; j < s.length(); j++) + i += getCharWidth(s.charAt(j)); + return i; + } + + public static int getCharWidth(char c) { + int k = charWidthIndexIndex.indexOf(c); + if ((c != '§') && (k >= 0)) + return charWidths[k]; + return 0; + } +} + +/* + * Location: C:\Users\Michael\AppData\Local\Temp\Rar$DR01.151\MyWarp.jar + * Qualified Name: + * org.angelsl.minecraft.randomshit.fontwidth.MinecraftFontWidthCalculator + * JD-Core Version: 0.6.0 + */ \ No newline at end of file diff --git a/com/nidefawl/Stats/Permissions/GroupUserResolver.java b/com/nidefawl/Stats/Permissions/GroupUserResolver.java new file mode 100755 index 0000000..90950c4 --- /dev/null +++ b/com/nidefawl/Stats/Permissions/GroupUserResolver.java @@ -0,0 +1,65 @@ +package com.nidefawl.Stats.Permissions; + +import java.util.logging.Logger; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +import com.bukkit.authorblues.GroupUsers.GroupUsers; + +public class GroupUserResolver implements PermissionsResolver { + public static final Logger log = Logger.getLogger("Minecraft"); + JavaPlugin plugin = null; + private GroupUsers perms = null; + + public GroupUserResolver(JavaPlugin plugin) { + this.plugin = plugin; + check(); + } + + public boolean check() { + if (perms == null) { + Plugin checkPlugin = plugin.getServer().getPluginManager().getPlugin("GroupUsers"); + if (checkPlugin != null) { + perms = (GroupUsers) checkPlugin; + } else + return false; + } + if (perms.isEnabled() == false) + return false; + return true; + } + + public boolean permission(Player player, String permCmd) { + if (!check()) + return false; + return perms.playerCanUseCommand(player, permCmd); + } + + public String getGroup(String player) { + return ""; + } + + public String getGroupPrefix(String player) { + return ""; + } + + public String getGroupSuffix(String player) { + return ""; + } + + public boolean canGroupBuild(String group) { + return true; + } + + public boolean inGroup(Player player, String group) { + if (!check()) + return false; + return perms.isInGroup(player, group); + } + + @Override + public void reloadPerms() { + } + +} diff --git a/com/nidefawl/Stats/Permissions/NijiPermissionsResolver.java b/com/nidefawl/Stats/Permissions/NijiPermissionsResolver.java new file mode 100755 index 0000000..00dab6b --- /dev/null +++ b/com/nidefawl/Stats/Permissions/NijiPermissionsResolver.java @@ -0,0 +1,78 @@ +package com.nidefawl.Stats.Permissions; + +import java.util.logging.Logger; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; +import com.nijikokun.bukkit.Permissions.Permissions; + +public class NijiPermissionsResolver implements PermissionsResolver { + public static final Logger log = Logger.getLogger("Minecraft"); + JavaPlugin plugin = null; + private Permissions perms = null; + + public NijiPermissionsResolver(JavaPlugin plugin) { + this.plugin = plugin; + check(); + } + + public boolean check() { + if (perms == null) { + Plugin checkPlugin = plugin.getServer().getPluginManager().getPlugin("Permissions"); + if (checkPlugin != null) { + if (!((Permissions) checkPlugin).isEnabled()) + return false; + perms = (Permissions) checkPlugin; + } else { + return false; + } + } + return true; + } + + public boolean permission(Player player, String permCmd) { + + if (!check()) + return false; + return perms.getHandler().permission(player, permCmd); + } + + public String getGroup(String player) { + if (!check()) + return ""; + return perms.getHandler().getGroup(player); + } + + public String getGroupPrefix(String player) { + if (!check()) + return ""; + return perms.getHandler().getGroupPrefix(player); + } + + public String getGroupSuffix(String player) { + if (!check()) + return ""; + return perms.getHandler().getGroupSuffix(player); + } + + public boolean canGroupBuild(String group) { + if (!check()) + return false; + return perms.getHandler().canGroupBuild(group); + } + + @Override + public boolean inGroup(Player player, String group) { + if (!check()) + return false; + return perms.getHandler().inGroup(player.getName(), group); + } + + @Override + public void reloadPerms() { + if (!check()) + return; + perms.setupPermissions(); + } + +} diff --git a/com/nidefawl/Stats/Permissions/PermissionsResolver.java b/com/nidefawl/Stats/Permissions/PermissionsResolver.java new file mode 100755 index 0000000..606b49b --- /dev/null +++ b/com/nidefawl/Stats/Permissions/PermissionsResolver.java @@ -0,0 +1,23 @@ +package com.nidefawl.Stats.Permissions; + +import org.bukkit.entity.Player; + +public interface PermissionsResolver { + + public abstract boolean check(); + + public abstract boolean permission(Player player, String permCmd); + + public abstract String getGroup(String player); + + public abstract boolean inGroup(Player player, String group); + + public abstract String getGroupPrefix(String player); + + public abstract String getGroupSuffix(String player); + + public abstract boolean canGroupBuild(String group); + + public abstract void reloadPerms(); + +} \ No newline at end of file diff --git a/com/nidefawl/Stats/Permissions/defaultResolver.java b/com/nidefawl/Stats/Permissions/defaultResolver.java new file mode 100755 index 0000000..4e09f55 --- /dev/null +++ b/com/nidefawl/Stats/Permissions/defaultResolver.java @@ -0,0 +1,54 @@ +package com.nidefawl.Stats.Permissions; + +import org.bukkit.entity.Player; + +public class defaultResolver implements PermissionsResolver { + + @Override + public boolean permission(Player player, String permCmd) { + if (player.isOp()) + return true; + if (permCmd.equals("/achievements") || permCmd.equals("/ach")) + return true; + if (permCmd.equals("/listach") || permCmd.equals("/listachievements")) + return true; + if (permCmd.equals("/stats")) + return true; + return false; + } + + @Override + public String getGroup(String player) { + return ""; + } + + @Override + public boolean inGroup(Player player, String group) { + return false; + } + + @Override + public String getGroupPrefix(String player) { + return ""; + } + + @Override + public String getGroupSuffix(String player) { + return ""; + } + + @Override + public boolean canGroupBuild(String group) { + return false; + } + + @Override + public boolean check() { + return true; + } + + @Override + public void reloadPerms() { + } + +} diff --git a/com/nidefawl/Stats/PropertiesFile.java b/com/nidefawl/Stats/PropertiesFile.java new file mode 100755 index 0000000..bfbc57a --- /dev/null +++ b/com/nidefawl/Stats/PropertiesFile.java @@ -0,0 +1,176 @@ +package com.nidefawl.Stats; + +import java.io.*; +import java.util.*; +import java.util.Map.Entry; +import java.util.logging.Level; + +import org.bukkit.ChatColor; + +public class PropertiesFile { + private HashMap map; + private File file; + private boolean modified; + public final String premessage = ChatColor.YELLOW + "[Stats-" + Stats.version + "] " + ChatColor.WHITE; + + public PropertiesFile(File file) { + this.file = file; + map = new HashMap(); + Scanner scan; + try { + if (!file.exists()) + file.createNewFile(); + scan = new Scanner(file); + while (scan.hasNextLine()) { + String line = scan.nextLine(); + if (!line.contains("=")) + continue; + if (line.length() == 0) + continue; + if (line.trim().charAt(0) == '#') + continue; + int equals = line.indexOf("="); + int commentIndex = line.length(); + if (line.contains("#")) { + commentIndex = line.indexOf("#"); + } + + String key = line.substring(0, equals).trim(); + if (key.equals("")) + continue; + String value = line.substring(equals + 1, commentIndex).trim(); + String comment = ""; + if (commentIndex < line.length() - 1) { + comment = line.substring(commentIndex + 1, line.length()).trim(); + } + map.put(key, new PropertiesEntry(value, comment)); + } + } catch (FileNotFoundException e) { + Stats.log.log(Level.SEVERE, "[Stats] Cannot read file " + file.getName()); + } catch (IOException e) { + Stats.log.log(Level.SEVERE, "[Stats] Cannot create file " + file.getName()); + } + } + + public boolean getBoolean(String key, Boolean defaultValue, String defaultComment) { + if (map.containsKey(key)) { + return Boolean.parseBoolean(map.get(key).value); + } else { + map.put(key, new PropertiesEntry(defaultValue.toString(), defaultComment)); + modified = true; + return defaultValue; + } + } + + public boolean getBoolean(String key) { + if (map.containsKey(key)) { + return Boolean.parseBoolean(map.get(key).value); + } + return false; + } + + + public void remove(String key) { + map.remove(key); + } + + public String getString(String key, String defaultValue, String defaultComment) { + if (map.containsKey(key)) { + return map.get(key).value; + } else { + map.put(key, new PropertiesEntry(defaultValue.toString(), defaultComment)); + modified = true; + return defaultValue; + } + } + + public int getInt(String key, Integer defaultValue, String defaultComment) { + if (map.containsKey(key)) { + try { + return Integer.parseInt(map.get(key).value); + } catch (Exception e) { + Stats.log.log(Level.WARNING, "[Stats] Trying to get Integer from " + key + ": " + map.get(key).value); + return 0; + } + } else { + map.put(key, new PropertiesEntry(defaultValue.toString(), defaultComment)); + modified = true; + return defaultValue; + } + } + + public double getDouble(String key, Double defaultValue, String defaultComment) { + if (map.containsKey(key)) { + try { + return Double.parseDouble(map.get(key).value); + } catch (Exception e) { + Stats.log.log(Level.WARNING, "[Stats] Trying to get Double from " + key + ": " + map.get(key).value); + return 0; + } + } else { + map.put(key, new PropertiesEntry(defaultValue.toString(), defaultComment)); + modified = true; + return defaultValue; + } + } + + public void save() { + if (!modified) + return; + BufferedWriter bwriter = null; + FileWriter fwriter = null; + try { + if (!file.exists()) + file.createNewFile(); + fwriter = new FileWriter(file); + bwriter = new BufferedWriter(fwriter); + SortedSet> results = new TreeSet>(new Comparator>() { + public int compare(Map.Entry a, Map.Entry b) { + // int d = a.getValue().compareTo(b.getValue()); + int d = a.getKey().compareTo(b.getKey()); + return d; + } + + }); + results.addAll(map.entrySet()); + for (Entry entry : results) { + StringBuilder builder = new StringBuilder(); + builder.append(entry.getKey()); + builder.append(" = "); + builder.append(entry.getValue().value); + if (!entry.getValue().comment.equals("")) { + builder.append(" #"); + builder.append(entry.getValue().comment); + } + bwriter.write(builder.toString()); + bwriter.newLine(); + } + bwriter.flush(); + } catch (IOException e) { + Stats.log.log(Level.SEVERE, "[Stats] IO Exception with file " + file.getName()); + } finally { + try { + if (bwriter != null) { + bwriter.flush(); + bwriter.close(); + } + if (fwriter != null) { + fwriter.close(); + } + } catch (IOException e) { + Stats.log.log(Level.SEVERE, "[Stats] IO Exception with file " + file.getName() + " (on close)"); + } + } + + } + + private class PropertiesEntry { + public String value; + public String comment; + + public PropertiesEntry(String value, String comment) { + this.value = value; + this.comment = comment; + } + } +} \ No newline at end of file diff --git a/com/nidefawl/Stats/Stats.java b/com/nidefawl/Stats/Stats.java new file mode 100755 index 0000000..541f3f3 --- /dev/null +++ b/com/nidefawl/Stats/Stats.java @@ -0,0 +1,911 @@ +package com.nidefawl.Stats; + +import java.io.File; +import java.io.FilenameFilter; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.entity.Vehicle; +import org.bukkit.event.Event.Priority; +import org.bukkit.event.Event; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; +import com.nidefawl.Stats.ItemResolver.hModItemResolver; +import com.nidefawl.Stats.ItemResolver.itemResolver; +import com.nidefawl.Stats.ItemResolver.myGeneralItemResolver; +import com.nidefawl.Stats.Permissions.GroupUserResolver; +import com.nidefawl.Stats.Permissions.NijiPermissionsResolver; +import com.nidefawl.Stats.Permissions.PermissionsResolver; +import com.nidefawl.Stats.Permissions.defaultResolver; +import com.nidefawl.Stats.datasource.Category; +import com.nidefawl.Stats.datasource.PlayerStat; +import com.nidefawl.Stats.datasource.PlayerStatSQL; +import com.nidefawl.Stats.datasource.StatsSQLConnectionManager; +import com.nidefawl.Stats.util.Updater; + +public class Stats extends JavaPlugin { + public final static Logger log = Logger.getLogger("Minecraft"); + public final static double version = 0.53; + public final static String logprefix = "[Stats-" + version + "]"; + public final static String defaultCategory = "stats"; + public boolean enabled = false; + protected HashMap stats = new HashMap(); + protected itemResolver items = new hModItemResolver("items.txt"); + private static PermissionsResolver perms = null; + private static StatsPlayerListener playerListener; + private static StatsVehicleListener vehicleListener; + private static StatsBlockListener blockListener; + private static StatsEntityListener entityListener; + long lastDebugWrite = System.currentTimeMillis(); + /** + * LWC updater + * + * TODO: Remove when Bukkit has an updater that is working + */ + private Updater updater; + + /** + * @return the Updater instance + */ + public Updater getUpdater() { + return updater; + } + + + public PermissionsResolver Perms() { + if (perms == null) { + log.info(logprefix + " Recreating Nijis Permissions for permissions"); + CreatePermissionResolver(); + if (perms == null) + log.log(Level.SEVERE, logprefix + " Couldn't link to Nijis Permissions plugin!!!"); + } + return perms; + } + + public void ReloadPerms() { + if (perms != null) { + perms.reloadPerms(); + + } + } + public static void LogError(String Message) { + log.log(Level.SEVERE, logprefix + " " + Message); + } + + public static void LogInfo(String Message) { + log.info(logprefix + " " + Message); + } + private boolean checkSchema() { + Connection conn = null; + DatabaseMetaData dbm = null; + PreparedStatement ps = null; + ResultSet rs = null; + boolean result = false; + try { + conn = StatsSQLConnectionManager.getConnection(); + dbm = conn.getMetaData(); + rs = dbm.getTables(null, null, StatsSettings.dbTable, null); + if (!rs.next()) { + ps = conn.prepareStatement("CREATE TABLE `" + StatsSettings.dbTable + "` (" + "`player` varchar(32) NOT NULL DEFAULT '-'," + "`category` varchar(32) NOT NULL DEFAULT 'stats'," + "`stat` varchar(32) NOT NULL DEFAULT '-'," + "`value` int(11) NOT NULL DEFAULT '0'," + "PRIMARY KEY (`player`,`category`,`stat`));"); + ps.executeUpdate(); + log.info(logprefix + " " + this.getClass().getName() + " created table '" + StatsSettings.dbTable + "'."); + } + result = true; + } catch (SQLException ex) { + log.log(Level.SEVERE, logprefix + " " + this.getClass().getName() + " SQL exception", ex); + result = false; + } finally { + try { + if (rs != null) + rs.close(); + if (ps != null) + ps.close(); + if (conn != null) + conn.close(); + } catch (SQLException ex) { + log.log(Level.SEVERE, logprefix + " " + this.getClass().getName() + " SQL exception on close", ex); + result = false; + } + } + return result; + } + + + public void setSavedStats(Player admin, String player, String category, String key, String value) { + ArrayList tounload = new ArrayList(); + tounload.addAll(stats.keySet()); + for (String name : tounload) { + unload(name); + } + + stats.clear(); + int result = 0; + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = StatsSQLConnectionManager.getConnection(); + StringBuilder statement = new StringBuilder(); + int conditions = 0; + statement.append("UPDATE " + StatsSettings.dbTable + " set value = ?"); + if (!player.equals("*")) + statement.append((conditions++ == 0 ? " where" : " and") + " player = ?"); + if (!category.equals("*")) + statement.append((conditions++ == 0 ? " where" : " and") + " category = ?"); + if (!key.equals("*")) + statement.append((conditions++ == 0 ? " where" : " and") + " stat = ?"); + + ps = conn.prepareStatement(statement.toString()); + ps.setString(1, value); + conditions++; + if (!key.equals("*")) + ps.setString(conditions--, key); + if (!category.equals("*")) + ps.setString(conditions--, category); + if (!player.equals("*")) + ps.setString(conditions--, player); + result = ps.executeUpdate(); + } catch (SQLException ex) { + log.log(Level.SEVERE, logprefix + " " + this.getClass().getName() + " SQL exception", ex); + Messaging.send(admin, StatsSettings.premessage + ex.getMessage()); + } finally { + try { + if (rs != null) + rs.close(); + if (ps != null) + ps.close(); + } catch (SQLException ex) { + log.log(Level.SEVERE, logprefix + " " + this.getClass().getName() + " SQL exception on close", ex); + Messaging.send(admin, StatsSettings.premessage + ex.getMessage()); + } + } + Messaging.send(admin, StatsSettings.premessage + "Updated " + result + " stats."); + for (Player p : getServer().getOnlinePlayers()) { + load(p); + } + } + + public int editPlayerStat(PlayerStat ps, String category, String key, String value) { + + int statsEdited = 0; + if (category.equals("*")) { + for (String catName : ps.categories.keySet()) { + if (key.equals("*")) { + for (String keyName : ps.categories.get(catName).getEntries()) { + ps.categories.get(catName).set(keyName, Integer.valueOf(value)); + statsEdited++; + } + } else { + if (!ps.categories.get(catName).getEntries().contains(key)) + continue; + ps.categories.get(catName).set(key, Integer.valueOf(value)); + statsEdited++; + } + + } + } else { + if (ps.categories.containsKey(category)) { + if (key.equals("*")) { + for (String keyName : ps.categories.get(category).getEntries()) { + ps.categories.get(category).set(keyName, Integer.valueOf(value)); + statsEdited++; + } + } else { + if (!ps.categories.get(category).getEntries().contains(key)) + return statsEdited; + ps.categories.get(category).set(key, Integer.valueOf(value)); + statsEdited++; + } + } + } + return statsEdited; + } + + public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) { + LogInfo("asdf"); + if (!(sender instanceof Player)) + return false; + Player player = (Player) sender; + if (commandLabel.equals("played") && Perms().permission(player, "/stats")) { + int playedFor = get(player.getName(), "stats", "playedfor"); + if (playedFor == 0) { + Messaging.send(player, StatsSettings.premessage + "No Playedtime yet!"); + return true; + } + Messaging.send(player, StatsSettings.premessage + "You played for &f" + GetTimeString(playedFor)); + return true; + } + if (commandLabel.equals("stats") && Perms().permission(player, "/stats")) { + if (args.length == 1 && args[0].equalsIgnoreCase("help")) { + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "/stats - Shows your stats summary"); + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "/stats - Shows players stats summary"); + if (Perms().permission(player, "/statsadmin")) { + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "/stats list - Shows loaded players"); + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "/stats set - Set stats manually"); + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "/stats debug - Prints stat-update messages to console."); + Messaging.send(player, StatsSettings.premessage + "Usage: " + ChatColor.WHITE + "/stats [category|debug|statname|list|helpset]"); + Messaging.send(player, StatsSettings.premessage + "or /stats [player] [category|statname]"); + } else { + Messaging.send(player, StatsSettings.premessage + "Usage: " + ChatColor.WHITE + "/stats [category|statname|help] or /stats [player] [category|statname]"); + } + return true; + } + if (Perms().permission(player, "/statsadmin")) { + if (args.length == 1 && args[0].equalsIgnoreCase("list") && Perms().permission(player, "/statsadmin")) { + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "Loaded playerstats (" + stats.size() + "): " + StatsPlayerList()); + return true; + } + if (args.length == 1 && args[0].equalsIgnoreCase("entlist")) { + entityListener.sendEntList(player); + return true; + } + if (args.length > 0 && args[0].equalsIgnoreCase("set")) { + if (args.length < 5) { + Messaging.send(player, StatsSettings.premessage + ChatColor.RED + "Need more arguments (use * to select all)"); + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "/stats set [player] [category] [key] [value]- Set stats manually"); + return true; + } + try { + Integer.valueOf(args[4]); + } catch (Exception e) { + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "[value] should be a number (" + args[4] + " is not)!"); + return true; + } + setSavedStats(player, args[1], args[2], args[3], args[4]); + return true; + } + if (args.length == 1 && args[0].equalsIgnoreCase("debug")) { + StatsSettings.debugOutput = !StatsSettings.debugOutput; + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "Debugging " + (StatsSettings.debugOutput ? "enabled. Check server log." : "disabled.")); + return true; + + } + if (args.length == 1 && args[0].equalsIgnoreCase("disable")) { + enabled = false; + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "Debugging: Stats is now disabled."); + return true; + + } + if (args.length == 1 && args[0].equalsIgnoreCase("enable")) { + enabled = true; + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "Debugging: Stats is now enabled."); + return true; + + } + } + Player who = player; + if (args.length > 0) { + int offs = 1; + who = playerMatch(args[0]); + if (who == null) { + who = player; + offs--; + } + if (args.length == offs + 1) { + if (isStat(player.getName(), args[offs])) { + printStat(player, who, "stats", args[offs]); + return true; + } else if (getItems().getItem(args[offs]) != 0 && !(args[offs].equals("boat") || args[offs].equals("minecart"))) { + printStat(player, who, "blockcreate", args[offs]); + printStat(player, who, "blockdestroy", args[offs]); + return true; + } else if (isCat(player.getName(), args[offs])) { + Messaging.send(player, StatsSettings.premessage + "Please choose: (/stats " + args[offs] + " )"); + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + getCatEntries(who.getName(), args[offs])); + return true; + } else { + Messaging.send(player, StatsSettings.premessage + ChatColor.RED + "stat/category '" + args[offs] + "' not found. Possible values:"); + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + getCats(who.getName())); + return true; + } + } else if (args.length == offs + 2) { + if (isCat(player.getName(), args[offs])) { + printStat(player, who, args[offs], args[offs + 1]); + return true; + } else { + Messaging.send(player, StatsSettings.premessage + ChatColor.RED + "stat/category '" + args[offs] + "' not found. Possible values:"); + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + getCats(who.getName())); + return true; + } + } + } + int playedTime = get(who.getName(), "stats", "playedfor"); + int movedBlocks = get(who.getName(), "stats", "move"); + int totalCreate = get(who.getName(), "stats", "totalblockcreate"); + int totalDestroy = get(who.getName(), "stats", "totalblockdestroy"); + int tkills = get(who.getName(), "kills", "total"); + int tdeaths = get(who.getName(), "deaths", "total"); + int pdeaths = get(who.getName(), "deaths", "player"); + int pkills = get(who.getName(), "kills", "player"); + int totalDamage = get(who.getName(), "damagetaken", "total"); + int totalDamageDealt = get(who.getName(), "damagedealt", "total"); + try { + Messaging.send(player, "------------------------------------------------"); + Messaging.send(player, "&e stats for &f" + who.getName() + "&e: (&f/stats help for more&e)"); + Messaging.send(player, "------------------------------------------------"); + String s1 = "&6 [&ePlayedtime&6]"; + while (MinecraftFontWidthCalculator.getStringWidth(s1) < 110) + s1 += " "; + s1 += "&f" + GetTimeString(playedTime); + Messaging.send(player, s1); + s1 = "&6 [&eMoved&6]"; + while (MinecraftFontWidthCalculator.getStringWidth(s1) < 110) + s1 += " "; + s1 += "&f" + movedBlocks + " blocks"; + Messaging.send(player, s1); + printStatFormated(player, "Blocks", "created", totalCreate, "destroyed", totalDestroy); + printStatFormated(player, "Deaths", "total", tdeaths, "player", pdeaths); + printStatFormated(player, "Kills", "total", tkills, "player", pkills); + printStatFormated(player, "Damage", "dealt", totalDamageDealt, "taken", totalDamage); + Messaging.send(player, "------------------------------------------------"); + } catch (Exception e) { + // TODO: handle exception + } + return true; + + } + + return false; + } + + private void printStatFormated(Player p, String name, String title1, int value1, String title2, int value2) { + String s1 = "&6 [&e" + name + "&6]&e"; + while (MinecraftFontWidthCalculator.getStringWidth(s1) < 120) + s1 += " "; + if (title2 != null) + s1 += "&f" + title1 + "/" + title2; + else + s1 += "&f" + title1; + while (MinecraftFontWidthCalculator.getStringWidth(s1) < 240) + s1 += " "; + if (title2 != null) + s1 += value1 + "/" + value2; + else + s1 += value1; + Messaging.send(p, s1); + } + + public void printStat(Player sendTo, Player statPlayer, String cat, String stat) { + long statVal = get(statPlayer.getName(), cat, stat); + String statString = "" + statVal; + if (stat.equalsIgnoreCase("playedfor")) { + statString = GetTimeString((int) statVal); + } + if (stat.equalsIgnoreCase("lastlogout") || stat.equalsIgnoreCase("lastlogin")) { + Date logDate = new Date(statVal * 1000); + SimpleDateFormat format = new SimpleDateFormat("dd-MMM-yy hh:mm"); + statString = format.format(logDate); + } + + Messaging.send(sendTo, StatsSettings.premessage + cat + "/" + stat + ": &f" + statString); + } + + public String GetTimeString(int Seconds) { + int days = (int) Math.ceil(Seconds / (24 * 3600)); + int hours = (int) Math.ceil((Seconds - (24 * 3600 * days)) / 3600); + int minutes = (int) Math.ceil((Seconds - (24 * 3600 * days + 3600 * hours)) / 60); + String timeString = ""; + timeString += days + "d " + hours + "h " + minutes + "m"; + return timeString; + } + + public void CreatePermissionResolver() { + Plugin permPlugin = this.getServer().getPluginManager().getPlugin("Permissions"); + if (permPlugin != null) { + log.info(logprefix + " Using Nijis Permissions for permissions"); + perms = new NijiPermissionsResolver(this); + return; + } + permPlugin = this.getServer().getPluginManager().getPlugin("GroupUsers"); + if (permPlugin != null) { + log.info(logprefix + " Using GroupUsers for permissions"); + perms = new GroupUserResolver(this); + return; + } + log.info(logprefix + " Using bukkit's isOp() for permissions"); + perms = new defaultResolver(); + return; + } + + public String StatsPlayerList() { + if (stats.size() == 0) + return "No players loaded"; + int length = (stats.size() - 1); + + int on = 0; + String list = ""; + for (String currentName : stats.keySet()) { + if (currentName == null) { + ++on; + continue; + } + + list += (on >= length) ? currentName : currentName + ", "; + ++on; + } + list += " "; + return list; + } + public void convertFlatFiles() { + File dir = new File(StatsSettings.directory); + FilenameFilter filter = new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".txt"); + } + }; + + FilenameFilter filterOld = new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".txt.old"); + } + }; + String[] files = dir.list(filterOld); + if (files != null&&files.length>0) { + for (int i = 0; i < files.length; i++) { + String location = StatsSettings.directory + File.separator + files[i]; + String basename = files[i].substring(0, files[i].lastIndexOf(".")); + File fnew = new File(location); + File fold = new File(StatsSettings.directory + File.separator + basename); + fnew.renameTo(fold); + } + } + files = dir.list(filter); + if (files == null||files.length==0) { + } + + int count = 0; + PlayerStatSQL ps; + for (int i = 0; i < files.length; i++) { + String location = StatsSettings.directory + File.separator + files[i]; + File fold = new File(location); + if (!fold.exists()) + continue; + + String basename = files[i].substring(0, files[i].lastIndexOf(".")); + ps = new PlayerStatSQL(basename, this); + ps.convertFlatFile(StatsSettings.directory); + ps.save(); + count++; + } + Stats.LogInfo("Converted " + count + " stat files to "+(StatsSettings.useMySQL?"MySQL":"SQLite")); + } + public Stats() { + StatsSettings.initialize(); + updater = new Updater(); + System.setProperty("org.sqlite.lib.path", updater.getOSSpecificFolder()); + StatsSQLConnectionManager.getConnection(); + try { + if(StatsSettings.autoUpdate) { + updater.checkDist(); + } else { + updater.check(); + } + updater.update(); + } catch (Exception e) { + e.printStackTrace(); + } + try { + if (StatsSettings.useMySQL) { + Class.forName("com.mysql.jdbc.Driver"); + } else { + Class.forName("org.sqlite.JDBC"); + } + } catch (ClassNotFoundException e) { + LogError("JDBC driver for "+(StatsSettings.useMySQL?"MySQL":"SQLite")+" not found. Disabling Stats"); + getServer().getPluginManager().disablePlugin(this); + e.printStackTrace(); + return; + } + Connection conn = StatsSQLConnectionManager.getConnection(); + if (conn == null) { + LogError("Could not establish SQL connection. Disabling Stats"); + getServer().getPluginManager().disablePlugin(this); + return; + } else { + try { + if(conn!=null) { + conn.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + return; + } + } + if (!checkSchema()) { + LogError("Could not create table. Disabling Stats"); + getServer().getPluginManager().disablePlugin(this); + return; + } + convertFlatFiles(); + if(new File("MyGeneral.jar").exists()) { + Plugin myPlug = this.getServer().getPluginManager().getPlugin("MyGeneral"); + if (myPlug != null) { + LogInfo("Using MyGeneral Item Resolver"); + setItems(new myGeneralItemResolver(myPlug)); + } + } + } + public void onEnable() { + + stats = new HashMap(); + CreatePermissionResolver(); + enabled = true; + playerListener = new StatsPlayerListener(this); + blockListener = new StatsBlockListener(this); + entityListener = new StatsEntityListener(this); + vehicleListener = new StatsVehicleListener(this); + initialize(); + LogInfo("Plugin Enabled"); + for (Player p : getServer().getOnlinePlayers()) { + load(p); + } + + getServer().getScheduler().scheduleAsyncRepeatingTask(this, new SaveTask(this), StatsSettings.delay * 20, StatsSettings.delay * 20); + } + + public Player playerMatch(String name) { + List list = getServer().matchPlayer(name); + for (Player p : list) + if (p != null && p.getName().equalsIgnoreCase(name)) + return p; + return null; + } + + private static class SaveTask implements Runnable { + private Stats statsInstance; + + SaveTask(Stats plugin) { + statsInstance = plugin; + } + + @Override + public void run() { + if (!statsInstance.enabled) + return; + statsInstance.saveAll(); + } + } + + public void onDisable() { + getServer().getScheduler().cancelTasks(this); + saveAll(); + stats = null; + enabled = false; + updater.saveInternal(); + log.info(logprefix + " " + version + " Plugin Disabled"); + } + + public void initialize() { + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_JOIN, playerListener, Priority.Normal, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_COMMAND, playerListener, Priority.Normal, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_QUIT, playerListener, Priority.Normal, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_CHAT, playerListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_MOVE, playerListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_ANIMATION, playerListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_TELEPORT, playerListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_ITEM, playerListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_DROP_ITEM, playerListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_PICKUP_ITEM, playerListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_RESPAWN, playerListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.BLOCK_PLACED, blockListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.BLOCK_RIGHTCLICKED, blockListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.BLOCK_INTERACT, blockListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.BLOCK_IGNITE, blockListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.BLOCK_BREAK, blockListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.ENTITY_DEATH, entityListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.ENTITY_DAMAGED, entityListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.VEHICLE_ENTER, vehicleListener, Priority.Monitor, this); + getServer().getPluginManager().registerEvent(Event.Type.VEHICLE_MOVE, vehicleListener, Priority.Monitor, this); + } + + public void updateStat(Player player, String statType) { + updateStat(player, statType, 1); + } + + public void updateStat(Player player, String statType, int num) { + updateStat(player.getName(), defaultCategory, statType, num); + } + + public void updateStat(Player player, String statType, Block block) { + updateStat(player, statType, block, 1); + } + + public void updateStat(Player player, String statType, Block block, int num) { + if (block.getTypeId() <= 0) + return; + String blockName = getItems().getItem(block.getTypeId()); + updateStat(player.getName(), statType, blockName, num); + } + + + public void updateStat(Player player, String category, String key, int val) { + updateStat(player.getName(), category, key, val); + } + + public void updateStat(String player, String category, String key, int val) { + if (!enabled) + return; + if (player == null || player.length() < 1) { + log.log(Level.SEVERE, logprefix + " updateStat got empty player for [" + category + "] [" + key + "] [" + val + "]"); + return; + } + + PlayerStat ps = stats.get(player); + if (ps == null) + return; + Category cat = ps.get(category); + if (cat == null) + cat = ps.newCategory(category); + cat.add(key, val); + if (StatsSettings.debugOutput) + log.info(logprefix + " [DEBUG]: adding " + val + " to " + category + "/" + key + " of " + player); + } + public void updateStatUnsafe(String player, String category, String key, int val) { + if (!enabled) + return; + if (player == null || player.length() < 1) { + log.log(Level.SEVERE, logprefix + " updateStat got empty player for [" + category + "] [" + key + "] [" + val + "]"); + return; + } + + PlayerStat ps = stats.get(player); + if (ps == null) + return; + Category cat = ps.get(category); + if (cat == null) + cat = ps.newCategory(category); + cat.addUnsafe(key, val); + if (StatsSettings.debugOutput) + log.info(logprefix + " [DEBUG]: adding " + val + " to " + category + "/" + key + " of " + player + " without touching modifed flag"); + } + + protected void setStat(String player, String category, String key, int val) { + PlayerStat ps = stats.get(player); + if (ps == null) + return; + ps.put(category, key, val); + } + + public boolean isCat(String player, String category) { + PlayerStat ps = stats.get(player); + if (ps == null) + return false; + Category cat = ps.get(category); + if (cat == null) + return false; + return true; + } + + String viewStats(String player, String stat) { + return stat; + + } + + protected void updateMove(String player, Location from, Location to) { + if (!enabled) + return; + if (player == null || player.length() < 1) { + log.log(Level.SEVERE, logprefix + " updateMove got empty player for " + player); + return; + } + PlayerStat ps = stats.get(player); + if (ps == null) + return; + ps.UpdateMove(from.toVector().distance(to.toVector())); + + } + + protected void updateVehicleMove(String player, Vehicle vhc, Location from, Location to) { + if (!enabled) + return; + if (player == null || player.length() < 1) { + log.log(Level.SEVERE, logprefix + " updateVehicleMove got empty player for " + player); + return; + } + PlayerStat ps = stats.get(player); + if (ps == null) + return; + double Distance = from.toVector().distance(to.toVector()); + if (vhc instanceof org.bukkit.entity.Boat) { ps.UpdateBoatMove(Distance); } + else if (vhc instanceof org.bukkit.entity.Minecart) { ps.UpdateMinecartMove(Distance); } + } + + public String getCatEntries(String player, String category) { + PlayerStat ps = stats.get(player); + if (ps == null) + return "player not found"; + Set cats = ps.getCats(); + if (cats.size() == 0) + return "no categories founnd"; + + Category cat = ps.get(category); + if (cat == null) + return "category not found"; + Set entris = cat.getEntries(); + int length = (entris.size() - 1); + + int on = 0; + String list = ""; + for (String currentName : entris) { + if (currentName == null) { + ++on; + continue; + } + + list += (on >= length) ? currentName : currentName + ", "; + ++on; + } + list += " "; + return list; + } + + public String getCats(String player) { + PlayerStat ps = stats.get(player); + if (ps == null) + return "no categories found"; + Set cats = ps.getCats(); + if (cats.size() == 0) + return "no categories found"; + int length = (cats.size() - 1); + + int on = 0; + String list = ""; + for (String currentName : cats) { + if (currentName == null) { + ++on; + continue; + } + + list += (on >= length) ? currentName : currentName + ", "; + ++on; + } + list += " "; + return list; + } + + public boolean isStat(String player, String stat) { + PlayerStat ps = stats.get(player); + if (ps == null) + return false; + Category cat = ps.get("stats"); + if (cat == null) + return false; + if (cat.get(stat) == 0) + return false; + return true; + } + + public int get(String player, String category, String key) { + PlayerStat ps = stats.get(player); + if (ps == null) + return 0; + Category cat = ps.get(category.toLowerCase()); + if (cat == null && ps.get(category) != null) + cat = ps.get(category); + if (cat == null) + return 0; + if (cat.get(key) == 0 && cat.get(key.toLowerCase()) != 0) + return cat.get(key.toLowerCase()); + return cat.get(key); + } + + protected void load(Player player) { + if (!Perms().permission(player, "/stats")) { + if (StatsSettings.debugOutput) + log.info(logprefix + " player " + player.getName() + " has no /stats permission. Not loading/logging actions"); + return; + } + if (stats.containsKey(player.getName())) { + log.log(Level.SEVERE, logprefix + " attempting to load already loaded player: " + player.getName()); + return; + } + PlayerStat ps = new PlayerStatSQL(player.getName(), this); + ps.load(); + ps.skipTeleports = 2; + stats.put(player.getName(), ps); + if (StatsSettings.debugOutput) + log.info(logprefix + " player " + player.getName() + " has been loaded."); + } + + protected void unload(String player) { + entityListener.UnloadPlayer(player); + if (stats.containsKey(player)) { + PlayerStat ps = stats.get(player); + ps.save(); + stats.remove(player); + return; + } + } + + private void saveAll() { + if (StatsSettings.debugOutput) + log.info("Stats debug: saving " + stats.size() + " players stats"); + for(PlayerStat stat : stats.values()) { + if (stat == null || playerMatch(stat.getName()) == null) { + stat.unload = true; + continue; + } + updateStat(stat.getName(), defaultCategory, "playedfor", (int)StatsSettings.delay); + stat.save(); + } + for(PlayerStat stat : stats.values()) { + if(!stat.unload) continue; + log.log(Level.SEVERE, logprefix + " " + " onDisconnect did not happen, logging out+ unloading " + stat.getName() + " now"); + logout(stat.getName()); + unload(stat.getName()); + } + } + + public void setItems(itemResolver items) { + this.items = items; + } + + public itemResolver getItems() { + if (items == null) { + Plugin myPlug = this.getServer().getPluginManager().getPlugin("MyGeneral"); + if (myPlug != null) { + setItems(new myGeneralItemResolver(myPlug)); + } else + setItems(new hModItemResolver("items.txt")); + } + return items; + } + + public void login(Player player) { + int lastLog = get(player.getName(), defaultCategory, "lastlogin"); + int now = (int) (System.currentTimeMillis() / 1000L); + if (now - lastLog > StatsSettings.loginRateLimit) { + updateStat(player, "login"); + } + setStat(player.getName(), defaultCategory, "lastlogin", now); + } + + public void logout(String player) { + int now = (int) (System.currentTimeMillis() / 1000L); + setStat(player, defaultCategory, "lastlogout", now); + } + + public void updateVehicleEnter(String player, Vehicle vhc) { + if (!enabled) + return; + if (player == null || player.length() < 1) { + log.log(Level.SEVERE, logprefix + " updateVehicleEnter got empty player for " + player); + return; + } + PlayerStat ps = stats.get(player); + if (ps == null) + return; + int now = (int) (System.currentTimeMillis() / 1000L); + + if (vhc instanceof org.bukkit.entity.Boat) { + if (now - ps.getLastBoatEnter() > 60) { + updateStat(player, "boat", "enter", 1); + ps.setLastBoatEnter(now); + } + + } else if (vhc instanceof org.bukkit.entity.Minecart) { + if (now - ps.getLastMinecartEnter() > 60) { + updateStat(player, "minecart", "enter", 1); + ps.setLastMinecartEnter(now); + } + } + } + +} \ No newline at end of file diff --git a/com/nidefawl/Stats/StatsBlockListener.java b/com/nidefawl/Stats/StatsBlockListener.java new file mode 100755 index 0000000..bec6599 --- /dev/null +++ b/com/nidefawl/Stats/StatsBlockListener.java @@ -0,0 +1,181 @@ +package com.nidefawl.Stats; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockCanBuildEvent; +import org.bukkit.event.block.BlockDamageEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockIgniteEvent; +import org.bukkit.event.block.BlockInteractEvent; +import org.bukkit.event.block.BlockListener; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockRedstoneEvent; +import org.bukkit.event.block.BlockRightClickEvent; +import org.bukkit.event.block.LeavesDecayEvent; +import org.bukkit.event.block.SignChangeEvent; + +public class StatsBlockListener extends BlockListener { + private Stats plugin; + + public StatsBlockListener(Stats plugin) { + this.plugin = plugin; + } + + /** + * Called when a block is damaged (or broken) + * + * @param event + * Relevant event details + */ + @Override + public void onBlockDamage(BlockDamageEvent event) { + } + + /** + * Called when a sign is changed + * + * @param event + * Relevant event details + */ + @Override + public void onSignChange(SignChangeEvent event) { + } + + /** + * Called when a block is destroyed from burning + * + * @param event + * Relevant event details + */ + @Override + public void onBlockBurn(BlockBurnEvent event) { + } + + /** + * Called when a block is destroyed by a player. + * + * @param event + * Relevant event details + */ + @Override + public void onBlockBreak(BlockBreakEvent event) { + if (event.isCancelled()) + return; + if (!(event.getPlayer() instanceof Player)) + return; + plugin.updateStat(event.getPlayer(), "blockdestroy", event.getBlock()); + plugin.updateStat(event.getPlayer(), "totalblockdestroy"); + } + + /** + * Called when we try to place a block, to see if we can build it + */ + @Override + public void onBlockCanBuild(BlockCanBuildEvent event) { + } + + /** + * Called when a block flows (water/lava) + * + * @param event + * Relevant event details + */ + @Override + public void onBlockFlow(BlockFromToEvent event) { + } + + /** + * Called when a block gets ignited + * + * @param event + * Relevant event details + */ + @Override + public void onBlockIgnite(BlockIgniteEvent event) { + if (event.isCancelled()) + return; + if (!(event.getPlayer() instanceof Player)) + return; + plugin.updateStat(event.getPlayer(), "lighter"); + + } + + /** + * Called when block physics occurs + * + * @param event + * Relevant event details + */ + @Override + public void onBlockPhysics(BlockPhysicsEvent event) { + } + + /** + * Called when a player places a block + * + * @param event + * Relevant event details + */ + @Override + public void onBlockPlace(BlockPlaceEvent event) { + if (event.isCancelled()) + return; + if (!(event.getPlayer() instanceof Player)) + return; + plugin.updateStat(event.getPlayer(), "blockcreate", event.getBlockPlaced()); + plugin.updateStat(event.getPlayer(), "totalblockcreate"); + } + + /** + * Called when a block is interacted with + * + * @param event + * Relevant event details + */ + @Override + public void onBlockInteract(BlockInteractEvent event) { + if (event.isCancelled()) + return; + if (!event.isPlayer()) + return; + if (event.getBlock().getType() == Material.CHEST) { + plugin.updateStat((Player) event.getEntity(), "openchest"); + } + } + + /** + * Called when a player right clicks a block + * + * @param event + * Relevant event details + */ + @Override + public void onBlockRightClick(BlockRightClickEvent event) { + + } + + /** + * Called when redstone changes From: the source of the redstone change To: + * The redstone dust that changed + * + * @param event + * Relevant event details + */ + @Override + public void onBlockRedstoneChange(BlockRedstoneEvent event) { + } + + /** + * Called when leaves are decaying naturally + * + * @param event + * Relevant event details + */ + @Override + public void onLeavesDecay(LeavesDecayEvent event) { + } + +} \ No newline at end of file diff --git a/com/nidefawl/Stats/StatsEntityListener.java b/com/nidefawl/Stats/StatsEntityListener.java new file mode 100755 index 0000000..565a63a --- /dev/null +++ b/com/nidefawl/Stats/StatsEntityListener.java @@ -0,0 +1,446 @@ +package com.nidefawl.Stats; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.entity.CraftItem; +import org.bukkit.entity.*; +import org.bukkit.event.entity.*; + +import com.nidefawl.Stats.datasource.PlayerStat; +import com.nidefawl.Stats.event.StatsMobDeathByPlayerEvent; +import com.nidefawl.Stats.event.StatsPlayerDamagedPlayerEvent; +import com.nidefawl.Stats.event.StatsPlayerDeathByEntityEvent; +import com.nidefawl.Stats.event.StatsPlayerDeathByOtherEvent; +import com.nidefawl.Stats.event.StatsPlayerDeathByPlayerEvent; + +/** + * Handles all events fired in relation to entities + */ +public class StatsEntityListener extends EntityListener { + private Stats plugin; + HashMap> entsKilledByEnt = new HashMap>(); + HashMap otherDeathCauses = new HashMap(); + + private Entity getEntFromEnt(Entity entity, boolean setNull) { + Entity res = null; + ArrayList removeThat = new ArrayList(); + for (Entity ee : entsKilledByEnt.keySet()) { // cycle through Ents that + // dealt damage + + if (ee == null) + continue; + + ArrayList ents = entsKilledByEnt.get(ee); + if (ents.size() == 0) { + removeThat.add(ee); + continue; + } + for (Entity ent : ents) { // cycle through the ents that were + // damaged by ee + if (ent == null) + continue; + if (ent.equals(entity)) { + res = ee; // return ee, he killed that ent + break; + } + } + if(res!=null) { + if (setNull) { + entsKilledByEnt.get(res).remove(entity); + if (entsKilledByEnt.get(res).size() == 0) + removeThat.add(res); + } + break; + } + } + for (Entity e : removeThat) { + entsKilledByEnt.remove(e); + } + return res; + } + + public void UnloadPlayer(String player) { + ArrayList removeThat = new ArrayList(); + Entity playerEnt = null; + for (Entity ee : entsKilledByEnt.keySet()) { // cycle through Ents that + // dealt damage + if (ee == null) + continue; + + ArrayList ents = entsKilledByEnt.get(ee); + if (ents.size() == 0) { + removeThat.add(ee); + continue; + } + if (ee instanceof Player) { + if (((Player) ee).getName().equals(player)) { + playerEnt = ee; + } + } + Entity Remove = null; + for (Entity ent : ents) { // cycle through the ents that were + // damaged by ee + if (ent == null) + continue; + if (ent instanceof Player) { + if (((Player) ent).getName().equals(player)) { + Remove = ent; + break; + } + + } + } + if (Remove != null) + ents.remove(Remove); + } + for (Entity e : removeThat) { + entsKilledByEnt.remove(e); + } + if (playerEnt != null) + entsKilledByEnt.remove(playerEnt); + otherDeathCauses.remove(player); + } + + private void saveEntToEnt(Entity damager, Entity entity) { + if (!entsKilledByEnt.keySet().contains(damager)) { + ArrayList ents = new ArrayList(); + ents.add(entity); + entsKilledByEnt.put(damager, ents); + } else { + ArrayList ents = entsKilledByEnt.get(damager); + for (Entity ent : ents) { + if (ent.equals(entity)) + return; + } + ents.add(entity); + entsKilledByEnt.put(damager, ents); + } + } + public String getNiceDamageString(String cause) { + if(cause.equals("fire")) + return "burned to death"; + if(cause.equals("fall")) + return "died by falling down a cliff"; + if(cause.equals("drowning")) + return "died by drowning"; + if(cause.equals("entityexplosion")||cause.equals("explosion")) + return "was hit by an explosion"; + if(cause.equals("lava")) + return "had a bath in lava"; + if(cause.equals("suffocation")) + return "suffocated"; + if(cause.equals("entityattack")) + return "was hunt down by some creature"; + if(cause.equals("unknown")) + return "was killed by Herobrine"; + return "was killed by "+cause.toLowerCase(); + } + private void checkOtherDamage(EntityDamageEvent event) { + if (event.getEntity() instanceof Player) { + String cause = "unknown"; + switch (event.getCause()) { + case FIRE_TICK: + case FIRE: + cause = "fire"; + break; + case FALL: + cause = "fall"; + break; + case DROWNING: + cause = "drowning"; + break; + case BLOCK_EXPLOSION: + cause = "explosion"; + break; + case LAVA: + cause = "lava"; + break; + case SUFFOCATION: + cause = "suffocation"; + break; + case ENTITY_ATTACK: + cause = "entityattack"; + break; + case ENTITY_EXPLOSION: + cause = "entityexplosion"; + break; + case CONTACT: + if (event instanceof EntityDamageByBlockEvent) { + cause = ((EntityDamageByBlockEvent) event).getDamager().getType().toString(); + if (cause != null) + break; + } + case CUSTOM: + default: + cause = "unknown"; + } + plugin.updateStat((Player) event.getEntity(), "damagetaken", cause, event.getDamage()); + plugin.updateStat((Player) event.getEntity(), "damagetaken", "total", event.getDamage()); + if (event.getDamage() >= ((Player) event.getEntity()).getHealth() && plugin.stats.keySet().contains(((Player) event.getEntity()).getName())) { + otherDeathCauses.put((Player) event.getEntity(), cause); + } + + } + + } + public void sendEntList(Player player) { + int LoadedEnts = 0; + int nullEnts = 0; + for (Entity e : entsKilledByEnt.keySet()) { + if (e == null) { // WONDER IF THIS HAPPENS + nullEnts++; + continue; + } + String entName = "(unknown)"; + if (e instanceof Player) + entName = ((Player) e).getName(); + else + entName = StatsEntityListener.EntToString(e); + String entsList = ""; + for (Entity ee : entsKilledByEnt.get(e)) { + if (ee instanceof Player) + entsList += ((Player) ee).getName() + ", "; + else + entsList += StatsEntityListener.EntToString(ee) + " (" + ee.getEntityId() + ","+((LivingEntity)ee).getHealth()+"), "; + + } + if (entsList.length() > 2) + entsList.substring(0, entsList.length() - 2); + Messaging.send(player, "killed entitys for: " + entName + "(" + e.getEntityId() + "): " + entsList); + LoadedEnts++; + LoadedEnts += entsKilledByEnt.get(e).size(); + } + Messaging.send(player, StatsSettings.premessage + ChatColor.WHITE + "Total chached ents: " + LoadedEnts + ", Nulls: " + nullEnts); + + } + + private boolean checkEntDamage(Entity entity, Entity damager, int amount) { + + if (!(damager instanceof Player) && !(entity instanceof Player)) { + return true; + } + String typeName = null; + if ((damager instanceof Player) && (entity instanceof Player)) { + typeName = "Player"; + if(((LivingEntity) entity).getHealth()>0 ) { + StatsPlayerDamagedPlayerEvent damageevent = new StatsPlayerDamagedPlayerEvent((Player)damager,(Player)entity,amount); + plugin.getServer().getPluginManager().callEvent(damageevent); + if(damageevent.isCancelled()) { + return false; + } + plugin.updateStat((Player) damager, "damagedealt", typeName, amount); + plugin.updateStat((Player) entity, "damagetaken", typeName, amount); + if (amount >= ((LivingEntity) entity).getHealth() && plugin.stats.keySet().contains(((Player) damager).getName())) { + if (getEntFromEnt(entity, false) == null) + saveEntToEnt(damager, entity); + } + } + return true; + } + if (damager instanceof Player) { + typeName = EntToString(entity); + if (!(entity instanceof LivingEntity)) { + plugin.updateStat((Player) damager, "damagedealt", typeName, amount); + plugin.updateStat((Player) damager, "damagedealt", "total", amount); + return true; + } else { + if (((LivingEntity) entity).getHealth() > 0) { + plugin.updateStat((Player) damager, "damagedealt", typeName, amount); + plugin.updateStat((Player) damager, "damagedealt", "total", amount); + if (amount >= ((LivingEntity) entity).getHealth() && plugin.stats.keySet().contains(((Player) damager).getName())) { + if (getEntFromEnt(entity, false) == null) + saveEntToEnt(damager, entity); + } + } + } + + + } + if (entity instanceof Player) { + typeName = EntToString(damager); + if (((LivingEntity) entity).getHealth() > 0) { + plugin.updateStat((Player) entity, "damagetaken", typeName, amount); + plugin.updateStat((Player) entity, "damagetaken", "total", amount); + if (amount >= ((Player) entity).getHealth() && plugin.stats.keySet().contains(((Player) entity).getName())) { + if (getEntFromEnt(entity, false) == null) + saveEntToEnt(damager, entity); + } + } + } + return true; + } + + public StatsEntityListener(Stats plugin) { + this.plugin = plugin; + } + + @Override + public void onEntityDeath(EntityDeathEvent event) { + Entity e = getEntFromEnt(event.getEntity(), true); + if (event.getEntity() instanceof Player) { + + Player p = (Player) event.getEntity(); + PlayerStat ps = plugin.stats.get(p.getName()); + if (ps == null) + return; + ps.skipTeleports = 1; + plugin.updateStat(p, "deaths", "total", 1); + String otherReason = otherDeathCauses.get(p); + otherReason = otherReason != null ? otherReason : "unknown"; + if (StatsSettings.deathNotifying) { + if (e instanceof Player) { + + plugin.updateStat(((Player) e), "kills", "total", 1); + plugin.updateStat(((Player) e), "kills", "player", 1); + Messaging.broadcast(plugin.getServer(), p.getName() + " &4was killed by &8" + ((Player) e).getName()); + } else if (e instanceof LivingEntity) { + Messaging.broadcast(plugin.getServer(), p.getName() + " &4was killed by &8" + EntToString(e)); + } else if (otherReason != null) { + Messaging.broadcast(plugin.getServer(), p.getName() + " &4"+getNiceDamageString(otherReason)); + } else { + Messaging.broadcast(plugin.getServer(), p.getName() + " &4died"); + } + } + if (e instanceof LivingEntity) { + plugin.updateStat(p, "deaths", EntToString(e), 1); + if(e instanceof Player) { + StatsPlayerDeathByPlayerEvent ev = new StatsPlayerDeathByPlayerEvent((Player)event.getEntity(),(Player)e); + plugin.getServer().getPluginManager().callEvent(ev); + } else { + StatsPlayerDeathByEntityEvent ev = new StatsPlayerDeathByEntityEvent((Player)event.getEntity(),e); + plugin.getServer().getPluginManager().callEvent(ev); + } + } else if (otherReason != null) { + plugin.updateStat(p, "deaths", otherReason, 1); + StatsPlayerDeathByOtherEvent ev = new StatsPlayerDeathByOtherEvent((Player)event.getEntity(),otherReason); + plugin.getServer().getPluginManager().callEvent(ev); + } + otherDeathCauses.remove(p); + + } else if (event.getEntity() instanceof LivingEntity) { + if (e instanceof Player) { + plugin.updateStat((Player) e, "kills", "total", 1); + plugin.updateStat((Player) e, "kills", EntToString(event.getEntity()), 1); + StatsMobDeathByPlayerEvent ev = new StatsMobDeathByPlayerEvent((Player)e,event.getEntity()); + plugin.getServer().getPluginManager().callEvent(ev); + } + entsKilledByEnt.remove(e); + } + entsKilledByEnt.remove(event.getEntity()); + } + + + + @Override + public void onEntityCombust(EntityCombustEvent event) { + + } + + @Override + public void onEntityDamage(EntityDamageEvent event) { + if (event.isCancelled()) + return; + if(event instanceof EntityDamageByProjectileEvent) { + if(!checkEntDamage(event.getEntity(), ((EntityDamageByProjectileEvent)event).getDamager(), event.getDamage())) { + event.setCancelled(true); + return; + } + } else if(event instanceof EntityDamageByEntityEvent) { + if(!checkEntDamage(((EntityDamageByEntityEvent)event).getEntity(), ((EntityDamageByEntityEvent)event).getDamager(), event.getDamage())) { + event.setCancelled(true); + return; + } + } else if(event instanceof EntityDamageByBlockEvent) { + checkOtherDamage((EntityDamageByBlockEvent)event); + } else { + checkOtherDamage(event); + } + } + + @Override + public void onEntityExplode(EntityExplodeEvent event) { + } + + static final public String EntToString(Entity ent) { + if (ent == null) + return "(null)"; + if (ent instanceof Chicken) { + return "Chicken"; + } else if (ent instanceof Cow) { + return "Cow"; + } else if (ent instanceof Spider) { + return "Spider"; + } else if (ent instanceof Fish) { + return "Fish"; + } else if (ent instanceof Pig) { + return "Pig"; + } else if (ent instanceof Sheep) { + return "Sheep"; + } else if (ent instanceof Arrow) { + return "Arrow"; + } else if (ent instanceof Creeper) { + return "Creeper"; + } else if (ent instanceof PigZombie) { + return "PigZombie"; + } else if (ent instanceof Skeleton) { + return "Skeleton"; + } else if (ent instanceof Egg) { + return "Egg"; + } else if (ent instanceof Giant) { + return "Giant"; + } else if (ent instanceof FallingSand) { + return "FallingSand"; + } else if (ent instanceof Fireball) { + return "Fireball"; + } else if (ent instanceof Ghast) { + return "Ghast"; + } else if (ent instanceof Flying) { + return "Flying"; + } else if (ent instanceof Item) { + return "Item"; + } else if (ent instanceof CraftItem) { + return "ItemDrop"; + } else if (ent instanceof Painting) { + return "Painting"; + } else if (ent instanceof Player) { + return "Player"; + } else if (ent instanceof Snowball) { + return "Snowball"; + } else if (ent instanceof Zombie) { + return "Zombie"; + } else if (ent instanceof Monster) { + return "Monster"; + } else if (ent instanceof Squid) { + return "Squid"; + } else if (ent instanceof WaterMob) { + return "WaterMob"; + } else if (ent instanceof Slime) { + return "Slime"; + } else if (ent instanceof Animals) { + return "Animals"; + } else if (ent instanceof Creature) { + return "Creature"; + } else if (ent instanceof HumanEntity) { + return "HumanEntity"; + } else if (ent instanceof LivingEntity) { + return "LivingEntity"; + } else if (ent instanceof TNTPrimed) { + return "TNTPrimed"; + } else if (ent instanceof PoweredMinecart) { + return "PoweredMinecart"; + } else if (ent instanceof StorageMinecart) { + return "StorageMinecart"; + } else if (ent instanceof Minecart) { + return "Minecart"; + } else if (ent instanceof Boat) { + return "Boat"; + } else if (ent instanceof Vehicle) { + return "Vehicle"; + } else if (ent instanceof Entity) { + return "Entity"; + } + return "(unknown)"; + } +} \ No newline at end of file diff --git a/com/nidefawl/Stats/StatsPlayerListener.java b/com/nidefawl/Stats/StatsPlayerListener.java new file mode 100755 index 0000000..3f4e1ef --- /dev/null +++ b/com/nidefawl/Stats/StatsPlayerListener.java @@ -0,0 +1,248 @@ +package com.nidefawl.Stats; + +import org.bukkit.Material; +import org.bukkit.craftbukkit.entity.CraftItem; +import org.bukkit.event.player.*; + +import com.nidefawl.Stats.datasource.PlayerStat; + +public class StatsPlayerListener extends PlayerListener { + protected Stats plugin; + + public StatsPlayerListener(Stats plugin) { + this.plugin = plugin; + } + + /** + * Called when a player leaves a server + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerQuit(PlayerEvent event) { + plugin.logout(event.getPlayer().getName()); + plugin.unload(event.getPlayer().getName()); + + } + + /** + * Called when a player sends a chat message + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerChat(PlayerChatEvent event) { + if (event.isCancelled()) + return; + plugin.updateStat(event.getPlayer(), "chat"); + plugin.updateStat(event.getPlayer(), "chatletters", event.getMessage().length()); + } + + /** + * Called when a player attempts to use a command + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerCommand(PlayerChatEvent event) { + if (event.isCancelled()) + return; + plugin.updateStat(event.getPlayer(), "command"); + } + + /** + * Called when a player attempts to move location in a world + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerMove(PlayerMoveEvent event) { + if (event.isCancelled()) + return; + plugin.updateMove(event.getPlayer().getName(), event.getFrom(), event.getTo()); + + } + + /** + * Called when a player attempts to teleport to a new location in a world + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerTeleport(PlayerMoveEvent event) { + if (event.isCancelled()) + return; + if (event.getTo().equals(event.getPlayer().getWorld().getSpawnLocation())) + return; + PlayerStat ps = plugin.stats.get(event.getPlayer().getName()); + if (ps == null) + return; + if (ps.skipTeleports>0) { + ps.skipTeleports--; + return; + } + plugin.updateStat(event.getPlayer(), "teleport"); + } + + /** + * Called when a player uses an item + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerItem(PlayerItemEvent event) { + if (event.isCancelled()||event.getBlockFace()==null) + return; + switch (event.getMaterial()) { + case LAVA_BUCKET: + case WATER_BUCKET: + case SIGN: + case BUCKET: + case CAKE_BLOCK: + case FLINT_AND_STEEL: + case TNT: + plugin.updateStat(event.getPlayer(), "itemuse", plugin.getItems().getItem(event.getMaterial().getId()), 1); + break; + default: + break; + } + + } + + /** + * Called when a player attempts to log in to the server + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerJoin(PlayerEvent event) { + plugin.load(event.getPlayer()); + plugin.login(event.getPlayer()); + } + + /** + * Called when a player plays an animation, such as an arm swing + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerAnimation(PlayerAnimationEvent event) { + if (event.getAnimationType() == PlayerAnimationType.ARM_SWING && event.getPlayer().getItemInHand().getType() == Material.AIR) { + plugin.updateStat(event.getPlayer(), "armswing"); + } + } + + /** + * Called when a player throws an egg and it might hatch + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerEggThrow(PlayerEggThrowEvent event) { + plugin.updateStat(event.getPlayer(), "eggthrow"); + } + + /** + * Called when a player drops an item from their inventory + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerDropItem(PlayerDropItemEvent event) { + if(event.getItemDrop()==null) return; + if (event.getItemDrop() instanceof CraftItem) { + if(((CraftItem)event.getItemDrop()).getItemStack() == null) return; + plugin.updateStat(event.getPlayer(), "itemdrop", plugin.getItems().getItem(((CraftItem)event.getItemDrop()).getItemStack().getTypeId()), 1); + } + + } + + /** + * Called when a player gets kicked from the server + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerKick(PlayerKickEvent event) { + if (event.isCancelled()) + return; + plugin.updateStat(event.getPlayer(), "kick"); + } + + /** + * Called when a player respawns + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerRespawn(PlayerRespawnEvent event) { + plugin.updateStat(event.getPlayer(), "respawn"); + } + + /** + * Called when a player attempts to log in to the server + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerLogin(PlayerLoginEvent event) { + } + + /** + * Called when a player picks an item up off the ground + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerPickupItem(PlayerPickupItemEvent event) { + if(event.getItem()==null) return; + if (event.getItem() instanceof CraftItem) { + if(((CraftItem)event.getItem()).getItemStack() == null) return; + plugin.updateStat(event.getPlayer(), "itempickup", plugin.getItems().getItem(((CraftItem)event.getItem()).getItemStack().getTypeId()), 1); + } + } + + /** + * Called when a player opens an inventory + * + * @param event + * Relevant event details + */ + @Override + public void onInventoryOpen(PlayerInventoryEvent event) { + } + + /** + * Called when a player changes their held item + * + * @param event + * Relevant event details + */ + @Override + public void onItemHeldChange(PlayerItemHeldEvent event) { + } + + /** + * Called when a player toggles sneak mode + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerToggleSneak(PlayerToggleSneakEvent event) { + } +} diff --git a/com/nidefawl/Stats/StatsSettings.java b/com/nidefawl/Stats/StatsSettings.java new file mode 100755 index 0000000..e442d1f --- /dev/null +++ b/com/nidefawl/Stats/StatsSettings.java @@ -0,0 +1,74 @@ +package com.nidefawl.Stats; + +import java.io.File; + +import org.bukkit.ChatColor; + + + +public class StatsSettings { + + public static String directory = "stats"; + public static String liteDb; + public static int loginRateLimit = 3600; + public static long delay = 30; + public static String dbUrl; + public static String dbUsername; + public static String dbPassword; + public static String dbTable; + public static boolean deathNotifying; + public static boolean debugOutput; + public static boolean autoUpdate; + public static boolean useMySQL; + public static String libPath; + public static String premessage = ChatColor.YELLOW + "[Stats]" + ChatColor.WHITE; + + public static void initialize() { + if (!new File(directory).exists()) { + try { + (new File(directory)).mkdir(); + } catch (Exception ex) { + Stats.LogError("Unable to create " + directory + " directory"); + } + Stats.LogInfo("directory '" + directory + "' created!"); + Stats.LogInfo("make sure to check stats/stats.properties and mysql.properties "); + } + liteDb = "jdbc:sqlite:" + directory + File.separator + "stats.db"; + loadPropertiesFiles(); + } + + public static void onDisable() { + } + + private static void loadPropertiesFiles() { + + PropertiesFile properties = new PropertiesFile(new File(directory + File.separator + "stats.properties")); + delay = (long) properties.getInt("stats-save-delay", 30, "delay between automatic saving (seconds)"); + loginRateLimit = properties.getInt("stats-login-delay", 3600, "limit between login-count increases"); + + boolean useSQL = properties.getBoolean("stats-use-sql"); + properties.remove("stats-use-sql"); + String dataSource = properties.getString("stats-datasource", useSQL?"mysql":"sqlite", "dropped flatfile support"); + if(dataSource.toLowerCase().equals("mysql")) { + useMySQL = true; + } else { + useMySQL = false; + } + + premessage = properties.getString("stats-message-prefix", "&e[Stats]&f", ""); + debugOutput = properties.getBoolean("stats-debug", false, ""); + deathNotifying = properties.getBoolean("stats-deathnotify", true, ""); + autoUpdate = properties.getBoolean("stats-autoUpdate", true, ""); + properties.save(); + if (premessage.length() > 0) + if (premessage.charAt(premessage.length() - 1) != ' ') + premessage += " "; + properties = new PropertiesFile(new File("mysql.properties")); + dbUrl = properties.getString("sql-db", "jdbc:mysql://localhost:3306/minecraft", ""); + dbUsername = properties.getString("sql-user", "root", ""); + dbPassword = properties.getString("sql-pass", "root", ""); + dbTable = properties.getString("sql-table-stats", "stats", ""); + properties.save(); + } + +} diff --git a/com/nidefawl/Stats/StatsVehicleListener.java b/com/nidefawl/Stats/StatsVehicleListener.java new file mode 100755 index 0000000..1c1d5d8 --- /dev/null +++ b/com/nidefawl/Stats/StatsVehicleListener.java @@ -0,0 +1,89 @@ +package com.nidefawl.Stats; + +import org.bukkit.entity.Player; +import org.bukkit.event.vehicle.*; + +/** + * Listener for vehicle events. + * + * @author sk89q + */ +public class StatsVehicleListener extends VehicleListener { + private Stats plugin; + + public StatsVehicleListener(Stats plugin) { + this.plugin = plugin; + } + + /** + * Called when a vehicle is created by a player. This hook will be called + * for all vehicles created. + * + * @param event + */ + @Override + public void onVehicleCreate(VehicleCreateEvent event) { + } + + /** + * Called when a vehicle is damaged by the player. + * + * @param event + */ + @Override + public void onVehicleDamage(VehicleDamageEvent event) { + } + + /** + * Called when a vehicle collides with a block. + * + * @param event + */ + @Override + public void onVehicleBlockCollision(VehicleBlockCollisionEvent event) { + } + + /** + * Called when a vehicle collides with an entity. + * + * @param event + */ + @Override + public void onVehicleEntityCollision(VehicleEntityCollisionEvent event) { + } + + /** + * Called when an entity enters a vehicle. + * + * @param event + */ + @Override + public void onVehicleEnter(VehicleEnterEvent event) { + if (!(event.getEntered() instanceof Player)) + return; + plugin.updateVehicleEnter(((Player) event.getEntered()).getName(), event.getVehicle()); + } + + /** + * Called when an entity exits a vehicle. + * + * @param event + */ + @Override + public void onVehicleExit(VehicleExitEvent event) { + } + + /** + * Called when an vehicle moves. + * + * @param event + */ + @Override + public void onVehicleMove(VehicleMoveEvent event) { + if (event.getVehicle() == null) + return; + if (!(event.getVehicle().getPassenger() instanceof Player)) + return; + plugin.updateVehicleMove(((Player) event.getVehicle().getPassenger()).getName(), event.getVehicle(), event.getFrom(), event.getTo()); + } +} \ No newline at end of file diff --git a/com/nidefawl/Stats/datasource/Category.java b/com/nidefawl/Stats/datasource/Category.java new file mode 100755 index 0000000..9921763 --- /dev/null +++ b/com/nidefawl/Stats/datasource/Category.java @@ -0,0 +1,60 @@ +package com.nidefawl.Stats.datasource; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; +import java.util.logging.Logger; + + +public class Category { + public boolean modified = false; + protected HashMap stats; + static final Logger log = Logger.getLogger("Minecraft"); + + Category() { + stats = new HashMap(); + modified = false; + } + + public int get(String name) { + Integer data = stats.get(name); + if (data == null) + return 0; + return data; + } + + public Set getEntries() { + return stats.keySet(); + } + + public void put(String name, Integer value) { + stats.put(name, value); + modified = true; + } + + public void set(String name, Integer value) { + put(name, value); + } + + public void add(String name, Integer value) { + if (!stats.containsKey(name)) { + put(name, value); + return; + } + Integer oldval = stats.get(name); + put(name, value + oldval); + } + + public void addUnsafe(String name, Integer value) { + if (!stats.containsKey(name)) { + put(name, value); + return; + } + Integer oldval = stats.get(name); + stats.put(name, value+oldval); + } + + Iterator iterator() { + return stats.keySet().iterator(); + } +} \ No newline at end of file diff --git a/com/nidefawl/Stats/datasource/PlayerStat.java b/com/nidefawl/Stats/datasource/PlayerStat.java new file mode 100755 index 0000000..01d78db --- /dev/null +++ b/com/nidefawl/Stats/datasource/PlayerStat.java @@ -0,0 +1,136 @@ +package com.nidefawl.Stats.datasource; + +import java.io.File; +import java.util.HashMap; +import java.util.Set; +import java.util.logging.Logger; + +import org.bukkit.block.Block; + +public abstract class PlayerStat { + private String name; + public HashMap categories; + static final Logger log = Logger.getLogger("Minecraft"); + private double moveDistance = 0; + private double minecartDistance = 0; + private double boatDistance = 0; + private int lastBoatEnter = 0; + private int lastMinecartEnter = 0; + public int skipTeleports = 0; + Block lastFace = null; + public boolean unload = false; + + PlayerStat(String name) { + this.name = name; + this.categories = new HashMap(); + int now = (int) (System.currentTimeMillis() / 1000L); + lastBoatEnter = lastMinecartEnter = now; + } + + public Category get(String name) { + return categories.get(name); + } + + public Set getCats() { + return categories.keySet(); + } + + public Category newCategory(String name) { + Category category = new Category(); + categories.put(name, category); + return category; + } + + public void put(String category, String key, int val) { + Category cat; + if (!categories.containsKey(category)) + cat = newCategory(category); + else + cat = categories.get(category); + + cat.put(key, val); + } + + protected void copy(PlayerStat from) + { + this.name = from.name; + this.categories = new HashMap(from.categories); + } + + public void convertFlatFile(String directory) { + PlayerStat psold = new PlayerStatFile(name, directory); + psold.load(); + copy(psold); + + String location = directory + "/" + name + ".txt"; + File fold = new File(location); + File fnew = new File(location + ".bak"); + fold.renameTo(fnew); + } + + public abstract void save(); + + public abstract void load(); + + public void UpdateMove(double distance) { + moveDistance += distance; + if(moveDistance>10.0F) { + Category cat = categories.get("stats"); + if (cat == null) + cat = newCategory("stats"); + cat.add("move", 10); + moveDistance = 0; + } + } + public void UpdateMinecartMove(double distance) { + minecartDistance += distance; + if(minecartDistance>=10.0F) { + Category cat = categories.get("minecart"); + if (cat == null) + cat = newCategory("minecart"); + cat.add("move", 10); + minecartDistance = 0; + } + } + + public void UpdateBoatMove(double distance) { + boatDistance += distance; + if(boatDistance>=10.0F) { + Category cat = categories.get("boat"); + if (cat == null) + cat = newCategory("boat"); + cat.add("move", 10); + boatDistance = 0; + } + } + + public void setLastMinecartEnter(int lastMinecartEnter) { + this.lastMinecartEnter = lastMinecartEnter; + } + + public int getLastMinecartEnter() { + return lastMinecartEnter; + } + + public void setLastBoatEnter(int lastBoatEnter) { + this.lastBoatEnter = lastBoatEnter; + } + + public int getLastBoatEnter() { + return lastBoatEnter; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the name + */ + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/com/nidefawl/Stats/datasource/PlayerStatFile.java b/com/nidefawl/Stats/datasource/PlayerStatFile.java new file mode 100755 index 0000000..07a4f61 --- /dev/null +++ b/com/nidefawl/Stats/datasource/PlayerStatFile.java @@ -0,0 +1,54 @@ +package com.nidefawl.Stats.datasource; + +import java.io.File; +import java.util.Scanner; +import java.util.logging.Logger; +import java.util.logging.Level; + +import org.bukkit.ChatColor; + +import com.nidefawl.Stats.Stats; + +public class PlayerStatFile extends PlayerStat { + private String directory; + static final Logger log = Logger.getLogger("Minecraft"); + public final String logprefix = ChatColor.YELLOW + "[Stats-" + Stats.version + "] " + ChatColor.WHITE; + + PlayerStatFile(String name, String directory) { + super(name); + this.directory = directory; + } + + public void save() { + } + + public void load() { + String location = directory + File.separator + getName() + ".txt"; + + if (!new File(location).exists()) { + return; + } + + try { + Scanner scanner = new Scanner(new File(location)); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.startsWith("#") || line.equals("")) + continue; + String[] split = line.split(":"); + if (split.length != 3) { + log.log(Level.SEVERE, logprefix + " Malformed line (" + line + ") in " + location); + continue; + } + String category = split[0]; + String key = split[1]; + Integer val = Integer.parseInt(split[2]); + + put(category, key, val); + } + } catch (Exception ex) { + log.log(Level.SEVERE, logprefix + " Exception while reading " + location, ex); + return; + } + } +} \ No newline at end of file diff --git a/com/nidefawl/Stats/datasource/PlayerStatSQL.java b/com/nidefawl/Stats/datasource/PlayerStatSQL.java new file mode 100755 index 0000000..f969303 --- /dev/null +++ b/com/nidefawl/Stats/datasource/PlayerStatSQL.java @@ -0,0 +1,104 @@ +package com.nidefawl.Stats.datasource; + +import java.util.logging.Logger; +import java.sql.*; + +import com.nidefawl.Stats.Stats; +import com.nidefawl.Stats.StatsSettings; + + +public class PlayerStatSQL extends PlayerStat { + static final Logger log = Logger.getLogger("Minecraft"); + public final String logprefix = "[Stats-" + Stats.version + "]"; + Stats plugin = null; + + public PlayerStatSQL(String name, Stats plugin) { + super(name); + this.plugin = plugin; + } + + public void save() { + Connection conn = null; + PreparedStatement ps = null; + + try { + conn = StatsSQLConnectionManager.getConnection(); + conn.setAutoCommit(false); + for(String catName : categories.keySet()) { + Category cat = categories.get(catName); + if (!cat.modified) { + continue; + } + for(String statName : cat.stats.keySet()) { + int value = cat.get(statName); + ps = conn.prepareStatement("UPDATE " + StatsSettings.dbTable + " set value=? where player = ? and category = ? and stat = ?;", Statement.RETURN_GENERATED_KEYS); + + ps.setInt(1, value); + ps.setString(2, getName()); + ps.setString(3, catName); + ps.setString(4, statName); + if(ps.executeUpdate()==0) { + ps = conn.prepareStatement("INSERT INTO " + StatsSettings.dbTable + " (player,category,stat,value) VALUES(?,?,?,?);", Statement.RETURN_GENERATED_KEYS); + ps.setString(1, getName()); + ps.setString(2, catName); + ps.setString(3, statName); + ps.setInt(4, value); + ps.executeUpdate(); + } + } + cat.modified=false; + } + conn.commit(); + } catch (SQLException ex) { + Stats.LogError("SQL exception: " + ex.getMessage()); + ex.printStackTrace(); + } finally { + try { + if (ps != null) { + ps.close(); + } + if(conn != null) { + conn.close(); + } + } catch (SQLException ex) { + Stats.LogError("SQL exception: " + ex.getMessage()); + ex.printStackTrace(); + } + } + } + + public void load() { + if (!plugin.enabled) + return; + + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + + try { + conn = StatsSQLConnectionManager.getConnection(); + ps = conn.prepareStatement("SELECT * from " + StatsSettings.dbTable + " where player = ?"); + ps.setString(1, getName()); + rs = ps.executeQuery(); + while (rs.next()) { + put(rs.getString("category"), rs.getString("stat"), rs.getInt("value")); + } + } catch (SQLException ex) { + Stats.LogError("SQL exception: " + ex.getMessage()); + ex.printStackTrace(); + } finally { + try { + if (rs != null) + rs.close(); + if (ps != null) + ps.close(); + if(conn != null) { + conn.close(); + } + } catch (SQLException ex) { + Stats.LogError("SQL exception (on close): " + ex.getMessage()); + ex.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/com/nidefawl/Stats/datasource/StatsSQLConnectionManager.java b/com/nidefawl/Stats/datasource/StatsSQLConnectionManager.java new file mode 100755 index 0000000..3030da2 --- /dev/null +++ b/com/nidefawl/Stats/datasource/StatsSQLConnectionManager.java @@ -0,0 +1,37 @@ +package com.nidefawl.Stats.datasource; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +import com.nidefawl.Stats.Stats; +import com.nidefawl.Stats.StatsSettings; + + +public class StatsSQLConnectionManager { + public static Connection getConnection() { + try { + if (StatsSettings.useMySQL) { + Class.forName("com.mysql.jdbc.Driver"); + Connection ret = DriverManager.getConnection(StatsSettings.dbUrl, StatsSettings.dbUsername, StatsSettings.dbPassword); + ret.setAutoCommit(true); + return ret; + } else { + Class.forName("org.sqlite.JDBC"); + Connection ret = DriverManager.getConnection(StatsSettings.liteDb); + ret.setAutoCommit(true); + return ret; + } + } catch (SQLException e) { + Stats.LogError("Error getting SQL-connection: "+e.getMessage()); + e.printStackTrace(); + return null; + } catch (ClassNotFoundException e) { + Stats.LogError("Error getting SQL-connection: "+e.getMessage()); + e.printStackTrace(); + return null; + } + } + + +} diff --git a/com/nidefawl/Stats/event/StatsListener.java b/com/nidefawl/Stats/event/StatsListener.java new file mode 100755 index 0000000..c78f7a0 --- /dev/null +++ b/com/nidefawl/Stats/event/StatsListener.java @@ -0,0 +1,51 @@ +package com.nidefawl.Stats.event; + +import org.bukkit.event.CustomEventListener; +import org.bukkit.event.Event; +import org.bukkit.event.Listener; + +public class StatsListener extends CustomEventListener implements Listener { + + public StatsListener() { + + } + public void onCustomEvent(Event event) { + if (event instanceof StatsMobDeathByPlayerEvent) { + onStatsMobDeathByPlayerEvent((StatsMobDeathByPlayerEvent) event); + } else if (event instanceof StatsPlayerDamagedPlayerEvent) { + onStatsPlayerDamagedPlayerEvent((StatsPlayerDamagedPlayerEvent) event); + } else if (event instanceof StatsPlayerDeathByEntityEvent) { + onStatsPlayerDeathByEntityEvent((StatsPlayerDeathByEntityEvent) event); + } else if (event instanceof StatsPlayerDeathByPlayerEvent) { + onStatsPlayerDeathByPlayerEvent((StatsPlayerDeathByPlayerEvent) event); + } else if (event instanceof StatsPlayerDeathByOtherEvent) { + onStatsPlayerDeathByOtherEvent((StatsPlayerDeathByOtherEvent) event); + }else if (event instanceof StatsPlayerMoveEvent) { + onStatsPlayerMoveEvent((StatsPlayerMoveEvent) event); + } + } + + public void onStatsPlayerMoveEvent(StatsPlayerMoveEvent event) { + + } + + public void onStatsPlayerDeathByOtherEvent(StatsPlayerDeathByOtherEvent event) { + + } + + public void onStatsPlayerDeathByPlayerEvent(StatsPlayerDeathByPlayerEvent event) { + + } + + public void onStatsPlayerDeathByEntityEvent(StatsPlayerDeathByEntityEvent event) { + + } + + public void onStatsPlayerDamagedPlayerEvent(StatsPlayerDamagedPlayerEvent event) { + + } + + public void onStatsMobDeathByPlayerEvent(StatsMobDeathByPlayerEvent event) { + } + +} diff --git a/com/nidefawl/Stats/event/StatsMobDeathByPlayerEvent.java b/com/nidefawl/Stats/event/StatsMobDeathByPlayerEvent.java new file mode 100755 index 0000000..a789827 --- /dev/null +++ b/com/nidefawl/Stats/event/StatsMobDeathByPlayerEvent.java @@ -0,0 +1,57 @@ +package com.nidefawl.Stats.event; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +public class StatsMobDeathByPlayerEvent extends org.bukkit.event.Event implements Cancellable { + private Entity entity; + private Player player; + boolean isCancelled; + + @Override + public boolean isCancelled() { + return this.isCancelled; + } + + @Override + public void setCancelled(boolean arg0) { + isCancelled = arg0; + } + + public StatsMobDeathByPlayerEvent(Player player, Entity entity) { + super("StatsPlayerDamageEvent"); + this.entity = entity; + this.player = player; + isCancelled=false; + } + + /** + * @param entity the entity to set + */ + public void setEntity(Entity entity) { + this.entity = entity; + } + + /** + * @return the entity + */ + public Entity getEntity() { + return entity; + } + + /** + * @param player the player to set + */ + public void setPlayer(Player player) { + this.player = player; + } + + /** + * @return the player + */ + public Player getPlayer() { + return player; + } + +} diff --git a/com/nidefawl/Stats/event/StatsPlayerDamagedPlayerEvent.java b/com/nidefawl/Stats/event/StatsPlayerDamagedPlayerEvent.java new file mode 100755 index 0000000..d19a14f --- /dev/null +++ b/com/nidefawl/Stats/event/StatsPlayerDamagedPlayerEvent.java @@ -0,0 +1,71 @@ +package com.nidefawl.Stats.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +public class StatsPlayerDamagedPlayerEvent extends org.bukkit.event.Event implements Cancellable { + private Player player; + private Player damaged; + private int damage; + boolean isCancelled; + + @Override + public boolean isCancelled() { + return this.isCancelled; + } + + @Override + public void setCancelled(boolean arg0) { + isCancelled = arg0; + } + public StatsPlayerDamagedPlayerEvent(Player player, Player damaged, int damage) { + super("StatsPlayerDamageEvent"); + this.player = player; + this.damaged = damaged; + this.damage = damage; + isCancelled=false; + } + + /** + * @param player the player to set + */ + public void setPlayer(Player player) { + this.player = player; + } + + /** + * @return the player + */ + public Player getPlayer() { + return player; + } + + /** + * @param damage the damage to set + */ + public void setDamage(int damage) { + this.damage = damage; + } + + /** + * @return the damage + */ + public int getDamage() { + return damage; + } + + /** + * @param damaged the damaged to set + */ + public void setDamagedPlayer(Player damaged) { + this.damaged = damaged; + } + + /** + * @return the damaged + */ + public Player getDamagedPlayer() { + return damaged; + } + +} diff --git a/com/nidefawl/Stats/event/StatsPlayerDeathByEntityEvent.java b/com/nidefawl/Stats/event/StatsPlayerDeathByEntityEvent.java new file mode 100755 index 0000000..8f7ffa3 --- /dev/null +++ b/com/nidefawl/Stats/event/StatsPlayerDeathByEntityEvent.java @@ -0,0 +1,57 @@ +package com.nidefawl.Stats.event; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +public class StatsPlayerDeathByEntityEvent extends org.bukkit.event.Event implements Cancellable { + private Player player; + private Entity entity; + boolean isCancelled; + + @Override + public boolean isCancelled() { + return this.isCancelled; + } + + @Override + public void setCancelled(boolean arg0) { + isCancelled = arg0; + } + + public StatsPlayerDeathByEntityEvent(Player player, Entity entity) { + super("StatsPlayerDamageEvent"); + this.player = player; + this.entity = entity; + isCancelled=false; + } + /** + * @param player the player to set + */ + public void setPlayer(Player player) { + this.player = player; + } + + /** + * @return the player + */ + public Player getPlayer() { + return player; + } + + /** + * @param entity the entity to set + */ + public void setEntity(Entity entity) { + this.entity = entity; + } + + /** + * @return the entity + */ + public Entity getEntity() { + return entity; + } + + +} diff --git a/com/nidefawl/Stats/event/StatsPlayerDeathByOtherEvent.java b/com/nidefawl/Stats/event/StatsPlayerDeathByOtherEvent.java new file mode 100755 index 0000000..ebbd4b8 --- /dev/null +++ b/com/nidefawl/Stats/event/StatsPlayerDeathByOtherEvent.java @@ -0,0 +1,56 @@ +package com.nidefawl.Stats.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +public class StatsPlayerDeathByOtherEvent extends org.bukkit.event.Event implements Cancellable { + private Player player; + private String reason; + boolean isCancelled; + + @Override + public boolean isCancelled() { + return this.isCancelled; + } + + @Override + public void setCancelled(boolean arg0) { + isCancelled = arg0; + } + + public StatsPlayerDeathByOtherEvent(Player player, String reason) { + super("StatsPlayerDamageEvent"); + this.player = player; + this.reason = reason; + isCancelled=false; + } + + /** + * @param player the player to set + */ + public void setPlayer(Player player) { + this.player = player; + } + + /** + * @return the player + */ + public Player getPlayer() { + return player; + } + + /** + * @param reason the reason to set + */ + public void setReason(String reason) { + this.reason = reason; + } + + /** + * @return the reason + */ + public String getReason() { + return reason; + } + +} diff --git a/com/nidefawl/Stats/event/StatsPlayerDeathByPlayerEvent.java b/com/nidefawl/Stats/event/StatsPlayerDeathByPlayerEvent.java new file mode 100755 index 0000000..c134a33 --- /dev/null +++ b/com/nidefawl/Stats/event/StatsPlayerDeathByPlayerEvent.java @@ -0,0 +1,55 @@ +package com.nidefawl.Stats.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +public class StatsPlayerDeathByPlayerEvent extends org.bukkit.event.Event implements Cancellable { + private Player player; + private Player killer; + boolean isCancelled; + + @Override + public boolean isCancelled() { + return this.isCancelled; + } + + @Override + public void setCancelled(boolean arg0) { + isCancelled = arg0; + } + + public StatsPlayerDeathByPlayerEvent(Player player, Player killer) { + super("StatsPlayerDamageEvent"); + this.player = player; + this.killer = killer; + isCancelled=false; + } + /** + * @param player the player to set + */ + public void setPlayer(Player player) { + this.player = player; + } + + /** + * @return the player + */ + public Player getPlayer() { + return player; + } + + /** + * @param killer the killer to set + */ + public void setKiller(Player killer) { + this.killer = killer; + } + + /** + * @return the killer + */ + public Player getKiller() { + return killer; + } + +} diff --git a/com/nidefawl/Stats/event/StatsPlayerMoveEvent.java b/com/nidefawl/Stats/event/StatsPlayerMoveEvent.java new file mode 100755 index 0000000..72727e4 --- /dev/null +++ b/com/nidefawl/Stats/event/StatsPlayerMoveEvent.java @@ -0,0 +1,36 @@ +package com.nidefawl.Stats.event; + +public class StatsPlayerMoveEvent extends org.bukkit.event.Event{ + private String player; + private int distance; + public StatsPlayerMoveEvent(String player, int distance) { + super("StatsPlayerDamageEvent"); + this.player = player; + this.distance = distance; + } + /** + * @param player the player to set + */ + public void setPlayer(String player) { + this.player = player; + } + /** + * @return the player + */ + public String getPlayer() { + return player; + } + /** + * @param distance the distance to set + */ + public void setDistance(int distance) { + this.distance = distance; + } + /** + * @return the distance + */ + public int getDistance() { + return distance; + } + +} diff --git a/com/nidefawl/Stats/util/Updater.java b/com/nidefawl/Stats/util/Updater.java new file mode 100755 index 0000000..14fb950 --- /dev/null +++ b/com/nidefawl/Stats/util/Updater.java @@ -0,0 +1,427 @@ +/** + * This file is taken from LWC (https://github.com/Hidendra/LWC) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nidefawl.Stats.util; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Logger; + +import com.nidefawl.Stats.Stats; + + +public class Updater { + + /** + * The logging object for this class + */ + public final static Logger logger = Logger.getLogger("Minecraft"); + + /** + * URL to the base update site + */ + private final static String UPDATE_SITE = "http://dev.craftland.org/stats/"; + + /** + * File used to obtain the latest version + */ + private final static String VERSION_FILE = "VERSION"; + + /** + * File used for the distribution + */ + private final static String DIST_FILE = "Stats.jar"; + + /** + * List of files to download + */ + private List needsUpdating = new ArrayList(); + + /** + * Internal config + */ + private HashMap config = new HashMap(); + + public Updater() { + //enableSSL(); + + /* + * Default config values + */ + config.put("sqlite", "1.00"); + + /* + * Parse the internal config + */ + parseInternalConfig(); + } + + /** + * Check for dependencies + * + * @return true if Stats should be reloaded + */ + public void check() { + String[] paths = new String[] { "lib/sqlite.jar", getFullNativeLibraryPath(), "lib/mysql.jar" }; + + for (String path : paths) { + File file = new File(path); + + if (file != null && !file.exists() && !file.isDirectory()) { + UpdaterFile updaterFile = new UpdaterFile(UPDATE_SITE + path); + updaterFile.setLocalLocation(path); + + needsUpdating.add(updaterFile); + } + } + + double latestVersion = getLatestPluginVersion(); + + if (latestVersion > Stats.version) { + logger.info("Update detected for Stats"); + logger.info("Latest version: " + latestVersion); + } + } + + /** + * Force update of binaries + */ + private void requireBinaryUpdate() { + String[] paths = new String[] { "lib/sqlite.jar", getFullNativeLibraryPath() , "lib/mysql.jar" }; + + for (String path : paths) { + UpdaterFile updaterFile = new UpdaterFile(UPDATE_SITE + path); + updaterFile.setLocalLocation(path); + + needsUpdating.add(updaterFile); + } + } + + /** + * Check to see if the distribution is outdated + * + * @return + */ + public boolean checkDist() { + + double latestVersion = getLatestPluginVersion(); + + if (latestVersion > Stats.version) { + UpdaterFile updaterFile = new UpdaterFile(UPDATE_SITE + DIST_FILE); + updaterFile.setLocalLocation("plugins/Stats.jar"); + + needsUpdating.add(updaterFile); + + try { + update(); + logger.info("Updated successful"); + return true; + } catch (Exception e) { + logger.info("Update failed: " + e.getMessage()); + e.printStackTrace(); + } + } + + return false; + } + + /** + * Get the latest version + * + * @return + */ + public double getLatestPluginVersion() { + try { + URL url = new URL(UPDATE_SITE + VERSION_FILE); + + InputStream inputStream = url.openStream(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + + double version = Double.parseDouble(bufferedReader.readLine()); + + bufferedReader.close(); + + return version; + } catch (Exception e) { + e.printStackTrace(); + } + + return 0.00; + } + + /** + * @return the current sqlite version + */ + public double getCurrentSQLiteVersion() { + return Double.parseDouble(config.get("sqlite")); + } + public String combineSplit(int startIndex, String[] string, String seperator) { + if (string.length == 0) + return ""; + StringBuilder builder = new StringBuilder(); + for (int i = startIndex; i < string.length; i++) { + builder.append(string[i]); + builder.append(seperator); + } + if (builder.length() > seperator.length()) + builder.deleteCharAt(builder.length() - seperator.length()); // remove + return builder.toString(); + } + /** + * @return the latest sqlite version + */ + public double getLatestSQLiteVersion() { + try { + URL url = new URL(UPDATE_SITE + VERSION_FILE); + + InputStream inputStream = url.openStream(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + + bufferedReader.readLine(); + double version = Double.parseDouble(bufferedReader.readLine()); + + bufferedReader.close(); + + return version; + } catch (Exception e) { + e.printStackTrace(); + } + + return 0.00; + } + + /** + * @return the internal config file + */ + private File getInternalFile() { + return new File("stats" + File.separator + "internal.ini"); + } + + /** + * Parse the internal config file + */ + private void parseInternalConfig() { + try { + File file = getInternalFile(); + + if (!file.exists()) { + saveInternal(); + return; + } + + BufferedReader reader = new BufferedReader(new FileReader(file)); + String line; + + while ((line = reader.readLine()) != null) { + if (line.trim().startsWith("#")) { + continue; + } + + if (!line.contains(":")) { + continue; + } + + /* + * Split the array + */ + String[] arr = line.split(":"); + + if (arr.length < 2) { + continue; + } + + /* + * Get the key/value + */ + String key = arr[0]; + String value = combineSplit(1,arr, ":"); + //value = value.substring(0, value.length() - 1); + + /* + * Set the config value + */ + config.put(key, value); + } + + reader.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Create the internal updater config file + */ + public void saveInternal() { + try { + File file = getInternalFile(); + + if (file.exists()) { + file.delete(); + } + file.createNewFile(); + BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + + writer.write("# Stats Internal Config\n"); + writer.write("#################################\n"); + writer.write("### DO NOT MODIFY THIS FILE ###\n"); + writer.write("### THIS DOES NOT CHANGE ###\n"); + writer.write("### STATS'S VISIBLE BEHAVIOUR ###\n"); + writer.write("#################################\n\n"); + writer.write("#################################\n"); + writer.write("### THANK YOU! ###\n"); + writer.write("#################################\n\n"); + + for (String key : config.keySet()) { + String value = config.get(key); + + writer.write(key + ":" + value + "\n"); + } + + writer.flush(); + writer.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * @return the full path to the native library for sqlite + */ + public String getFullNativeLibraryPath() { + return getOSSpecificFolder() + getOSSpecificFileName(); + } + + /** + * @return the os/arch specific file name for sqlite's native library + */ + public String getOSSpecificFileName() { + String osname = System.getProperty("os.name").toLowerCase(); + + if (osname.contains("windows")) { + return "sqlitejdbc.dll"; + } else if (osname.contains("mac")) { + return "libsqlitejdbc.jnilib"; + } else { /* We assume linux/unix */ + return "libsqlitejdbc.so"; + } + } + + /** + * @return the os/arch specific folder location for SQLite's native library + */ + public String getOSSpecificFolder() { + String osname = System.getProperty("os.name").toLowerCase(); + String arch = System.getProperty("os.arch").toLowerCase(); + + if (osname.contains("windows")) { + return "lib/native/Windows/" + arch + "/"; + } else if (osname.contains("mac")) { + return "lib/native/Mac/" + arch + "/"; + } else { /* We assume linux/unix */ + return "lib/native/Linux/" + arch + "/"; + } + } + + /** + * Ensure we have all of the required files (if not, download them) + */ + public void update() throws Exception { + /* + * Check internal versions + */ + double latestVersion = getLatestSQLiteVersion(); + if (latestVersion > getCurrentSQLiteVersion()) { + requireBinaryUpdate(); + logger.info("Binary update required"); + config.put("sqlite", latestVersion + ""); + } + + if (needsUpdating.size() == 0) { + return; + } + + /* + * Make the native folder hierarchy if needed + */ + File folder = new File(getOSSpecificFolder()); + folder.mkdirs(); + + logger.info("Need to download " + needsUpdating.size() + " file(s)"); + + Iterator iterator = needsUpdating.iterator(); + + while (iterator.hasNext()) { + UpdaterFile item = iterator.next(); + + logger.info(" - Downloading file : " + item.getRemoteLocation()); + + URL url = new URL(item.getRemoteLocation()); + File file = new File(item.getLocalLocation()); + + if (file.exists()) { + file.delete(); + } + + InputStream inputStream = url.openStream(); + OutputStream outputStream = new FileOutputStream(file); + + saveTo(inputStream, outputStream); + + inputStream.close(); + outputStream.close(); + + logger.info(" + Download complete"); + iterator.remove(); + } + + /* + * In the event we updated binaries, we should force an ini save! + */ + saveInternal(); + } + + + /** + * Write an input stream to an output stream + * + * @param inputStream + * @param outputStream + */ + private void saveTo(InputStream inputStream, OutputStream outputStream) throws IOException { + byte[] buffer = new byte[1024]; + int len = 0; + + while ((len = inputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, len); + } + } + +} \ No newline at end of file diff --git a/com/nidefawl/Stats/util/UpdaterFile.java b/com/nidefawl/Stats/util/UpdaterFile.java new file mode 100755 index 0000000..6ecc45c --- /dev/null +++ b/com/nidefawl/Stats/util/UpdaterFile.java @@ -0,0 +1,69 @@ +/** + * This file is part of LWC (https://github.com/Hidendra/LWC) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nidefawl.Stats.util; + +public class UpdaterFile { + + /** + * The remote url location + */ + private String remoteLocation; + + /** + * The local url location + */ + private String localLocation; + + public UpdaterFile(String location) { + remoteLocation = location; + localLocation = location; + } + + /** + * @return the local file location + */ + public String getLocalLocation() { + return localLocation; + } + + /** + * @return the remote url location + */ + public String getRemoteLocation() { + return remoteLocation; + } + + /** + * Set the local file location + * + * @param localLocation + */ + public void setLocalLocation(String localLocation) { + this.localLocation = localLocation; + } + + /** + * Set the remote url location + * + * @param remoteLocation + */ + public void setRemoteLocation(String remoteLocation) { + this.remoteLocation = remoteLocation; + } + +} diff --git a/plugin.yml b/plugin.yml new file mode 100755 index 0000000..d47d7b9 --- /dev/null +++ b/plugin.yml @@ -0,0 +1,12 @@ +name: Stats +main: com.nidefawl.Stats.Stats +version: 0.53 +commands: + stats: + description: Stats command + usage: / + / [category|statname|convert|list|help] + / [player] [category|statname] + played: + description: Shows your played time + usage: / \ No newline at end of file