- Metrics to monitor plugin usage
 - Region Safemode: http://dev.bukkit.org/server-mods/limited-creative/tickets/81-getting-out-of-creative-region-with-creative/
This commit is contained in:
Jascha Starke 2013-01-29 22:31:01 +01:00
parent 8cfb65365a
commit 5078df241e
10 changed files with 350 additions and 6 deletions

View file

@ -141,6 +141,13 @@ region:
# default: false # default: false
remember: false remember: false
# RegionSafeMode
# When a player leaves a region he always will get back to the world gamemode, even if he entered the region already
# in the region-gamemode. So its the opposite analog to RegionRememberOptional.
# That means: If a GM in creative-mode walks/flies through a creative-region in a survival world, he will get back
# to survival on leaving the region.
# default: false
safemode: false
cmdblock: cmdblock:
# CommandBlockerEnabled # CommandBlockerEnabled
@ -168,3 +175,10 @@ cmdblock:
# System-Locale is used (selected by Java depending on LC_LANG-Environment-Variable # System-Locale is used (selected by Java depending on LC_LANG-Environment-Variable
# default: none (Use System-Default Locale) # default: none (Use System-Default Locale)
#locale: en_US #locale: en_US
# Metrics
# This settings allows the Addon-Author to track the Servers using this plugin. It will not track any player
# related data like names, ips, online time or such. Please do not disable the option! As more servers are using
# the plugin and the author knows, as more he is willing to support the plugin! Its a win-win for both.
# default: true
metrics: true

View file

@ -1,6 +1,6 @@
name: LimitedCreative name: LimitedCreative
main: de.jaschastarke.minecraft.limitedcreative.Core main: de.jaschastarke.minecraft.limitedcreative.Core
version: 1.4.7a version: 1.4.7b
softdepend: [WorldGuard, WorldEdit, MultiInv, xAuth, AuthMe, MultiInv, Multiverse-Inventories] softdepend: [WorldGuard, WorldEdit, MultiInv, xAuth, AuthMe, MultiInv, Multiverse-Inventories]
dev-url: http://dev.bukkit.org/server-mods/limited-creative/ dev-url: http://dev.bukkit.org/server-mods/limited-creative/
commands: commands:

View file

@ -3,7 +3,7 @@
<groupId>de.jaschastarke</groupId> <groupId>de.jaschastarke</groupId>
<artifactId>LimitedCreative</artifactId> <artifactId>LimitedCreative</artifactId>
<name>LimitedCreative</name> <name>LimitedCreative</name>
<version>1.4.7a</version> <version>1.4.7b</version>
<url>https://github.com/possi/LimitedCreative</url> <url>https://github.com/possi/LimitedCreative</url>
<scm> <scm>
<connection>scm:git:git://github.com/possi/LimitedCreative.git</connection> <connection>scm:git:git://github.com/possi/LimitedCreative.git</connection>
@ -57,6 +57,7 @@
<includes> <includes>
<include>plugin.yml</include> <include>plugin.yml</include>
<include>config.yml</include> <include>config.yml</include>
<include>settings.properties</include>
</includes> </includes>
</resource> </resource>
<resource> <resource>
@ -81,13 +82,13 @@
<dependency> <dependency>
<groupId>org.bukkit</groupId> <groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId> <artifactId>bukkit</artifactId>
<version>1.4.6-R0.1</version> <version>1.4.7-R0.1</version>
</dependency> </dependency>
<dependency> <dependency>
<!-- http://dl.bukkit.org/ --> <!-- http://dl.bukkit.org/ -->
<groupId>org.bukkit</groupId> <groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId> <artifactId>craftbukkit</artifactId>
<version>1.4.6-R0.1</version> <version>1.4.7-R0.1</version>
</dependency> </dependency>
<dependency> <dependency>
<!-- http://dev.bukkit.org/server-mods/worldedit/ --> <!-- http://dev.bukkit.org/server-mods/worldedit/ -->

2
settings.properties Normal file
View file

@ -0,0 +1,2 @@
piwik_url = http://stats.ja-s.de/piwikProxy.php
piwik_site_id = 2

View file

