Make LogManager an interface.

* Some cleanups (spaces, commented out references updated).
* LogManager implement INotifyReload, but gets processed extra (not
added with addComponent).
This commit is contained in:
asofold 2014-12-04 15:41:47 +01:00
parent a41b7a6329
commit c0a188d2c1
14 changed files with 195 additions and 112 deletions

View File

@ -0,0 +1,94 @@
package fr.neatmonster.nocheatplus.logging;
import java.util.logging.Level;
/**
* Central access point log manager with a bias towards String messages.
* @author dev1mc
*
*/
public interface LogManager {
/**
* A stream that skips all messages. It's not registered officially.
* @return
*/
public StreamID getVoidStreamID();
/**
* This should be a fail-safe direct String-logger, that has the highest probability of working
* within the default context and rather skips messages instead of failing or scheduling tasks,
* typically the main application primary thread.
* @return
*/
public StreamID getInitStreamID();
/**
* Don't use this prefix for custom registrations with StreamID and LoggerID.
* @return
*/
public String getDefaultPrefix();
/**
* Case-insensitive lookup.
* @param name
* @return
*/
public boolean hasLogger(String name);
/**
* A newly created id can be used here (case-insensitive comparison by name). For logging use existing ids always.
* @param loggerID
* @return
*/
public boolean hasLogger(final LoggerID loggerID);
/**
* Case-insensitive lookup.
* @param name
* @return Returns the registered StreamID or null, if not registered.
*/
public LoggerID getLoggerID(String name);
/**
* Case-insensitive lookup.
* @param name
* @return
*/
public boolean hasStream(String name);
/**
* A newly created id can be used here (case-insensitive comparison by name). For logging use existing ids always.
* @param streamID
* @return
*/
public boolean hasStream(StreamID streamID);
/**
* Case-insensitive lookup.
* @param name
* @return Returns the registered StreamID or null, if not registered.
*/
public StreamID getStreamID(String name);
void debug(StreamID streamID, String message);
void info(StreamID streamID, String message);
void warning(StreamID streamID, String message);
void severe(StreamID streamID, String message);
void log(StreamID streamID, Level level, String message);
void debug(StreamID streamID, Throwable t);
void info(StreamID streamID, Throwable t);
void warning(StreamID streamID, Throwable t);
void severe(StreamID streamID, Throwable t);
void log(StreamID streamID, Level level, Throwable t);
}

View File

