public class TmHelp extends MainTM {

	/**
	 * Help messages
	 */
	// Always copy this content in the README.md
	private static String headerHelp = "§e---------§r Help: " + prefixTMColor + " §e---------";
	private static String checkconfigHelpMsg = "§6/" + CMD_TM + " " + CMD_CHECKCONFIG
			+ " §rAdmins and console can display a summary of the config.yml and lang.yml files.";
	private static String checkSqlHelpMsg = "§6/" + CMD_TM + " " + CMD_CHECKSQL
			+ " §rCheck the availability of the mySQL server according to the values provided in the config.yml file. This only checks the ip address and the correct port opening.";
	private static String checktimeHelpMsg = "§6/" + CMD_TM + " " + CMD_CHECKTIME
			+ " [all|server|world] §rAdmins and console can display a debug/managing message, who displays the startup server's time, the current server's time and the current time, start time and speed for a specific world (or for all of them).";
	private static String checkupdateHelpMsg = "§6/" + CMD_TM + " " + CMD_CHECKUPDATE
			+ " [bukkit|spigot|github] §rSearch if a newer version of the plugin exists on the chosen server. (MC 1.18.9+ only)";
	private static String helpHelpMsg = "§6/" + CMD_TM + " " + CMD_HELP
			+ " [cmd] [<subCmd>] §rHelp provides you the correct usage and a short description of targeted command or subcommand.";
	private static String tmNowHelpMsg = "§6/" + CMD_TM + " " + CMD_NOW
			+ " [msg|title|actionbar] [all|player|world] §rSend the '/now' (chat, title or action bar) message to a specific player, all players in a specific world, or all online players.";
	private static String reloadHelpMsg = "§6/" + CMD_TM + " " + CMD_RELOAD
			+ " [all|cmds|config|lang] §rThis command allows you to reload datas from yaml files after manual modifications. All timers will be immediately resynchronized.";
	private static String resyncHelpMsg = "§6/" + CMD_TM + " " + CMD_RESYNC
			+ " [all|world] §rThis command will re-synchronize a single or all worlds timers, based on the startup server's time, the elapsed time and the current speed modifier.";
	private static String setDateHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_DATE
			+ " [today|yyyy-mm-dd] [all|world] §rSets current date for the specified world (or all of them). Could be §otoday§r or any yyyy-mm-dd date. The length of the months corresponds to reality, with the exception of February which always lasts 28 days. A year therefore always lasts 365 days.";
	private static String setDebugHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_DEBUG
			+ " [true|false] §rSet true to enable colored verbose messages in the console. Useful to understand some mechanisms of this plugin.";
	private static String setDefLangHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_DEFLANG
			+ " [lg_LG] §rChoose the translation to use if player's locale doesn't exist in the lang.yml or when §o'multiLang'§r is false.";
	private static String setE_DaysHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_E_DAYS
			+ " [0 → ∞] [all|world] §rSets current number of elapsed days for the specified world (or all of them). Could be an integer between §o0§r and §oinfinity§r (or almost). Setting this to §o0§r will bring the world back to day §oone§r.";
	private static String setInitialTickHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_INITIALTICK
			+ " [ticks|HH:mm:ss] §rModify the server's initial tick.";
	private static String setMultilangHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_MULTILANG
			+ " [true|false] §rSet true or false to use an automatic translation for the §o/now §rcommand.";
	private static String setPlayerOffsetHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_PLAYEROFFSET
			+ " [-23999 → 23999] [all|player] §rDefine a specific offset relative to the world time on player's client (the world speed will be still active). Set to '0' to cancel."; //TODO 1.6.0
	private static String setPlayerTimeHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_PLAYERTIME
			+ " [ticks|daypart|HH:mm:ss|reset] [all|player] §rDefine a specific time on player's client (the world speed will be still active). Use the 'reset' argument to cancel."; //TODO 1.6.0
	private static String setRefreshRateHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_REFRESHRATE
			+ " [ticks] §rSet the delay (in ticks) before actualizing the speed stretch/expand effect. Must be an integer between §o" + refreshMin + "§r and §o" + refreshMax + "§r. Default value is §o" + defRefresh + " ticks§r, please note that a too small value can cause server lags.";
	private static String setSleepHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_SLEEP
			+ " [true|false|linked] [all|world] §rDefine if players can sleep until the next day in the specified world (or in all of them). By default, all worlds will start with parameter true, unless their timer is in real time who will be necessary false. If you want to both allow sleep and keep the same time in multiple worlds, you can use the 'linked' function which allows a group of worlds to spend the night together.";
	private static String setSpeedHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_SPEED
			+ " [multiplier] [all|world] §rThe decimal number argument will multiply the world(s) speed. Use §o0.0§r to freeze time, numbers from §o0.1§r to §o0.9§r to slow time, §o1.0§r to get normal speed and numbers from §o1.1§r to " + speedMax + " to speedup time. Set this value to §o24.0§r or §orealtime§r to make the world time match the real speed time.";
	private static String setSpeed_D_N_HelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_D_SPEED + " §ror §6/"
			+ CMD_TM + " " + CMD_SET + " " + CMD_SET_N_SPEED
			+ " [multiplier] [all|world] §rFrom §o0.0§r to §o10.0§r, the values of daySpeed and nightSpeed can be different from each other.";
	private static String setStartHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_START
			+ " [ticks|daypart|HH:mm:ss|timeShift] [all|world] §rDefines the time at server startup for the specified world (or all of them). By default, all worlds will start at §otick #0§r. The timer(s) will be immediately resynchronized. If a world is using the real time speed, the start value will determine the UTC time shift and values like +1 or -1 will be accepted.";
	private static String setSyncHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_SYNC
			+ " [true|false] [all|world] §rDefine if the speed distortion method will increase/decrease the world's actual tick, or fit the theoretical tick value based on the server one. By default, all worlds will start with parameter false. Real time based worlds and frozen worlds do not use this option, on the other hand this will affect even the worlds with a normal speed.";
	private static String setTimeHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_TIME
			+ " [ticks|daypart|HH:mm:ss] [all|world] §rSets current time for the specified world (or all of them). Consider using this instead of the vanilla §o/time§r command. The tab completion also provides handy presets like \"day\", \"noon\", \"night\", \"midnight\", etc.";
	private static String setupdateSrcHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_UPDATE
			+ " [bukkit|spigot|github] §rDefine the source server for the update search. (MC 1.8.8+ only)";
	private static String setUseCmdsHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " " + CMD_SET_USECMDS
			+ " [true|false] §rSet true to enable a custom commands scheduler. See the " + CMDSFILENAME + " file for details.";
	// Except this line, used when 'set' is used without additional argument
	private static String missingSetArgHelpMsg = "§6/" + CMD_TM + " " + CMD_SET + " ["
			+ CMD_SET_DATE + "|"
			+ CMD_SET_DEBUG + "|"
			+ CMD_SET_DEFLANG + "|"
			+ CMD_SET_E_DAYS + "|"
			+ CMD_SET_INITIALTICK + "|"
			+ CMD_SET_MULTILANG + "|"
			+ CMD_SET_PLAYEROFFSET + "|"
			+ CMD_SET_PLAYERTIME + "|"
			+ CMD_SET_REFRESHRATE + "|"
			+ CMD_SET_SLEEP + "|"
			+ CMD_SET_SPEED + "|"
			+ CMD_SET_D_SPEED + "|"
			+ CMD_SET_N_SPEED + "|"
			+ CMD_SET_START + "|"
			+ CMD_SET_SYNC + "|"
			+ CMD_SET_TIME + "|"
			+ CMD_SET_UPDATE + "|"
			+ CMD_SET_USECMDS
			+ "]: §rThis command, used with arguments, permit to change plugin parameters.";

