commit 19102de07781e8dd9f282d979f3fa8aeee426836 Author: Pascal Koenig Date: Fri Oct 7 19:51:59 2011 +0200 Initial commit diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..251fd2f --- /dev/null +++ b/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..dad5a99 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + Stats + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..05c45f4 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Fri Oct 07 19:48:56 CEST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..e754489 --- /dev/null +++ b/src/META-INF/MANIFEST.MF @@ -0,0 +1,8 @@ +Manifest-Version: 1.0 +Class-Path: Stats/lib/sqlite.jar Stats/lib/mysql.jar GroupManager.jar Permissions.jar + + + + + + diff --git a/src/README b/src/README new file mode 100644 index 0000000..e69de29 diff --git a/src/com/nidefawl/Stats/ItemResolver/hModItemResolver.java b/src/com/nidefawl/Stats/ItemResolver/hModItemResolver.java new file mode 100644 index 0000000..6a3beca --- /dev/null +++ b/src/com/nidefawl/Stats/ItemResolver/hModItemResolver.java @@ -0,0 +1,331 @@ +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.Logger; + +import com.nidefawl.Stats.Stats; + +public class hModItemResolver implements itemResolver { + static final Logger log = Logger.getLogger("Minecraft"); + protected Map items; + String location = null; + + + public hModItemResolver(File itemsFile) { + location = itemsFile.getPath(); + loadItems(itemsFile); + } + + public void loadItems(File itemsFile) { + if (!itemsFile.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("bedblock:26\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("repeateron:93\r\n"); + writer.write("repeateroff:94\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("bed:355\r\n"); + writer.write("repeater:356\r\n"); + writer.write("goldrecord:2256\r\n"); + writer.write("greenrecord:2257\r\n"); + } catch (Exception e) { + Stats.LogError("Exception while creating " + location + " " + e); + e.printStackTrace(); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + Stats.LogError("Exception while closing writer for " + location + " " + e); + e.printStackTrace(); + } + } + } + } + items = new HashMap(); + try { + Scanner scanner = new Scanner(itemsFile); + 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) { + Stats.LogError("Exception while reading " + location + " (Are you sure you formatted it correctly?)"+ e); + e.printStackTrace(); + } + } + + + @Override + public int getItem(String name) { + if (items.containsKey(name)) { + return items.get(name); + } + try { + int i = Integer.valueOf(name); + if(i>0 && i < 3000) { + if(!getItem(i).equals(name)) { + return i; + } + } + } catch (Exception e) { + } + return 0; + } + + + @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/src/com/nidefawl/Stats/ItemResolver/itemResolver.java b/src/com/nidefawl/Stats/ItemResolver/itemResolver.java new file mode 100644 index 0000000..3631c2c --- /dev/null +++ b/src/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/src/com/nidefawl/Stats/Messaging.java b/src/com/nidefawl/Stats/Messaging.java new file mode 100644 index 0000000..c55f476 --- /dev/null +++ b/src/com/nidefawl/Stats/Messaging.java @@ -0,0 +1,198 @@ +package com.nidefawl.Stats; + +import org.bukkit.Server; +import org.bukkit.World; +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)); + } + } + + /** + * Brodcast a message to every player in given world. + * + * @param message + * - The message to be sent. + */ + + public static void worldbroadcast(World world, String message) { + for (Player p : world.getPlayers()) { + p.sendMessage(parse(message)); + } + } +} \ No newline at end of file diff --git a/src/com/nidefawl/Stats/MinecraftFontWidthCalculator.java b/src/com/nidefawl/Stats/MinecraftFontWidthCalculator.java new file mode 100644 index 0000000..a20e3e7 --- /dev/null +++ b/src/com/nidefawl/Stats/MinecraftFontWidthCalculator.java @@ -0,0 +1,37 @@ +package com.nidefawl.Stats; + +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; + +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(CommandSender sender, String s) { + int i = 0; + if (s != null) { + if(sender instanceof ConsoleCommandSender) { + return s.length()*5; + } + 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/src/com/nidefawl/Stats/Permissions/GroupManagerResolver.java b/src/com/nidefawl/Stats/Permissions/GroupManagerResolver.java new file mode 100644 index 0000000..689e844 --- /dev/null +++ b/src/com/nidefawl/Stats/Permissions/GroupManagerResolver.java @@ -0,0 +1,66 @@ +package com.nidefawl.Stats.Permissions; + +import java.util.logging.Logger; + +import org.anjocaido.groupmanager.GroupManager; +import org.anjocaido.groupmanager.data.Group; +import org.anjocaido.groupmanager.data.User; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +public class GroupManagerResolver implements PermissionsResolver { + public static final Logger log = Logger.getLogger("Minecraft"); + Plugin plugin = null; + private GroupManager perms = null; + + public GroupManagerResolver(Plugin plugin) { + this.plugin = plugin; + } + + @Override + public boolean load() { + if (perms == null) { + Plugin checkPlugin = plugin.getServer().getPluginManager().getPlugin("GroupManager"); + if (checkPlugin != null && checkPlugin.isEnabled() && checkPlugin instanceof GroupManager) { + perms = (GroupManager) checkPlugin; + } else + return false; + } + return true; + } + + @Override + public boolean permission(CommandSender sender, String permCmd) { + if(sender.isOp()) return true; + if(!(sender instanceof Player)) return false; + if (!load()) + return false; + final Player player = (Player)sender; + return perms.getWorldsHolder().getWorldData(player).getPermissionsHandler().has(player, permCmd); + } + + + @Override + public boolean inGroup(Player player, String group) { + if (!load()) + return false; + Group g = perms.getWorldsHolder().getWorldData(player).getGroup(group); + if(g==null) return false; + User u = perms.getWorldsHolder().getWorldData(player).getUser(player.getName()); + if(u==null) return false; + return u.containsSubGroup(g)||u.getGroup().equals(g); + } + + @Override + public void reloadPerms() { + } + + @Override + public String getGroup(Player player) { + User u = perms.getWorldsHolder().getWorldData(player).getUser(player.getName()); + if(u==null) return ""; + return u.getGroupName(); + } + +} diff --git a/src/com/nidefawl/Stats/Permissions/NijiPermissionsResolver.java b/src/com/nidefawl/Stats/Permissions/NijiPermissionsResolver.java new file mode 100644 index 0000000..0881c5f --- /dev/null +++ b/src/com/nidefawl/Stats/Permissions/NijiPermissionsResolver.java @@ -0,0 +1,69 @@ +package com.nidefawl.Stats.Permissions; + +import java.util.logging.Logger; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import com.nijikokun.bukkit.Permissions.Permissions; + +public class NijiPermissionsResolver implements PermissionsResolver { + public static final Logger log = Logger.getLogger("Minecraft"); + Plugin plugin = null; + private Permissions perms = null; + + public NijiPermissionsResolver(Plugin plugin) { + this.plugin = plugin; + load(); + } + + @Override + public boolean load() { + if (perms == null) { + Plugin checkPlugin = plugin.getServer().getPluginManager().getPlugin("Permissions"); + if (checkPlugin != null && checkPlugin.isEnabled() && checkPlugin instanceof Permissions) { + perms = (Permissions) checkPlugin; + } else { + return false; + } + } + return true; + } + + @Override + public boolean permission(CommandSender sender, String permCmd) { + if(sender.isOp()) return true; + if(!(sender instanceof Player)) return false; + if (!load()) + return false; + return perms.getHandler().permission((Player)sender, permCmd); + } + + @Override + public String getGroup(Player player) { + if (!load()) + return ""; + return perms.getHandler().getGroup(player.getWorld().getName(), player.getName()); + } + + + + @Override + public boolean inGroup(Player player, String group) { + if (!load()) + return false; + return perms.getHandler().inGroup(player.getWorld().getName(), player.getName(), group); + } + + @Override + public void reloadPerms() { + if (!load()) + return; + if(Permissions.version.toLowerCase().startsWith("3.")) { + ((Permissions)Permissions.instance).getHandler().reload(); + } else { + perms.setupPermissions(); + } + } + +} diff --git a/src/com/nidefawl/Stats/Permissions/PermissionsResolver.java b/src/com/nidefawl/Stats/Permissions/PermissionsResolver.java new file mode 100644 index 0000000..b619b2d --- /dev/null +++ b/src/com/nidefawl/Stats/Permissions/PermissionsResolver.java @@ -0,0 +1,18 @@ +package com.nidefawl.Stats.Permissions; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public interface PermissionsResolver { + + public abstract boolean load(); + + public abstract boolean permission(CommandSender player, String permCmd); + + public abstract String getGroup(Player player); + + public abstract boolean inGroup(Player player, String group); + + public abstract void reloadPerms(); + +} \ No newline at end of file diff --git a/src/com/nidefawl/Stats/Permissions/defaultResolver.java b/src/com/nidefawl/Stats/Permissions/defaultResolver.java new file mode 100644 index 0000000..6b3fa4a --- /dev/null +++ b/src/com/nidefawl/Stats/Permissions/defaultResolver.java @@ -0,0 +1,39 @@ +package com.nidefawl.Stats.Permissions; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class defaultResolver implements PermissionsResolver { + + @Override + public boolean permission(CommandSender sender, String permCmd) { + if (sender.isOp()) + return true; + if(!(sender instanceof Player)) return false; + if (permCmd.startsWith("achievements.view") || permCmd.equals("achievements.check")) + return true; + if (permCmd.startsWith("stats.view")||permCmd.equals("stats.log")) + return true; + return false; + } + + @Override + public String getGroup(Player player) { + return ""; + } + + @Override + public boolean inGroup(Player player, String group) { + return false; + } + + @Override + public boolean load() { + return true; + } + + @Override + public void reloadPerms() { + } + +} diff --git a/src/com/nidefawl/Stats/PropertiesFile.java b/src/com/nidefawl/Stats/PropertiesFile.java new file mode 100644 index 0000000..742597f --- /dev/null +++ b/src/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>() { + @Override + 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/src/com/nidefawl/Stats/Stats.java b/src/com/nidefawl/Stats/Stats.java new file mode 100644 index 0000000..0004e0f --- /dev/null +++ b/src/com/nidefawl/Stats/Stats.java @@ -0,0 +1,751 @@ +package com.nidefawl.Stats; + +import java.io.File; +import java.io.FilenameFilter; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +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.Achievements.Achievements; +import com.nidefawl.Stats.ItemResolver.hModItemResolver; +import com.nidefawl.Stats.ItemResolver.itemResolver; +import com.nidefawl.Stats.Permissions.GroupManagerResolver; +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.udpates.Update1; +import com.nidefawl.Stats.udpates.Update2; +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.99; + public final static String logprefix = "[Stats-" + version + "]"; + public final static String defaultCategory = "stats"; + public boolean enabled = false; + public boolean updated = false; + private HashMap stats = new HashMap(); + private itemResolver items = null; + private PermissionsResolver perms = null; + private StatsPlayerListener playerListener = null; + private StatsVehicleListener vehicleListener = null; + private StatsBlockListener blockListener = null; + private StatsEntityListener entityListener = null; + private StatsServerListener serverListener = null; + private Updater updater = null; + + /** + * @return the Updater instance + */ + public Updater getUpdater() { + return updater; + } + public PlayerStat getPlayerStat(String name) { + return stats.get(name); + } + public PermissionsResolver Perms() { + if (perms == null) { + LogInfo("Recreating PermissionsResolver"); + CreatePermissionResolver(); + if (perms == null) + LogError("Couldn't link PermissionsResolver!"); + } + 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(StatsSettings.useMySQL); + 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(); + LogInfo("created table '" + StatsSettings.dbTable + "'"); + } + result = true; + } catch (SQLException ex) { + LogError("SQL exception" + ex); + ex.printStackTrace(); + result = false; + } finally { + try { + if (rs != null) + rs.close(); + if (ps != null) + ps.close(); + if (conn != null) + conn.close(); + } catch (SQLException ex) { + LogError("SQL exception (on close)" + ex); + ex.printStackTrace(); + result = false; + } + } + return result; + } + private void updateTimedStats(PlayerStat stat) { + if (playerListener.distWalked.containsKey(stat.getName())) { + int distance = (int) Math.floor(playerListener.distWalked.get(stat.getName())); + if (distance >= 1) { + Category cat = stat.categories.get("stats"); + if (cat == null) + cat = stat.newCategory("stats"); + cat.add("move", distance); + playerListener.distWalked.put(stat.getName(), 0.0f); + stat.setLastActivity(); + } + } + if (vehicleListener.distBoat.containsKey(stat.getName())) { + int distance = (int) Math.floor(vehicleListener.distBoat.get(stat.getName())); + if (distance >= 1) { + Category cat = stat.categories.get("boat"); + if (cat == null) + cat = stat.newCategory("boat"); + cat.add("move", distance); + vehicleListener.distBoat.put(stat.getName(), 0.0f); + stat.setLastActivity(); + } + } + if (vehicleListener.distCart.containsKey(stat.getName())) { + int distance = (int) Math.floor(vehicleListener.distCart.get(stat.getName())); + if (distance >= 1) { + Category cat = stat.categories.get("minecart"); + if (cat == null) + cat = stat.newCategory("minecart"); + cat.add("move", distance); + vehicleListener.distCart.put(stat.getName(), 0.0f); + stat.setLastActivity(); + } + } + if (StatsSettings.afkTimer > 0 && !stat.isAfk()) { + updateStat(stat.getName(), defaultCategory, "playedfor", (int) (System.currentTimeMillis() - stat.lastUpdate) / 1000, false); + } + stat.lastUpdate = System.currentTimeMillis(); + } + public void setSavedStats(CommandSender sender, 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(StatsSettings.useMySQL); + 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) { + LogError("SQL exception" + ex); + ex.printStackTrace(); + sender.sendMessage(StatsSettings.premessage + ex.getMessage()); + } finally { + try { + if (rs != null) + rs.close(); + if (ps != null) + ps.close(); + if (conn != null) + conn.close(); + } catch (SQLException ex) { + LogError("SQL exception (on close)" + ex); + ex.printStackTrace(); + sender.sendMessage(StatsSettings.premessage + ex.getMessage()); + } + } + sender.sendMessage(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) { + if (sender instanceof Player) { + Player player = (Player) sender; + if (commandLabel.equals("played") && Perms().permission(player, "stats.view.playtime")) { + 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 "+ChatColor.WHITE + StatsView.GetTimeString(playedFor)); + return true; + } + } + if (commandLabel.equals("stats")) { + if (args.length == 1 && args[0].equalsIgnoreCase("help") || ((sender instanceof ConsoleCommandSender) && args.length == 0)) { + if ((sender instanceof Player) && Perms().permission(sender, "stats.view.playtime")) { + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + "/played - Shows your play-time"); + } + if ((sender instanceof Player) && Perms().permission(sender, "stats.view.own")) { + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + "/stats - Shows your stats summary"); + } + if(Perms().permission(sender, "stats.view.others")) { + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + "/stats - Shows players stats summary"); + } + if (Perms().permission(sender, "stats.admin")) { + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + "/stats list - Shows loaded players"); + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + "/stats set - Set stats manually"); + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + "/stats debug - Prints stat-update messages to console."); + sender.sendMessage(StatsSettings.premessage + "Usage: " + ChatColor.WHITE + "/stats [category|debug|statname|list|helpset]"); + sender.sendMessage(StatsSettings.premessage + "or /stats [player] [category|statname]"); + } else { + sender.sendMessage(StatsSettings.premessage + "Usage: " + ChatColor.WHITE + "/stats [category|statname|help] or /stats [player] [category|statname]"); + } + return true; + } + else if (args.length == 1 && args[0].equalsIgnoreCase("list") && Perms().permission(sender, "stats.admin")) { + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + "Loaded playerstats (" + stats.size() + "): " + StatsPlayerList()); + return true; + } + else if (args.length > 0 && args[0].equalsIgnoreCase("set") && Perms().permission(sender, "stats.admin")) { + if (args.length < 5) { + sender.sendMessage(StatsSettings.premessage + ChatColor.RED + "Need more arguments (use * to select all)"); + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + "/stats set [player] [category] [key] [value]- Set stats manually"); + return true; + } + try { + Integer.valueOf(args[4]); + } catch (Exception e) { + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + "[value] should be a number (" + args[4] + " is not)!"); + return true; + } + setSavedStats(sender, args[1], args[2], args[3], args[4]); + return true; + } + else if (args.length == 1 && args[0].equalsIgnoreCase("debug") && Perms().permission(sender, "stats.admin")) { + StatsSettings.debugOutput = !StatsSettings.debugOutput; + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + "Debugging " + (StatsSettings.debugOutput ? "enabled. Check server log." : "disabled.")); + return true; + } + return StatsView.onCommand(this, sender, args); + } + + return false; + } + + + + public void CreatePermissionResolver() { + + Plugin permPlugin = this.getServer().getPluginManager().getPlugin("GroupManager"); + if (permPlugin != null) { + log.info(logprefix + " Using GroupManager for permissions"); + perms = new GroupManagerResolver(this); + return; + } + permPlugin = this.getServer().getPluginManager().getPlugin("Permissions"); + if (permPlugin != null) { + log.info(logprefix + " Using Nijis Permissions for permissions"); + perms = new NijiPermissionsResolver(this); + return; + } + + log.info(logprefix + " Using bukkit's isOp() for permissions (until other plugin is enabled)"); + 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; + } + protected final FilenameFilter filter = new FilenameFilter() { + public boolean accept(File dir, String name) { + if(name.equals("items.txt")) return false; + return name.endsWith(".txt"); + } + }; + + protected final FilenameFilter filterOld = new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".txt.old"); + } + }; + public void convertFlatFiles() { + String[] files = getDataFolder().list(filterOld); + if (files != null && files.length > 0) { + for (int i = 0; i < files.length; i++) { + String basename = files[i].substring(0, files[i].lastIndexOf(".")); + File fnew = new File(getDataFolder(), files[i]); + File fold = new File(getDataFolder(), basename); + fnew.renameTo(fold); + } + } + files = getDataFolder().list(filter); + if (files == null || files.length == 0) { + } + + int count = 0; + PlayerStatSQL ps; + for (int i = 0; i < files.length; i++) { + File fold = new File(getDataFolder(), files[i]); + if (!fold.exists()) + continue; + + String basename = files[i].substring(0, files[i].lastIndexOf(".")); + ps = new PlayerStatSQL(basename, this); + ps.convertFlatFile(getDataFolder().getPath()); + ps.save(); + count++; + } + if(count > 0) { + Stats.LogInfo("Converted " + count + " stat files to " + (StatsSettings.useMySQL ? "MySQL" : "SQLite")); + } + } + + public Stats() { + + } + + public void onEnable() { + getDataFolder().mkdirs(); + File statsDirectory = new File("stats"); + if (statsDirectory.exists() && statsDirectory.isDirectory()) { + File intSettings = new File("stats", "internal.ini"); + if (intSettings.exists()) { + intSettings.delete(); + } + LogInfo("Moving ./stats/ directory to " + getDataFolder().getPath()); + if (!statsDirectory.renameTo(new File(getDataFolder().getPath()))) { + LogError("Moving ./stats/ directory to " + getDataFolder().getPath() + " failed"); + LogError("Please move your files manually and delete the old 'stats' directory. Thanks"); + LogError("Disabling Stats"); + getServer().getPluginManager().disablePlugin(this); + return; + } + } + StatsSettings.load(this); + updater = new Updater(this); + try { + updated = updater.updateDist(StatsSettings.autoUpdate); + if (updated) { + LogInfo("UPDATE INSTALLED. PLEASE RESTART...."); + return; + } + } catch (Exception e) { + e.printStackTrace(); + } + Connection conn = StatsSQLConnectionManager.getConnection(StatsSettings.useMySQL); + try { + if (conn == null || conn.isClosed()) { + LogError("Could not establish SQL connection. Disabling Stats"); + getServer().getPluginManager().disablePlugin(this); + return; + } + } catch (SQLException e) { + LogError("Could not establish SQL connection. Disabling Stats"); + e.printStackTrace(); + getServer().getPluginManager().disablePlugin(this); + return; + } + if (!checkSchema()) { + LogError("Could not create table. Disabling Stats"); + getServer().getPluginManager().disablePlugin(this); + return; + } + convertFlatFiles(); + if (updated) + return; + Update1.execute(this); + Update2.execute(this); + items = new hModItemResolver(new File(getDataFolder(),"items.txt")); + stats = new HashMap(); + CreatePermissionResolver(); + enabled = true; + playerListener = new StatsPlayerListener(this); + blockListener = new StatsBlockListener(this); + entityListener = new StatsEntityListener(this); + vehicleListener = new StatsVehicleListener(this); + serverListener = new StatsServerListener(this); + initialize(); + LogInfo("Plugin Enabled"); + for (Player p : getServer().getOnlinePlayers()) { + load(p); + } + getServer().getScheduler().scheduleSyncRepeatingTask(this, new SaveTask(this), StatsSettings.delay * 20, StatsSettings.delay * 20); + } + + + + public static class SaveTask implements Runnable { + private Stats statsInstance; + + public SaveTask(Stats plugin) { + statsInstance = plugin; + } + + @Override + public void run() { + if (!statsInstance.enabled) + return; + statsInstance.saveAll(); + } + } + + public void onDisable() { + if (enabled) { + saveAll(); + Plugin achPlugin = getServer().getPluginManager().getPlugin("Achievements"); + if (achPlugin != null && achPlugin.isEnabled()) { + if (((Achievements) achPlugin).enabled) { + ((Achievements) achPlugin).checkAchievements(); + ((Achievements) achPlugin).Disable(); + } + } + enabled = false; + getServer().getScheduler().cancelTasks(this); + stats = null; + updater.saveInternal(); + StatsSQLConnectionManager.closeConnection(StatsSettings.useMySQL); + } + LogInfo("Plugin Disabled"); + } + + public void initialize() { + getServer().getPluginManager().registerEvent(Event.Type.PLUGIN_DISABLE, serverListener, Priority.Normal, this); + getServer().getPluginManager().registerEvent(Event.Type.PLUGIN_ENABLE, serverListener, Priority.Normal, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_JOIN, playerListener, Priority.Highest, this); + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_COMMAND_PREPROCESS, 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_TELEPORT, 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); + if(StatsSettings.logPlayerAnimations) { + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_ANIMATION, playerListener, Priority.Monitor, this); + } + if(StatsSettings.logMove) { + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_MOVE, playerListener, Priority.Monitor, this); + } + if(StatsSettings.logBlockCreate) { + getServer().getPluginManager().registerEvent(Event.Type.BLOCK_PLACE, blockListener, Priority.Monitor, this); + } + if(StatsSettings.logBlockDestroy) { + getServer().getPluginManager().registerEvent(Event.Type.BLOCK_BREAK, blockListener, Priority.Monitor, this); + } + if(StatsSettings.logItemUse) { + getServer().getPluginManager().registerEvent(Event.Type.PLAYER_INTERACT, playerListener, Priority.Monitor, this); + } + if(StatsSettings.logBlockIgnite){ + getServer().getPluginManager().registerEvent(Event.Type.BLOCK_IGNITE, blockListener, Priority.Monitor, this); + } + if(StatsSettings.logDamage) { + getServer().getPluginManager().registerEvent(Event.Type.ENTITY_DEATH, entityListener, Priority.Highest, this); + getServer().getPluginManager().registerEvent(Event.Type.ENTITY_DAMAGE, entityListener, Priority.Highest, this); + } + if(StatsSettings.logVehicle) { + 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, boolean resetAfkTimer) { + updateStat(player, statType, 1, resetAfkTimer); + } + + public void updateStat(Player player, String statType, int num, boolean resetAfkTimer) { + updateStat(player.getName(), defaultCategory, statType, num, resetAfkTimer); + } + + public void updateStat(Player player, String statType, Block block, boolean resetAfkTimer) { + updateStat(player, statType, block, 1, resetAfkTimer); + } + + public void updateStat(Player player, String statType, Block block, int num, boolean resetAfkTimer) { + if (block.getTypeId() <= 0) + return; + String blockName = getItems().getItem(block.getTypeId()); + updateStat(player.getName(), statType, blockName, num, resetAfkTimer); + } + + public void updateStat(Player player, String category, String key, int val, boolean resetAfkTimer) { + updateStat(player.getName(), category, key, val, resetAfkTimer); + } + + public void updateStat(String player, String category, String key, int val, boolean resetAfkTimer) { + if (!enabled) + return; + if (player == null || player.length() < 1) { + LogError("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 (resetAfkTimer) + ps.setLastActivity(); + if (StatsSettings.debugOutput) + log.info(logprefix + " [DEBUG]: adding " + val + " to " + category + "/" + key + " of " + player); + } + + public 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 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); + } + + public void load(Player player) { + if (!Perms().permission(player, "stats.log")) { + if (StatsSettings.debugOutput) + LogInfo("player " + player.getName() + " has no stats.log permission. Not loading/logging actions"); + return; + } + if (stats.containsKey(player.getName())) { + LogError("attempting to load already loaded player: " + player.getName()); + return; + } + PlayerStat ps = new PlayerStatSQL(player.getName(), this); + ps.load(); + stats.put(player.getName(), ps); + if (StatsSettings.debugOutput) + LogInfo("player " + player.getName() + " has been loaded."); + } + + public void unload(String player) { + entityListener.UnloadPlayer(player); + if (stats.containsKey(player)) { + PlayerStat ps = stats.get(player); + updateTimedStats(ps); + ps.save(); + stats.remove(player); + return; + } + } + + public boolean isAfk(Player p) { + if (!stats.containsKey(p.getName())) + return false; + return stats.get(p.getName()).isAfk(); + } + + public void saveAll() { + if (StatsSettings.debugOutput) + log.info("Stats debug: saving " + stats.size() + " players stats"); + try { + Connection conn = StatsSQLConnectionManager.getConnection(StatsSettings.useMySQL); + if (conn == null) + return; + conn.setAutoCommit(false); + } catch (SQLException e) { + e.printStackTrace(); + } + for (PlayerStat stat : stats.values()) { + if (stat == null || getServer().getPlayer(stat.getName()) == null) { + stat.unload = true; + continue; + } + updateTimedStats(stat); + stat.save(false); + } + StatsSQLConnectionManager.closeConnection(StatsSettings.useMySQL); + for (PlayerStat stat : stats.values()) { + if (!stat.unload) + continue; + LogError("onPlayerQuit did not happen, unloading " + stat.getName() + " now"); + logout(stat.getName()); + unload(stat.getName()); + } + } + + public void setItems(itemResolver items) { + this.items = items; + } + + public itemResolver getItems() { + 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", true); + } + 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) { + LogError("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, true); + ps.setLastBoatEnter(now); + } + + } else if (vhc instanceof org.bukkit.entity.Minecart) { + if (now - ps.getLastMinecartEnter() > 60) { + updateStat(player, "minecart", "enter", 1, true); + ps.setLastMinecartEnter(now); + } + } + } + + public void setStats(HashMap stats) { + this.stats = stats; + } + + public HashMap getStats() { + return stats; + } + + public PermissionsResolver getPerms() { + return perms; + } + + public void setPerms(PermissionsResolver perms) { + this.perms = perms; + } + +} \ No newline at end of file diff --git a/src/com/nidefawl/Stats/StatsBlockListener.java b/src/com/nidefawl/Stats/StatsBlockListener.java new file mode 100644 index 0000000..ff1f11c --- /dev/null +++ b/src/com/nidefawl/Stats/StatsBlockListener.java @@ -0,0 +1,143 @@ +package com.nidefawl.Stats; + +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.BlockIgniteEvent; +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.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(), true); + plugin.updateStat(event.getPlayer(), "totalblockdestroy", true); + } + + /** + * 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 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", true); + + } + + /** + * 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(), true); + plugin.updateStat(event.getPlayer(), "totalblockcreate", true); + } + + + + + /** + * 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/src/com/nidefawl/Stats/StatsEntityListener.java b/src/com/nidefawl/Stats/StatsEntityListener.java new file mode 100644 index 0000000..787dc03 --- /dev/null +++ b/src/com/nidefawl/Stats/StatsEntityListener.java @@ -0,0 +1,444 @@ +package com.nidefawl.Stats; + +import java.util.ArrayList; +import java.util.HashMap; + +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(),false); + plugin.updateStat((Player) event.getEntity(), "damagetaken", "total", event.getDamage(),false); + if (event.getDamage() >= ((Player) event.getEntity()).getHealth() && plugin.getPlayerStat(((Player) event.getEntity()).getName())!=null) { + otherDeathCauses.put((Player) event.getEntity(), cause); + } + + } + + } + /*public void sendEntList(CommandSender sender) { + int LoadedEnts = 0; + int nullEnts = 0; + for (Entity e : entsKilledByEnt.keySet()) { + if (e == null) { + 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); + sender.sendMessage("killed entitys for: " + entName + "(" + e.getEntityId() + "): " + entsList); + LoadedEnts++; + LoadedEnts += entsKilledByEnt.get(e).size(); + } + sender.sendMessage(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,false); + plugin.updateStat((Player) entity, "damagetaken", typeName, amount,false); + if (amount >= ((LivingEntity) entity).getHealth() && plugin.getPlayerStat(((Player) damager).getName())!=null) { + 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,false); + plugin.updateStat((Player) damager, "damagedealt", "total", amount,false); + return true; + } else { + if (((LivingEntity) entity).getHealth() > 0) { + plugin.updateStat((Player) damager, "damagedealt", typeName, amount,false); + plugin.updateStat((Player) damager, "damagedealt", "total", amount,false); + if (amount >= ((LivingEntity) entity).getHealth() && plugin.getPlayerStat(((Player) damager).getName())!=null) { + 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,false); + plugin.updateStat((Player) entity, "damagetaken", "total", amount,false); + if (amount >= ((Player) entity).getHealth() && plugin.getPlayerStat(((Player) entity).getName())!=null) { + 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.getPlayerStat(p.getName()); + if (ps == null) + return; + plugin.updateStat(p, "deaths", "total", 1,false); + String otherReason = otherDeathCauses.get(p); + otherReason = otherReason != null ? otherReason : "unknown"; + if (StatsSettings.deathNotifying) { + String name = p.getDisplayName(); + String message = name + " &4died"; + if (e instanceof Player) { + plugin.updateStat(((Player) e), "kills", "total", 1,false); + plugin.updateStat(((Player) e), "kills", "player", 1,false); + String name2 = ((Player) e).getName(); + message = name + " &4was killed by &8" + name2; + } else if (e instanceof LivingEntity) { + message = name + " &4was killed by &8" + EntToString(e); + } else if (otherReason != null) { + message = name + " &4"+getNiceDamageString(otherReason); + } else { + message = name + " &4died"; + } + Messaging.worldbroadcast(event.getEntity().getWorld(), message); + } + if (e instanceof LivingEntity) { + plugin.updateStat(p, "deaths", EntToString(e), 1,false); + if(e instanceof Player) { + StatsPlayerDeathByPlayerEvent ev = new StatsPlayerDeathByPlayerEvent(event,(Player)event.getEntity(),(Player)e); + plugin.getServer().getPluginManager().callEvent(ev); + } else { + StatsPlayerDeathByEntityEvent ev = new StatsPlayerDeathByEntityEvent(event,(Player)event.getEntity(),e); + plugin.getServer().getPluginManager().callEvent(ev); + } + } else if (otherReason != null) { + plugin.updateStat(p, "deaths", otherReason, 1,false); + StatsPlayerDeathByOtherEvent ev = new StatsPlayerDeathByOtherEvent(event,(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,false); + plugin.updateStat((Player) e, "kills", EntToString(event.getEntity()), 1,false); + StatsMobDeathByPlayerEvent ev = new StatsMobDeathByPlayerEvent(event, (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); + } + } else if(event instanceof EntityDamageByEntityEvent) { + if(!checkEntDamage(((EntityDamageByEntityEvent)event).getEntity(), ((EntityDamageByEntityEvent)event).getDamager(), event.getDamage())) { + event.setCancelled(true); + } + } 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 Wolf) { + return "Wolf"; + } 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/src/com/nidefawl/Stats/StatsPlayerListener.java b/src/com/nidefawl/Stats/StatsPlayerListener.java new file mode 100644 index 0000000..819aa76 --- /dev/null +++ b/src/com/nidefawl/Stats/StatsPlayerListener.java @@ -0,0 +1,255 @@ +package com.nidefawl.Stats; + +import java.util.HashMap; +import org.bukkit.Material; +import org.bukkit.craftbukkit.entity.CraftItem; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.*; + +public class StatsPlayerListener extends PlayerListener { + + public HashMap distWalked = new HashMap(); + 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(PlayerQuitEvent 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", false); + plugin.updateStat(event.getPlayer(), "chatletters", event.getMessage().length(), false); + } + + /** + * Called when a player attempts to use a command + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { + if (event.isCancelled()) + return; + plugin.updateStat(event.getPlayer(), "command", false); + } + + /** + * 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; + if (distWalked.containsKey(event.getPlayer().getName())) { + float newDistance = distWalked.get(event.getPlayer().getName()) + (float) (event.getFrom().toVector().distance(event.getTo().toVector())); + distWalked.put(event.getPlayer().getName(), newDistance); + } else { + distWalked.put(event.getPlayer().getName(), (float) (event.getFrom().toVector().distance(event.getTo().toVector()))); + } + } + + /** + * Called when a player attempts to teleport to a new location in a world + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerTeleport(PlayerTeleportEvent event) { + if (event.isCancelled()) + return; + if(event.getFrom().toVector().distance(event.getTo().toVector())>5) + plugin.updateStat(event.getPlayer(), "teleport", true); + } + + /** + * Called when a player uses an item + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.isCancelled() || event.getBlockFace() == null) + return; + if(event.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (event.getClickedBlock().getType() == Material.CHEST) { + plugin.updateStat(event.getPlayer(), "openchest", true); + } + } else + 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, false); + break; + default: + break; + } + + } + + /** + * Called when a player attempts to log in to the server + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerJoin(PlayerJoinEvent 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", false); + } + } + + /** + * 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", false); + } + + /** + * Called when a player drops an item from their inventory + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerDropItem(PlayerDropItemEvent event) { + if (event.isCancelled()) + 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, false); + } + + } + + /** + * 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", false); + } + + /** + * Called when a player respawns + * + * @param event + * Relevant event details + */ + @Override + public void onPlayerRespawn(PlayerRespawnEvent event) { + plugin.updateStat(event.getPlayer(), "respawn", false); + } + + /** + * 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.isCancelled()) + 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, false); + } + } + + /** + * 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/src/com/nidefawl/Stats/StatsServerListener.java b/src/com/nidefawl/Stats/StatsServerListener.java new file mode 100644 index 0000000..de81309 --- /dev/null +++ b/src/com/nidefawl/Stats/StatsServerListener.java @@ -0,0 +1,44 @@ +package com.nidefawl.Stats; + +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.event.server.PluginEnableEvent; +import org.bukkit.event.server.ServerListener; +import org.bukkit.plugin.Plugin; + +import com.nidefawl.Stats.Permissions.GroupManagerResolver; +import com.nidefawl.Stats.Permissions.NijiPermissionsResolver; +import com.nidefawl.Stats.Permissions.defaultResolver; + +public class StatsServerListener extends ServerListener { + Stats stats = null; + public StatsServerListener(Stats plugin) { + this.stats = plugin; + } + @Override + public void onPluginEnable(PluginEnableEvent event) { + Plugin plugin = event.getPlugin(); + String name = plugin.getDescription().getName(); + if (name.equals("GroupManager")) { + stats.setPerms(new GroupManagerResolver(plugin)); + } else if (name.equals("Permissions")) { + stats.setPerms(new NijiPermissionsResolver(plugin)); + } + } + + /** + * Called when a plugin is disabled + * + * @param event Relevant event details + */ + @Override + public void onPluginDisable(PluginDisableEvent event) { + Plugin plugin = event.getPlugin(); + String name = plugin.getDescription().getName(); + if (name.equals("GroupManager")) { + stats.setPerms(new defaultResolver()); + } else if (name.equals("Permissions")) { + stats.setPerms(new defaultResolver()); + } + } + +} diff --git a/src/com/nidefawl/Stats/StatsSettings.java b/src/com/nidefawl/Stats/StatsSettings.java new file mode 100644 index 0000000..0c54bbf --- /dev/null +++ b/src/com/nidefawl/Stats/StatsSettings.java @@ -0,0 +1,72 @@ +package com.nidefawl.Stats; + +import java.io.File; + +import org.bukkit.ChatColor; + +public class StatsSettings { + + public static String liteDb; + public static int loginRateLimit = 3600; + public static long delay = 30; + public static long afkTimer = 300; + 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 boolean logMove; + public static boolean logVehicle; + public static boolean logBlockCreate; + public static boolean logBlockDestroy; + public static boolean logDamage; + public static boolean logItemUse; + public static boolean logBlockIgnite; + public static boolean logPlayerAnimations; + + public static void load(Stats plugin) { + + PropertiesFile properties = new PropertiesFile(new File(plugin.getDataFolder(), "stats.properties")); + liteDb = "jdbc:sqlite:" + plugin.getDataFolder().getPath() + File.separator + "stats.db"; + delay = properties.getInt("stats-save-delay", 30, "delay between automatic saving (seconds)"); + loginRateLimit = properties.getInt("stats-login-delay", 3600, "limit between login-count increases"); + afkTimer = properties.getInt("stats-afk-delay", 300, " (seconds) If there is no player-activity in this time playedfor does not get updated. Set to 0 to disable."); + + boolean useSQL = properties.getBoolean("stats-use-sql"); + properties.remove("stats-use-sql"); + String dataSource = properties.getString("stats-datasource", useSQL ? "mysql" : "sqlite", "sqlite or mysql"); + 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", false, ""); + logMove = properties.getBoolean("stats-log-move", true, "disable/enable logging player move events"); + logVehicle = properties.getBoolean("stats-log-vehicle", true, "disable/enable logging of vehicle events"); + logBlockCreate = properties.getBoolean("stats-log-blockcreate", true, "disable/enable logging blockcreate"); + logBlockDestroy = properties.getBoolean("stats-log-blockdestroy", true, "disable/enable logging blockdestroy"); + logDamage = properties.getBoolean("stats-log-damage-events", true, "disable/enable logging of damage AND death events"); + logItemUse = properties.getBoolean("stats-log-itemuse", true, "disable/enable logging of item use events"); + logBlockIgnite = properties.getBoolean("stats-log-block-ignite", true, "disable/enable logging of block ignite events"); + logPlayerAnimations = properties.getBoolean("stats-log-player-animations", true, "disable/enable logging of player-animations (armswing)"); + if (premessage.length() > 0) + if (premessage.charAt(premessage.length() - 1) != ' ') + premessage += " "; + premessage = premessage.replaceAll("(&([a-f0-9]))", "\u00A7$2"); + 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/src/com/nidefawl/Stats/StatsVehicleListener.java b/src/com/nidefawl/Stats/StatsVehicleListener.java new file mode 100644 index 0000000..64da595 --- /dev/null +++ b/src/com/nidefawl/Stats/StatsVehicleListener.java @@ -0,0 +1,108 @@ +package com.nidefawl.Stats; + +import java.util.HashMap; +import org.bukkit.entity.Boat; +import org.bukkit.entity.Minecart; +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 HashMap distBoat = new HashMap(); + public HashMap distCart = new HashMap(); + 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; + Player p = (Player) event.getVehicle().getPassenger(); + if(event.getVehicle() instanceof Boat) { + if(distBoat.containsKey(p.getName())) { + float newDistance = distBoat.get(p.getName()) + (float) (event.getFrom().toVector().distance(event.getTo().toVector())); + distBoat.put(p.getName(), newDistance); + } else { + distBoat.put(p.getName(), (float) (event.getFrom().toVector().distance(event.getTo().toVector()))); + } + } else if (event.getVehicle() instanceof Minecart) { + if(distBoat.containsKey(p.getName())) { + float newDistance = distBoat.get(p.getName()) + (float) (event.getFrom().toVector().distance(event.getTo().toVector())); + distBoat.put(p.getName(), newDistance); + } else { + distBoat.put(p.getName(), (float) (event.getFrom().toVector().distance(event.getTo().toVector()))); + } + } + } +} \ No newline at end of file diff --git a/src/com/nidefawl/Stats/StatsView.java b/src/com/nidefawl/Stats/StatsView.java new file mode 100644 index 0000000..40e9575 --- /dev/null +++ b/src/com/nidefawl/Stats/StatsView.java @@ -0,0 +1,223 @@ +package com.nidefawl.Stats; + +import java.sql.Date; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Set; +import org.bukkit.ChatColor; +import org.bukkit.Server; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; +import com.nidefawl.Stats.datasource.Category; +import com.nidefawl.Stats.datasource.PlayerStat; + +public class StatsView { + + public static boolean onCommand(Stats plugin, CommandSender sender, String[] args) { + if (!plugin.Perms().permission(sender, "stats.view.own")) { + sender.sendMessage(ChatColor.RED + "You don't have permission to view your stats!"); + return true; + } + Player who = null; + if (sender instanceof Player) { + who = (Player) sender; + } + int offs = 0; + if (args.length > 0) { + who = playerMatch(plugin.getServer(), args[0]); + if (who != null) { + if (!plugin.Perms().permission(sender, "stats.view.others")) { + sender.sendMessage(ChatColor.RED + "You don't have permission to view others stats!"); + return true; + } + offs++; + } else { + if ((sender instanceof ConsoleCommandSender)) { + sender.sendMessage(ChatColor.RED + "Player '" + args[0] + "' is not online!"); + return false; + } else { + who = (Player) sender; + } + } + } + if (args.length == offs + 1) { + if (isStat(plugin, who.getName(), args[offs])) { + printStat(plugin, sender, who, "stats", args[offs]); + return true; + } else if (plugin.getItems().getItem(args[offs]) != 0 && !(args[offs].equals("boat") || args[offs].equals("minecart"))) { + printStat(plugin, sender, who, "blockcreate", args[offs]); + printStat(plugin, sender, who, "blockdestroy", args[offs]); + return true; + } else if (isCat(plugin, who.getName(), args[offs])) { + sender.sendMessage(StatsSettings.premessage + "Please choose: (/stats " + args[offs] + " )"); + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + getCatEntries(plugin, who.getName(), args[offs])); + return true; + } else { + sender.sendMessage(StatsSettings.premessage + ChatColor.RED + "stat/category '" + args[offs] + "' not found. Possible values:"); + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + getCats(plugin, who.getName())); + return true; + } + } else if (args.length == offs + 2) { + if (isCat(plugin, who.getName(), args[offs])) { + printStat(plugin, sender, who, args[offs], args[offs + 1]); + return true; + } else { + sender.sendMessage(StatsSettings.premessage + ChatColor.RED + "stat/category '" + args[offs] + "' not found. Possible values:"); + sender.sendMessage(StatsSettings.premessage + ChatColor.WHITE + getCats(plugin, who.getName())); + return true; + } + } + int playedTime = plugin.get(who.getName(), "stats", "playedfor"); + int movedBlocks = plugin.get(who.getName(), "stats", "move"); + int totalCreate = plugin.get(who.getName(), "stats", "totalblockcreate"); + int totalDestroy = plugin.get(who.getName(), "stats", "totalblockdestroy"); + int tkills = plugin.get(who.getName(), "kills", "total"); + int tdeaths = plugin.get(who.getName(), "deaths", "total"); + int pdeaths = plugin.get(who.getName(), "deaths", "player"); + int pkills = plugin.get(who.getName(), "kills", "player"); + int totalDamage = plugin.get(who.getName(), "damagetaken", "total"); + int totalDamageDealt = plugin.get(who.getName(), "damagedealt", "total"); + try { + sender.sendMessage("------------------------------------------------"); + sender.sendMessage(ChatColor.GOLD + " stats for " + ChatColor.WHITE + who.getName() + ChatColor.GOLD + ": (" + ChatColor.WHITE + "/stats help for more" + ChatColor.GOLD + ")"); + sender.sendMessage("------------------------------------------------"); + String s1 = ChatColor.GOLD + "[" + ChatColor.YELLOW + "Playedtime" + ChatColor.GOLD + "]" + ChatColor.YELLOW; + while (MinecraftFontWidthCalculator.getStringWidth(sender, s1) < 120) + s1 += " "; + s1 += ChatColor.WHITE + GetTimeString(playedTime); + sender.sendMessage(s1); + s1 = ChatColor.GOLD + "[" + ChatColor.YELLOW + "Moved" + ChatColor.GOLD + "]" + ChatColor.YELLOW; + while (MinecraftFontWidthCalculator.getStringWidth(sender, s1) < 120) + s1 += " "; + s1 += ChatColor.WHITE + String.valueOf(movedBlocks) + " blocks"; + sender.sendMessage(s1); + printStatFormatted(sender, "Blocks", "created", totalCreate, "destroyed", totalDestroy); + printStatFormatted(sender, "Deaths", "total", tdeaths, "player", pdeaths); + printStatFormatted(sender, "Kills", "total", tkills, "player", pkills); + printStatFormatted(sender, "Damage", "dealt", totalDamageDealt, "taken", totalDamage); + sender.sendMessage("------------------------------------------------"); + } catch (Exception e) { + // TODO: handle exception + } + return true; + } + + public static Player playerMatch(Server server, String name) { + List list = server.matchPlayer(name); + for (Player p : list) + if (p != null && p.getName().equalsIgnoreCase(name)) + return p; + return null; + } + + private static void printStatFormatted(CommandSender sender, String name, String title1, int value1, String title2, int value2) { + String s1 = ChatColor.GOLD + "[" + ChatColor.YELLOW + name + ChatColor.GOLD + "]" + ChatColor.YELLOW; + while (MinecraftFontWidthCalculator.getStringWidth(sender, s1) < 120) + s1 += " "; + if (title2 != null) + s1 += ChatColor.WHITE + title1 + "/" + title2; + else + s1 += ChatColor.WHITE + title1; + while (MinecraftFontWidthCalculator.getStringWidth(sender, s1) < 240) + s1 += " "; + if (title2 != null) + s1 += value1 + "/" + value2; + else + s1 += value1; + sender.sendMessage(s1); + } + + public static boolean isCat(Stats plugin, String player, String category) { + PlayerStat ps = plugin.getStats().get(player); + if (ps == null) + return false; + Category cat = ps.get(category); + if (cat == null) + return false; + return true; + } + + public static void printStat(Stats plugin, CommandSender sendTo, Player statPlayer, String cat, String stat) { + long statVal = plugin.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); + } + sendTo.sendMessage(StatsSettings.premessage + cat + "/" + stat + ": " + ChatColor.WHITE + statString); + } + + public static 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 static String getCatEntries(Stats plugin, String player, String category) { + PlayerStat ps = plugin.getStats().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 static String getCats(Stats plugin, String player) { + PlayerStat ps = plugin.getStats().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 static boolean isStat(Stats plugin, String player, String stat) { + PlayerStat ps = plugin.getStats().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; + } +} diff --git a/src/com/nidefawl/Stats/datasource/Category.java b/src/com/nidefawl/Stats/datasource/Category.java new file mode 100644 index 0000000..04a53ce --- /dev/null +++ b/src/com/nidefawl/Stats/datasource/Category.java @@ -0,0 +1,50 @@ +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; + public HashMap stats; + static final Logger log = Logger.getLogger("Minecraft"); + + public 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); + } + + Iterator iterator() { + return stats.keySet().iterator(); + } +} \ No newline at end of file diff --git a/src/com/nidefawl/Stats/datasource/PlayerStat.java b/src/com/nidefawl/Stats/datasource/PlayerStat.java new file mode 100644 index 0000000..ea68ab0 --- /dev/null +++ b/src/com/nidefawl/Stats/datasource/PlayerStat.java @@ -0,0 +1,114 @@ +package com.nidefawl.Stats.datasource; + +import java.io.File; +import java.util.HashMap; +import java.util.Set; +import com.nidefawl.Stats.StatsSettings; + +public abstract class PlayerStat { + + private String name; + public HashMap categories; + private int lastBoatEnter = 0; + private int lastMinecartEnter = 0; + public long lastUpdate = System.currentTimeMillis(); + public boolean unload = false; + private long lastActivity = System.currentTimeMillis(); + + public 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 save(boolean close); + + public abstract void load(); + + 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; + } + + /** + * @param lastUpdate + * the lastUpdate to set + */ + public void setLastActivity() { + this.lastActivity = System.currentTimeMillis(); + } + + /** + * @return the lastUpdate + */ + public boolean isAfk() { + return System.currentTimeMillis() - lastActivity > StatsSettings.afkTimer * 1000; + } +} \ No newline at end of file diff --git a/src/com/nidefawl/Stats/datasource/PlayerStatFile.java b/src/com/nidefawl/Stats/datasource/PlayerStatFile.java new file mode 100644 index 0000000..43c9519 --- /dev/null +++ b/src/com/nidefawl/Stats/datasource/PlayerStatFile.java @@ -0,0 +1,54 @@ +package com.nidefawl.Stats.datasource; + +import java.io.File; +import java.util.Scanner; + +import com.nidefawl.Stats.Stats; + +public class PlayerStatFile extends PlayerStat { + private String directory; + + PlayerStatFile(String name, String directory) { + super(name); + this.directory = directory; + } + + @Override + public void save() { + } + + @Override + 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) { + Stats.LogInfo("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) { + Stats.LogInfo("Exception while reading " + location + " " + ex); + return; + } + } + + @Override + public void save(boolean close) { + } +} \ No newline at end of file diff --git a/src/com/nidefawl/Stats/datasource/PlayerStatSQL.java b/src/com/nidefawl/Stats/datasource/PlayerStatSQL.java new file mode 100644 index 0000000..41f39a2 --- /dev/null +++ b/src/com/nidefawl/Stats/datasource/PlayerStatSQL.java @@ -0,0 +1,109 @@ +package com.nidefawl.Stats.datasource; + +import java.sql.*; + +import com.nidefawl.Stats.Stats; +import com.nidefawl.Stats.StatsSettings; + +public class PlayerStatSQL extends PlayerStat { + Stats plugin = null; + + public PlayerStatSQL(String name, Stats plugin) { + super(name); + this.plugin = plugin; + } + + @Override + public void save(boolean close) { + Connection conn = null; + PreparedStatement ps = null; + + try { + conn = StatsSQLConnectionManager.getConnection(StatsSettings.useMySQL); + if (close) { + conn.setAutoCommit(false); + } + for (String catName : categories.keySet()) { + Category cat = categories.get(catName); + if (!cat.modified) { + continue; + } + for (String statName : cat.getEntries()) { + int value = cat.get(statName); + ps = conn.prepareStatement(StatsSQLConnectionManager.getPreparedPlayerStatUpdateStatement()); + + ps.setInt(1, value); + ps.setString(2, getName()); + ps.setString(3, catName); + ps.setString(4, statName); + if (ps.executeUpdate() == 0) { + ps = conn.prepareStatement(StatsSQLConnectionManager.getPreparedPlayerStatInsertStatement()); + 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 && close) { + conn.close(); + } + } catch (SQLException ex) { + Stats.LogError("SQL exception: " + ex.getMessage()); + ex.printStackTrace(); + } + } + } + + @Override + public void load() { + if (!plugin.enabled) + return; + + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + + try { + conn = StatsSQLConnectionManager.getConnection(StatsSettings.useMySQL); + 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(); + } + } + } + + @Override + public void save() { + save(true); + } +} \ No newline at end of file diff --git a/src/com/nidefawl/Stats/datasource/StatsSQLConnectionManager.java b/src/com/nidefawl/Stats/datasource/StatsSQLConnectionManager.java new file mode 100644 index 0000000..c382287 --- /dev/null +++ b/src/com/nidefawl/Stats/datasource/StatsSQLConnectionManager.java @@ -0,0 +1,64 @@ +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 { + static Connection connMySQL = null; + static Connection connSQLite = null; + + public final static String getPreparedPlayerStatUpdateStatement() { + return "UPDATE " + StatsSettings.dbTable + " set value=? where player = ? and category = ? and stat = ?;"; + } + + public final static String getPreparedPlayerStatInsertStatement() { + return "INSERT INTO " + StatsSettings.dbTable + " (player,category,stat,value) VALUES(?,?,?,?);"; + } + + public static Connection getConnection(boolean MySQL) { + try { + if (MySQL) { + if (connMySQL == null || connMySQL.isClosed()) { + Class.forName("com.mysql.jdbc.Driver"); + connMySQL = DriverManager.getConnection(StatsSettings.dbUrl, StatsSettings.dbUsername, StatsSettings.dbPassword); + } + return connMySQL; + } else { + if (connSQLite == null || connSQLite.isClosed()) { + Class.forName("org.sqlite.JDBC"); + connSQLite = DriverManager.getConnection(StatsSettings.liteDb); + } + return connSQLite; + } + } 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; + } + } + + public static void closeConnection(boolean MySQL) { + try { + if (MySQL) { + if (connMySQL != null && !connMySQL.isClosed()) { + connMySQL.close(); + } + } else { + if (connSQLite != null && !connSQLite.isClosed()) { + connSQLite.close(); + } + } + } catch (SQLException e) { + Stats.LogError("Error closing SQL-connection: " + e.getMessage()); + e.printStackTrace(); + } + } + +} diff --git a/src/com/nidefawl/Stats/event/StatsListener.java b/src/com/nidefawl/Stats/event/StatsListener.java new file mode 100644 index 0000000..ba39706 --- /dev/null +++ b/src/com/nidefawl/Stats/event/StatsListener.java @@ -0,0 +1,53 @@ +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() { + + } + + @Override + 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/src/com/nidefawl/Stats/event/StatsMobDeathByPlayerEvent.java b/src/com/nidefawl/Stats/event/StatsMobDeathByPlayerEvent.java new file mode 100644 index 0000000..0db0c1f --- /dev/null +++ b/src/com/nidefawl/Stats/event/StatsMobDeathByPlayerEvent.java @@ -0,0 +1,45 @@ +package com.nidefawl.Stats.event; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDeathEvent; + +public class StatsMobDeathByPlayerEvent extends org.bukkit.event.Event { + /** + * + */ + private static final long serialVersionUID = 2158229946386582299L; + private Player player; + boolean isCancelled; + EntityDeathEvent base; + + public StatsMobDeathByPlayerEvent(EntityDeathEvent event, Player player, Entity entity) { + super("StatsMobDeathByPlayerEvent"); + this.base = event; + this.player = player; + isCancelled = false; + } + + /** + * @return the entity + */ + public Entity getEntity() { + return this.base.getEntity(); + } + + /** + * @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/src/com/nidefawl/Stats/event/StatsPlayerDamagedPlayerEvent.java b/src/com/nidefawl/Stats/event/StatsPlayerDamagedPlayerEvent.java new file mode 100644 index 0000000..9520a45 --- /dev/null +++ b/src/com/nidefawl/Stats/event/StatsPlayerDamagedPlayerEvent.java @@ -0,0 +1,79 @@ +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 static final long serialVersionUID = -380510384968697307L; + 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("StatsPlayerDamagedPlayerEvent"); + 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/src/com/nidefawl/Stats/event/StatsPlayerDeathByEntityEvent.java b/src/com/nidefawl/Stats/event/StatsPlayerDeathByEntityEvent.java new file mode 100644 index 0000000..fb86647 --- /dev/null +++ b/src/com/nidefawl/Stats/event/StatsPlayerDeathByEntityEvent.java @@ -0,0 +1,74 @@ +package com.nidefawl.Stats.event; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.entity.EntityDeathEvent; + +public class StatsPlayerDeathByEntityEvent extends org.bukkit.event.Event implements Cancellable { + /** + * + */ + private static final long serialVersionUID = -7763150082128350151L; + private Player player; + private Entity entity; + boolean isCancelled; + private EntityDeathEvent base; + + @Override + public boolean isCancelled() { + return this.isCancelled; + } + + @Override + public void setCancelled(boolean arg0) { + isCancelled = arg0; + } + + public StatsPlayerDeathByEntityEvent(EntityDeathEvent event, Player player, Entity entity) { + + super("StatsPlayerDeathByEntityEvent"); + this.base = event; + 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; + } + + /** + * @return the base + */ + public EntityDeathEvent getBase() { + return base; + } + +} diff --git a/src/com/nidefawl/Stats/event/StatsPlayerDeathByOtherEvent.java b/src/com/nidefawl/Stats/event/StatsPlayerDeathByOtherEvent.java new file mode 100644 index 0000000..cf466a5 --- /dev/null +++ b/src/com/nidefawl/Stats/event/StatsPlayerDeathByOtherEvent.java @@ -0,0 +1,72 @@ +package com.nidefawl.Stats.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.entity.EntityDeathEvent; + +public class StatsPlayerDeathByOtherEvent extends org.bukkit.event.Event implements Cancellable { + /** + * + */ + private static final long serialVersionUID = -7138441428433873857L; + private Player player; + private String reason; + boolean isCancelled; + private EntityDeathEvent base; + + @Override + public boolean isCancelled() { + return this.isCancelled; + } + + @Override + public void setCancelled(boolean arg0) { + isCancelled = arg0; + } + + public StatsPlayerDeathByOtherEvent(EntityDeathEvent event, Player player, String reason) { + super("StatsPlayerDeathByOtherEvent"); + this.base = event; + 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 base + */ + public EntityDeathEvent getBase() { + return base; + } + + /** + * @return the reason + */ + public String getReason() { + return reason; + } + +} diff --git a/src/com/nidefawl/Stats/event/StatsPlayerDeathByPlayerEvent.java b/src/com/nidefawl/Stats/event/StatsPlayerDeathByPlayerEvent.java new file mode 100644 index 0000000..4008227 --- /dev/null +++ b/src/com/nidefawl/Stats/event/StatsPlayerDeathByPlayerEvent.java @@ -0,0 +1,72 @@ +package com.nidefawl.Stats.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.entity.EntityDeathEvent; + +public class StatsPlayerDeathByPlayerEvent extends org.bukkit.event.Event implements Cancellable { + /** + * + */ + private static final long serialVersionUID = 1834044792921833350L; + private Player player; + private Player killer; + boolean isCancelled; + private EntityDeathEvent base; + + @Override + public boolean isCancelled() { + return this.isCancelled; + } + + @Override + public void setCancelled(boolean arg0) { + isCancelled = arg0; + } + + public StatsPlayerDeathByPlayerEvent(EntityDeathEvent event, Player player, Player killer) { + super("StatsPlayerDeathByPlayerEvent"); + this.base = event; + 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 base + */ + public EntityDeathEvent getBase() { + return base; + } + + /** + * @return the killer + */ + public Player getKiller() { + return killer; + } + +} diff --git a/src/com/nidefawl/Stats/event/StatsPlayerMoveEvent.java b/src/com/nidefawl/Stats/event/StatsPlayerMoveEvent.java new file mode 100644 index 0000000..3a9433d --- /dev/null +++ b/src/com/nidefawl/Stats/event/StatsPlayerMoveEvent.java @@ -0,0 +1,47 @@ +package com.nidefawl.Stats.event; + +public class StatsPlayerMoveEvent extends org.bukkit.event.Event { + /** + * + */ + private static final long serialVersionUID = 4195026324747114268L; + private String player; + private int distance; + + public StatsPlayerMoveEvent(String player, int distance) { + super("StatsPlayerMoveEvent"); + 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/src/com/nidefawl/Stats/udpates/Update1.java b/src/com/nidefawl/Stats/udpates/Update1.java new file mode 100644 index 0000000..b3187e6 --- /dev/null +++ b/src/com/nidefawl/Stats/udpates/Update1.java @@ -0,0 +1,15 @@ +package com.nidefawl.Stats.udpates; + +import java.io.File; + +import com.nidefawl.Stats.Stats; + +public class Update1 { + public static void execute(Stats plugin) { + File oldLoc = new File("items.txt"); + if(oldLoc.exists()) { + Stats.LogInfo("Moving items.txt to "+plugin.getDataFolder().getPath()+"/items.txt"); + oldLoc.renameTo(new File(plugin.getDataFolder(),"items.txt")); + } + } +} diff --git a/src/com/nidefawl/Stats/udpates/Update2.java b/src/com/nidefawl/Stats/udpates/Update2.java new file mode 100644 index 0000000..3c7f81c --- /dev/null +++ b/src/com/nidefawl/Stats/udpates/Update2.java @@ -0,0 +1,96 @@ +package com.nidefawl.Stats.udpates; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import com.nidefawl.Stats.Stats; +import com.nidefawl.Stats.StatsSettings; +import com.nidefawl.Stats.ItemResolver.hModItemResolver; +import com.nidefawl.Stats.ItemResolver.itemResolver; +import com.nidefawl.Stats.datasource.StatsSQLConnectionManager; + +public class Update2 { + public static void execute(Stats plugin) { + FileWriter writer; + itemResolver items = new hModItemResolver(new File(plugin.getDataFolder(),"items.txt")); + try { + writer = new FileWriter(new File(plugin.getDataFolder(),"items.txt"),true); + if (writer != null) { + try { + if(items.getItem(26).equals("26")) { + Stats.LogInfo("Adding bedblock (26) to items.txt"); + writer.write("bedblock:26\r\n"); + Stats.LogInfo("Updating stats in database"); + UpdateItemStatKey("26","bedblock"); + } + if(items.getItem(93).equals("93")) { + Stats.LogInfo("Adding repeateron (93) to items.txt"); + writer.write("repeateron:93\r\n"); + Stats.LogInfo("Updating stats in database"); + UpdateItemStatKey("93","repeateron"); + } + if(items.getItem(94).equals("94")) { + Stats.LogInfo("Adding repeateroff (94) to items.txt"); + writer.write("repeateroff:94\r\n"); + Stats.LogInfo("Updating stats in database"); + UpdateItemStatKey("94","repeateroff"); + } + if(items.getItem(355).equals("355")) { + Stats.LogInfo("Adding bed (355) to items.txt"); + writer.write("bed:355\r\n"); + Stats.LogInfo("Updating stats in database"); + UpdateItemStatKey("355","bed"); + } + if(items.getItem(356).equals("356")) { + Stats.LogInfo("Adding repeater (356) to items.txt"); + writer.write("repeater:356\r\n"); + Stats.LogInfo("Updating stats in database"); + UpdateItemStatKey("356","repeater"); + } + writer.close(); + plugin.setItems( new hModItemResolver(new File(plugin.getDataFolder(),"items.txt"))); + } catch (IOException e) { + Stats.LogError("Exception while updating "+plugin.getDataFolder().getPath()+"/items.txt "+ e); + e.printStackTrace(); + } + } + } catch (IOException e1) { + e1.printStackTrace(); + } + } + static void UpdateItemStatKey(String oldKey,String newKey) { + + int result = 0; + Connection conn = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + conn = StatsSQLConnectionManager.getConnection(StatsSettings.useMySQL); + ps = conn.prepareStatement("UPDATE " + StatsSettings.dbTable + " set stat = ? where stat = ? and (category = 'blockdestroy' or category = 'blockcreate' or category = 'itemuse' or category = 'itemdrop' or category = 'itempickup');"); + ps.setString(1, newKey); + ps.setString(2, oldKey); + result = ps.executeUpdate(); + } catch (SQLException ex) { + Stats.LogError("SQL exception" + ex); + 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); + ex.printStackTrace(); + } + } + Stats.LogInfo("Updated " + result + " stats."); + } +} diff --git a/src/com/nidefawl/Stats/util/Updater.java b/src/com/nidefawl/Stats/util/Updater.java new file mode 100644 index 0000000..aaae68f --- /dev/null +++ b/src/com/nidefawl/Stats/util/Updater.java @@ -0,0 +1,226 @@ +/** + * 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.FileReader; +import java.io.FileWriter; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; + +import com.nidefawl.Achievements.Achievements; +import com.nidefawl.Stats.Stats; + +public class Updater { + + /** + * 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 = "VERSIONS"; + + /** + * Internal config + */ + private HashMap config = new HashMap(); + + private Stats plugin = null; + + public Updater(Stats plugin) { + this.plugin = plugin; + config.put("sqlite", "1.00"); + config.put("mysql", "1.00"); + parseInternalConfig(); + } + /** + * @return the current sqlite version + */ + public double getCurrentSQLiteVersion() { + return Double.parseDouble(config.get("sqlite")); + } + /** + * @return the current sqlite version + */ + public double getCurrentMySQLVersion() { + return Double.parseDouble(config.get("mysql")); + } + 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(plugin.getDataFolder() + 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(); + } + } + + + public boolean updateDist(boolean autoUpdate) throws Exception { + URL url = new URL(UPDATE_SITE + VERSION_FILE); + InputStream inputStream = url.openStream(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + double SQLiteVersion = Double.parseDouble(bufferedReader.readLine()); + double MySQLVersion = Double.parseDouble(bufferedReader.readLine()); + double StatsVersion = Double.parseDouble(bufferedReader.readLine()); + double AchievementsVersion = Double.parseDouble(bufferedReader.readLine()); + bufferedReader.close(); + inputStream.close(); + String plugPath = plugin.getDataFolder().getPath()+File.separator; + boolean updated = false; + updated |= (new UpdaterFile(UPDATE_SITE + "lib/mysql.jar",plugPath+"lib/mysql.jar",getCurrentMySQLVersion(),MySQLVersion)).update(true); + config.put("mysql", String.valueOf(MySQLVersion)); + updated |= (new UpdaterFile(UPDATE_SITE + "lib/sqlite.jar",plugPath+"lib/sqlite.jar",getCurrentSQLiteVersion(),SQLiteVersion)).update(true); + config.put("sqlite", String.valueOf(SQLiteVersion)); + if (new File("plugins/Achievements.jar").exists()) { + updated |= (new UpdaterFile(UPDATE_SITE + "Achievements.jar","plugins/Achievements.jar",Achievements.getVersion(),AchievementsVersion)).update(autoUpdate); + } + updated |= (new UpdaterFile(UPDATE_SITE + "Stats.jar","plugins/Stats.jar",Stats.version,StatsVersion)).update(autoUpdate); + saveInternal(); + return updated; + } + +} \ No newline at end of file diff --git a/src/com/nidefawl/Stats/util/UpdaterFile.java b/src/com/nidefawl/Stats/util/UpdaterFile.java new file mode 100644 index 0000000..8d0ea4a --- /dev/null +++ b/src/com/nidefawl/Stats/util/UpdaterFile.java @@ -0,0 +1,123 @@ +/** + * 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; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; + +import com.nidefawl.Stats.Stats; + +public class UpdaterFile { + + /** + * The remote url location + */ + private String remoteLocation; + + /** + * The local url location + */ + private String localLocation; + private double localVersion; + private double remoteVersion; + + public UpdaterFile(String remoteLocation, String localLocation, double localVersion, double remoteVersion) { + this.remoteLocation = remoteLocation; + this.localLocation = localLocation; + this.localVersion = localVersion; + this.remoteVersion = remoteVersion; + } + + /** + * @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; + } + + 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); + } + } + + public boolean update(boolean autoUpdate) throws Exception { + if (remoteVersion > localVersion) { + if (autoUpdate) { + try { + Stats.LogInfo("Newer version of "+localLocation+" found. local: "+localVersion+" remote: "+remoteVersion); + Stats.LogInfo("Downloading file : " + remoteLocation); + URL url = new URL(remoteLocation); + File file = new File(localLocation); + file.mkdirs(); + if (file.exists()) { + file.delete(); + } + InputStream inputStream = url.openStream(); + OutputStream outputStream = new FileOutputStream(file); + saveTo(inputStream, outputStream); + inputStream.close(); + outputStream.close(); + Stats.LogInfo("Download complete. File saved to "+file.getAbsolutePath()); + return true; + } catch (Exception e) { + Stats.LogInfo("Download failed: " + e.getMessage()); + e.printStackTrace(); + return false; + } + } else { + Stats.LogInfo("There is an update for " + localLocation); + return false; + } + } + return false; + } + +} diff --git a/src/plugin.yml b/src/plugin.yml new file mode 100644 index 0000000..b18574f --- /dev/null +++ b/src/plugin.yml @@ -0,0 +1,13 @@ +name: Stats +main: com.nidefawl.Stats.Stats +version: 0.99 +author: nidefawl +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