@ -7,6 +7,7 @@ import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import fr.neatmonster.nocheatplus.logging.LogManager;
import fr.neatmonster.nocheatplus.logging.LoggerID;
import fr.neatmonster.nocheatplus.logging.StreamID;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
@ -16,20 +17,17 @@ import fr.neatmonster.nocheatplus.utilities.StringUtil;
* @author dev1mc
*
*/
public abstract class AbstractLogManager {
public abstract class AbstractLogManager implements LogManager {
// TODO: Visibility of methods.
// TODO: Add option for per stream prefixes.
// TODO: Concept for adding in the time at the point of call/scheduling.
// TODO: Add a void stream (no loggers, allow logging unknown ids to void).
// TODO: Allow route log with non existing stream to init or void (flag).
// TODO: Attaching loggers with different options to different streams is necessary (e.g. normal -> async logging, but any thread with init).
// TODO: Re-register with other options: Add methods for LoggerID + StreamID + options.
// TODO: Hierarchical LogNode relations, to ensure other log nodes with the same logger are removed too [necessary to allow removing individual loggers].
// TODO: Temporary streams, e.g. for players, unregistering with command and/or logout.
// TODO: Mechanics of removing temporary streams: 1. remove
// TODO: Mechanics of removing temporary streams (flush stream, remove entries from queues, wait with removal until tasks have run once more).
// TODO: Consider generalizing the (internal) implementation right away (sub registry by content class).
// TODO: Consider adding a global cache (good for re-mapping, contra: reload is not intended to happen on a regular basis).
@ -124,66 +122,52 @@ public abstract class AbstractLogManager {
return dispatcher;
}
/**
* Don't use this prefix for custom registrations with StreamID and LoggerID.
* @return
*/
@Override
public String getDefaultPrefix() {
return defaultPrefix;
}
/**
* This should be a fail-safe direct String-logger, that has the highest probability of working
* within the default context and rather skips messages instead of failing or scheduling tasks,
* typically the main application primary thread.
*
* @return
*/
@Override
public StreamID getInitStreamID() {
return initStreamID;
}
/**
* A stream that skips all messages. It's not registered officially.
* @return
*/
@Override
public StreamID getVoidStreamID() {
return voidStreamID;
}
/**
* Case-insensitive lookup.
* @param name
* @return Returns the registered StreamID or null, if not present.
*/
@Override
public StreamID getStreamID(String name) {
return nameStreamIDMap.get(name.toLowerCase());
}
/**
* Case-insensitive lookup.
* @param name
* @return Returns the registered StreamID or null, if not present.
*/
@Override
public LoggerID getLoggerID(String name) {
return nameLoggerIDMap.get(name.toLowerCase());
}
@Override
public void debug(final StreamID streamID, final String message) {
log(streamID, Level.FINE, message); // TODO: Not sure what happens with FINE and provided Logger instances.
}
@Override
public void info(final StreamID streamID, final String message) {
log(streamID, Level.INFO, message);
}
@Override
public void warning(final StreamID streamID, final String message) {
log(streamID, Level.WARNING, message);
}
@Override
public void severe(final StreamID streamID, final String message) {
log(streamID, Level.SEVERE, message);
}
@Override
public void log(final StreamID streamID, final Level level, final String message) {
if (streamID != voidStreamID) {
final ContentStream<String> stream = idStreamMap.get(streamID);
@ -203,36 +187,38 @@ public abstract class AbstractLogManager {
}
}
@Override
public void debug(final StreamID streamID, final Throwable t) {
log(streamID, Level.FINE, t); // TODO: Not sure what happens with FINE and provided Logger instances.
}
@Override
public void info(final StreamID streamID, final Throwable t) {
log(streamID, Level.INFO, t);
}
@Override
public void warning(final StreamID streamID, final Throwable t) {
log(streamID, Level.WARNING, t);
}
@Override
public void severe(final StreamID streamID, final Throwable t) {
log(streamID, Level.SEVERE, t);
}
@Override
public void log(final StreamID streamID, final Level level, final Throwable t) {
// Not sure adding streams for Throwable would be better.
log(streamID, level, StringUtil.throwableToString(t));
}
/**
* A newly created id can be used here. For logging use existing ids always.
* @param streamID
* @return
*/
@Override
public boolean hasStream(final StreamID streamID) {
return this.idStreamMap.containsKey(streamID) || this.nameStreamMap.containsKey(streamID.name.toLowerCase());
}
@Override
public boolean hasStream(String name) {
return getStreamID(name) != null;
}
@ -275,15 +261,12 @@ public abstract class AbstractLogManager {
return stream;
}
/**
* A newly created id can be used here. For logging use existing ids always.
* @param loggerID
* @return
*/
@Override
public boolean hasLogger(final LoggerID loggerID) {
return this.idNodeMap.containsKey(loggerID) || this.nameNodeMap.containsKey(loggerID.name.toLowerCase());
}
@Override
public boolean hasLogger(String name) {
return getLoggerID(name) != null;
}

View File

@ -172,7 +172,7 @@ public class BlockBreakListener extends CheckListener {
priority = EventPriority.MONITOR)
public void onPlayerAnimation(final PlayerAnimationEvent event) {
// Just set a flag to true when the arm was swung.
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "Animation");
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "Animation");
BlockBreakData.getData(event.getPlayer()).noSwingArmSwung = true;
}
@ -186,7 +186,7 @@ public class BlockBreakListener extends CheckListener {
@EventHandler(
ignoreCancelled = false, priority = EventPriority.LOWEST)
public void onPlayerInteract(final PlayerInteractEvent event) {
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "Interact("+event.isCancelled()+"): " + event.getClickedBlock());
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "Interact("+event.isCancelled()+"): " + event.getClickedBlock());
// The following is to set the "first damage time" for a block.
// Return if it is not left clicking a block.

View File

@ -445,7 +445,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
damagedData.fastHealRefTime = System.currentTimeMillis();
}
}
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, event.getCause());
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, event.getCause());
// Attacking entities.
if (event instanceof EntityDamageByEntityEvent) {
final EntityDamageByEntityEvent e = (EntityDamageByEntityEvent) event;

View File

@ -80,7 +80,7 @@ public class AxisVelocity {
// TODO: Could check for alternating signum (error).
final Velocity vel = it.next();
if (vel.actCount <= 0 || vel.tick < tick) {
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "Invalidate queued: " + vel);
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "Invalidate queued: " + vel);
it.remove();
}
}