	/**
	 * CMD /tm help [cmd]
	 */
	public static boolean cmdHelp(CommandSender sender, String[] args) {
		
		int argsNb = args.length;
		String specificCmdMsg = "";
		
		// /tm help set [arg]
		if (argsNb >= 3) {
			if (args[1].equalsIgnoreCase(CMD_SET)) {
				String subCmd = args[2];
				switch (subCmd) {
				// /tm help set date
				case CMD_SET_DATE :
					specificCmdMsg = setDateHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_DEBUG : // /tm help set debugMode
					specificCmdMsg = setDebugHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_DEFLANG : // /tm help set defLang
					specificCmdMsg = setDefLangHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_E_DAYS : // /tm help set elapsedDays
					specificCmdMsg = setE_DaysHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_INITIALTICK : // /tm help set initialTick
					specificCmdMsg = setInitialTickHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_MULTILANG : // /tm help set multiLang
					specificCmdMsg = setMultilangHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_PLAYEROFFSET : // /tm help set playerOffset
					specificCmdMsg = setPlayerOffsetHelpMsg; // Help msg (in case of 2 args)
					break;				
				case CMD_SET_PLAYERTIME : // /tm help set playerTime
					specificCmdMsg = setPlayerTimeHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_REFRESHRATE : // /tm help set refreshRate
					specificCmdMsg = setRefreshRateHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_SLEEP : // /tm help set sleep
					specificCmdMsg = setSleepHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_SPEED : // /tm help set speed
					specificCmdMsg = setSpeedHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_D_SPEED : // /tm help set speedDay
				case CMD_SET_N_SPEED : // /tm help set speedNight
					specificCmdMsg = setSpeed_D_N_HelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_START : // /tm help set start
					specificCmdMsg = setStartHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_SYNC : // /tm help set sync
					specificCmdMsg = setSyncHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_TIME : // /tm help set time
					specificCmdMsg = setTimeHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_UPDATE : // /tm help set updateMsgSrc
					if (MainTM.serverMcVersion >= MainTM.reqMcVForUpdate)
						specificCmdMsg = setupdateSrcHelpMsg; // Help msg (in case of 2 args)
					break;
				case CMD_SET_USECMDS : // /tm help set time
					specificCmdMsg = setUseCmdsHelpMsg; // Help msg (in case of 2 args)
					break;
				}
			}
		// /tm help [arg]
		} else if (argsNb >= 2) {
			String subCmd = args[1];
			switch (subCmd) {
			case CMD_CHECKCONFIG : // /tm help checkconfig
				specificCmdMsg = checkconfigHelpMsg; // Help msg (in case of 1 arg)
				break;
			case CMD_CHECKSQL : // /tm help checksql
				specificCmdMsg = checkSqlHelpMsg; // Help msg (in case of 1 arg)
				break;
			case CMD_CHECKTIME : // /tm help checktime
				specificCmdMsg = checktimeHelpMsg; // Help msg (in case of 1 arg)
				break;
			case CMD_CHECKUPDATE : // /tm help checkupdate
				if (MainTM.serverMcVersion >= MainTM.reqMcVForUpdate)
					specificCmdMsg = checkupdateHelpMsg; // Help msg (in case of 1 arg)
				break;
			case CMD_TMNOW : // /tm help now
				specificCmdMsg = tmNowHelpMsg; // Help msg (in case of 1 arg)
				break;
			case CMD_RELOAD : // // /tm help reload
				specificCmdMsg = reloadHelpMsg; // Help msg (in case of 1 arg)
				break;
			case CMD_RESYNC : // // /tm help resync
				specificCmdMsg = resyncHelpMsg; // Help msg (in case of 1 arg)
				break;
			case CMD_SET : // // /tm help set <null>
				specificCmdMsg = missingSetArgHelpMsg; // Help msg (in case of 1 arg)
				break;
			// Maybe someone could forget the 'set' part, so think of its place
			case CMD_SET_DATE :
			case CMD_SET_DEBUG :
			case CMD_SET_DEFLANG :
			case CMD_SET_E_DAYS :
			case CMD_SET_INITIALTICK :
			case CMD_SET_MULTILANG :
			case CMD_SET_PLAYERTIME :
			case CMD_SET_REFRESHRATE :
			case CMD_SET_SLEEP :
			case CMD_SET_SPEED :
			case CMD_SET_D_SPEED :
			case CMD_SET_N_SPEED :
			case CMD_SET_START :
			case CMD_SET_SYNC :
			case CMD_SET_TIME :
			case CMD_SET_UPDATE :
			case CMD_SET_USECMDS :
				Bukkit.dispatchCommand(sender, CMD_TM + " " + CMD_HELP + " " + CMD_SET + " " + subCmd); // retry with correct arguments
				return true;
			}
		}
		// Display Help header
		sender.sendMessage(headerHelp); // Final msg (always)
		// Display specific cmd msg
		if (!specificCmdMsg.equalsIgnoreCase("") && !specificCmdMsg.equalsIgnoreCase(" ")) {
			sender.sendMessage(specificCmdMsg);
			return true;
		}
		// Else, display basic help msg and the list of cmds from plugin.yml
		else {
			sender.sendMessage(helpHelpMsg); // Final msg (always)
			return false;
		}
	}

}; public class TmNow extends MainTM {

	/**
	 * CMD /tm now [msg|title|actionbar] [player|all|world]
	 */
	public static void cmdNow(CommandSender sender, String display, String target) {
		
		// #1. Don't launch the command if there is no players (empty server, empty targeted world or unknown target)
		// #1.A. Stop if the server is empty
		if (Bukkit.getServer().getOnlinePlayers().size() == 0) {
			MsgHandler.debugMsg(tmNowEmptyServerMsg);
			if (sender instanceof CommandBlock) MsgHandler.playerAdminMsg(sender, tmNowEmptyServerMsg);
			return;
		}
		// #1.B. Stop if the targeted world is empty
		List<String> playersList = new ArrayList<>(); // Get the online players list
		for (Player listedPlayer : Bukkit.getServer().getOnlinePlayers()) playersList.add(listedPlayer.getName());
		List<String> worldsList = CfgFileHandler.setAnyListFromConfig(CF_WORLDSLIST); // Get the worlds list
		if (target.equalsIgnoreCase(ARG_ALL) || playersList.contains(target)) { // If target is "all" or is an online player, don't do nothing special
		} else if (worldsList.contains(target)) { // Else, if target is a world
			List<Player> players = Bukkit.getServer().getWorld(target).getPlayers();			
			if (players.size() == 0) {
				MsgHandler.debugMsg("World  §e" + target + " §b " + tmNowEmptyWorldMsg);
				MsgHandler.playerAdminMsg(sender, "World §e" + target + "§r " + tmNowEmptyWorldMsg);
				return;
			}
		// #1.C. Else, stop if the target is unknown
		} else {
			MsgHandler.cmdErrorMsg(sender, "§cThe §e" + target + "§c " + tmNowUnknownArgMsg, CMD_TMNOW);
			return;
		}
		
		// #2. Get all he players
		for (Player p : Bukkit.getOnlinePlayers()) {
			String world = p.getWorld().getName();
			String player = p.getName();
			
			// #3. Check who will receive the msg
			if (player.equalsIgnoreCase(target) || target.equalsIgnoreCase(ARG_ALL) || target.equalsIgnoreCase(world)) {
				String lang = PlayerLangHandler.setLangToUse(p);
				
				// #4. Get the prefix from the lang.yml file
				String prefix = MainTM.getInstance().langConf.getString(CF_LANGUAGES + "." + lang + "." + CF_PREFIX);
				prefix = prefix.replace("&", "§");		
				
				// #5. Configure message content
				String msg = null;
				String subtitle = null;
				switch (display) {
				case ARG_MSG :		
					if (world.contains(ARG_NETHER)) {
						msg = MainTM.getInstance().langConf.getString(CF_LANGUAGES + "." + lang + "." + CF_NETHERMSG);
					} else if (world.contains(ARG_THEEND)) {
						msg = MainTM.getInstance().langConf.getString(CF_LANGUAGES + "." + lang + "." + CF_ENDMSG);
					} else {
						msg = MainTM.getInstance().langConf.getString(CF_LANGUAGES + "." + lang + "." + CF_MSG);	
					}
					break;
				case ARG_TITLE :
					msg = MainTM.getInstance().langConf.getString(CF_LANGUAGES + "." + lang + "." + CF_TITLE);
					subtitle = MainTM.getInstance().langConf.getString(CF_LANGUAGES + "." + lang + "." + CF_SUBTITLE);
					break;
				case ARG_ACTIONBAR :
					msg = MainTM.getInstance().langConf.getString(CF_LANGUAGES + "." + lang + "." + CF_ACTIONBAR);
					break;
				}
				
				// #6. Replace placeholders
				msg = msg.replace("&", "§");
				msg = msg.replace("{" + PH_PREFIX + PH_PLAYER + "}", player);
				msg = PlaceholdersHandler.replaceAllPlaceholders(msg, world, lang, p);
				if (display.equalsIgnoreCase(ARG_TITLE)) {
					subtitle = subtitle.replace("&", "§");
					subtitle = subtitle.replace("{" + PH_PREFIX + PH_PLAYER + "}", player);
					subtitle = PlaceholdersHandler.replaceAllPlaceholders(subtitle, world, lang, p);		
				}
				
				// #7. Configure and send command
				switch (display) {
				case ARG_MSG :
					MsgHandler.playerChatMsg(p, prefix, msg);
					break;
				case ARG_TITLE :
					MsgHandler.playerTitleMsg(p, msg, subtitle);
					break; 
				case ARG_ACTIONBAR :
					MsgHandler.playerActionbarMsg(p, msg);
					break;
				}
			}
		}
	}

}; public class TmCheckConfig extends MainTM {

	/**
	 * CMD /tm checkConfig
	 */
	public static void cmdCheckConfig(CommandSender sender) {

		/*****************
		 *** VARIABLES ***
		 *****************/

		// Version
		String versionMsg = "You are running the " + versionTM() + " version.";
		String colVersionMsg = "You are running the §e" + versionTM() + "§r version.";

		// Multilanguage
		String multiLangOnOff = "disabled";
		if (MainTM.getInstance().langConf.getString(CF_USEMULTILANG).equalsIgnoreCase(ARG_TRUE)) {
			multiLangOnOff = "enabled";
		}
		String multiLangMsg = "Multilanguage is " + multiLangOnOff + ".";
		String colMultiLangMsg = "Multilanguage is §e" + multiLangOnOff + "§r.";

		// Default language
		String defLangMsg = "Default language is " + MainTM.getInstance().langConf.getString(CF_DEFAULTLANG) + ".";
		String colDefLangMsg = "Default language is §e" + MainTM.getInstance().langConf.getString(CF_DEFAULTLANG) + "§r.";

		// Available languages
		List<String> availableLg = LgFileHandler.setAnyListFromLang(CF_LANGUAGES);
		String availableLangMsg = "Available languages are : " + availableLg + ".";
		String colAvailableLangMsg = "Available languages are : §e" + availableLg + "§r.";

		// Refresh rate
		String refRateMsg = refreshRateMsg + " " + MainTM.getInstance().getConfig().getString(CF_REFRESHRATE) + " ticks.";
		String colRefRateMsg = refreshRateMsg + " §e" + MainTM.getInstance().getConfig().getString(CF_REFRESHRATE) + " ticks§r.";

		// Wake up tick
		String wakeUpTickMsg = "Players will wake up at #" + MainTM.getInstance().getConfig().getString(CF_WAKEUPTICK) + ".";
		String colwakeUpTickMsg = "Players will wake up at §e#" + MainTM.getInstance().getConfig().getString(CF_WAKEUPTICK) + "§r.";	

		// New day will start at
		String tick = "#18000";
		if (MainTM.getInstance().getConfig().getString(CF_NEWDAYAT).equalsIgnoreCase(newDayStartsAt_6h00)) tick = "#0";
		String newDayAtMsg = "In the calendar, new day starts at " + MainTM.getInstance().getConfig().getString(CF_NEWDAYAT) + ". (" + tick + ")";
		String colNewDayAtMsg = "In the calendar, new day starts at §e" + MainTM.getInstance().getConfig().getString(CF_NEWDAYAT) + "§r. (§e" + tick + "§r)";	

		// List of the worlds
		List<String> activeWorlds = CfgFileHandler.setAnyListFromConfig(CF_WORLDSLIST);
		String worldsMsg = "Active world(s) are : " + activeWorlds + ".";
		String colWorldsMsg = "Active world(s) are : §e" + activeWorlds + "§r.";

		// Initial tick reset status
		String resetOnOff = " not ";
		if (MainTM.getInstance().getConfig().getString(CF_INITIALTICK + "." + CF_RESETONSTARTUP).equalsIgnoreCase(ARG_TRUE)) {
			resetOnOff = " ";
		}
		String resetMsg = "The initial tick will" + resetOnOff + "reset on the next startup.";
		String colResetMsg = "The initial tick §ewill" + resetOnOff + "reset§r on the next startup.";

		// MySql
		String sqlOnOff = "the config.yml file";
		if (MainTM.getInstance().getConfig().getString(CF_INITIALTICK + "." + CF_USEMYSQL).equalsIgnoreCase(ARG_TRUE)) {
			sqlOnOff = "a MySql database";
		}
		String sqlMsg = "The initial tick is saved in " + sqlOnOff + ".";
		String colSqlMsg = "The initial tick is saved in §e" + sqlOnOff + "§r.";

		// Update
		String updateMsg = "The update message source can not be checked.";
		String colUpdateMsg = "The update message source §ecan not be checked§r.";
		if (!MainTM.getInstance().getConfig().getString(CF_UPDATEMSGSRC).equals(defUpdateMsgSrc)) {
			String updateSrc = "s" + MainTM.getInstance().getConfig().getString(CF_UPDATEMSGSRC);
			updateMsg = "The update message will check on " + updateSrc + " server to find a new version.";
			colUpdateMsg = "The update message will check on §e" + updateSrc + "§r server to find a new version.";
		} else {
			updateMsg = "The update message is disabled.";
			colUpdateMsg = "The update message is §edisabled§r.";
		}

		// Debug
		String debugOnOff = "disabled";
		if (MainTM.getInstance().getConfig().getString(CF_DEBUGMODE).equalsIgnoreCase(ARG_TRUE)) {
			debugOnOff = "enabled";
		}
		String debugMsg = "The debug mode is " + debugOnOff + ".";
		String colDebugMsg = "The debug mode is §e" + debugOnOff + "§r.";

		// Placeholders
		String PAPIOnOff = "aren't";
		if (MainTM.getInstance().getConfig().getString(CF_PLACEHOLDER + "." + CF_PLACEHOLDER_PAPI).equalsIgnoreCase(ARG_TRUE)) {
			PAPIOnOff = "are";
		}
		String MvDWPAPIOnOff = "aren't";
		if (MainTM.getInstance().getConfig().getString(CF_PLACEHOLDER + "." + CF_PLACEHOLDER_MVDWPAPI).equalsIgnoreCase(ARG_TRUE)) {
			MvDWPAPIOnOff = "are";
		}
		String placeholdersMsg = "Your placeholders " + PAPIOnOff + " registred in " + CF_PLACEHOLDER_PAPI + " and/but they " + MvDWPAPIOnOff + " registred in " + CF_PLACEHOLDER_MVDWPAPI + ".";
		String colPlaceholdersMsg = "Your placeholders " + PAPIOnOff + " registred in §e" + CF_PLACEHOLDER_PAPI + "§r and/but they " + MvDWPAPIOnOff + " registred in §e" + CF_PLACEHOLDER_MVDWPAPI + "§r.";

		/******************
		 ***** EVENT ******
		 ******************/

		if (sender instanceof Player) {
			// Display the version of the plugin
			MsgHandler.playerAdminMsg(sender, colVersionMsg);
			// Display the multilanguage status
			MsgHandler.playerAdminMsg(sender, colMultiLangMsg);
			// Display the default language
			MsgHandler.playerAdminMsg(sender, colDefLangMsg);
			// Display the available languages
			MsgHandler.playerAdminMsg(sender, colAvailableLangMsg);
			// Display the refresh rate
			MsgHandler.playerAdminMsg(sender, colRefRateMsg);
			// Display the wake up tick
			MsgHandler.playerAdminMsg(sender, colwakeUpTickMsg);
			// Display the new day at dawn/midnight
			MsgHandler.playerAdminMsg(sender, colNewDayAtMsg);
			// Display the world's list
			MsgHandler.playerAdminMsg(sender, colWorldsMsg);
			// Display the initial tick reset status
			MsgHandler.playerAdminMsg(sender, colResetMsg);
			// Display the MySql status
			MsgHandler.playerAdminMsg(sender, colSqlMsg);
			// Display the update source status
			MsgHandler.playerAdminMsg(sender, colUpdateMsg);
			// Display the debug mode status
			MsgHandler.playerAdminMsg(sender, colDebugMsg);
			// Display the placeholder API status
			MsgHandler.playerAdminMsg(sender, colPlaceholdersMsg);
		} else {
			// Display the version of the plugin
			MsgHandler.infoMsg(versionMsg);
			// Display the multilanguage status
			MsgHandler.infoMsg(multiLangMsg);
			// Display the default language
			MsgHandler.infoMsg(defLangMsg);
			// Display the available languages
			MsgHandler.infoMsg(availableLangMsg);
			// Display the refresh rate
			MsgHandler.infoMsg(refRateMsg);
			// Display the wake up tick
			MsgHandler.infoMsg(wakeUpTickMsg);
			// Display the new day at dawn/midnight
			MsgHandler.infoMsg(newDayAtMsg);
			// Display the world's list
			MsgHandler.infoMsg(worldsMsg);
			// Display the initial tick reset status
			MsgHandler.infoMsg(resetMsg);
			// Display the MySql status
			MsgHandler.infoMsg(sqlMsg);
			// Display the update source status
			MsgHandler.infoMsg(updateMsg);
			// Display the debug mode status
			MsgHandler.infoMsg(debugMsg);
			// Display the placeholder API status
			MsgHandler.infoMsg(placeholdersMsg);
		}
	}

}; public class TmCheckSql extends MainTM {

	/**
	 * CMD /tm checkSql
	 */
	public static void cmdSqlcheck(CommandSender sender) {

		BukkitRunnable asyncCmdSqlcheck = new BukkitRunnable() {
			@Override
			public void run() {
				String isSslOn = " without";
				if (ssl.equalsIgnoreCase(ARG_TRUE)) {
					isSslOn = "";
				}
				// Start notifications
				MsgHandler.playerAdminMsg(sender, tryReachHostMsg + " \"§e" + host + "§r\" on port §e#" + port + "§r" + isSslOn + " using ssl."); // Player final msg (in case)
				MsgHandler.infoMsg(tryReachHostMsg + " \"" + host + "\" on port #" + port + isSslOn + " using ssl."); // Console final msg (always)
				// Test the connection
				boolean okOrNot = SqlHandler.connectionToHostIsAvailable(true);
				// Notifications
				if (sender instanceof Player) { // Console messages are displayed by 'SqlHandler.connectionToHostIsAvailable()'
					if (okOrNot == true) { // If the connection is ok
						MsgHandler.playerAdminMsg(sender, "The mySQL host \"§e" + host + "§r\" " + connectionOkMsg + " §e#" + port + "§r" + isSslOn + " using ssl."); // Player final msg (in case)
						SqlHandler.closeConnection("Host"); // Stop the connection
					} else { // If the connection is not ok
						MsgHandler.playerAdminMsg(sender, connectionFailMsg + " \"§e" + host + "§r\". " + checkLogMsg); // Player final msg (in case)
					}
				}
			}
		};

		asyncCmdSqlcheck.runTaskAsynchronously(MainTM.getInstance());

	}

}; public class TmCheckTime extends MainTM {

	/**
	 * CMD /tm checkTime [all|server|world]
	 */
	public static void cmdCheckTime(CommandSender sender, String world) {
		
		// If the arg is "all" or "server", get the server's initial and actual ticks
		if (world.equalsIgnoreCase(ARG_ALL) || world.equalsIgnoreCase(ARG_SERVER)) {
			// Get the current server tick
			long currentServerTick = ValuesConverter.getServerTick();
			// Get the current server UTC time in HH:mm:ss
			String currentServerTime = ValuesConverter.getServerTime();
			// Display the reference tick and HH:mm:ss
			if (sender instanceof Player) {
				MsgHandler.playerAdminMsg(sender, serverInitTickMsg + " §e#" + initialTick + " §r(§e" + initialTime + "§r)."); // Final player msg
			} else {
				MsgHandler.infoMsg(serverInitTickMsg + " #" + initialTick + " (" + initialTime + ")."); // Final console msg
			}
			// Get the current tick
			if (sender instanceof Player) {
				MsgHandler.playerAdminMsg(sender, serverCurrentTickMsg + " §e#" + currentServerTick + " §r(§e" + currentServerTime + "§r)."); // Final player msg
			} else {
				MsgHandler.infoMsg(serverCurrentTickMsg + " #" + currentServerTick + " (" + currentServerTime + ")."); // Final console msg
			}
		}
		// If the arg is "all", get each world start tick, actual tick, speeds and sync params
		if (world.equalsIgnoreCase(ARG_ALL)) {
			// Relaunch this for each world
			for (String listedWorld : MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false)) {
				cmdDisplayTime(sender, listedWorld);
			}
		}
		// Else, if the string argument is a listed world, check a single world
		else if (MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false).contains(world)) {
			cmdDisplayTime(sender, world);
		}
	}

	/**
	 * Display a world time message
	 */
	private static void cmdDisplayTime(CommandSender sender, String world) {
		Long d = ValuesConverter.elapsedDaysFromTick(Bukkit.getWorld(world).getFullTime());
		String elapsedDays = d.toString();
		String date = ValuesConverter.dateFromElapsedDays(d, PH_YYYY) + "-" + ValuesConverter.dateFromElapsedDays(d, PH_MM) + "-" + ValuesConverter.dateFromElapsedDays(d, PH_DD);
		long listedWorldStartTick = MainTM.getInstance().getConfig().getLong(CF_WORLDSLIST + "." + world + "." + CF_START);
		long listedWorldCurrentTick = Bukkit.getServer().getWorld(world).getTime();
		String listedWorldStartTime = ValuesConverter.formattedTimeFromTick(listedWorldStartTick);
		String formattedUTCTime = ValuesConverter.formattedUTCShiftfromTick(listedWorldStartTick);
		String formattedUTCTick = ValuesConverter.tickUTCShiftfromTick(listedWorldStartTick);
		String listedWorldCurrentTime = ValuesConverter.formattedTimeFromTick(listedWorldCurrentTick);
		double listedWorldDaySpeed = MainTM.getInstance().getConfig().getDouble(CF_WORLDSLIST + "." + world + "." + CF_D_SPEED);
		String listedWorldNightSpeed = MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + CF_N_SPEED);
		String listedWorldSync = "";
		String listedWorldSleep = MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + CF_SLEEP);
		if (MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + CF_SYNC).equals(ARG_FALSE))
			listedWorldSync = "not ";
		if (listedWorldDaySpeed == realtimeSpeed) { // Display realtime message (speed = 24.00)
			if (sender instanceof Player) {
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r " + worldCurrentElapsedDaysMsg + " §e" + elapsedDays + "§r whole day(s) (§e" + date + "§r)."); // Final console msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r " + worldCurrentStartMsg + " §e" + formattedUTCTime + " §r(§e" + formattedUTCTick + " §rticks)."); // Final player msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r" + worldCurrentTimeMsg + " " + listedWorldCurrentTime + " §r(§e#" + listedWorldCurrentTick + "§r)."); // Final player msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r" + worldCurrentSpeedMsg + " §e" + worldRealSpeedMsg + "§r."); // Final player msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r is §e" + listedWorldSync + worldCurrentSyncMsg + "§r."); // Final player msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r" + worldCurrentSleepMsg + " " + listedWorldSleep + "§r."); // Final player msg
			} else {
				MsgHandler.infoMsg("The world " + world + " " + worldCurrentElapsedDaysMsg + " " + elapsedDays + " whole day(s) (" + date + ")."); // Final console msg
				MsgHandler.infoMsg("The world " + world + " " + worldCurrentStartMsg + " " + formattedUTCTime + " (" + formattedUTCTick + " ticks)."); // Final console msg
				MsgHandler.infoMsg("The world " + world + worldCurrentTimeMsg + " " + listedWorldCurrentTime + " (#" + listedWorldCurrentTick + ")."); // Final console msg
				MsgHandler.infoMsg("The world " + world + worldCurrentSpeedMsg + " " + worldRealSpeedMsg + "."); // Final console msg
				MsgHandler.infoMsg("The world " + world + " is " + listedWorldSync + worldCurrentSyncMsg + "."); // Final console msg
				MsgHandler.infoMsg("The world " + world + worldCurrentSleepMsg + " " + listedWorldSleep + "."); // Final console msg
			}
		} else { // Display usual message (any speed but 24.00)
			if (sender instanceof Player) {
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r " + worldCurrentElapsedDaysMsg + " §e" + elapsedDays + "§r whole day(s) (§e" + date + "§r)."); // Final console msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r " + worldCurrentStartMsg + " §e" + listedWorldStartTime + " §r(§e+" + listedWorldStartTick + " §rticks)."); // Final player msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r" + worldCurrentTimeMsg + " §e" + listedWorldCurrentTime + " §r(§e#" + listedWorldCurrentTick + "§r)."); // Final player msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r" + worldCurrentDaySpeedMsg + " §e" + listedWorldDaySpeed + "§r."); // Final player msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r" + worldCurrentNightSpeedMsg + " §e" + listedWorldNightSpeed + "§r."); // Final player msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r is §e" + listedWorldSync + worldCurrentSyncMsg + "§r."); // Final player msg
				MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r" + worldCurrentSleepMsg + " §e" + listedWorldSleep + "§r."); // Final player msg
			} else {
				MsgHandler.infoMsg("The world " + world + " " + worldCurrentElapsedDaysMsg + " " + elapsedDays + " whole day(s) (" + date + ")."); // Final console msg
				MsgHandler.infoMsg("The world " + world + " " + worldCurrentStartMsg + " " + listedWorldStartTime + " (+" + listedWorldStartTick + " ticks)."); // Final console msg
				MsgHandler.infoMsg("The world " + world + worldCurrentTimeMsg + " " + listedWorldCurrentTime + " (#" + listedWorldCurrentTick + ")."); // Final console msg
				MsgHandler.infoMsg("The world " + world + worldCurrentDaySpeedMsg + " " + listedWorldDaySpeed + "."); // Final console msg
				MsgHandler.infoMsg("The world " + world + worldCurrentNightSpeedMsg + " " + listedWorldNightSpeed + "."); // Final console msg
				MsgHandler.infoMsg("The world " + world + " is " + listedWorldSync + worldCurrentSyncMsg + "."); // Final console msg
				MsgHandler.infoMsg("The world " + world + worldCurrentSleepMsg + " " + listedWorldSleep + "."); // Final console msg
			}
		}
	}

}; public class TmCheckUpdate extends MainTM {

	/**
	 * CMD /tm checkUpdate [none|bukkit|spigot|github]
	 */
	public static void cmdCheckUpdate(CommandSender sender, String updateSource) {
		
		if (updateSource == null) { // If the argument is empty, try to get the value from the configuration
			if	(MainTM.getInstance().getConfig().getKeys(false).contains(CF_UPDATEMSGSRC))
				updateSource = MainTM.getInstance().getConfig().getString(CF_UPDATEMSGSRC).toLowerCase();
		}
		// If the argument still doesn't exist or doesn't match with any expected case, use "CF_BUKKIT" as the default value
		if ((!updateSource.equalsIgnoreCase(ARG_CURSE))
				&& (!updateSource.equalsIgnoreCase(ARG_TWITCH))
				&& (!updateSource.equalsIgnoreCase(ARG_SPIGOT))
				&& (!updateSource.equalsIgnoreCase(ARG_PAPER))
				&& (!updateSource.equalsIgnoreCase(ARG_GITHUB))) {
			updateSource = ARG_BUKKIT;
		}
		UpdateHandler.checkForUpdate(sender, updateSource, false);
	}

	// In case of missing arg
	public static void cmdCheckUpdate(CommandSender sender) {
		cmdCheckUpdate(sender, null);
	}

}; public class TmReload extends MainTM {

	/**
	 * CMD /tm reload [all|config|lang|cmds]
	 */
	public static void cmdReload(CommandSender sender, String whatToReload) {

		// When do reload the config.yml file
		if (whatToReload.equalsIgnoreCase(ARG_CONFIG) || whatToReload.equalsIgnoreCase("conf") || whatToReload.equalsIgnoreCase("cfg") || whatToReload.equalsIgnoreCase("all")) {
			CfgFileHandler.loadConfig(ARG_RE);
			// Re-synchronize all the worlds based on a server constant point
			TmResync.cmdResync(Bukkit.getServer().getConsoleSender(), ARG_ALL);
			// Detect if this world needs to change its speed value
			SpeedHandler.speedScheduler(ARG_ALL);
			// 'config.yml is reloaded' notification
			MsgHandler.playerAdminMsg(sender, cfgFileReloadMsg); // Player final msg (in case)
			MsgHandler.infoMsg(cfgFileReloadMsg); // Console final msg (always)
			return;
		}		
		// When do reload the lang.yml file
		if (whatToReload.equalsIgnoreCase(ARG_LANG) || whatToReload.equalsIgnoreCase("languages") || whatToReload.equalsIgnoreCase("lg") || whatToReload.equalsIgnoreCase("all")) {
			LgFileHandler.loadLang(ARG_RE);
			// 'lang.yml is reloaded' notification
			MsgHandler.playerAdminMsg(sender, lgFileReloadMsg); // Player final msg (in case)
			MsgHandler.infoMsg(lgFileReloadMsg); // Console final msg (always)
			return;
		}		
		// When do reload the cmds.yml file
		if (whatToReload.equalsIgnoreCase(ARG_CMDS) || whatToReload.equalsIgnoreCase("commands") || whatToReload.equalsIgnoreCase("cmd") || whatToReload.equalsIgnoreCase("all")) {
			CmdsFileHandler.loadCmds(ARG_RE);
			// 'cmds.yml is reloaded' notification
			MsgHandler.playerAdminMsg(sender, cmdsFileReloadMsg); // Player final msg (in case)
			MsgHandler.infoMsg(cmdsFileReloadMsg); // Console final msg (always)
			return;
		}		
		// Else, return an error and help message
		MsgHandler.cmdErrorMsg(sender, wrongYmlMsg, "reload");
	}

}; public class TmResync extends MainTM {

	/**
	 * CMD /tm resync [all|world]
	 */
	public static void cmdResync(CommandSender sender, String world) {
		
		// Re-synchronize all worlds
		if (world.equalsIgnoreCase("all")) {
			// Relaunch this for each world
			for (String listedWorld : MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false)) {
				cmdResync(sender, listedWorld);
			}
		}		
		// Else, if the string argument is a listed world, re-synchronize a single world
		else if (MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false).contains(world)) {
			// Do the synchronization
			SyncHandler.worldSync(sender, world);
		}		
		// Else, return an error and display help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.wrongWorldMsg, MainTM.CMD_SET + " " + CMD_RESYNC);
		}
	}

}; public class TmSetDebugMode extends MainTM {

	/**
	 * CMD /tm set debugMode [true|false]
	 */
	public static void cmdDebugMode(CommandSender sender, String onOff) {

		// Check if the argument matches what is expected
		if (onOff.equalsIgnoreCase(ARG_TRUE) || onOff.equalsIgnoreCase(ARG_FALSE)) {
			MainTM.getInstance().getConfig().set(CF_DEBUGMODE, onOff);
			MainTM.getInstance().saveConfig();
			if (onOff.equalsIgnoreCase(ARG_TRUE)) {
				debugMode = true;
				MsgHandler.debugMsg(enableDebugModeDebugMsg); // Console debug msg (always)
				MsgHandler.playerAdminMsg(sender, enableDebugModeDebugMsg); // Player debug msg (in case)
			} else if (onOff.equalsIgnoreCase("false")) {
				MsgHandler.debugMsg(disableDebugModeDebugMsg); // Console debug msg (always)
				MsgHandler.playerAdminMsg(sender, disableDebugModeDebugMsg); // Player debug msg (in case)
				debugMode = false;
			}
		}
		// Else, return an error and help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.isNotBooleanMsg, MainTM.CMD_SET + " " + CMD_SET_DEBUG);
		}
	}

	/**
	 * CMD /tm set devMode [true|false]
	 */
	public static void cmdDevMode(CommandSender sender, String onOff) {

		// Check if the argument matches what is expected
		if (onOff.equalsIgnoreCase(ARG_TRUE) || onOff.equalsIgnoreCase(ARG_FALSE)) {
			if (onOff.equalsIgnoreCase(ARG_TRUE)) {
				devMode = true;
				MsgHandler.devMsg(enableDevModeDebugMsg); // Console dev msg (always)
				MsgHandler.playerAdminMsg(sender, enableDevModeDebugMsg); // Player dev msg (in case)
			} else if (onOff.equalsIgnoreCase("false")) {
				MsgHandler.devMsg(disableDevModeDebugMsg); // Console debug msg (always)
				MsgHandler.playerAdminMsg(sender, disableDevModeDebugMsg); // Player dev msg (in case) 
				devMode = false;
			}
		}
		// Else, return an error and help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.isNotBooleanMsg, MainTM.CMD_SET + " " + CMD_SET_DEV);
		}
	}

	/**
	 * CMD /tm set timerMode [true|false]
	 */
	public static void cmdTimerMode(CommandSender sender, String onOff) {

		// Check if the argument matches what is expected
		if (onOff.equalsIgnoreCase(ARG_TRUE) || onOff.equalsIgnoreCase(ARG_FALSE)) {
			if (onOff.equalsIgnoreCase(ARG_TRUE)) {
				timerMode = true;
				MsgHandler.timerMsg(enableTimerModeDebugMsg); // Console timer msg (always)
				MsgHandler.playerAdminMsg(sender, enableTimerModeDebugMsg); // Player timer msg (in case)
			} else if (onOff.equalsIgnoreCase("false")) {
				MsgHandler.timerMsg(disableTimerModeDebugMsg); // Console timer msg (always)
				MsgHandler.playerAdminMsg(sender, disableTimerModeDebugMsg); // Player timer msg (in case)
				timerMode = false;
			} 
		}
		// Else, return an error and help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.isNotBooleanMsg, MainTM.CMD_SET + " " + CMD_SET_TIMER);
		}
	}

}; public class TmSetDefLang extends MainTM {

	/**
	 * CMD /tm set defLang [lg_LG]
	 */
	public static void cmdDefLg(CommandSender sender, String newLang) {

		// Check if the argument matches what is expected
		if (MainTM.getInstance().langConf.getConfigurationSection(CF_LANGUAGES).getKeys(false).contains(newLang)) {
			MainTM.getInstance().langConf.set(CF_DEFAULTLANG, newLang);
			LgFileHandler.SaveLangYml();
			serverLang = newLang;
			MsgHandler.infoMsg(defLangCheckMsg + " " + newLang + "."); // Console final msg (always)
			MsgHandler.playerAdminMsg(sender, defLangCheckMsg + " §e" + newLang + "§r."); // Player final msg (in case)
		}
		// Else, return an error and help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.wrongLangMsg, MainTM.CMD_SET + " " + CMD_SET_DEFLANG);
		}
	}

}; public class TmSetInitialTick extends MainTM {

	/**
	 * CMD /tm set initialTick [tick|HH:mm:ss]
	 */
	public static void cmdInitTick(CommandSender sender, Long newTick) {

		// Get the previous initial tick value
		Long oldTick = MainTM.getInstance().getConfig().getLong(CF_INITIALTICK + "." + CF_INITIALTICKNB);
		newTick = ValuesConverter.correctInitTicks(newTick);
		Long sqlTick = null;
		if (MainTM.getInstance().getConfig().getString(CF_INITIALTICK + "." + CF_USEMYSQL).equals(ARG_TRUE)) {
			if (SqlHandler.openTheConnectionIfPossible(false)) {
				sqlTick = SqlHandler.getServerTickSQL();
			}
		}
		// Check if the new tick is different than the old one
		if (!newTick.equals(oldTick) && !newTick.equals(sqlTick)) {
			// Adapt the value
			initialTick = newTick;
			initialTime = ValuesConverter.realFormattedTimeFromTick(initialTick);

			// Save the value in the config.yml
			MainTM.getInstance().getConfig().set(CF_INITIALTICK + "." + CF_INITIALTICKNB, initialTick);
			MainTM.getInstance().saveConfig();
			if (MainTM.getInstance().getConfig().getString(CF_USEMYSQL).equalsIgnoreCase(ARG_FALSE)) {
				MsgHandler.infoMsg(MsgHandler.prefixTM + " " + initialTickYmlMsg); // Notify the console
			}
			// Save the value in the yml and if necessary in the MySql database
			// Try to use MySQL if needed
			if (MainTM.getInstance().getConfig().getString(CF_USEMYSQL).equalsIgnoreCase(ARG_TRUE)) { // If mySQL is true
				if (SqlHandler.openTheConnectionIfPossible(true)) {
					SqlHandler.updateServerTickSQL(newTick); // Set the reference tick from the config.yml to the mySQL
					// database
					MsgHandler.infoMsg(MsgHandler.prefixTM + " " + initialTickSqlMsg); // Notify the console
				}
			}
			// Resynchronization
			SyncHandler.worldSync(sender, ARG_ALL);

		} else {
			// Notifications
			MsgHandler.playerAdminMsg(sender, initialTickNoChgMsg); // Notify the player (in case)
			MsgHandler.infoMsg(initialTickNoChgMsg); // Notify the console (in case)
		}
	}
}; public class TmSetMultiLang extends MainTM {

	/**
	 * CMD /tm set multiLang [true|false]
	 */
	public static void cmdMultiLg(CommandSender sender, String onOff) {

		// Check if the argument matches what is expected
		if (onOff.equalsIgnoreCase(ARG_TRUE) || onOff.equalsIgnoreCase(ARG_FALSE)) {
			MainTM.getInstance().langConf.set(CF_USEMULTILANG, onOff);
			LgFileHandler.SaveLangYml();
			if (onOff.equalsIgnoreCase(ARG_TRUE)) {
				MsgHandler.infoMsg(multiLangIsOnMsg); // Console final msg (always)
				MsgHandler.playerAdminMsg(sender, multiLangIsOnMsg); // Player final msg (in case)
			} else if (onOff.equalsIgnoreCase(ARG_FALSE)) {
				MsgHandler.infoMsg(multiLangIsOffMsg); // Console final msg (always)
				MsgHandler.playerAdminMsg(sender, multiLangIsOffMsg); // Player final msg (in case)
			}
		}
		// Else, return an error and help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.isNotBooleanMsg, MainTM.CMD_SET + " " + CMD_SET_MULTILANG);
		}
	}

}; public class TmSetPlayerOffset extends MainTM {

	/**
	 * CMD /tm set playerOffset [-23999 → 23999] [all|player]
	 */
	public static void cmdSetPlayerOffset(CommandSender sender, long offset, String player, boolean timechange) {
		
		// Limit the offset to one day
		offset = offset % 24000;
		
		// Modify all players time
		if (player.equalsIgnoreCase(ARG_ALL)) {
			// Relaunch this for each world
			for (Player listedPlayer : Bukkit.getOnlinePlayers()) {
				String listedPlayerName = listedPlayer.getName();
				cmdSetPlayerOffset(sender, offset, listedPlayerName, timechange);
			}
		} // Else, if the string argument is an online player, modify a single player time
		else {
			Player p = Bukkit.getPlayer(player);
			if (p != null) {
				if (offset != 0) {
					p.setPlayerTime(offset, true);
					// Notifications
					long tick = p.getPlayerTime();
					tick = ValuesConverter.correctDailyTicks(tick);
					String time = ValuesConverter.formattedTimeFromTick(tick);
					if (timechange) {
						MsgHandler.infoMsg(playerTimeChgMsg1 + " " + player + " " + playerTimeChgMsg2 + " tick #" + tick + " (" + time + ")."); // Console final msg (always)
						MsgHandler.playerAdminMsg(sender, playerTimeChgMsg1 + " §e" + player + "§r " + playerTimeChgMsg2 + " §etick #" + tick + " §r(§e" + time + "§r)."); // Player final msg (in case)	
					} else {
						MsgHandler.infoMsg(playerOffsetChgMsg1 + " " + player + " " + playerTimeChgMsg2 + " " + offset + "."); // Console final msg (always)
						MsgHandler.playerAdminMsg(sender, playerOffsetChgMsg1 + " §e" + player + "§r " + playerTimeChgMsg2 + " §e" + offset + "§r."); // Player final msg (in case)
					}
				} else {
					p.resetPlayerTime();
					// Notifications
					if (timechange) {
						MsgHandler.infoMsg(playerTimeChgMsg1 + " " + player + " " + playerTimeResetMsg2); // Console final msg (always)
						MsgHandler.playerAdminMsg(sender, playerTimeChgMsg1 + " §e" + player + "§r " + playerTimeResetMsg2); // Player final msg (in case)	
					} else {
						MsgHandler.infoMsg(playerOffsetChgMsg1 + " " + player + " " + playerTimeResetMsg2); // Console final msg (always)
						MsgHandler.playerAdminMsg(sender, playerOffsetChgMsg1 + " §e" + player + "§r " + playerTimeResetMsg2); // Player final msg (in case)
					}
				}
			} // Else, return an error and help message
			else {
				if (timechange) {
					MsgHandler.cmdErrorMsg(sender, MainTM.playerFormatMsg, MainTM.CMD_SET + " " + CMD_SET_PLAYERTIME);
				} else {
					MsgHandler.cmdErrorMsg(sender, MainTM.playerFormatMsg, MainTM.CMD_SET + " " + CMD_SET_PLAYEROFFSET);
				}
			}
		}
	}

}; public class TmSetPlayerTime extends MainTM {

	/**
	 * CMD /tm set playerTime [tick|daypart|HH:mm:ss|reset] [all|player]
	 */
	public static void cmdSetPlayerTime(CommandSender sender, long tick, String player, boolean reset) {

		// Adapt wrong values in the arg
		tick = ValuesConverter.correctDailyTicks(tick);

		// Calculate an offset based on wanted tick
		Player p = Bukkit.getPlayer(player);
		World w = p.getWorld();
		long worldtime = w.getTime(); 
		long offset = tick - worldtime;
		if (reset) offset = 0L;

		// Use the offset method
		TmSetPlayerOffset.cmdSetPlayerOffset(sender, offset, player, true);
	}

}; public class TmSetRefreshRate extends MainTM {

	/**
	 * CMD /tm set refreshRate [ticks]
	 */
	public static void cmdRefRate(CommandSender sender, Integer refreshRate) {

		// Adapt wrong values
		refreshRate = ValuesConverter.correctRefreshRate(refreshRate);

		MainTM.getInstance().getConfig().set(CF_REFRESHRATE, refreshRate);
		MainTM.getInstance().saveConfig();

		// Notifications
		MsgHandler.playerAdminMsg(sender, refreshRateMsg + " §e" + refreshRate + " ticks§r."); // Notify the player (in case)
		MsgHandler.infoMsg(MsgHandler.prefixTM + " " + refreshRateMsg + " " + refreshRate + " ticks."); // Notify the console (always)
	}

}; public class TmSetFullTime extends MainTM {

	/**
	 * CMD /tm set elapsedDays [today|number] [world]
	 */
	public static void cmdSetDay(CommandSender sender, long elapsedDays, String world) {
		
		// Adapt wrong values in the arg
		if (elapsedDays < 0 ) elapsedDays = 0L;

		// Modify all worlds
		if (world.equalsIgnoreCase(ARG_ALL)) {
			// Relaunch this for each world
			for (String w : MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false)) {
				cmdSetDay(sender, elapsedDays, w);
			}
		}
		// Else, if the string argument is a listed world, modify a single world
		else if (MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false).contains(world)) {
			// Modify targeted world's timer
			World w = Bukkit.getWorld(world);
			long t = w.getTime();
			long tickToSet = (elapsedDays * 24000) + t;
			if (elapsedDays > 0 && t > 18000 && MainTM.getInstance().getConfig().getString(CF_NEWDAYAT).equalsIgnoreCase(newDayStartsAt_0h00)) {
				tickToSet = tickToSet - 24000;
			}
			w.setFullTime(tickToSet);
			// Notifications
			if (elapsedDays == 0 && t > 18000 && MainTM.getInstance().getConfig().getString(CF_NEWDAYAT).equalsIgnoreCase(newDayStartsAt_0h00)) {
				String hour = ValuesConverter.formattedTimeFromTick(t);
				MsgHandler.infoMsg(tooLateForDayZeroMsg1 + hour + tooLateForDayZeroMsg2); // Console final msg (always)
				MsgHandler.playerAdminMsg(sender, tooLateForDayZeroMsg1 + "§e" + hour + "§r" + tooLateForDayZeroMsg2); // Console final msg (always)
			}
			elapsedDays = ValuesConverter.elapsedDaysFromTick(w.getFullTime());
			String date = ValuesConverter.dateFromElapsedDays(elapsedDays, PH_YYYY) + "-" + ValuesConverter.dateFromElapsedDays(elapsedDays, PH_MM) + "-" + ValuesConverter.dateFromElapsedDays(elapsedDays, PH_DD);
			MsgHandler.infoMsg(worldFullTimeChgMsg + " " + world + " " + worldTimeChgMsg2 + " #" + elapsedDays + " (" + date + ")."); // Console final msg (always)
			MsgHandler.playerAdminMsg(sender, worldFullTimeChgMsg + " §e" + world + "§r " + worldTimeChgMsg2 + " §e#" + elapsedDays + " §r(§e" + date + "§r)."); // Player final msg (in case)
		}
		// Else, return an error and help message
		else MsgHandler.cmdErrorMsg(sender, MainTM.wrongWorldMsg, MainTM.CMD_SET + " " + CMD_SET_E_DAYS);
	}

	/**
	 * CMD /tm set date [yyyy-mm-dd] [world]
	 */
	public static void cmdSetDate(CommandSender sender, String date, String world) {
		
		// Modify all worlds
		if (world.equalsIgnoreCase(ARG_ALL)) {
			// Relaunch this for each world
			for (String w : MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false)) {
				cmdSetDate(sender, date, w);
			}
		}
		// Else, if the string argument is a listed world, modify a single world
		else if (MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false).contains(world)) {
			Long tick = ValuesConverter.tickFromFormattedDate(date);
			Long elapsedDays = ValuesConverter.elapsedDaysFromTick(tick);
			cmdSetDay(sender, elapsedDays, world);
		}
		// Else, return an error and help message
		else MsgHandler.cmdErrorMsg(sender, MainTM.wrongWorldMsg, MainTM.CMD_SET + " " + CMD_SET_DATE);
	}

}; public class TmSetSpeed extends MainTM {

	/**
	 * CMD /tm set speed [multiplier] [world]
	 * CMD /tm set speedDay [multiplier] [world]
	 * CMD /tm set speedNight [multiplier] [world]
	 */
	public static void cmdSetSpeed(CommandSender sender, double speed, String when, String world) {

		// Adapt wrong values in the arg
		speed = ValuesConverter.correctSpeed(speed);

		// Modify all worlds
		if (world.equalsIgnoreCase(ARG_ALL)) {
			// Relaunch this for each world
			for (String listedWorld : MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false)) {
				cmdSetSpeed(sender, speed, when, listedWorld);
			}
		}
		// Else, if the string argument is a listed world, modify a single world
		else if (MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false).contains(world)) {
			// Get the old speed value of this world to correctly resynchronize 24h worlds
			long t = Bukkit.getWorld(world).getTime();
			Double oldSpeed = MainTM.getInstance().getConfig().getDouble(CF_WORLDSLIST + "." + world + "." + ValuesConverter.wichSpeedParam(t));
			// Modify the speed in the config    
			if (when.equalsIgnoreCase(CMD_SET_SPEED) || speed == 24.0) {
				MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_D_SPEED, speed);
				MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_N_SPEED, speed);
			} else if (when.equalsIgnoreCase(CMD_SET_D_SPEED)) {
				MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_D_SPEED, speed);	
			} else if (when.equalsIgnoreCase(CMD_SET_N_SPEED)) {
				MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_N_SPEED, speed);	
			}
			// Restrain the sleep value
			ValuesConverter.restrainSleep(world);
			// Restrain the sync value
			ValuesConverter.restrainSync(world, oldSpeed);
			// Do daylightCycle change if needed
			DoDaylightCycleHandler.adjustDaylightCycle(world);
			// Save the config
			MainTM.getInstance().saveConfig();
			// Detect if this world needs to change its speed value
			MsgHandler.debugMsg(launchSchedulerDebugMsg); // Console debug msg
			SpeedHandler.speedScheduler(world);

			// Notifications
			if (speed == realtimeSpeed) { // Display realtime message (speed = 24.00)
				MsgHandler.infoMsg(worldSpeedChgIntro + " " + world + " " + worldRealSpeedChgMsg); // Console final msg (always)
				MsgHandler.playerAdminMsg(sender, worldSpeedChgIntro + " §e" + world + " §r" + worldRealSpeedChgMsg); // Player final msg (in case)

			} else { // Display usual message (any speed but 24.00)
				if (when.equalsIgnoreCase(CMD_SET_SPEED)) {
					MsgHandler.infoMsg(worldSpeedChgIntro + " " + world + " " + worldSpeedChgMsg + " " + speed + "."); // Console final msg (always)
					MsgHandler.playerAdminMsg(sender, worldSpeedChgIntro + " §e" + world + " §r" + worldSpeedChgMsg + " §e" + speed + "§r."); // Player final msg (in case)

				} else if (when.equalsIgnoreCase(CMD_SET_D_SPEED)) {
					MsgHandler.infoMsg(worldDaySpeedChgIntro + " " + world + " " + worldSpeedChgMsg + " " + speed + "."); // Console final msg (always)
					MsgHandler.playerAdminMsg(sender, worldDaySpeedChgIntro + " §e" + world + " §r" + worldSpeedChgMsg + " §e" + speed + "§r."); // Player final msg (in case)

				} else if (when.equalsIgnoreCase(CMD_SET_N_SPEED)) {
					MsgHandler.infoMsg(worldNightSpeedChgIntro + " " + world + " " + worldSpeedChgMsg + " " + speed + "."); // Console final msg (always)
					MsgHandler.playerAdminMsg(sender, worldNightSpeedChgIntro + " §e" + world + " §r" + worldSpeedChgMsg + " §e" + speed + "§r."); // Player final msg (in case)

				}
			}
		}
		// Else, return an error and help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.wrongWorldMsg, MainTM.CMD_SET + " " + CMD_SET_SPEED);
		}
	}


	/**
	 * CMD /tm set speed [multiplier] [world]
	 */
	public static void cmdSetSpeed(CommandSender sender, double speed, String world) {
		cmdSetSpeed(sender, speed, CMD_SET_SPEED, world);
	}
}; public class TmSetStart extends MainTM {

	/**
	 * CMD /tm set start [tick|daypart|HH:mm:ss] [world]
	 */
	public static void cmdSetStart(CommandSender sender, long tick, String world) {
		
		// Adapt wrong values in the arg
		tick = ValuesConverter.correctDailyTicks(tick);

		// Modify all worlds
		if (world.equalsIgnoreCase(ARG_ALL)) {
			// Relaunch this for each world
			for (String listedWorld : MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false)) {
				cmdSetStart(sender, tick, listedWorld);
			}		
		// Else, if the string argument is a listed world, modify a single world
		} else if (MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false).contains(world)) {
			// Adapt wrong values
			World w = Bukkit.getWorld(world);
			long t = w.getTime();
			double currentSpeed = MainTM.getInstance().getConfig().getDouble(CF_WORLDSLIST + "." + world + "." + ValuesConverter.wichSpeedParam(t));
			if (currentSpeed == realtimeSpeed) {
				tick = ValuesConverter.getUTCShiftFromTick(tick) * 1000;
			} else {
				tick = tick % 24000;
			}
			// Modify and save the start tick in the config.yml
			MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_START, tick);
			MainTM.getInstance().saveConfig();
			// Resync this world
			SyncHandler.worldSync(sender, world);
			// Notifications
			Bukkit.getLogger().info(MsgHandler.prefixTM + " " + worldStartChgMsg1 + " " + world + " " + worldStartChgMsg2); // Console final msg (always)
			MsgHandler.playerAdminMsg(sender, worldStartChgMsg1 + " §e" + world + "§r " + worldStartChgMsg2); // Player final msg (in case)
		}
		// Else, return an error and display help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.wrongWorldMsg, MainTM.CMD_SET + " " + CMD_SET_START);
		}
	}

}; public class TmSetSleep extends MainTM {

	/**
	 * CMD /tm set sleep [true|false|linked] [world]
	 */
	public static void cmdSetSleep(CommandSender sender, String sleepValue, String world) {

		// Modify all worlds
		if (world.equalsIgnoreCase(ARG_ALL)) {
			// Relaunch this for each world
			for (String listedWorld : MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false)) {
				cmdSetSleep(sender, sleepValue, listedWorld);
			}
		}
		// Else, if the string argument is a listed world, modify a single world
		else if (MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false).contains(world)) {
			// Avoid impossible values
			if (!sleepValue.equalsIgnoreCase(ARG_TRUE) && !sleepValue.equalsIgnoreCase(ARG_LINKED)) sleepValue = ARG_FALSE;
			World w = Bukkit.getWorld(world);
			long t = w.getTime();
			String currentSpeed = MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + ValuesConverter.wichSpeedParam(t));
			if ((sleepValue.equalsIgnoreCase(ARG_TRUE) || (sleepValue.equalsIgnoreCase(ARG_LINKED)) && (currentSpeed.equals("24.0")))) {
				// Notifications
				MsgHandler.infoMsg(worldSleepNoChgMsg + " " + world + "."); // Console final msg (always)
				MsgHandler.playerAdminMsg(sender, worldSleepNoChgMsg + " §e" + world + "§r."); // Player final msg (in case)
			} else {
				// Modify the value
				MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_SLEEP, sleepValue);
				// Avoid to synchronize worlds where players can sleep
				if ((sleepValue.equalsIgnoreCase(ARG_TRUE) || sleepValue.equalsIgnoreCase(ARG_LINKED)) && MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + CF_SYNC).equals(ARG_TRUE)) {
					MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_SYNC, ARG_FALSE);
					MsgHandler.infoMsg("The world " + world + " " + sleepWorldSyncChgMsg); // Console warn msg (always)
					MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r " + sleepWorldSyncChgMsg); // Player warn msg (in case)
				}
				// Save the value(s) in the config.yml
				MainTM.getInstance().saveConfig();
				// Notifications
				if (sleepValue.equalsIgnoreCase(ARG_TRUE)) {
					MsgHandler.infoMsg(worldSleepTrueChgMsg + " " + world + "."); // Console final msg (always)
					MsgHandler.playerAdminMsg(sender, worldSleepTrueChgMsg + " §e" + world + "§r."); // Player final msg (in case)
				} else if (sleepValue.equalsIgnoreCase(ARG_LINKED)) {
					MsgHandler.infoMsg(worldSleepTrueChgMsg + " " + world + ". " + worldSleepLinkedChgMsg); // Console final msg (always)
					MsgHandler.playerAdminMsg(sender, worldSleepTrueChgMsg + " §e" + world + "§r. " + worldSleepLinkedChgMsg); // Player final msg (in case)
				} else if (sleepValue.equalsIgnoreCase(ARG_FALSE)) {
					MsgHandler.infoMsg(worldSleepFalseChgMsg + " " + world + "."); // Console final msg (always)
					MsgHandler.playerAdminMsg(sender, worldSleepFalseChgMsg + " §e" + world + "§r."); // Player final msg (in case)
				}
			}
		}
		// Else, return an error and help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.wrongWorldMsg, MainTM.CMD_SET + " " + MainTM.CMD_SET_SLEEP);
		}
	}

}; public class TmSetSync extends MainTM {

	/**
	 * CMD /tm set sync [boolean] [world]
	 */
	public static void cmdSetSync(CommandSender sender, String syncOrNo, String world) {
		
		// Modify all worlds
		if (world.equalsIgnoreCase(ARG_ALL)) {
			// Relaunch this for each world
			for (String listedWorld : MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false)) {
				cmdSetSync(sender, syncOrNo, listedWorld);
			}
		}
		// Else, if the string argument is a listed world, modify a single world
		else if (MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false).contains(world)) {			
			// Avoid impossible values
			World w = Bukkit.getWorld(world);
			long t = w.getTime();
			String speed = MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + ValuesConverter.wichSpeedParam(t));
			if (speed.equals("0.0") || speed.equals("24.0")) {
				// Notifications
				MsgHandler.infoMsg(worldSyncNoChgMsg + " " + world + "."); // Console final msg (always)
				MsgHandler.playerAdminMsg(sender, worldSyncNoChgMsg + " §e" + world + "§r."); // Player final msg (in case)				
			} else {
				// Modify the value
				MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_SYNC, syncOrNo);
				// If sync is true, make some changes
				if (syncOrNo.equals(ARG_TRUE)) {
					// Detect if this world needs to change its speed value
					SpeedHandler.speedScheduler(world);
					// Avoid players to sleep in a synchronized world
					if (!MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + CF_SLEEP).equals(ARG_FALSE)) {
						MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_SLEEP, ARG_FALSE);
						MsgHandler.infoMsg("The world " + world + " " + worldSyncSleepChgMsg); // Console warn msg (always)
						MsgHandler.playerAdminMsg(sender, "The world §e" + world + "§r " + worldSyncSleepChgMsg); // Player warn msg (in case)
					}
				}				
				// Save the value(s) in the config.yml
				MainTM.getInstance().saveConfig();				
				// Notifications
				if (syncOrNo.equals(ARG_TRUE)) {
					MsgHandler.infoMsg(worldSyncTrueChgMsg + " " + world + "."); // Console final msg (always)
					MsgHandler.playerAdminMsg(sender, worldSyncTrueChgMsg + " §e" + world + "§r."); // Player final msg (in case)
				} else if (syncOrNo.equals(ARG_FALSE)) {
					MsgHandler.infoMsg(worldSyncFalseChgMsg + " " + world + "."); // Console final msg (always)
					MsgHandler.playerAdminMsg(sender, worldSyncFalseChgMsg + " §e" + world + "§r."); // Player final msg (in case)
				}
			}
		}
		// Else, return an error and help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.wrongWorldMsg, MainTM.CMD_SET + " " + CMD_SET_SYNC);
		}
	}

}; public class TmSetTime extends MainTM {

	/**
	 * CMD /tm set time [tick|daypart|HH:mm:ss] [world]
	 */
	public static void cmdSetTime(CommandSender sender, long tick, String world) {
		
		// Adapt wrong values in the arg
		tick = ValuesConverter.correctDailyTicks(tick);

		// Modify all worlds
		if (world.equalsIgnoreCase(ARG_ALL)) {
			// Relaunch this for each world
			for (String listedWorld : MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false)) {
				cmdSetTime(sender, tick, listedWorld);
			}
		}
		// Else, if the string argument is a listed world, modify a single world
		else if (MainTM.getInstance().getConfig().getConfigurationSection(CF_WORLDSLIST).getKeys(false).contains(world)) {
			World w = Bukkit.getWorld(world);
			// Avoid real time worlds
			long s = MainTM.getInstance().getConfig().getLong(CF_WORLDSLIST + "." + world + "." + ValuesConverter.wichSpeedParam(w.getTime()));
			if (s == 24) {
				MsgHandler.infoMsg("The time of the world " + world + " " + worldRealSyncTimeChgMsg); // Console warn msg (always)
				MsgHandler.playerAdminMsg(sender, "The time of the world " + world + " " + worldRealSyncTimeChgMsg); // Player warn msg (in case)
			// Check if sync is activated for this world if true, calculate an equivalent "start" value
			} else if (MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + CF_SYNC).equalsIgnoreCase(ARG_TRUE)) {
				long oldStartNb = (MainTM.getInstance().getConfig().getLong(CF_WORLDSLIST + "." + world + "." + CF_START));
				long currentTime = w.getTime();
				long startTickToSet = (ValuesConverter.correctDailyTicks(oldStartNb + tick - currentTime));
				// Debug messages
				MsgHandler.debugMsg("SetTime >>> SetStart: Calculation of " + worldStartAtVar + " for world §e" + world + "§b:");
				MsgHandler.debugMsg(worldStartAtCalculation + " = §3" + oldStartNb + "§b + §8" + tick + "§b - §c" + currentTime + "§b = §e" + (oldStartNb + tick - currentTime) + "§b restrained to one day = §etick #" + startTickToSet);
				// Notifications
				MsgHandler.infoMsg("The world " + world + " " + worldSyncTimeChgMsg); // Console warn msg (always)
				MsgHandler.playerAdminMsg(sender, "The world " + world + " " + worldSyncTimeChgMsg); // Player warn msg (in case)
				// Change the 'start' value
				TmSetStart.cmdSetStart(sender, startTickToSet, world);
			} else { // If false, do the usual time change
				w.setTime(tick);
				// Detect if this world needs to change its speed value
				SpeedHandler.speedScheduler(world);
				// Adjust doDaylightCycle value
				DoDaylightCycleHandler.adjustDaylightCycle(world);
				// Notifications
				String timeToSet = ValuesConverter.formattedTimeFromTick(tick);
				MsgHandler.infoMsg(worldTimeChgMsg1 + " " + world + " " + worldTimeChgMsg2 + " tick #" + tick + " (" + timeToSet + ")."); // Console final msg (always)
				MsgHandler.playerAdminMsg(sender, worldTimeChgMsg1 + " §e" + world + "§r " + worldTimeChgMsg2 + " §etick #" + tick + " §r(§e" + timeToSet + "§r)."); // Player final msg (in case)
			}
		}
		// Else, return an error and help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.wrongWorldMsg, MainTM.CMD_SET + " " + CMD_SET_TIME);
		}
	}

}; public class TmSetUpdateMsgSrc extends MainTM {

	/**
	 * CMD /tm set update [none|bukkit|spigot|github]
	 */
	public static void cmdSetUpdateSrc(CommandSender sender, String updateSource) {

		// Check if the argument matches what is expected
		if (updateSource.equalsIgnoreCase(ARG_BUKKIT)
				|| updateSource.equalsIgnoreCase(ARG_CURSE)
				|| updateSource.equalsIgnoreCase(ARG_TWITCH)
				|| updateSource.equalsIgnoreCase(ARG_SPIGOT)
				|| updateSource.equalsIgnoreCase(ARG_PAPER)
				|| updateSource.equalsIgnoreCase(ARG_GITHUB)) {

			// Format the configuration value
			updateSource = updateSource.replaceFirst(".", (updateSource.charAt(0) + "").toUpperCase());
			MainTM.getInstance().getConfig().set(CF_UPDATEMSGSRC, updateSource);

			MsgHandler.infoMsg(updateEnableCheckMsg + " " + updateSource + " as the source."); // Console final msg (always)
			MsgHandler.playerAdminMsg(sender, updateEnableCheckMsg + " §e" + updateSource + "§r as the source."); // Player final msg (in case)

		} // Disable auto update if the updateSource is false, void or unknown
		else { 
			MainTM.getInstance().getConfig().set(CF_UPDATEMSGSRC, defUpdateMsgSrc);

			MsgHandler.infoMsg(updateDisableCheckMsg + " disable."); // Console final msg (always)
			MsgHandler.playerAdminMsg(sender, updateDisableCheckMsg + "§e disable§r."); // Player final msg (in case)
		}
		// Save changes in config.yml
		MainTM.getInstance().saveConfig();
	}

}; public class TmSetUseCmds extends MainTM {

	/**
	 * CMD /tm set useCmds [true|false]
	 */
	public static void cmdUseCmds(CommandSender sender, String onOff) {

		// Check if the argument matches what is expected
		if (onOff.equalsIgnoreCase(ARG_TRUE) || onOff.equalsIgnoreCase(ARG_FALSE)) {
			MainTM.getInstance().getConfig().set(CMD_SET_USECMDS, onOff);
			MainTM.getInstance().saveConfig();
			if (onOff.equalsIgnoreCase(ARG_TRUE)) {
				debugMode = true;
				MsgHandler.colorMsg(enableCmdsSchedulerDebugMsg); // Console debug msg (always)
				MsgHandler.playerAdminMsg(sender, enableCmdsSchedulerDebugMsg); // Player debug msg (in case)
			} else if (onOff.equalsIgnoreCase(ARG_FALSE)) {
				MsgHandler.colorMsg(disableCmdsSchedulerDebugMsg); // Console debug msg (always)
				MsgHandler.playerAdminMsg(sender, disableCmdsSchedulerDebugMsg); // Player debug msg (in case)
				debugMode = false;
			}
		}
		// Else, return an error and help message
		else {
			MsgHandler.cmdErrorMsg(sender, MainTM.isNotBooleanMsg, MainTM.CMD_SET + " " + CMD_SET_USECMDS);
		}
	}

}; public class MsgHandler extends MainTM {

	/**
	 * Info msg
	 */
	public static void infoMsg(String msg) {
		Bukkit.getLogger().info(MainTM.prefixTM + " " + msg);
	}

	/**
	 * Warning msg
	 */
	public static void warnMsg(String msg) {
		Bukkit.getLogger().warning(MainTM.prefixTM + " " + msg);
	}

	/**
	 * Error msg
	 */
	public static void errorMsg(String msg) {
		Bukkit.getLogger().severe(MainTM.prefixTM + " " + msg);
	}

	/**
	 * Colored msg
	 */
	public static void colorMsg(String msg) {
		Bukkit.getServer().getConsoleSender().sendMessage(MainTM.prefixTM + " " + msg);
	}

	/**
	 * Command error message and its associated help message
	 */
	public static void cmdErrorMsg(CommandSender sender, String msgError, String cmdHelp) {
		playerAdminMsg(sender, "§c" + msgError); // Player error msg (in case is player)
		warnMsg(msgError); // Console error msg (always)
		Bukkit.dispatchCommand(sender, "tm help " + cmdHelp); // Sender help msg (always)
	}

	/**
	 * Debug msg
	 */
	public static void debugMsg(String msg) {
		if (debugMode) Bukkit.getServer().getConsoleSender().sendMessage(prefixDebugMode + " " + msg);
	}

	/**
	 * Dev msg
	 */
	public static void devMsg(String msg) {
		if (devMode) Bukkit.getServer().getConsoleSender().sendMessage(prefixDebugMode + "§9 " + msg);
	}

	/**
	 * Timer msg
	 */
	public static void timerMsg(String msg) {
		if (timerMode) Bukkit.getServer().getConsoleSender().sendMessage(prefixDebugMode + "§5 " + msg);
	}

	/**
	 * Admin msg
	 */
	public static void playerAdminMsg(CommandSender sender, String msg) {
		if (sender instanceof Player) sender.sendMessage(prefixTMColor + " " + msg);
		else if (sender instanceof CommandBlock) sender.sendMessage(prefixTM + " " + msg);
	}

	/**
	 * Player chat msg
	 */
	public static void playerChatMsg(Player p, String prefix, String msg) {
		p.sendMessage(prefix + "§r " + msg);
	}

	/**
	 * Player title msg
	 */
	@SuppressWarnings("deprecation")
	public static void playerTitleMsg(Player p, String title, String subtitle) {
		int fadeIn = MainTM.getInstance().langConf.getInt(CF_TITLES + "." + CF_FADEIN);
		int stay = MainTM.getInstance().langConf.getInt(CF_TITLES + "." + CF_STAY);
		int fadeOut = MainTM.getInstance().langConf.getInt(CF_TITLES + "." + CF_FADEOUT);
		if (serverMcVersion >= reqMcVForNewSendTitleMsg) p.sendTitle(title, subtitle, fadeIn, stay, fadeOut);
		else p.sendTitle(title, subtitle);
	}
	
	/**
	 * Player action bar msg
	 */
	public static void playerActionbarMsg(Player p, String msg) {
		// Up to MC 1.8
		if (serverMcVersion < reqMcVForActionbarMsg) {
			MsgHandler.infoMsg(noActionbarMsg);
		// CraftBukkit since MC 1.9
		} else if (serverType.equalsIgnoreCase(ARG_BUKKIT)) {
			ConsoleCommandSender console = Bukkit.getServer().getConsoleSender();
			String command = ARG_TITLE + " " + p.getName() + " " + ARG_ACTIONBAR + " \"" + msg + "\"";
			Bukkit.dispatchCommand(console, command);
		// Spigot and forks since MC 1.9
		} else {
			HiddenClassHandler.playerActionbarMsg(p, msg);
		}
	}

}; public class ValuesConverter extends MainTM {

	/**
	 * Checks and corrects any 'speed' value
	 * (returns a double)
	 */
	public static double correctSpeed(double speed) {
		if (speed != realtimeSpeed) { // Don't modify the real time value
			if (speed > speedMax) { // Forbid too big numbers
				speed = speedMax;
			} else if (speed < 0) { // Forbid too small numbers
				speed = 0.0;
			}
		}
		return speed;
	}

	/**
	 * Checks and corrects the 'refreshRate' value
	 * (returns an integer)
	 */
	public static Integer correctRefreshRate(int newRefreshRate) {
		if (newRefreshRate > refreshMax) { // Forbid too big numbers
			newRefreshRate = refreshMax;
		} else if (newRefreshRate < refreshMin) {
			newRefreshRate = refreshMin; // Forbid too small numbers
		}
		return newRefreshRate;
	}

	/**
	 * Converts a decimal to a fraction, to produce the speed change with the ratio between the time to add and the refresh rate
	 * (returns a Long)
	 */
	public static Long fractionFromDecimal(Double currentSpeed, String value) {
		Long modifTime = 0L;
		Long refreshRate = 0L;
		if (currentSpeed >= 0.9) {
			modifTime = 10L;
			refreshRate = 11L;
		} else if (currentSpeed >= 0.8) {
			modifTime = 5L;
			refreshRate = 6L;
		} else if (currentSpeed >= 0.7) {
			modifTime = 5L;
			refreshRate = 7L;
		} else if (currentSpeed >= 0.65) {
			modifTime = 2L;
			refreshRate = 3L;
		} else if (currentSpeed >= 0.6) {
			modifTime = 5L;
			refreshRate = 8L;
		} else if (currentSpeed >= 0.55) {
			modifTime = 5L;
			refreshRate = 9L;
		} else if (currentSpeed >= 0.5) {
			modifTime = 4L;
			refreshRate = 8L;
		} else if (currentSpeed >= 0.45) {
			modifTime = 5L;
			refreshRate = 11L;
		} else if (currentSpeed >= 0.4) {
			modifTime = 2L;
			refreshRate = 5L;
		} else if (currentSpeed >= 0.3) {
			modifTime = 2L;
			refreshRate = 6L;
		} else if (currentSpeed >= 0.25) {
			modifTime = 2L;
			refreshRate = 8L;
		} else if (currentSpeed >= 0.2) {
			modifTime = 2L;
			refreshRate = 10L;
		} else if (currentSpeed >= 0.1) {
			modifTime = 1L;
			refreshRate = 10L;
		} else if (currentSpeed > 0.05) {
			modifTime = 1L;
			refreshRate = 15L;
		} else if (currentSpeed <= 0.05) {
			modifTime = 1L;
			refreshRate = 20L;
		}
		if (value.equalsIgnoreCase("modifTime")) return modifTime;
		else if (value.equalsIgnoreCase("refreshRate")) return refreshRate;
		else return null;
	}

	/**
	 * Checks and corrects any 'start' or 'time' tick value
	 * (returns a long)
	 */
	public static long correctDailyTicks(long time) {
		time = ((time % 24000) + 24000) % 24000; // Forbid numbers lower than 0 and higher than 23999 (= end of the MC day)
		return time;
	}

	/**
	 * Checks and corrects the 'initialTickNb' tick value
	 * (returns a long)
	 */
	public static long correctInitTicks(long time) {
		time = ((time % 1728000) + 1728000) % 1728000; // Forbid numbers lower than 0 and higher than 727999 (= end of the real day)
		return time;
	}

	/**
	 * Checks and corrects the 'wakeUpTick' tick value
	 * (returns a long)
	 */
	public static long correctwakeUpTick(long time) {
		if (time > 6000) time = 6000L;// Forbid numbers higher than 6000
		if (time < 0) time = 0L; // Forbid numbers smaller than 0
		return time;
	}

	/**
	 * Converts a tick in its related part of the day (MC names)
	 * (returns a String)
	 */
	public static String getMCDayPart(long tick) {
		String wichPart;
		if (tick >= dawnStart && tick < dayStart) {
			wichPart = "dawn";
		} else if (tick >= dayStart && tick < duskStart) {
			wichPart = "day";
		} else if (tick >= duskStart && tick < nightStart) {
			wichPart = "dusk";
		} else {
			wichPart = "night";
		}
		return wichPart;
	}

	/**
	 * Converts a tick in its related part of the day (AM/PM)
	 * (returns a String)
	 */
	public static String getAmPm(long tick) {
		String wichPart;
		if (tick >= 6000 && tick < 18000) {
			wichPart = "PM";
		} else {
			wichPart = "AM";
		}
		return wichPart;
	}

	/**
	 * Gets the correct speed value's name (daySpeed or nightSpeed) for a given tick
	 * (returns a String)
	 */
	public static String wichSpeedParam(long tick) {
		String speedParam;
		if (getMCDayPart(tick).equalsIgnoreCase("night")) {	    
			speedParam = CF_N_SPEED;
		} else {
			speedParam = CF_D_SPEED;
		}
		return speedParam;
	}

	/**
	 * Converts a listed word or any number to a tick value
	 * (returns a Long)
	 */
	public static Long tickFromString(String dayPart) {
		if (dayPart.equalsIgnoreCase("day")) {
			return 1000L;
		} else if (dayPart.equalsIgnoreCase("midday") || dayPart.equalsIgnoreCase("noon")) {
			return 6000L;
		} else if (dayPart.equalsIgnoreCase("dusk") || dayPart.equalsIgnoreCase("sunset") || dayPart.equalsIgnoreCase("evening")) {
			return 12000L;
		} else if (dayPart.equalsIgnoreCase("night")) {
			return 13000L;
		} else if (dayPart.equalsIgnoreCase("midnight")) {
			return 18000L;
		} else if (dayPart.equalsIgnoreCase("dawn") || dayPart.equalsIgnoreCase("sunrise") || dayPart.equalsIgnoreCase("morning")) {
			return 0L;
		} else {
			try { // If not a formatted hour neither a word, try to get a tick number
				dayPart = dayPart.replace("#", "");
				return Long.parseLong(dayPart);
			} catch (NumberFormatException nfe) { // If not a Long, set a default value
				MsgHandler.errorMsg(tickFormatMsg); // Console error msg
				return 0L;
			}
		}
	}

	/**
	 * Gets and converts current milliseconds UTC+0 time to a 1/1728000 tick value
	 * (returns a long)
	 */
	public static long getServerTick() {
		long ticksSinceEpoch = System.currentTimeMillis() / 50L; // Get the server actual time in milliseconds and convert it into ticks
		long daillyServerTick = ticksSinceEpoch % 1728000L; // Display a 24h day loop (1728000 ticks = 1 real day)
		return daillyServerTick;
	}

	/**
	 * Converts a tick value and returns a correct UTC value
	 * (returns a long)
	 */
	public static long getUTCShiftFromTick(long tick) {
		if (tick >= 1000 || tick <= -1000) tick = (long) Math.floor(tick / 1000); // Use the 'start' value as an UTC modifier
		return tick % 24;
		
	}

	/**
	 * Formats a positive/negative number and return a formatted UTC+/-nh value
	 * (returns a String)
	 */
	public static String formattedUTCShiftfromTick(long tick) {
		tick = getUTCShiftFromTick(tick);
		String formattedUTC;
		if (tick < 0) {
			formattedUTC = "UTC" + tick + "h";
		} else {
			formattedUTC = "UTC+" + tick + "h";
		}
		return formattedUTC;
	}

	/**
	 * Formats a positive/negative number and return a tick +/-n value
	 * (returns a String)
	 */
	public static String tickUTCShiftfromTick(Long tick) {
		String shiftUTC;
		if (tick < 0) {
			shiftUTC = tick.toString();
		} else {
			shiftUTC = "+" + tick;
		}
		return shiftUTC;
	}

	/**
	 * Gets and converts the current millisecond UTC+0 time to HH:mm:ss
	 * (returns a String)
	 */
	public static String getServerTime() {
		long seconds = System.currentTimeMillis() / 1000L; // x ms in 1 second
		long s = seconds % 60;
		long m = (seconds / 60) % 60;
		long H = (seconds / (60 * 60)) % 24;
		return String.format("%02d:%02d:%02d", H, m, s) + " UTC";
	}

	/**
	 * Gets and converts a real time tick (1/1728000) to HH:mm:ss
	 * (returns a String)
	 */
	public static String realFormattedTimeFromTick(long tick) {
		long newTick = tick / 20L; // x tick in 1 seconds
		long s = newTick % 60;
		long m = (newTick / 60) % 60;
		long H = (newTick / (60 * 60)) % 24;
		return String.format("%02d:%02d:%02d", H, m, s) + " UTC";
	}

	/**
	 * Gets and converts HH:mm[:ss] to a tick nb (1/1728000)
	 * (returns a Long)
	 */
	public static Long tickFromServerTime(String time) {
		String[] splitedHms = time.split(":");
		try {
			long H = Long.parseLong(splitedHms[0]) % 24;
			long m = 0L;
			long s = 0L;
			if (splitedHms.length >= 2)
				m = Long.parseLong(splitedHms[1]) % 60;
			if (splitedHms.length >= 3)
				s = Long.parseLong(splitedHms[2]) % 60;
			Long calcTick = ((H * 72000) + (m * 1200) + (s * 20)) % 1728000;
			return calcTick;
		} catch (NumberFormatException nfe) {
			MsgHandler.errorMsg(hourFormatMsg); // Console error msg
			return 0L;
		}
	}

	/**
	 * Returns correct case of the locale (xx_XX)
	 * (returns a String)
	 */
	public static String getCorrectLocaleCase(String l) {
		String checkedLocale;
		if (l.contains("_")) {
			String[] splitLocale = l.split("_");
			String lg_LG_Locale = splitLocale[0] + "_" + splitLocale[1].toUpperCase();
			checkedLocale = lg_LG_Locale;
		} else {
			checkedLocale = l;
		}
		return checkedLocale;
	}

	/**
	 * Uses the first part to reach the nearest lang [en_GB] >>> [en_] >>> [en_US]
	 * (returns a String)
	 */
	public static String findNearestLang(String l) {
		String nearestLocale = serverLang; // If not existing, use the default language value
		if (l.contains("_")) {
			String[] splitLocale = l.split("_");
			String lg_Locale = splitLocale[0] + "_";
			List<String> existingLangList = LgFileHandler.setAnyListFromLang(CF_LANGUAGES);
			for (String lang : existingLangList) {
				if (lang.contains(lg_Locale)) {
					nearestLocale = lang;
				}
			}
		}
		return nearestLocale;
	}

	/**
	 * Gets and converts a MC tick (1/24000) to HH:mm:ss
	 * (returns a String)
	 */
	public static String formattedTimeFromTick(long ticks) {
		return formattedTimeFromTick(ticks, PH_TIME24);
	}
	public static String formattedTimeFromTick(long ticks, String format) {
		long newTicks = (ticks + 6000L) * 72L; // Adjust offset and go real time
		newTicks = correctInitTicks(newTicks);
		newTicks = newTicks / 20L; // x tick in 1 seconds
		int daylong;
		switch (format) {
		default :
		case PH_TIME24 :
		case PH_HOURS24 :
			daylong = 24;
			break;
		case PH_TIME12 :
		case PH_HOURS12 :
			daylong = 12;
			break;
		}
		long ss = newTicks % 60;
		long mm = (newTicks / 60) % 60;
		long HH = (newTicks / (60 * 60)) % daylong;
		String output;
		switch (format) {
		default :
		case PH_TIME12 :
			if (HH == 0) HH = 12;
		case PH_TIME24 :
			output = String.format("%02d:%02d:%02d", HH, mm, ss);
			break;
		case PH_HOURS12 :
			if (HH == 0) HH = 12;
		case PH_HOURS24 :
			output = String.format("%02d", HH);
			break;
		case PH_MINUTES :
			output = String.format("%02d", mm);
			break;
		case PH_SECONDS :
			output = String.format("%02d", ss);
			break;
		}
		if (debugMode) Bukkit.getServer().getConsoleSender().sendMessage(prefixDebugMode + " Given tick \"§e" + ticks + "§b\" was converted to \"§e" + output + "§b\"."); // Console debug msg
		return output;
	}

	/**
	 * Gets and converts [HH:mm:ss] to a tick nb (1/24000)
	 * (returns a Long)
	 */
	public static Long tickFromFormattedTime(String time) {
		String[] splitedHms = time.split(":");
		try {
			long H = Long.parseLong(splitedHms[0]) % 24;
			long m = 0L;
			long s = 0L;
			if (splitedHms.length >= 2)
				m = Long.parseLong(splitedHms[1]) % 60;
			if (splitedHms.length >= 3)
				s = Long.parseLong(splitedHms[2]) % 60;
			Float calcTick = (float) (((H * 24000 / 24) + (m * 16.678) + (s * 0.278) - 6000L) % 24000);
			return (long) Math.floor(calcTick);
		} catch (NumberFormatException nfe) {
			MsgHandler.errorMsg(hourFormatMsg); // Console error msg
			return 0L;
		}
	}
	
	/**
	 * Gets and converts [yyyy-mm-dd] to a tick
	 * (returns a Long)
	 */
	public static Long tickFromFormattedDate(String date) {
		try {
			String[] splitedDate = date.split("-");
			Long year = Long.parseLong(splitedDate[0]);
			Long month = Long.parseLong(splitedDate[1]);
			Long day = Long.parseLong(splitedDate[2]);
			Long monthToDay = 0L; // January
			Long maxDays = 31L;
			if (month == 2) {
				monthToDay = 31L; // February
				maxDays = 28L;
			} else if (month == 3) {
				monthToDay = 59L; // March
			} else if (month == 4) {
				monthToDay = 90L; // April
				maxDays = 30L;
			} else if (month == 5) {
				monthToDay = 120L; // May
			} else if (month == 6) {
				monthToDay = 151L; // June
				maxDays = 30L;
			} else if (month == 7) {
				monthToDay = 181L; // July
			} else if (month == 8) {
				monthToDay = 212L; // August
			} else if (month == 9) {
				monthToDay = 243L; // September
				maxDays = 30L;
			} else if (month == 10) {
				monthToDay = 273L; // October
			} else if (month == 11) {
				monthToDay = 304L; // November
				maxDays = 30L;
			} else if (month >= 12) {
				monthToDay = 334L; // December
			}
			// Avoid wrong values, send warn msgs
			if (year > 9999) {
				MsgHandler.warnMsg(yearFormatMsg); // Console warn msg
				year = 9999L;
			}
			if (month > 12)	MsgHandler.warnMsg(monthFormatMsg); // Console warn msg
			if (day > maxDays) {
				MsgHandler.warnMsg(dayFormatMsg + maxDays + "."); // Console warn msg	
				day = maxDays;		
			}
			Long y;
			Long m;			
			Long d;
			y = (year - 1) * 8760000; // (= 365j * 20m * 60s * 20t)	
			m = (monthToDay) * 24000; // (= 20m * 60s * 20t)			
			d = (day - 1) * 24000; // (= 20m * 60s * 20t)
			Long tick =  y + m + d;
			return tick;
		} catch (NumberFormatException nfe) {
			MsgHandler.errorMsg(dateFormatMsg); // Console error msg
			return null;
		}	
	}
	
	/**
	 * Gets and converts the current real date to a number of days
	 * (returns a Long)
	 */
	public static Long daysFromCurrentDate() {
		int year = Calendar.getInstance().get(Calendar.YEAR);
		int day = Calendar.getInstance().get(Calendar.DAY_OF_YEAR);
		Long elapsedDays = (long) (((year - 1) * 365) + (day - 1));
		return elapsedDays;
	}

	/**
	 * Gets and converts a tick (current Fulltime) to a number of elapsed days
	 * (returns a Long)
	 */
	public static Long elapsedDaysFromTick(long fulltime) {
		// A real day begin at 00:00
		if (MainTM.getInstance().getConfig().getString(CF_NEWDAYAT).equalsIgnoreCase(newDayStartsAt_0h00)) {
			MsgHandler.debugMsg("New day begins at §e00:00§b, so the calculation of elapsed days is : (§e" + fulltime
					+ " §b+ §e6000 §b= §e" + (fulltime + 6000) + "§b) / §e24000 §b= §e" + (fulltime + 6000) / 24000 + "§b."); // Console dev msg
			return (fulltime + 6000) / 24000;
		} else { // A MC day begin at 06:00
			MsgHandler.debugMsg("New day begins at §e06:00§b, so the calculation of elapsed days is : §e" + fulltime
					+ " §b/ §e24000 §b= §e" + (fulltime / 24000) + "§b."); // Console dev msg
			return fulltime / 24000;
		}
	}

	/**
	 * Gets and converts a tick (current Fulltime) to the number of the week (returns a Long)
	 */
	public static Long weekFromTick(long fulltime) {
		long daysNb = elapsedDaysFromTick(fulltime);
		return 1 + (daysNb / 7);
	}
	
	/**
	 * Gets and converts a tick (current Fulltime) to the number of the week in the year (returns a Long)
	 */
	public static Long yearWeekFromTick(long fulltime) {
		long daysNb = elapsedDaysFromTick(fulltime) % 365;
		return 1 + (daysNb / 7);
	}

	/**
	 * Gets and converts a number of days to a date part [dd] or [mm] or [yy] or [yyyy]
	 * (returns a String)
	 */
	public static String dateFromElapsedDays(long daysNb, String datePart) {
		// #1. Years
		if (datePart.contains("yy")) {
			long years = (1 + (long) Math.floor(daysNb / 365));
			if (datePart.equalsIgnoreCase("yyyy")) {
				years = years % 10000;
				return String.format("%04d", years);
			} else {
				years = years % 100;
				return String.format("%02d", years);
			}
		}
		// #2. Months
		long dayOfYear = 1 + (daysNb % 365); // Check what day of the year it is today to set the correct month length
		long dayOfMonth = 0L;
		Integer month = 0;
		if (dayOfYear >=1 && dayOfYear <=31) { month = 1; dayOfMonth = dayOfYear; // January 
		} else if (dayOfYear >=32 && dayOfYear <=59) { month = 2; dayOfMonth = dayOfYear - 31; // February 
		} else if (dayOfYear >=60 && dayOfYear <=90) { month = 3; dayOfMonth = dayOfYear - 59; // March 
		} else if (dayOfYear >=91 && dayOfYear <=120) { month = 4; dayOfMonth = dayOfYear - 90; // April 
		} else if (dayOfYear >=121 && dayOfYear <=151) { month = 5; dayOfMonth = dayOfYear - 120; // May 
		} else if (dayOfYear >=152 && dayOfYear <=181) { month = 6; dayOfMonth = dayOfYear - 151; // June
		} else if (dayOfYear >=182 && dayOfYear <=212) { month = 7; dayOfMonth = dayOfYear - 181; // July
		} else if (dayOfYear >=213 && dayOfYear <=243) { month = 8; dayOfMonth = dayOfYear - 212; // August 
		} else if (dayOfYear >=244 && dayOfYear <=273) { month = 9; dayOfMonth = dayOfYear - 243; // September
		} else if (dayOfYear >=274 && dayOfYear <=304) { month = 10; dayOfMonth = dayOfYear - 273; // October
		} else if (dayOfYear >=305 && dayOfYear <=334) { month = 11; dayOfMonth = dayOfYear - 304; // November
		} else if (dayOfYear >=335 && dayOfYear <=365) { month = 12; dayOfMonth = dayOfYear - 334; // December
		}
		if (datePart.equalsIgnoreCase("mm")) {
			String mm = String.format("%02d", month);
			return mm;
		}
		// #3. Days
		if (datePart.equalsIgnoreCase("dd")) {
			long days = dayOfMonth;
			String dd = String.format("%02d", days);
			return dd;
		}
		return null;
	}

	/**
	 * Compares two TimeManager versions, returns "true" if edgeVersion is bigger than the current one
	 * (returns a boolean)
	 */
	public static boolean tmVersionIsOk(String srcFile, int edgeMajor, int edgeMinor, int edgePatch, int edgeRelease, int edgeDev) {
		String currentVersion;
		int currentMajor = 0;
		int currentMinor = 0;
		int currentPatch = 0;
		int currentRelease = 4;
		int currentDev = 0;
		// Check current version
		if (srcFile.equalsIgnoreCase("lg")) {
			currentVersion = MainTM.getInstance().langConf.getString(CF_VERSION);
		} else {
			currentVersion = versionTM();
		}
		currentVersion = replaceChars(currentVersion);    	
		// Split version numbers
		String[] currentVersionNb = currentVersion.split("[.]");
		if (currentVersionNb.length >= 2) {
			currentMajor = Integer.parseInt(currentVersionNb[0]);
			currentMinor = Integer.parseInt(currentVersionNb[1]);
		}
		if (currentVersionNb.length >= 3) currentPatch = Integer.parseInt(currentVersionNb[2]);
		if (currentVersionNb.length >= 4) currentRelease = Integer.parseInt(currentVersionNb[3]);
		if (currentVersionNb.length >= 5) currentDev = Integer.parseInt(currentVersionNb[4]);    	
		// Compares versions
		if ((edgeMajor > currentMajor) 
				|| (edgeMajor == currentMajor && edgeMinor > currentMinor)
				|| (edgeMajor == currentMajor && edgeMinor == currentMinor && edgePatch > currentPatch)
				|| (edgeMajor == currentMajor && edgeMinor == currentMinor && edgePatch == currentPatch && edgeRelease > currentRelease)
				|| (edgeMajor == currentMajor && edgeMinor == currentMinor && edgePatch == currentPatch && edgeRelease == currentRelease && edgeDev > currentDev)) {
			return true;
		}
		return false;
	}

	/**
	 * Replaces characters before splitting version String into integers
	 */
	public static String replaceChars(String version) {
		MsgHandler.devMsg("version : " + version);
		version = version.replace("dev", "d")
				.replace("alpha", "a")
				.replace("beta", "b")
				.replace("d", ".0.")
				.replace("a", ".1.")
				.replace("b", ".2.")
				.replace("rc", ".3.")
				.replace("--", ".")
				.replace("-", ".")
				.replace("...", ".")
				.replace("..", ".");
		try {
			String versionIntTest = version.replace(".", "");
			Integer.parseInt(versionIntTest); // Prevent all other parse errors
		} catch (NumberFormatException nfe) {
			MsgHandler.errorMsg(versionTMFormatMsg); // Console error msg
			return null;
		}
		return version;
	}
	
	/**
	 * Concatenate world name in several parts
	 */
	public static String concatenateNameWithSpaces(CommandSender sender, String[] args, int firstPartArg) {
		List<String> worlds = CfgFileHandler.setAnyListFromConfig(MainTM.CF_WORLDSLIST);
		String concatWorldName = args[firstPartArg];
		int nbArgs = args.length;
		int currentArg = firstPartArg + 1;
		while (currentArg < nbArgs) {
			concatWorldName = (concatWorldName + " " + args[currentArg++]);
			if (worlds.contains(concatWorldName)) {
				MsgHandler.devMsg("Concatenate world name : " + concatWorldName);
				return concatWorldName;
			}
		}
		MsgHandler.devMsg("Concatenate world name : " + concatWorldName);
		return concatWorldName;
	}

	/**
	 * Restrains refresh rate
	 * (modifies the configuration without saving the file)
	 */
	public static void restrainRate() {
		try { // Check if value is an integer
			refreshRateInt = MainTM.getInstance().getConfig().getInt(CF_REFRESHRATE);
			refreshRateInt = correctRefreshRate(refreshRateInt);
		} catch (NumberFormatException nfe) { // If not an integer, use the default refresh value
			refreshRateInt = defRefresh;
		}
		MainTM.getInstance().getConfig().set(CF_REFRESHRATE, refreshRateInt);
	}

	/**
	 * Restrains initial tick (modifies the configuration without saving the file)
	 */
	public static void restrainInitTick() {
		long newInitialTick;
		try { // Check if value is a long
			initialTick = MainTM.getInstance().getConfig().getLong(CF_INITIALTICK + "." + CF_INITIALTICKNB);
			newInitialTick = correctInitTicks(initialTick);
		} catch (NumberFormatException nfe) { // If not a long, use the current time value
			newInitialTick = getServerTick(); // Create the initial tick
		}
		initialTick = newInitialTick;
		MainTM.getInstance().getConfig().set(CF_INITIALTICK + "." + CF_INITIALTICKNB, newInitialTick);
	}

	/**
	 * Restrains wakeUpTick tick (modifies the configuration without saving the file)
	 */
	public static void restrainWakeUpTick() {
		long newWakeUpTick = defWakeUpTick;
		try { // Check if value is a long
			newWakeUpTick = MainTM.getInstance().getConfig().getLong(CF_WAKEUPTICK);
			newWakeUpTick = correctwakeUpTick(newWakeUpTick);
		} catch (NumberFormatException nfe) { // If not a long, keep the default value
			MsgHandler.errorMsg(wakeUpTickFormatMsg); // Console error msg
		}
		MainTM.getInstance().getConfig().set(CF_WAKEUPTICK, newWakeUpTick);
	}

	/**
	 * Restrains start timers
	 * (modifies the configuration without saving the file)
	 */
	public static void restrainStart(String world) {
		long t = Bukkit.getWorld(world).getTime();
		String time = MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + CF_START);
		if (time.contains("+")) time = time.replace("+", "");
		time = tickFromString(time).toString(); // Check if value is a part of the day
		String currentSpeed = MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + wichSpeedParam(t));
		long tick;
		try { // Check if value is a long
			tick = Long.parseLong(time);
			if (currentSpeed.contains(realtimeSpeed.toString()) || currentSpeed.equalsIgnoreCase("realtime")) { // First if speed is 'realtime', use UTC
				tick = getUTCShiftFromTick(tick) * 1000;
			} else {
				tick = correctDailyTicks(tick); // else, use ticks
			}
		} catch (NumberFormatException nfe) { // If not a long, use the default start value
			MsgHandler.errorMsg(startTickFormatMsg); // Console error msg
			tick = defStart;
		}
		MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_START, tick);
		MsgHandler.debugMsg(startAdjustDebugMsg + " §e" + time + "§b to §e" + tick + "§b for the world §e" + world + "§b."); // Console debug msg
	}

	/**
	 * Restrains speed modifiers
	 * (modifies the configuration without saving the file)
	 */
	public static void restrainSpeed(String world) {
		double daySpeedNb;
		String daySpeed = MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + CF_D_SPEED);
		double nightSpeedNb;
		String nightSpeed = MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + CF_N_SPEED);
		if (daySpeed.contains("24") || daySpeed.equalsIgnoreCase("realtime") || nightSpeed.contains("24") || nightSpeed.equalsIgnoreCase("realtime")) {
			daySpeedNb = realtimeSpeed;
			nightSpeedNb = realtimeSpeed;
		} else {
			try { // Check if day value is a double
				daySpeedNb = MainTM.getInstance().getConfig().getDouble(CF_WORLDSLIST + "." + world + "." + CF_D_SPEED);
				daySpeedNb = correctSpeed(daySpeedNb);
			} catch (NumberFormatException nfe) { // If not a double, use the default refresh value
				MsgHandler.errorMsg(speedFormatMsg); // Console error msg
				daySpeedNb = defSpeed;
			}
			try { // Check if night value is a double
				nightSpeedNb = MainTM.getInstance().getConfig().getDouble(CF_WORLDSLIST + "." + world + "." + CF_N_SPEED);
				nightSpeedNb = correctSpeed(nightSpeedNb);
			} catch (NumberFormatException nfe) { // If not a double, use the default refresh value
				MsgHandler.errorMsg(speedFormatMsg); // Console error msg
				nightSpeedNb = defSpeed;
			} 
		}
		MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_D_SPEED, daySpeedNb);
		MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_N_SPEED, nightSpeedNb);
		MsgHandler.debugMsg(daySpeedAdjustDebugMsg + " §e" + daySpeed + "§b to §e" + daySpeedNb + "§b for the world §e" + world + "§b."); // Console debug msg
		MsgHandler.debugMsg(nightSpeedAdjustDebugMsg + " §e" + nightSpeed + "§b to §e" + nightSpeedNb + "§b for the world §e" + world + "§b."); // Console debug msg
	}

	/**
	 * If a world gets a speed of "24", force 'sleep' to false
	 * Force 'sync' to false if 'sleep' is 'true' or 'linked'
	 * (modifies the configuration without saving the file)
	 */
	public static void restrainSleep(String world) {
		String sleep = MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + CF_SLEEP);
		long t = Bukkit.getWorld(world).getTime();
		String currentSpeed = MainTM.getInstance().getConfig().getString(CF_WORLDSLIST + "." + world + "." + wichSpeedParam(t));
		if (currentSpeed.contains("24") || (!sleep.equalsIgnoreCase(ARG_TRUE) && !sleep.equalsIgnoreCase(ARG_LINKED))) {
			MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_SLEEP, ARG_FALSE);
			MsgHandler.debugMsg(sleepAdjustFalseDebugMsg + " §e" + world + "§b."); // Console debug msg
		} else if (sleep.equalsIgnoreCase(ARG_TRUE) || sleep.equalsIgnoreCase(ARG_LINKED)) {
			MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_SYNC, ARG_FALSE);
			MsgHandler.debugMsg(syncAdjustFalseDebugMsg + " §e" + world + "§b."); // Console debug msg
		}
	}

	/**
	 * Force 'sync' to true for the 24.0 speed, then false when change to another speed ratio
	 * Force 'sync' to false for the 0.0 speed
	 * (modifies the configuration without saving the file)
	 */
	public static void restrainSync(String world, double oldSpeed) {
		long t = Bukkit.getWorld(world).getTime();
		double currentSpeed = MainTM.getInstance().getConfig().getDouble(CF_WORLDSLIST + "." + world + "." + wichSpeedParam(t));
		if (currentSpeed == 24.0) { // new speed is 24
			MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_SYNC, ARG_TRUE);
			MsgHandler.debugMsg(syncAdjustTrueDebugMsg + " §e" + world + "§b."); // Console debug msg
		} else if (currentSpeed == 0.0) { // new speed is 0
			MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_SYNC, ARG_FALSE);
			MsgHandler.debugMsg(syncAdjustFalseDebugMsg + " §e" + world + "§b."); // Console debug msg
		} else if (oldSpeed == 24.0) { // new speed is anything else with previous value 24
			MainTM.getInstance().getConfig().set(CF_WORLDSLIST + "." + world + "." + CF_SYNC, ARG_FALSE);
			MsgHandler.debugMsg(syncAdjustFalseDebugMsg + " §e" + world + "§b."); // Console debug msg
		}
	}

};
import org.bukkit.World;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmHelp;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmNow;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmCheckConfig;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmCheckSql;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmCheckTime;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmCheckUpdate;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmReload;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmResync;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetDebugMode;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetDefLang;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetInitialTick;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetMultiLang;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetPlayerOffset;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetPlayerTime;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetRefreshRate;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetFullTime;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetSpeed;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetStart;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetSleep;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetSync;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetTime;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetUpdateMsgSrc;
import net.vdcraft.arvdc.timemanager.cmdadmin.TmSetUseCmds;
import net.vdcraft.arvdc.timemanager.mainclass.MsgHandler;
import net.vdcraft.arvdc.timemanager.mainclass.ValuesConverter;

			// Check for an update on configured server
			else if ((args[0].equalsIgnoreCase(MainTM.CMD_CHECKUPDATE)) 
					&& (MainTM.serverMcVersion >= MainTM.reqMcVForUpdate)) {
				if (nbArgs < 2) {
					TmCheckUpdate.cmdCheckUpdate(sender);
					return true;
				} else {
					TmCheckUpdate.cmdCheckUpdate(sender, args[1]);
					return true;
				}
			}
			// If 'set' is used alone
			else if (args[0].equalsIgnoreCase(MainTM.CMD_SET) && nbArgs == 1) {
				MsgHandler.cmdErrorMsg(sender, MainTM.missingArgMsg, MainTM.CMD_SET); // Send error and help msg
				return true;
			}
			// Display details about commands use
			else if (args[0].equalsIgnoreCase(MainTM.CMD_HELP)) {
				boolean cmdListOnOff = TmHelp.cmdHelp(sender, args);
				return cmdListOnOff;
			}
			// Reload data from yaml file(s)
			else if (args[0].equalsIgnoreCase(MainTM.CMD_RELOAD)) {
				if (nbArgs < 2) {
					TmReload.cmdReload(sender, "all");
					return true;
				} else {
					TmReload.cmdReload(sender, args[1]);
					return true;
				}
			}
			// Synchronize all worlds timers based on server initial time
			else if (args[0].equalsIgnoreCase(MainTM.CMD_RESYNC)) {
				if (nbArgs < 2) {
					if (sender instanceof Player) {
						TmResync.cmdResync(sender, defaultWorld);
						return true;
					}
					MsgHandler.cmdErrorMsg(sender, MainTM.missingArgMsg, MainTM.CMD_RESYNC); // Send error and help msg
					return true;
				} else if (nbArgs == 2) {
					TmResync.cmdResync(sender, args[1]);
					return true;
				} else {
					String concatWorldName = ValuesConverter.concatenateNameWithSpaces(sender, args, 1);
					TmResync.cmdResync(sender, concatWorldName);
					return true;
				}
			}
			// Display initial and current server's clock, initial and current server's tick and all worlds initial and current timers.
			else if (args[0].equalsIgnoreCase(MainTM.CMD_CHECKTIME)) {
				if (nbArgs < 2) {
					if (sender instanceof Player) {
						TmCheckTime.cmdCheckTime(sender, defaultWorld);
						return true;
					}
					MsgHandler.cmdErrorMsg(sender, MainTM.missingArgMsg, MainTM.CMD_CHECKTIME); // Send error and help msg
					return true;
				} else if (nbArgs == 2) {
					TmCheckTime.cmdCheckTime(sender, args[1]);
					return true;
				} else {
					String concatWorldName = ValuesConverter.concatenateNameWithSpaces(sender, args, 1);
					TmCheckTime.cmdCheckTime(sender, concatWorldName);
					return true;
				}
			}
		}
		if (nbArgs >= 2) {
			// Display custom messages to one or many player(s) at different display places
			if (args[0].equalsIgnoreCase(MainTM.CMD_TMNOW)) {
				if (nbArgs < 3) {
					MsgHandler.cmdErrorMsg(sender, MainTM.missingArgMsg, MainTM.CMD_TMNOW); // Send error and help msg
					return true;
				} else if (nbArgs == 3) {
					TmNow.cmdNow(sender, args[1], args[2]);
					return true;
				} else {
					String concatWorldName = ValuesConverter.concatenateNameWithSpaces(sender, args, 2);
					TmNow.cmdNow(sender, args[1], concatWorldName);
					return true;
				}
			}
			else if (args[0].equalsIgnoreCase(MainTM.CMD_SET)) {
				// Enable or disable the console colored verbose messages
				if (args[1].equalsIgnoreCase(MainTM.CMD_SET_DEBUG)) {
					if (nbArgs < 3) {
						MsgHandler.cmdErrorMsg(sender, MainTM.missingArgMsg, MainTM.CMD_SET + " " + MainTM.CMD_SET_DEBUG); // Send error and help msg
						return true;
					} else {
						TmSetDebugMode.cmdDebugMode(sender, args[2]);
						return true;
					}
				}
				// Enable or disable the console colored verbose messages
				else if (args[1].equalsIgnoreCase(MainTM.CMD_SET_DEV)) {
					if (nbArgs < 3) {
						MsgHandler.cmdErrorMsg(sender, MainTM.missingArgMsg, MainTM.CMD_SET + " " + MainTM.CMD_SET_DEV); // Send error and help msg
						return true;
					} else {
						TmSetDebugMode.cmdDevMode(sender, args[2]);
						return true;
					}
				}
				// Enable or disable the console colored messages for time calculation
				else if (args[1].equalsIgnoreCase(MainTM.CMD_SET_TIMER)) {
					if (nbArgs < 3) {
						MsgHandler.cmdErrorMsg(sender, MainTM.missingArgMsg, MainTM.CMD_SET + " " + MainTM.CMD_SET_TIMER); // Send error and help msg
						return true;
					} else {
						TmSetDebugMode.cmdTimerMode(sender, args[2]);
						return true;
					}
				}
				// Set the default language to use, in case the asked locale doesn't exist
				else if (args[1].equalsIgnoreCase(MainTM.CMD_SET_DEFLANG)) {
					if (nbArgs < 3) {
						MsgHandler.cmdErrorMsg(sender, MainTM.missingArgMsg, MainTM.CMD_SET + " " + MainTM.CMD_SET_DEFLANG); // Send error and help msg
						return true;
					} else {

						TmSetDefLang.cmdDefLg(sender, args[2]);
