diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..79af4d0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,42 @@
+# Eclipse stuff
+/.classpath
+/.project
+/.settings
+
+# netbeans
+/nbproject
+
+# we use maven!
+/build.xml
+
+# maven
+/target
+
+# vim
+.*.sw[a-p]
+
+# various other potential build files
+/build
+/bin
+/dist
+/manifest.mf
+
+/world
+
+# Mac filesystem dust
+*.DS_Store
+
+# intellij
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# Project Stuff
+/src/main/resources/mcMMO-Towny
+
+# Other Libraries
+*.jar
+
+# Atlassian Stuff
+/atlassian-ide-plugin.xml
diff --git a/mcMMO-Towny/pom.xml b/mcMMO-Towny/pom.xml
new file mode 100644
index 0000000..af54db1
--- /dev/null
+++ b/mcMMO-Towny/pom.xml
@@ -0,0 +1,149 @@
+
+ 4.0.0
+ org.mcmmo
+ mcMMO-Towny
+ 1.0.0-SNAPSHOT
+ mcMMO-Towny
+ https://github.com/mcMMO-Dev/mcMMO-Towny
+
+ GitHub
+ https://github.com/mcMMO-Dev/mcMMO-Towny/issues
+
+
+ mcMMO-Towny
+ ${basedir}/src/main/java
+
+
+ .
+ true
+ ${basedir}/src/main/resources/
+
+ *.yml
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+ 1.6
+ 1.6
+
+
+
+ maven-assembly-plugin
+
+
+ src/main/assembly/package.xml
+
+
+
+
+ build
+ package
+
+ single
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 1.5
+
+
+
+ com.gmail.nossr50.mcMMO:mcMMO
+ org.mcstats.bukkit:metrics
+
+
+
+
+ org.mcstats
+ org.mcmmo.mcmmotowny.mcstats
+
+
+
+
+ com.gmail.nossr50.mcMMO:mcMMO
+
+ com/gmail/nossr50/events/experience*
+
+
+
+
+
+
+ package
+
+ shade
+
+
+
+
+
+
+
+ org.apache.maven.wagon
+ wagon-file
+ 2.2
+
+
+
+
+
+ bukkit-repo
+ http://repo.bukkit.org/content/groups/public/
+
+
+ md_5-repo
+ http://repo.md-5.net/
+
+
+ Plugin Metrics
+ http://repo.mcstats.org/content/repositories/public
+
+
+
+
+ org.bukkit
+ bukkit
+ LATEST
+ jar
+ compile
+
+
+ com.gmail.nossr50.mcMMO
+ mcMMO
+ RELEASE
+ jar
+ compile
+
+
+ org.mcstats.bukkit
+ metrics
+ R6
+ compile
+
+
+ com.palmergames.bukkit.towny
+ Towny
+ 0.86.0.0
+ system
+ ${project.basedir}/lib/Towny.jar
+
+
+
+
+ mcmmo-repo
+ file:///var/lib/jenkins/repo
+
+
+
+ UTF-8
+
+
\ No newline at end of file
diff --git a/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/config/Config.java b/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/config/Config.java
new file mode 100644
index 0000000..2cfd944
--- /dev/null
+++ b/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/config/Config.java
@@ -0,0 +1,35 @@
+package org.mcmmo.mcmmotowny.config;
+
+public class Config extends ConfigLoader {
+ private static Config instance;
+
+ private Config() {
+ super("config.yml");
+ validate();
+ }
+
+ public static Config getInstance() {
+ if (instance == null) {
+ instance = new Config();
+ }
+
+ return instance;
+ }
+
+ @Override
+ protected boolean validateKeys() {
+ return true;
+ }
+
+ @Override
+ protected void loadKeys() {}
+
+ /* GENERAL */
+ public boolean getStatsTrackingEnabled() { return config.getBoolean("General.Stats_Tracking", true); }
+ public boolean getUpdateCheckEnabled() { return config.getBoolean("General.Update_Check", true); }
+ public boolean getPreferBeta() { return config.getBoolean("General.Prefer_Beta", false); }
+
+ /* TOWNY */
+ public double getExperienceModifierGlobal() { return config.getDouble("Experience.Global_Modifier", 1.0); }
+ public double getExperienceModifierTown(String townName) { return config.getDouble("Experience.Towns." + townName, 1.0); }
+}
diff --git a/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/config/ConfigLoader.java b/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/config/ConfigLoader.java
new file mode 100644
index 0000000..cce0177
--- /dev/null
+++ b/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/config/ConfigLoader.java
@@ -0,0 +1,89 @@
+package org.mcmmo.mcmmotowny.config;
+
+import java.io.File;
+import java.util.List;
+
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import org.mcmmo.mcmmotowny.mcMMOTowny;
+
+public abstract class ConfigLoader {
+ protected static final mcMMOTowny plugin = mcMMOTowny.p;
+ protected String fileName;
+ private File configFile;
+ protected FileConfiguration config;
+
+ public ConfigLoader(String relativePath, String fileName) {
+ this.fileName = fileName;
+ configFile = new File(plugin.getDataFolder(), relativePath + File.separator + fileName);
+ loadFile();
+ }
+
+ public ConfigLoader(String fileName) {
+ this.fileName = fileName;
+ configFile = new File(plugin.getDataFolder(), fileName);
+ loadFile();
+ }
+
+ protected void loadFile() {
+ if (!configFile.exists()) {
+ plugin.debug("Creating mcMMOTowny " + fileName + " File...");
+
+ try {
+ plugin.saveResource(fileName, false); // Normal files
+ }
+ catch (IllegalArgumentException ex) {
+ plugin.saveResource(configFile.getParentFile().getName() + File.separator + fileName, false); // Mod files
+ }
+ }
+ else {
+ plugin.debug("Loading mcMMOTowny " + fileName + " File...");
+ }
+
+ config = YamlConfiguration.loadConfiguration(configFile);
+ }
+
+ protected abstract void loadKeys();
+
+ protected boolean validateKeys() {
+ return true;
+ }
+
+ protected boolean noErrorsInConfig(List issues) {
+ for (String issue : issues) {
+ plugin.getLogger().warning(issue);
+ }
+
+ return issues.isEmpty();
+ }
+
+ protected void validate() {
+ if (validateKeys()) {
+ plugin.debug("No errors found in " + fileName + "!");
+ }
+ else {
+ plugin.getLogger().warning("Errors were found in " + fileName + "! mcMMOTowny was disabled!");
+ plugin.getServer().getPluginManager().disablePlugin(plugin);
+ }
+ }
+
+ public File getFile() {
+ return configFile;
+ }
+
+ public void backup() {
+ plugin.getLogger().warning("You are using an old version of the " + fileName + " file.");
+ plugin.getLogger().warning("Your old file has been renamed to " + fileName + ".old and has been replaced by an updated version.");
+
+ configFile.renameTo(new File(configFile.getPath() + ".old"));
+
+ if (plugin.getResource(fileName) != null) {
+ plugin.saveResource(fileName, true);
+ }
+
+ plugin.getLogger().warning("Reloading " + fileName + " with new values...");
+ loadFile();
+ loadKeys();
+ }
+}
diff --git a/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/listeners/ExperienceListener.java b/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/listeners/ExperienceListener.java
new file mode 100644
index 0000000..38312f7
--- /dev/null
+++ b/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/listeners/ExperienceListener.java
@@ -0,0 +1,30 @@
+package org.mcmmo.mcmmotowny.listeners;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+
+import com.gmail.nossr50.events.experience.McMMOPlayerXpGainEvent;
+
+import com.palmergames.bukkit.towny.object.TownyUniverse;
+import org.mcmmo.mcmmotowny.config.Config;
+
+public class ExperienceListener implements Listener {
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void onPlayerXpGainEvent(McMMOPlayerXpGainEvent event) {
+ Player player = event.getPlayer();
+ float experienceGained = event.getRawXpGained();
+ String townName = TownyUniverse.getTownName(player.getLocation());
+
+ if (townName == null) {
+ return;
+ }
+
+ experienceGained *= Config.getInstance().getExperienceModifierGlobal();
+ experienceGained *= Config.getInstance().getExperienceModifierTown(townName);
+
+ event.setRawXpGained(experienceGained);
+ }
+}
diff --git a/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/mcMMOTowny.java b/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/mcMMOTowny.java
new file mode 100644
index 0000000..c837f72
--- /dev/null
+++ b/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/mcMMOTowny.java
@@ -0,0 +1,95 @@
+package org.mcmmo.mcmmotowny;
+
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import org.mcmmo.mcmmotowny.config.Config;
+import org.mcmmo.mcmmotowny.listeners.ExperienceListener;
+import org.mcmmo.mcmmotowny.util.LogFilter;
+
+public class mcMMOTowny extends JavaPlugin {
+ public static mcMMOTowny p;
+
+ private boolean mcMMOEnabled = false;
+ private boolean townyEnabled = false;
+
+ /**
+ * Things to be run when the plugin is enabled.
+ */
+ @Override
+ public void onEnable() {
+ try {
+ p = this;
+ getLogger().setFilter(new LogFilter(this));
+
+ setupMcMMO();
+ setupTowny();
+
+ if (!isMcMMOEnabled()) {
+ this.getLogger().warning("mcMMO-Towny requires mcMMO to run, please download mcMMO. http://dev.bukkit.org/server-mods/mcmmo/");
+ getServer().getPluginManager().disablePlugin(this);
+ return;
+ }
+
+ if (!isTownyEnabled()) {
+ this.getLogger().warning("mcMMO-Towny requires Towny to run, please download Towny. http://palmergames.com/towny/");
+ getServer().getPluginManager().disablePlugin(this);
+ return;
+ }
+
+ Config.getInstance();
+
+ registerEvents();
+ }
+ catch (Throwable t) {
+ getLogger().severe("There was an error while enabling mcMMO-Towny!");
+
+ if (!(t instanceof ExceptionInInitializerError)) {
+ t.printStackTrace();
+ }
+ else {
+ getLogger().info("Please do not replace the mcMMO-Towny jar while the server is running.");
+ }
+
+ getServer().getPluginManager().disablePlugin(this);
+ }
+ }
+
+ private void setupMcMMO() {
+ if (getServer().getPluginManager().isPluginEnabled("mcMMO")) {
+ mcMMOEnabled = true;
+ }
+ }
+
+ private void setupTowny() {
+ if (getServer().getPluginManager().isPluginEnabled("Towny")) {
+ townyEnabled = true;
+ }
+ }
+
+ /**
+ * Things to be run when the plugin is disabled.
+ */
+ @Override
+ public void onDisable() {
+ }
+
+ public void debug(String message) {
+ getLogger().info("[Debug] " + message);
+ }
+
+ public boolean isMcMMOEnabled() {
+ return mcMMOEnabled;
+ }
+
+ public boolean isTownyEnabled() {
+ return townyEnabled;
+ }
+
+ private void registerEvents() {
+ PluginManager pluginManager = getServer().getPluginManager();
+
+ // Register events
+ pluginManager.registerEvents(new ExperienceListener(), this);
+ }
+}
diff --git a/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/util/LogFilter.java b/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/util/LogFilter.java
new file mode 100644
index 0000000..16f2715
--- /dev/null
+++ b/mcMMO-Towny/src/main/java/org/mcmmo/mcmmotowny/util/LogFilter.java
@@ -0,0 +1,24 @@
+package org.mcmmo.mcmmotowny.util;
+
+import java.util.logging.Filter;
+import java.util.logging.LogRecord;
+
+import org.mcmmo.mcmmotowny.mcMMOTowny;
+
+public class LogFilter implements Filter {
+ private boolean debug;
+
+ public LogFilter(mcMMOTowny plugin) {
+ // Doing a config loading lite here, because we can't depend on the config loader to have loaded before any debug messages are sent
+ debug = plugin.getConfig().getBoolean("General.Verbose_Logging");
+ }
+
+ @Override
+ public boolean isLoggable(LogRecord record) {
+ if (record.getMessage().contains("[Debug]") && !debug) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/mcMMO-Towny/src/main/resources/config.yml b/mcMMO-Towny/src/main/resources/config.yml
new file mode 100644
index 0000000..e3723e5
--- /dev/null
+++ b/mcMMO-Towny/src/main/resources/config.yml
@@ -0,0 +1,26 @@
+#
+# mcMMO-Towny configuration
+# Last updated on ${project.version}
+#
+#####
+
+#
+# Settings for mcMMO-Towny in general
+###
+General:
+ # Should mcMMO-Towny print out debug messages?
+ Verbose_Logging: false
+ # Should mcMMO-Towny over-write configs to update, or make new ones ending in .new?
+ Config_Update_Overwrite: true
+
+#
+# Settings for experience in Towny towns
+###
+Experience:
+ # Global_Modifier: Modifies XP gained in any town
+ Global_Modifier: 1.0
+
+ # Towns.: Modifies XP gained in the defined town, global modifier still applies
+ Towns:
+ Town_Name1: 1.0
+ Town_Name2: 1.0
diff --git a/mcMMO-Towny/src/main/resources/plugin.yml b/mcMMO-Towny/src/main/resources/plugin.yml
new file mode 100644
index 0000000..fbe5ab3
--- /dev/null
+++ b/mcMMO-Towny/src/main/resources/plugin.yml
@@ -0,0 +1,11 @@
+name: mcMMO-Towny
+version: ${project.version}
+description: >
+ mcMMO-Towny is an extra plugin for mcMMO. It uses Towny to give certain players
+ modified XP gains, depending on whether or not they are inside specific towns.
+
+author: TfT_02
+website: http://dev.bukkit.org/server-mods/mcmmo-towny/
+
+main: org.mcmmo.mcmmotowny.mcMMOTowny
+softdepend: [mcMMO, Towny]