From 807ea6d1742d0f6641ee253ff90193a025f76fe0 Mon Sep 17 00:00:00 2001
From: rutgerkok <rutger.kok@live.com>
Date: Fri, 15 Apr 2016 10:48:02 +0200
Subject: [PATCH] Improve logging on Forge

Previously, we used the Forge Modloader logger, so messages would appear
as [FML]: [TerrainControl] (message). Now we use our own logger, so that
[TerrainControl] now replaces [FML].

However, this means that messages would appear as[TerrainControl]:
[TerrainControl] (message). The second [TerrainControl] was added by our
own logger class, as Bukkit (unlike Forge) doesn't prefix each message
with the mod name.

Now Bukkit and Forge have their own Logger implementation, and only the
Bukkit implementation adds [TerrainControl].
---
 common/build.gradle                           |   2 -
 .../khorn/terraincontrol/TerrainControl.java  |  22 +--
 .../terraincontrol/TerrainControlEngine.java  |  10 +-
 .../configuration/PluginConfig.java           |  37 ++---
 .../terraincontrol/logging/LogFactory.java    |  39 ------
 .../terraincontrol/logging/LogMarker.java     |  58 ++------
 .../terraincontrol/logging/Loggable.java      |  81 -----------
 .../khorn/terraincontrol/logging/Logger.java  | 130 ++++++------------
 .../terraincontrol/bukkit/BukkitEngine.java   |   1 +
 .../terraincontrol/bukkit/BukkitLogger.java   |  57 ++++++++
 .../terraincontrol/forge/ForgeEngine.java     |   3 +-
 .../terraincontrol/forge/ForgeLogger.java     |  52 +++++++
 12 files changed, 189 insertions(+), 303 deletions(-)
 delete mode 100644 common/src/main/java/com/khorn/terraincontrol/logging/LogFactory.java
 delete mode 100644 common/src/main/java/com/khorn/terraincontrol/logging/Loggable.java
 create mode 100644 platforms/bukkit/src/main/java/com/khorn/terraincontrol/bukkit/BukkitLogger.java
 create mode 100644 platforms/forge/src/main/java/com/khorn/terraincontrol/forge/ForgeLogger.java

diff --git a/common/build.gradle b/common/build.gradle
index 35edc4dd0..0e0e2ac66 100644
--- a/common/build.gradle
+++ b/common/build.gradle
@@ -15,6 +15,4 @@ repositories
 dependencies
 {
     testCompile 'junit:junit:4+'
-    compile 'org.apache.logging.log4j:log4j-api:2.0-beta9'
-    compile 'org.apache.logging.log4j:log4j-core:2.0-beta9'
 }
diff --git a/common/src/main/java/com/khorn/terraincontrol/TerrainControl.java b/common/src/main/java/com/khorn/terraincontrol/TerrainControl.java
index ab37dbb71..faba0d55f 100644
--- a/common/src/main/java/com/khorn/terraincontrol/TerrainControl.java
+++ b/common/src/main/java/com/khorn/terraincontrol/TerrainControl.java
@@ -9,9 +9,9 @@
 import com.khorn.terraincontrol.exception.InvalidConfigException;
 import com.khorn.terraincontrol.generator.biome.BiomeModeManager;
 import com.khorn.terraincontrol.generator.resource.Resource;
+import com.khorn.terraincontrol.logging.LogMarker;
 import com.khorn.terraincontrol.util.ChunkCoordinate;
 import com.khorn.terraincontrol.util.minecraftTypes.DefaultMaterial;