@ -0,0 +1,10 @@
package de.jaschastarke.bukkit.tools.stats;
public interface IStatistics {
public static final String SEPERATOR = "/";
/**
* Use the {@see SEPERATOR} to create subgroup of events
* @param event
*/
public void trackEvent(String event);
}

View file

@ -0,0 +1,245 @@
package de.jaschastarke.bukkit.tools.stats;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Stack;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
/**
* Use the piwik-Proxy https://gist.github.com/4664325 to track the online-count as seperate requests to get a propper
* graph of usage.
*
* Settings as Properties:
* - piwik_url : required; URL to the piwik.php or the proxy file (see above)
* - piwik_site_id : required; The Site-ID of the Piwik-Website to use for tracking
* - stats_interval : optional; seconds between tracking online count (defaults to 300 for 5 min)
*/
public class PiwikStatistics implements IStatistics {
private static final int TICKS_PER_SECOND = 20;
private static final long DEFAULT_WAIT = 6000L; // 6000 ticks or 300 seconds or 5 minutes
private static final int MAX_CVAR_SIZE = 200;
private static final int APIV = 1;
private URL apiUrl;
private int idSite;
private Plugin plugin;
private String pluginname;
private String version;
private String server;
private String serverid = getUniqueID();
private String servername;
private String servermotd;
private long wait = DEFAULT_WAIT;
private static final String PIWIK_FIELD_CVAR = "cvar";
/**
* Single call instantiate
*
* Also calls .register,
*/
public PiwikStatistics(final JavaPlugin plugin) {
Properties settings = new Properties();
try {
settings.load(plugin.getClass().getClassLoader().getResourceAsStream("settings.properties"));
init(settings);
register(plugin);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Single call instantiate
*
* Also calls .register,
*/
public PiwikStatistics(final JavaPlugin plugin, final InputStream settingsFile) {
Properties settings = new Properties();
try {
settings.load(settingsFile);
init(settings);
register(plugin);
} catch (IOException e) {
e.printStackTrace();
}
}
public PiwikStatistics(final Properties settings) {
init(settings);
}
private void init(final Properties settings) {
try {
String url = settings.getProperty("piwik_url");
if (url.isEmpty()) {
apiUrl = null;
return;
}
apiUrl = new URL(url);
idSite = Integer.parseInt(settings.getProperty("piwik_site_id"));
String seconds = settings.getProperty("stats_interval");
if (seconds != null && !seconds.isEmpty())
wait = Long.parseLong(seconds) * TICKS_PER_SECOND;
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid Piwik-URL defined", e);
}
}
public static String getUniqueID() {
return String.format("%016x", UUID.randomUUID().getMostSignificantBits());
}
public void register(final Plugin rplugin) {
if (apiUrl == null)
return;
plugin = rplugin;
//plugin.getServer().getPluginManager().registerEvents(new StatsListener(), plugin);
pluginname = plugin.getName();
version = plugin.getDescription().getVersion();
plugin.getServer().getScheduler().runTaskLaterAsynchronously(plugin, new Runnable() {
@Override
public void run() {
// Well, we all know it isn't http, but as piwik is a website tracking, it doesn't tracks the url if it isn't a http url ;)
server = "http://" + StatsUtils.getIP(plugin.getServer()) + ":" + plugin.getServer().getPort();
servername = ChatColor.stripColor(plugin.getServer().getServerName().replace(SEPERATOR, "-"));
servermotd = ChatColor.stripColor(plugin.getServer().getMotd().replace(SEPERATOR, "-").replaceAll("\\s+", " "));
trackEnable();
}
}, wait);
plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
@Override
public void run() {
final int playercount = plugin.getServer().getOnlinePlayers().length;
if (playercount > 0) {
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
@Override
public void run() {
trackOnlineUsage(playercount);
}
});
}
}
}, wait, wait);
}
private void trackEnable() {
Plugin[] pluginlist = plugin.getServer().getPluginManager().getPlugins();
List<String[]> cdata = new ArrayList<String[]>();
cdata.add(new String[]{"Server-Name", servername});
cdata.add(new String[]{"Server-Version", (plugin.getServer().getName() + " " + plugin.getServer().getVersion())});
cdata.add(new String[]{"Plugin-Version", pluginname + " " + version});
Stack<StringBuilder> plugins = new Stack<StringBuilder>();
plugins.add(new StringBuilder(""));
for (Plugin cplugin : pluginlist) {
StringBuilder currentPlugins = plugins.lastElement();
if ((currentPlugins.length() + cplugin.getName().length() + 1) > MAX_CVAR_SIZE) {
plugins.add(new StringBuilder());
currentPlugins = plugins.lastElement();
}
if (currentPlugins.length() > 0)
currentPlugins.append(",");
currentPlugins.append(cplugin.getName());
}
for (int i = 0; i < plugins.size(); i++) {
String plname = i == 0 ? "Plugins" : ("Plugins " + (i + 1));
cdata.add(new String[]{plname, plugins.get(i).toString()});
}
cdata.add(new String[]{"Mode", plugin.getServer().getOnlineMode() ? "Online" : "Offline"});
JSONObject cvar = getCVar(cdata.toArray(new String[cdata.size()][]));
String[][] args = new String[][]{
{"action_name", servermotd},
{PIWIK_FIELD_CVAR, cvar.toJSONString()}
};
track(server + SEPERATOR + pluginname + "/load", args);
}
private void trackOnlineUsage(final int playercount) {
List<String[]> cdata = new ArrayList<String[]>();
cdata.add(new String[]{"Online-Count", Integer.toString(playercount)});
if (!plugin.getServer().getOnlineMode())
cdata.add(new String[]{"Offline-Mode", "yes"});
JSONObject cvar = getCVar(cdata.toArray(new String[cdata.size()][]));
track(server + SEPERATOR + pluginname + "/usage", new String[][]{
{"multiple", Integer.toString(playercount)}, // handled by piwikProxy.php to create a Batch-Request to simulate multiple hits
{PIWIK_FIELD_CVAR, cvar.toJSONString()}
});
}
@SuppressWarnings("unchecked")
public static JSONObject getCVar(final String[][] cvars) {
JSONObject cvar = new JSONObject();
for (int i = 0; i < cvars.length; i++) {
JSONArray t = new JSONArray();
t.add(cvars[i][0]);
t.add(cvars[i][1]);
cvar.put(Integer.toString(i + 1), t);
}
return cvar;
}
protected void track(final String target, final String[][] addargs) {
String[][] basicargs = new String[][]{
{"idsite", Integer.toString(idSite)},
{"rec", "1"},
{"url", target},
{"_id", serverid},
{"rand", Long.toString(System.currentTimeMillis())},
{"apiv", Integer.toString(APIV)},
};
String[][] arguments;
if (addargs.length > 0) {
arguments = new String[basicargs.length + addargs.length][2];
System.arraycopy(basicargs, 0, arguments, 0, basicargs.length);
System.arraycopy(addargs, 0, arguments, basicargs.length, addargs.length);
} else {
arguments = basicargs;
}
try {
URL req = StatsUtils.buildRequest(apiUrl, arguments);
URLConnection conn = req.openConnection();
//System.out.println(req.toString());
conn.setUseCaches(false);
conn.connect();
InputStream in = conn.getInputStream();
in.read();
in.close();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/*class StatsListener implements Listener {
@EventHandler
public void onJoin(final PlayerJoinEvent event) {
plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, new Runnable() {
@Override
public void run() {
track(server + SEPERATOR + pluginname + "/join", new String[0][0]);
}
});
}
}*/
@Override
public void trackEvent(final String event) {
track(server + SEPERATOR + pluginname + SEPERATOR + event, new String[0][0]);
}
}

View file

@ -0,0 +1,58 @@
package de.jaschastarke.bukkit.tools.stats;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import org.bukkit.Server;
public final class StatsUtils {
private static final String ENCODING = "UTF-8";
private StatsUtils() {
}
public static String getIP(final Server server) {
String ip = server.getIp();
if (ip.isEmpty()) {
try {
URL getip = new URL("http://checkip.amazonaws.com/");
BufferedReader in = new BufferedReader(new InputStreamReader(getip.openStream()));
ip = in.readLine();
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return ip;
}
public static String enc(final String s) {
try {
return URLEncoder.encode(s, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return s;
}
public static URL buildRequest(final URL url, final String[][] arguments) {
StringBuilder u = new StringBuilder(url.toString());
for (int i = 0; i < arguments.length; i++) {
u.append(i == 0 ? "?" : "&");
u.append(arguments[i][0]);
u.append("=");
u.append(enc(arguments[i][1]));
}
try {
return new URL(u.toString());
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Arguments couldn't build to a new URL");
}
}
}

View file

@ -49,6 +49,7 @@ public class Configuration {
ADVENTUREINV("store.adventure", false), ADVENTUREINV("store.adventure", false),
REGION_OPTIONAL("region.optional", true), REGION_OPTIONAL("region.optional", true),
REGION_REMEMBER("region.remember", false), REGION_REMEMBER("region.remember", false),
REGION_SAFEMODE("region.safemode", false),
BLOCKPICKUP("limit.pickup", true), BLOCKPICKUP("limit.pickup", true),
BLOCKSIGN("limit.sign", true), BLOCKSIGN("limit.sign", true),
BLOCKBUTTON("limit.button", false), BLOCKBUTTON("limit.button", false),
@ -58,6 +59,7 @@ public class Configuration {
REMOVEPICKUP("limit.remove_pickup", false), REMOVEPICKUP("limit.remove_pickup", false),
PERM_WEPIF("permissions.wepif", true), PERM_WEPIF("permissions.wepif", true),
CMDBLOCKER("cmdblocker.enabled", true), CMDBLOCKER("cmdblocker.enabled", true),
METRICS("metrics", true),
DEBUG("debug", false); DEBUG("debug", false);
private String key; private String key;
@ -162,6 +164,9 @@ public class Configuration {
public boolean getRegionRememberOptional() { public boolean getRegionRememberOptional() {
return this.getRegionOptional() && this.getBoolean(Option.REGION_REMEMBER); return this.getRegionOptional() && this.getBoolean(Option.REGION_REMEMBER);
} }
public boolean getRegionSafeMode() {
return this.getBoolean(Option.REGION_SAFEMODE);
}
public String getLocale() { public String getLocale() {
if (c.contains("locale") && c.getString("locale") != "none") if (c.contains("locale") && c.getString("locale") != "none")

View file

@ -24,7 +24,9 @@ import org.bukkit.event.HandlerList;
import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import de.jaschastarke.bukkit.tools.stats.PiwikStatistics;
import de.jaschastarke.minecraft.integration.Communicator; import de.jaschastarke.minecraft.integration.Communicator;
import de.jaschastarke.minecraft.limitedcreative.Configuration.Option;
import de.jaschastarke.minecraft.limitedcreative.cmdblock.CommandBlocker; import de.jaschastarke.minecraft.limitedcreative.cmdblock.CommandBlocker;
import de.jaschastarke.minecraft.limitedcreative.listeners.LimitListener; import de.jaschastarke.minecraft.limitedcreative.listeners.LimitListener;
import de.jaschastarke.minecraft.limitedcreative.listeners.MainListener; import de.jaschastarke.minecraft.limitedcreative.listeners.MainListener;
@ -106,6 +108,9 @@ public class Core extends JavaPlugin {
Commands.register(this); Commands.register(this);
if (config.getBoolean(Option.METRICS))
new PiwikStatistics(this);
/*plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() { /*plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
@Override @Override
public void run() { public void run() {

View file

@ -161,9 +161,13 @@ public class LCPlayer {
_permanent_gamemode = temp; _permanent_gamemode = temp;
} }
public boolean isInPermanentGameMode() { public boolean isInPermanentGameMode() {
if (plugin.config.getRegionSafeMode())
return false;
return isInPermanentGameMode(getPlayer().getGameMode()); return isInPermanentGameMode(getPlayer().getGameMode());
} }
public boolean isInPermanentGameMode(GameMode temp) { public boolean isInPermanentGameMode(GameMode temp) {
if (plugin.config.getRegionSafeMode())
return false;
Core.debug(getName()+": get permanent game mode: " + _permanent_gamemode); Core.debug(getName()+": get permanent game mode: " + _permanent_gamemode);
return temp.equals(_permanent_gamemode); return temp.equals(_permanent_gamemode);
} }