View File

@ -401,7 +401,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
earlyReturn = true;
} else if (player.isSleeping()) {
// Ignore sleeping playerrs.
// TODO: sleeping: (which cb!) NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "-> " + player.isSleepingIgnored());
// TODO: sleeping: (which cb!) NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "-> " + player.isSleepingIgnored());
data.sfHoverTicks = -1;
earlyReturn = true;
} else if (!from.getWorld().equals(to.getWorld())) {

View File

@ -475,7 +475,7 @@ public class SurvivalFly extends Check {
if (hDistance <= (cc.velocityStrictInvalidation ? hAllowedDistance : hAllowedDistance / 2.0)) {
// TODO: Should there be other side conditions?
// Invalidate used horizontal velocity.
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "*** INVALIDATE ON SPEED");
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** INVALIDATE ON SPEED");
data.clearActiveHorVel();
// if (data.horizontalVelocityUsed > cc.velocityGraceTicks) {
// data.horizontalFreedom = 0;

View File

@ -55,7 +55,9 @@ public class ReloadCommand extends BaseCommand {
// Do the actual reload.
ConfigManager.cleanup();
ConfigManager.init(access);
logManager.onReload(); // Does not get exchanged (!).
if (logManager instanceof INotifyReload) { // TODO: This is a band-aid.
((INotifyReload) logManager).onReload();
}
// Remove all cached configs.
DataManager.clearConfigs(); // There you have to add XConfig.clear() form now on.

View File

@ -7,6 +7,8 @@ import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.components.INotifyReload;
import fr.neatmonster.nocheatplus.components.order.SetupOrder;
import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
@ -23,12 +25,14 @@ import fr.neatmonster.nocheatplus.logging.details.LogOptions.CallContext;
* at least as prefixes).<br>
* Note that logging to the init/plugin/server with debug/fine or finer, might
* result in the server loggers suppressing those. As long as default file is
* activated, logging to init will log all levels to the file.
* activated, logging to init will log all levels to the file.<hr>
* Not intended to be added as a component (INotifyReload is a band-aid and may be checked "early" by the reloading routine).
*
* @author dev1mc
*
*/
public class LogManager extends AbstractLogManager {
@SetupOrder(priority = Integer.MIN_VALUE) // Just in case.
public class BukkitLogManager extends AbstractLogManager implements INotifyReload {
// TODO: Make LogManager an interface <- AbstractLogManager <- BukkitLogManager (hide some / instanceof).
@ -41,7 +45,7 @@ public class LogManager extends AbstractLogManager {
* This will create all default loggers as well.
* @param plugin
*/
public LogManager(Plugin plugin) {
public BukkitLogManager(Plugin plugin) {
super(new BukkitLogNodeDispatcher(plugin), Streams.defaultPrefix, Streams.INIT);
this.plugin = plugin;
ConfigFile config = ConfigManager.getConfigFile();
@ -148,11 +152,10 @@ public class LogManager extends AbstractLogManager {
//
}
/**
* Not "official". TODO: Hide.
*/
@Override
public void onReload() {
// Hard clear and re-do loggers. Might result in loss of content.
// TODO: Register for "early onReload call", needs API addition.
clear(0L, true); // Can not afford to wait.
createDefaultLoggers(ConfigManager.getConfigFile());
}

View File

@ -2372,7 +2372,7 @@ public class BlockProperties {
final int iMaxY = Math.min(Location.locToBlock(maxY), maxBlockY);
final int iMinZ = Location.locToBlock(minZ);
final int iMaxZ = Location.locToBlock(maxZ);
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "*** isOnGround check size: " + ((iMaxX - iMinX + 1) * (iMaxY - iMinY + 1) * (iMaxZ - iMinZ + 1)));
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** isOnGround check size: " + ((iMaxX - iMinX + 1) * (iMaxY - iMinY + 1) * (iMaxZ - iMinZ + 1)));
for (int x = iMinX; x <= iMaxX; x++) {
for (int z = iMinZ; z <= iMaxZ; z++) {
@ -2629,7 +2629,7 @@ public class BlockProperties {
final int iMaxY = Location.locToBlock(maxY);
final int iMinZ = Location.locToBlock(minZ);
final int iMaxZ = Location.locToBlock(maxZ);
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "*** collect flags check size: " + ((iMaxX - iMinX + 1) * (iMaxY - iMinY + 1) * (iMaxZ - iMinZ + 1)));
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** collect flags check size: " + ((iMaxX - iMinX + 1) * (iMaxY - iMinY + 1) * (iMaxZ - iMinZ + 1)));
long flags = 0;
for (int x = iMinX; x <= iMaxX; x++) {
for (int z = iMinZ; z <= iMaxZ; z++) {

View File

@ -487,13 +487,13 @@ public class PlayerLocation {
// TODO: BlockHeight is needed for fences, use right away (above)?
if (!BlockProperties.isPassableWorkaround(blockCache, blockX, bY, blockZ, minX - blockX, minY - yOnGround - bY, minZ - blockZ, id, maxX - minX, yOnGround, maxZ - minZ, 1.0)
|| (flags & BlockProperties.F_GROUND_HEIGHT) != 0 && BlockProperties.getGroundMinHeight(blockCache, blockX, bY, blockZ, id, bounds, flags) <= y - bY) {
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "*** onground SHORTCUT");
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** onground SHORTCUT");
onGround = true;
}
}
}
if (onGround == null) {
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "*** fetch onground std");
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** fetch onground std");
// Full on-ground check (blocks).
// Note: Might check for half-block height too (getTypeId), but that is much more seldom.
onGround = BlockProperties.isOnGround(blockCache, minX, minY - yOnGround, minZ, maxX, minY, maxZ, 0L);
@ -503,7 +503,7 @@ public class PlayerLocation {
}
if (onGround) onGroundMinY = Math.min(onGroundMinY, yOnGround);
else {
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "*** onground check entities");
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** onground check entities");
// TODO: further confine this ?
notOnGroundMaxY = Math.max(notOnGroundMaxY, yOnGround);
final double d1 = 0.25D;
@ -568,7 +568,7 @@ public class PlayerLocation {
if (notOnGroundMaxY >= yOnGround) return false;
}
}
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "*** Fetch on-ground: yOnGround=" + yOnGround + " xzM=" + xzMargin + " yM=" + yMargin + " ign=" + ignoreFlags);
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "*** Fetch on-ground: yOnGround=" + yOnGround + " xzM=" + xzMargin + " yM=" + yMargin + " ign=" + ignoreFlags);
final boolean onGround = BlockProperties.isOnGround(blockCache, minX - xzMargin, minY - yOnGround - yMargin, minZ - xzMargin, maxX + xzMargin, minY + yMargin, maxZ + xzMargin, ignoreFlags);
if (ignoreFlags == 0) {
if (onGround) {

View File

@ -9,56 +9,56 @@ import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.logging.Streams;
public class TeleportUtil {
/** Temp use. LocUtil.clone on passing. setWorld(null) after use. */
private static final Location useLoc = new Location(null, 0, 0, 0);
/**
* Teleport the player with vehicle, temporarily eject the passenger and set teleported in MovingData.
* @param vehicle
* @param player
* @param location
*/
public static void teleport(final Entity vehicle, final Player player, final Location location, final boolean debug) {
// TODO: This handling could conflict with WorldGuard region flags.
// TODO: Account for nested passengers and inconsistencies.
final Entity passenger = vehicle.getPassenger();
final boolean vehicleTeleported;
final boolean playerIsPassenger = player.equals(passenger);
if (playerIsPassenger && !vehicle.isDead()){ // && vehicle.equals(player.getVehicle).
// TODO: Does VehicleExit fire here !? Consequences?
vehicle.eject();
vehicleTeleported = vehicle.teleport(location, TeleportCause.PLUGIN);
}
else if (passenger == null && !vehicle.isDead()){
vehicleTeleported = vehicle.teleport(location, TeleportCause.PLUGIN);
}
else vehicleTeleported = false;
final boolean playerTeleported = player.teleport(location);
if (playerIsPassenger && playerTeleported && vehicleTeleported && player.getLocation().distance(vehicle.getLocation(useLoc)) < 1.0){
// Somewhat check against tp showing something wrong (< 1.0).
// TODO: Does VehicleEnter fire here !? Consequences?
vehicle.setPassenger(player);
}
if (debug){
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, player.getName() + " vehicle set back: " + location);
}
useLoc.setWorld(null);
}
/**
* Force mounting the vehicle including teleportation.
* @param passenger
* @param vehicle
*/
public static void forceMount(Entity passenger, Entity vehicle) {
if (vehicle.getPassenger() != null) {
vehicle.eject();
}
if (passenger.teleport(vehicle) && !vehicle.isDead() && vehicle.isValid()) {
vehicle.setPassenger(passenger);
}
}
/** Temp use. LocUtil.clone on passing. setWorld(null) after use. */
private static final Location useLoc = new Location(null, 0, 0, 0);
/**
* Teleport the player with vehicle, temporarily eject the passenger and set teleported in MovingData.
* @param vehicle
* @param player
* @param location
*/
public static void teleport(final Entity vehicle, final Player player, final Location location, final boolean debug) {
// TODO: This handling could conflict with WorldGuard region flags.
// TODO: Account for nested passengers and inconsistencies.
final Entity passenger = vehicle.getPassenger();
final boolean vehicleTeleported;
final boolean playerIsPassenger = player.equals(passenger);
if (playerIsPassenger && !vehicle.isDead()){ // && vehicle.equals(player.getVehicle).
// TODO: Does VehicleExit fire here !? Consequences?
vehicle.eject();
vehicleTeleported = vehicle.teleport(location, TeleportCause.PLUGIN);
}
else if (passenger == null && !vehicle.isDead()){
vehicleTeleported = vehicle.teleport(location, TeleportCause.PLUGIN);
}
else vehicleTeleported = false;
final boolean playerTeleported = player.teleport(location);
if (playerIsPassenger && playerTeleported && vehicleTeleported && player.getLocation().distance(vehicle.getLocation(useLoc)) < 1.0){
// Somewhat check against tp showing something wrong (< 1.0).
// TODO: Does VehicleEnter fire here !? Consequences?
vehicle.setPassenger(player);
}
if (debug){
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, player.getName() + " vehicle set back: " + location);
}
useLoc.setWorld(null);
}
/**
* Force mounting the vehicle including teleportation.
* @param passenger
* @param vehicle
*/
public static void forceMount(Entity passenger, Entity vehicle) {
if (vehicle.getPassenger() != null) {
vehicle.eject();
}
if (passenger.teleport(vehicle) && !vehicle.isDead() && vehicle.isValid()) {
vehicle.setPassenger(passenger);
}
}
}

View File

@ -104,7 +104,7 @@ public class TrigUtil {
{
// // TODO: Here we have 0.x vs. 2.x, sometimes !
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(LogManager.TRACE_FILE, "COMBINED: " + combinedDirectionCheck(sourceX, sourceY, sourceZ, dirX, dirY, dirZ, targetX, targetY, targetZ, targetWidth, targetHeight, precision, 60));
// NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "COMBINED: " + combinedDirectionCheck(sourceX, sourceY, sourceZ, dirX, dirY, dirZ, targetX, targetY, targetZ, targetWidth, targetHeight, precision, 60));
// TODO: rework / standardize.

View File

@ -69,6 +69,7 @@ import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.event.IHaveMethodOrder;
import fr.neatmonster.nocheatplus.event.ListenerManager;
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
import fr.neatmonster.nocheatplus.logging.BukkitLogManager;
import fr.neatmonster.nocheatplus.logging.LogManager;
import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.logging.Streams;
@ -107,7 +108,7 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
// Not static.
/** Central logging access point. */
private LogManager logManager = null; // Not final, but intended to stay, once set [change to init=syso?].
private BukkitLogManager logManager = null; // Not final, but intended to stay, once set [change to init=syso?].
/** Names of players with a certain permission. */
protected final NameSetPermState nameSetPerms = new NameSetPermState(Permissions.NOTIFY);
@ -716,7 +717,7 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
NCPAPIProvider.setNoCheatPlusAPI(this);
// Read the configuration files.
ConfigManager.init(this); // TODO: Only load the bootstrap config (not all).
logManager = new LogManager(this);
logManager = new BukkitLogManager(this);
StaticLog.setStreamID(Streams.INIT);
StaticLog.setUseLogManager(true);
logManager.info(Streams.INIT, "[NoCheatPlus] Logging system initialized.");