-import org.apache.logging.log4j.Marker;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -54,7 +54,7 @@ public static boolean fireCanCustomObjectSpawnEvent(CustomObject object, LocalWo
 
     /**
      * @see TerrainControlEngine#firePopulationEndEvent(LocalWorld, Random,
-     * boolean, int, int)
+     * boolean, ChunkCoordinate)
      */
     public static void firePopulationEndEvent(LocalWorld world, Random random, boolean villageInChunk, ChunkCoordinate chunkCoord)
     {
@@ -63,7 +63,7 @@ public static void firePopulationEndEvent(LocalWorld world, Random random, boole
 
     /**
      * @see TerrainControlEngine#firePopulationStartEvent(LocalWorld, Random,
-     * boolean, int, int)
+     * boolean, ChunkCoordinate)
      */
     public static void firePopulationStartEvent(LocalWorld world, Random random, boolean villageInChunk, ChunkCoordinate chunkCoord)
     {
@@ -186,7 +186,7 @@ public static LocalWorld getWorld(String name)
      * @param messages The messages to log.
      * @param level    The severity of the message
      */
-    public static void log(Marker level, List<String> messages)
+    public static void log(LogMarker level, List<String> messages)
     {
         engine.getLogger().log(level, messages);
     }
@@ -201,7 +201,7 @@ public static void log(Marker level, List<String> messages)
      * @param params  The parameters belonging to {0...} in the message
      *                string
      */
-    public static void log(Marker level, String message, Object... params)
+    public static void log(LogMarker level, String message, Object... params)
     {
         engine.getLogger().log(level, message, params);
     }
@@ -214,7 +214,7 @@ public static void log(Marker level, String message, Object... params)
      * @param ifLevel  the Log level to test for
      * @param messages The messages to log.
      */
-    public static void logIfLevel(Marker ifLevel, List<String> messages)
+    public static void logIfLevel(LogMarker ifLevel, List<String> messages)
     {
         engine.getLogger().logIfLevel(ifLevel, messages);
     }
@@ -230,7 +230,7 @@ public static void logIfLevel(Marker ifLevel, List<String> messages)
      * @param params  The parameters belonging to {0...} in the message
      *                string
      */
-    public static void logIfLevel(Marker ifLevel, String message, Object... params)
+    public static void logIfLevel(LogMarker ifLevel, String message, Object... params)
     {
         engine.getLogger().logIfLevel(ifLevel, message, params);
     }
@@ -244,7 +244,7 @@ public static void logIfLevel(Marker ifLevel, String message, Object... params)
      * @param max      The maximum Log level to test for
      * @param messages The messages to log.
      */
-    public static void logIfLevel(Marker min, Marker max, List<String> messages)
+    public static void logIfLevel(LogMarker min, LogMarker max, List<String> messages)
     {
         engine.getLogger().logIfLevel(min, max, messages);
     }
@@ -261,7 +261,7 @@ public static void logIfLevel(Marker min, Marker max, List<String> messages)
      * @param params  The parameters belonging to {0...} in the message
      *                string
      */
-    public static void logIfLevel(Marker min, Marker max, String message, Object... params)
+    public static void logIfLevel(LogMarker min, LogMarker max, String message, Object... params)
     {
         engine.getLogger().logIfLevel(min, max, message, params);
     }
@@ -272,7 +272,7 @@ public static void logIfLevel(Marker min, Marker max, String message, Object...
      * @param level The log level to log this stack trace at
      * @param e     The Throwable object to obtain stack trace information from
      */
-    public static void printStackTrace(Marker level, Throwable e)
+    public static void printStackTrace(LogMarker level, Throwable e)
     {
         printStackTrace(level, e, Integer.MAX_VALUE);
     }
@@ -286,7 +286,7 @@ public static void printStackTrace(Marker level, Throwable e)
      *                 from
      * @param maxDepth The max number of trace elements to print
      */
-    public static void printStackTrace(Marker level, Throwable e, int maxDepth)
+    public static void printStackTrace(LogMarker level, Throwable e, int maxDepth)
     {
         StringWriter stringWriter = new StringWriter();
         PrintWriter printWriter = new PrintWriter(stringWriter);
diff --git a/common/src/main/java/com/khorn/terraincontrol/TerrainControlEngine.java b/common/src/main/java/com/khorn/terraincontrol/TerrainControlEngine.java
index 4786b321b..b04522067 100644
--- a/common/src/main/java/com/khorn/terraincontrol/TerrainControlEngine.java
+++ b/common/src/main/java/com/khorn/terraincontrol/TerrainControlEngine.java
@@ -12,7 +12,6 @@
 import com.khorn.terraincontrol.exception.InvalidConfigException;
 import com.khorn.terraincontrol.generator.biome.BiomeModeManager;
 import com.khorn.terraincontrol.generator.resource.Resource;
-import com.khorn.terraincontrol.logging.LogFactory;
 import com.khorn.terraincontrol.logging.Logger;
 import com.khorn.terraincontrol.util.ChunkCoordinate;
 import com.khorn.terraincontrol.util.minecraftTypes.DefaultMaterial;
@@ -33,14 +32,9 @@ public abstract class TerrainControlEngine
     private PluginConfig pluginConfig;
     private Logger logger;
 
-    public TerrainControlEngine()
+    public TerrainControlEngine(Logger logger)
     {
-        logger = LogFactory.getLogger();
-    }
-
-    public TerrainControlEngine(org.apache.logging.log4j.Logger log4jLogger)
-    {
-        logger = LogFactory.getLogger(log4jLogger);
+        this.logger = logger;
     }
 
     /**
diff --git a/common/src/main/java/com/khorn/terraincontrol/configuration/PluginConfig.java b/common/src/main/java/com/khorn/terraincontrol/configuration/PluginConfig.java
index 447ef5f88..05230e9f2 100644
--- a/common/src/main/java/com/khorn/terraincontrol/configuration/PluginConfig.java
+++ b/common/src/main/java/com/khorn/terraincontrol/configuration/PluginConfig.java
@@ -8,8 +8,6 @@
 import com.khorn.terraincontrol.configuration.standard.PluginStandardValues;
 import com.khorn.terraincontrol.configuration.standard.WorldStandardValues;
 import com.khorn.terraincontrol.logging.LogMarker;
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.Marker;
 
 import java.io.IOException;
 
@@ -22,37 +20,30 @@ public final class PluginConfig extends ConfigFile
 
     public ConfigMode SettingsMode;
 
-    public static enum LogLevels
+    public enum LogLevels
     {
 
-        Off(LogMarker.ERROR, Level.ERROR.intLevel()),
-        Quiet(LogMarker.WARN, Level.WARN.intLevel()),
-        Standard(LogMarker.INFO, Level.INFO.intLevel()),
-        Debug(LogMarker.DEBUG, Level.DEBUG.intLevel()),
-        Trace(LogMarker.TRACE, Level.TRACE.intLevel());
-        private final Marker marker;
-        private final int value;
+        Off(LogMarker.ERROR),
+        Quiet(LogMarker.WARN),
+        Standard(LogMarker.INFO),
+        Debug(LogMarker.DEBUG),
+        Trace(LogMarker.TRACE);
+        private final LogMarker marker;
 
-        private LogLevels(Marker marker, int value)
+        LogLevels(LogMarker marker)
         {
             this.marker = marker;
-            this.value = value;
         }
 
-        public Marker getLevel()
+        public LogMarker getLevel()
         {
             return marker;
         }
 
-        public int getValue()
-        {
-            return value;
-        }
-
     }
 
-    public LogLevels LogLevel = LogLevels.Standard;
-    public String biomeConfigExtension;
+    private LogLevels LogLevel = LogLevels.Standard;
+    String biomeConfigExtension;
 
     public PluginConfig(SettingsReader settingsReader)
     {
@@ -77,10 +68,8 @@ protected void correctSettings()
         if (!BiomeStandardValues.BiomeConfigExtensions.contains(this.biomeConfigExtension))
         {
             String newExtension = BiomeStandardValues.BIOME_CONFIG_EXTENSION.getDefaultValue();
-            TerrainControl.log(LogMarker.WARN, "BiomeConfig file extension {} is invalid, changing to {}", new Object[]
-            {
-                this.biomeConfigExtension, newExtension
-            });
+            TerrainControl.log(LogMarker.WARN, "BiomeConfig file extension {} is invalid, changing to {}",
+                this.biomeConfigExtension, newExtension);
             this.biomeConfigExtension = newExtension;
         }
 
diff --git a/common/src/main/java/com/khorn/terraincontrol/logging/LogFactory.java b/common/src/main/java/com/khorn/terraincontrol/logging/LogFactory.java
deleted file mode 100644
index bb4c8adc1..000000000
--- a/common/src/main/java/com/khorn/terraincontrol/logging/LogFactory.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.khorn.terraincontrol.logging;
-
-import org.apache.logging.log4j.LogManager;
-
-public class LogFactory
-{
-
-    /**
-     * This is the name of our Logger, currently pulling from
-     * PluginStandardValues for consistency
-     */
-    public static final String LOGGER_NAME = LogFactory.class.getName();
-
-    private LogFactory()
-    { //>>	Shouldnt be instantiated
-    }
-
-    /**
-     *
-     * @return a memoized TerrainControl Logger
-     */
-    public static Logger getLogger()
-    {
-        return new Logger(LogManager.getLogger(LOGGER_NAME));
-    }
-
-    /**
-     *
-     * @param logger The desired baseLogger of the returned Logger class
-     * @return a memoized TerrainControl Logger. If the logger passed in differs
-     *         in class from the memoized Logger's baseLogger, a new
-     *         TerrainControl logger will be created and returned
-     */
-    public static Logger getLogger(org.apache.logging.log4j.Logger logger)
-    {
-        return new Logger(logger);
-    }
-
-}
diff --git a/common/src/main/java/com/khorn/terraincontrol/logging/LogMarker.java b/common/src/main/java/com/khorn/terraincontrol/logging/LogMarker.java
index 2bb5da6c2..7c8433464 100644
--- a/common/src/main/java/com/khorn/terraincontrol/logging/LogMarker.java
+++ b/common/src/main/java/com/khorn/terraincontrol/logging/LogMarker.java
@@ -1,55 +1,17 @@
 package com.khorn.terraincontrol.logging;
 
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.Marker;
-import org.apache.logging.log4j.MarkerManager;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
 /**
  * Holds the log markers and allows to compare them to each other.
+ *
+ * <p>Markers for specific Log levels, we use these as internal Log Levels, but can
+ * be used to filter logs in a very specific way.</p>
  */
-public class LogMarker
+public enum LogMarker
 {
-
-    /*
-     * Markers for specific Log levels, we use these as internal Log Levels, but
-     * can be used to filter logs in a very specific way
-     */
-    public static final Marker FATAL = MarkerManager.getMarker("com.khorn.terraincontrol.FATAL");
-    public static final Marker ERROR = MarkerManager.getMarker("com.khorn.terraincontrol.ERROR", LogMarker.FATAL);
-    public static final Marker WARN = MarkerManager.getMarker("com.khorn.terraincontrol.WARN", LogMarker.ERROR);
-    public static final Marker INFO = MarkerManager.getMarker("com.khorn.terraincontrol.INFO", LogMarker.WARN);
-    public static final Marker DEBUG = MarkerManager.getMarker("com.khorn.terraincontrol.DEBUG", LogMarker.INFO);
-    public static final Marker TRACE = MarkerManager.getMarker("com.khorn.terraincontrol.TRACE", LogMarker.DEBUG);
-
-    private static Map<Marker, Integer> standardLevels = new LinkedHashMap<Marker, Integer>(6);
-
-    private LogMarker()
-    {
-    }
-
-    static
-    {
-        standardLevels.put(FATAL, Level.FATAL.intLevel());
-        standardLevels.put(ERROR, Level.ERROR.intLevel());
-        standardLevels.put(WARN, Level.WARN.intLevel());
-        standardLevels.put(INFO, Level.INFO.intLevel());
-        standardLevels.put(DEBUG, Level.DEBUG.intLevel());
-        standardLevels.put(TRACE, Level.TRACE.intLevel());
-    }
-
-    public static int compare(Marker first, Marker second)
-    {
-        Integer firstInt = standardLevels.get(first);
-        if (firstInt != null)
-        {
-            return standardLevels.get(first).compareTo(standardLevels.get(second));
-        } else
-        {
-            return 0;
-        }
-    }
-
+    FATAL,
+    ERROR,
+    WARN,
+    INFO,
+    DEBUG,
+    TRACE
 }
diff --git a/common/src/main/java/com/khorn/terraincontrol/logging/Loggable.java b/common/src/main/java/com/khorn/terraincontrol/logging/Loggable.java
deleted file mode 100644
index 3807036fb..000000000
--- a/common/src/main/java/com/khorn/terraincontrol/logging/Loggable.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.khorn.terraincontrol.logging;
-
-import org.apache.logging.log4j.Marker;
-
-/**
- * When implemented, the implementing class will have a suite of available
- * options for detailed, configurable logging
- */
-public interface Loggable
-{
-
-    /**
-     * Logs the message(s) with the given importance. Message will be
-     * prefixed with [TerrainControl], so don't do that yourself.
-     * <p/>
-     * @param level   The severity of the message
-     * @param message The messages to log
-     */
-    public void log(Marker level, String... message);
-
-    /**
-     * Logs a format string message with the given importance. Message will
-     * be prefixed with [TerrainControl], so don't do that yourself.
-     * <p/>
-     * @param level   The severity of the message
-     * @param message The messages to log formatted similar to Logger.log()
-     *                with the same args.
-     * @param params  The parameters belonging to {0...} in the message
-     *                string
-     */
-    public void log(Marker level, String message, Object... params);
-
-    /**
-     * Logs the message(s) with the given importance <b>ONLY IF</b> logger
-     * level matches the level provided. Message will be prefixed with
-     * [TerrainControl], so don't do that yourself.
-     * <p/>
-     * @param ifLevel  the Log level to test for
-     * @param messages The messages to log.
-     */
-    public void logIfLevel(Marker ifLevel, String... messages);
-
-    /**
-     * Logs the message(s) with the given importance <b>ONLY IF</b> logger
-     * level matches the level provided. Message will be prefixed with
-     * [TerrainControl], so don't do that yourself.
-     * <p/>
-     * @param ifLevel the Log level to test for
-     * @param message The messages to log formatted similar to
-     *                Logger.log() with the same args.
-     * @param params  The parameters belonging to {0...} in the message
-     *                string
-     */
-    public void logIfLevel(Marker ifLevel, String message, Object... params);
-
-    /**
-     * Logs the message(s) with the given importance <b>ONLY IF</b> logger
-     * level is between the min/max provided. Message will be prefixed with
-     * [TerrainControl], so don't do that yourself.
-     * <p/>
-     * @param min      The minimum Log level to test for
-     * @param max      The maximum Log level to test for
-     * @param messages The messages to log.
-     */
-    public void logIfLevel(Marker min, Marker max, String... messages);
-
-    /**
-     * Logs the message(s) with the given importance <b>ONLY IF</b> logger
-     * level is between the min/max provided. Message will be prefixed with
-     * [TerrainControl], so don't do that yourself.
-     * <p/>
-     * @param min     The minimum Log level to test for
-     * @param max     The maximum Log level to test for
-     * @param message The messages to log formatted similar to
-     *                Logger.log() with the same args.
-     * @param params  The parameters belonging to {0...} in the message
-     *                string
-     */
-    public void logIfLevel(Marker min, Marker max, String message, Object... params);
-
-}
diff --git a/common/src/main/java/com/khorn/terraincontrol/logging/Logger.java b/common/src/main/java/com/khorn/terraincontrol/logging/Logger.java
index c3e90a87b..0839a0c9c 100644
--- a/common/src/main/java/com/khorn/terraincontrol/logging/Logger.java
+++ b/common/src/main/java/com/khorn/terraincontrol/logging/Logger.java
@@ -1,149 +1,101 @@
 package com.khorn.terraincontrol.logging;
 
-import com.khorn.terraincontrol.configuration.PluginConfig;
-import com.khorn.terraincontrol.configuration.standard.PluginStandardValues;
 import com.khorn.terraincontrol.util.helpers.StringHelper;
-import org.apache.logging.log4j.Marker;
 
 import java.util.List;
 
-public class Logger
+public abstract class Logger
 {
 
-    private org.apache.logging.log4j.Logger baseLogger;
-    public static final String PLUGIN_NAME = PluginStandardValues.ChannelName;
-    private Marker logLevel;
+    protected LogMarker minimumLevel;
 
-    protected Logger(org.apache.logging.log4j.Logger logger)
+    public void setLevel(LogMarker level)
     {
-        logLevel = PluginConfig.LogLevels.Standard.getLevel();
-        baseLogger = logger;
-    }
-
-    public org.apache.logging.log4j.Logger getBaseLogger()
-    {
-        return baseLogger;
-    }
-
-    public void setLevel(Marker level)
-    {
-        logLevel = level;
+        minimumLevel = level;
     }
 
     /**
-     * Logs the message(s) with the given importance. Message will be
-     * prefixed with [TerrainControl], so don't do that yourself.
-     * <p/>
+     * Logs the message(s) with the given importance. Message will be prefixed
+     * with [TerrainControl], so don't do that yourself.
+     *
      * @param level   The severity of the message
      * @param message The messages to log
      */
-    public void log(Marker level, List<String> message)
+    public void log(LogMarker level, List<String> message)
     {
         log(level, "{}", (Object) StringHelper.join(message, " "));
     }
 
     /**
-     * Logs a format string message with the given importance. Message will
-     * be prefixed with [TerrainControl], so don't do that yourself.
-     * <p/>
+     * Logs a format string message with the given importance. Message will be
+     * prefixed with [TerrainControl], so don't do that yourself.
+     *
      * @param level   The severity of the message
-     * @param message The messages to log formatted similar to Logger.log()
-     *                with the same args.
-     * @param params  The parameters belonging to {0...} in the message
-     *                string
+     * @param message The messages to log formatted similar to Logger.log() with
+     *                the same args.
+     * @param params  The parameters belonging to {0...} in the message string
      */
-    public void log(Marker level, String message, Object... params)
-    {
-        if (LogMarker.compare(logLevel, level) >= 0)
-        {//>>	Only log messages that we want to see...
-
-            StringBuilder sb = new StringBuilder(50).append('[').append(PLUGIN_NAME).append("] ");
-
-            //>>	Log Fatal, Error, and Warn as what they are without Markers.
-            if (LogMarker.compare(LogMarker.FATAL, level) == 0)
-            {
-                baseLogger.fatal(sb.append(message).toString(), params);
-            } else if (LogMarker.compare(LogMarker.ERROR, level) == 0)
-            {
-                baseLogger.error(sb.append(message).toString(), params);
-            } else if (LogMarker.compare(LogMarker.WARN, level) == 0)
-            {
-                baseLogger.warn(sb.append(message).toString(), params);
-            } else if (LogMarker.compare(LogMarker.INFO, level) == 0)
-            {
-                baseLogger.info(sb.append(message).toString(), params);
-            } else
-            {//>>	Otherwise log the message as info and tag it with a marker
-                String levelName = level.getName();
-                sb.append("[")
-                        .append(levelName.substring(levelName.lastIndexOf('.')+1)) //>> only get the basic name not the FQN
-                        .append("] ");
-                baseLogger.info(level, sb.append(message).toString(), params);
-            }
-        }
-    }
+    public abstract void log(LogMarker level, String message, Object... params);
 
     /**
-     * Logs the message(s) with the given importance <b>ONLY IF</b> logger
-     * level matches the level provided. Message will be prefixed with
+     * Logs the message(s) with the given importance <b>ONLY IF</b> logger level
+     * matches the level provided. Message will be prefixed with
      * [TerrainControl], so don't do that yourself.
-     * <p/>
+     *
      * @param ifLevel  the Log level to test for
      * @param messages The messages to log.
      */
-    public void logIfLevel(Marker ifLevel, List<String> messages)
+    public void logIfLevel(LogMarker ifLevel, List<String> messages)
     {
-        if (LogMarker.compare(logLevel, ifLevel) == 0)
+        if (minimumLevel == ifLevel)
             log(ifLevel, messages);
     }
 
     /**
-     * Logs the message(s) with the given importance <b>ONLY IF</b> logger
-     * level matches the level provided. Message will be prefixed with
+     * Logs the message(s) with the given importance <b>ONLY IF</b> logger level
+     * matches the level provided. Message will be prefixed with
      * [TerrainControl], so don't do that yourself.
-     * <p/>
+     *
      * @param ifLevel the Log level to test for
-     * @param message The messages to log formatted similar to
-     *                Logger.log() with the same args.
-     * @param params  The parameters belonging to {0...} in the message
-     *                string
+     * @param message The messages to log formatted similar to Logger.log() with
+     *                the same args.
+     * @param params  The parameters belonging to {0...} in the message string
      */
-    public void logIfLevel(Marker ifLevel, String message, Object... params)
+    public void logIfLevel(LogMarker ifLevel, String message, Object... params)
     {
-        if (LogMarker.compare(logLevel, ifLevel) == 0)
+        if (minimumLevel == ifLevel)
             log(ifLevel, message, params);
     }
 
     /**
-     * Logs the message(s) with the given importance <b>ONLY IF</b> logger
-     * level is between the min/max provided. Message will be prefixed with
+     * Logs the message(s) with the given importance <b>ONLY IF</b> logger level
+     * is between the min/max provided. Message will be prefixed with
      * [TerrainControl], so don't do that yourself.
-     * <p/>
+     *
      * @param min      The minimum Log level to test for
      * @param max      The maximum Log level to test for
      * @param messages The messages to log.
      */
-    public void logIfLevel(Marker min, Marker max, List<String> messages)
+    public void logIfLevel(LogMarker min, LogMarker max, List<String> messages)
     {
-        if (LogMarker.compare(logLevel, max) <= 0 && LogMarker.compare(logLevel, min) >= 0)
+        if (minimumLevel.compareTo(max) <= 0 && minimumLevel.compareTo(min) >= 0)
             log(max, messages);
     }
 
     /**
-     * Logs the message(s) with the given importance <b>ONLY IF</b> logger
-     * level is between the min/max provided. Message will be prefixed with
+     * Logs the message with the given importance <b>ONLY IF</b> logger level
+     * is between the min/max provided. Message will be prefixed with
      * [TerrainControl], so don't do that yourself.
-     * <p/>
+     *
      * @param min     The minimum Log level to test for
      * @param max     The maximum Log level to test for
-     * @param message The messages to log formatted similar to
-     *                Logger.log() with the same args.
-     * @param params  The parameters belonging to {0...} in the message
-     *                string
+     * @param message The messages to log formatted similar to Logger.log() with
+     *                the same args.
+     * @param params  The parameters belonging to {0...} in the message string
      */
-    public void logIfLevel(Marker min, Marker max, String message, Object... params)
+    public void logIfLevel(LogMarker min, LogMarker max, String message, Object... params)
     {
-        if (LogMarker.compare(logLevel, max) <= 0 && LogMarker.compare(logLevel, min) >= 0)
+        if (minimumLevel.compareTo(max) <= 0 && minimumLevel.compareTo(min) >= 0)
             log(max, message, params);
     }
 
diff --git a/platforms/bukkit/src/main/java/com/khorn/terraincontrol/bukkit/BukkitEngine.java b/platforms/bukkit/src/main/java/com/khorn/terraincontrol/bukkit/BukkitEngine.java
index 161afc612..7b94bb22e 100644
--- a/platforms/bukkit/src/main/java/com/khorn/terraincontrol/bukkit/BukkitEngine.java
+++ b/platforms/bukkit/src/main/java/com/khorn/terraincontrol/bukkit/BukkitEngine.java
@@ -17,6 +17,7 @@ public class BukkitEngine extends TerrainControlEngine
 
     public BukkitEngine(TCPlugin plugin)
     {
+        super(new BukkitLogger(plugin.getLogger()));
         this.plugin = plugin;
     }
 
diff --git a/platforms/bukkit/src/main/java/com/khorn/terraincontrol/bukkit/BukkitLogger.java b/platforms/bukkit/src/main/java/com/khorn/terraincontrol/bukkit/BukkitLogger.java
new file mode 100644
index 000000000..41e80433e
--- /dev/null
+++ b/platforms/bukkit/src/main/java/com/khorn/terraincontrol/bukkit/BukkitLogger.java
@@ -0,0 +1,57 @@
+package com.khorn.terraincontrol.bukkit;
+
+import com.khorn.terraincontrol.configuration.standard.PluginStandardValues;
+import com.khorn.terraincontrol.logging.LogMarker;
+import com.khorn.terraincontrol.logging.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import java.util.logging.Level;
+
+/**
+ * Implementation of {@link Logger} for Bukkit.
+ */
+final class BukkitLogger extends Logger
+{
+    private final String logPrefix = "[" + PluginStandardValues.PLUGIN_NAME + "] ";
+    private final org.apache.logging.log4j.Logger logger = LogManager.getLogger(PluginStandardValues.PLUGIN_NAME);
+
+    BukkitLogger(java.util.logging.Logger logger)
+    {
+
+    }
+
+    @Override
+    public void log(LogMarker level, String message, Object... params)
+    {
+        if (minimumLevel.compareTo(level) < 0)
+        {
+            // Only log messages that we want to see...
+            return;
+        }
+        switch (level)
+        {
+            case FATAL:
+                logger.fatal(logPrefix + message, params);
+                break;
+            case ERROR:
+                logger.error(logPrefix + message, params);
+                break;
+            case WARN:
+                logger.warn(logPrefix + message, params);
+                break;
+            case INFO:
+                logger.info(logPrefix + message, params);
+                break;
+            case DEBUG:
+                logger.info(logPrefix + "[Debug] " + message, params);
+                break;
+            case TRACE:
+                logger.trace(logPrefix + "[Trace] " + message, params);
+                break;
+            default:
+                // Unknown log level, should never happen
+                logger.info(logPrefix + message, params); // Still log the message
+                throw new RuntimeException("Unknown log marker: " + level);
+        }
+    }
+}
diff --git a/platforms/forge/src/main/java/com/khorn/terraincontrol/forge/ForgeEngine.java b/platforms/forge/src/main/java/com/khorn/terraincontrol/forge/ForgeEngine.java
index fbeb855ae..9519b596f 100644
--- a/platforms/forge/src/main/java/com/khorn/terraincontrol/forge/ForgeEngine.java
+++ b/platforms/forge/src/main/java/com/khorn/terraincontrol/forge/ForgeEngine.java
@@ -11,6 +11,7 @@
 import net.minecraft.block.Block;
 import net.minecraftforge.fml.common.FMLCommonHandler;
 import net.minecraftforge.fml.common.Loader;
+import org.apache.logging.log4j.LogManager;
 
 import java.io.File;
 import java.lang.reflect.Field;
@@ -22,7 +23,7 @@ public class ForgeEngine extends TerrainControlEngine
 
     public ForgeEngine(TCWorldType worldType)
     {
-        super(FMLCommonHandler.instance().getFMLLogger());
+        super(new ForgeLogger());
         this.worldType = worldType;
     }
 
diff --git a/platforms/forge/src/main/java/com/khorn/terraincontrol/forge/ForgeLogger.java b/platforms/forge/src/main/java/com/khorn/terraincontrol/forge/ForgeLogger.java
new file mode 100644
index 000000000..23a63b3dd
--- /dev/null
+++ b/platforms/forge/src/main/java/com/khorn/terraincontrol/forge/ForgeLogger.java
@@ -0,0 +1,52 @@
+package com.khorn.terraincontrol.forge;
+
+import com.khorn.terraincontrol.configuration.standard.PluginStandardValues;
+import com.khorn.terraincontrol.logging.LogMarker;
+import com.khorn.terraincontrol.logging.Logger;
+import org.apache.logging.log4j.LogManager;
+
+/**
+ * CImplementation of {@link Logger} for Forge.
+ *
+ * <p>Note that Forge (unlike Bukkit) automatically adds the TerrainControl
+ * prefix, so we don't need to do that ourselves.</p>
+ */
+final class ForgeLogger extends Logger
+{
+    private org.apache.logging.log4j.Logger logger = LogManager.getLogger(PluginStandardValues.PLUGIN_NAME);
+
+    @Override
+    public void log(LogMarker level, String message, Object... params)
+    {
+        if (minimumLevel.compareTo(level) < 0)
+        {
+            // Only log messages that we want to see...
+            return;
+        }
+        switch (level)
+        {
+            case FATAL:
+                logger.fatal(message, params);
+                break;
+            case ERROR:
+                logger.error(message, params);
+                break;
+            case WARN:
+                logger.warn(message, params);
+                break;
+            case INFO:
+                logger.info(message, params);
+                break;
+            case DEBUG:
+                logger.debug(message, params);
+                break;
+            case TRACE:
+                logger.trace(message, params);
+                break;
+            default:
+                // Unknown log level, should never happen
+                logger.info(message, params); // Still log the message
+                throw new RuntimeException("Unknown log marker: " + level);
+        }
+    }
+}