package com.forgeessentials.scripting; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.text.DecimalFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.util.EnumChatFormatting; import com.forgeessentials.api.APIRegistry; import com.forgeessentials.api.UserIdent; import com.forgeessentials.chat.ChatConfig; import com.forgeessentials.commons.selections.WorldPoint; import com.forgeessentials.core.FEConfig; import com.forgeessentials.scripting.ScriptParser.MissingPlayerException; import com.forgeessentials.scripting.ScriptParser.ScriptArgument; import com.forgeessentials.scripting.ScriptParser.ScriptException; import com.forgeessentials.scripting.ScriptParser.SyntaxException; import com.forgeessentials.util.output.ChatOutputHandler; import com.forgeessentials.util.PlayerInfo; import com.forgeessentials.util.ServerUtil; import com.google.common.collect.ImmutableMap; public final class ScriptArguments { private static Map<String, ScriptArgument> scriptArguments = new HashMap<>(); public static void add(String name, ScriptArgument argument) { if (scriptArguments.containsKey(name)) throw new RuntimeException(String.format("Script argument name @%s already registered", name)); scriptArguments.put(name, argument); } public static ScriptArgument get(String name) { return scriptArguments.get(name); } public static Map<String, ScriptArgument> getAll() { return ImmutableMap.copyOf(scriptArguments); } public static final Pattern ARGUMENT_PATTERN = Pattern.compile("@\\{?(\\w+)\\}?"); public static String process(String text, ICommandSender sender) throws ScriptException { return process(text, sender, null); } public static String process(String text, ICommandSender sender, List<?> args) throws ScriptException { Matcher m = ARGUMENT_PATTERN.matcher(text); StringBuffer sb = new StringBuffer(); while (m.find()) { String modifier = m.group(1).toLowerCase(); ScriptArgument argument = get(modifier); if (argument != null) m.appendReplacement(sb, argument.process(sender)); else if (args == null) m.appendReplacement(sb, m.group()); else try { int idx = Integer.parseInt(modifier); if (args == null || idx >= args.size()) throw new SyntaxException("Missing argument @%d", idx); m.appendReplacement(sb, args.get(idx).toString()); } catch (NumberFormatException e) { m.appendReplacement(sb, m.group()); } } m.appendTail(sb); return sb.toString(); } public static String processSafe(String text, ICommandSender sender) { return processSafe(text, sender, null); } public static String processSafe(String text, ICommandSender sender, List<?> args) { Matcher m = ARGUMENT_PATTERN.matcher(text); StringBuffer sb = new StringBuffer(); while (m.find()) { String modifier = m.group(1).toLowerCase(); ScriptArgument argument = get(modifier); if (argument != null) { try { m.appendReplacement(sb, argument.process(sender)); } catch (ScriptException e) { m.appendReplacement(sb, m.group()); } } else if (args == null) m.appendReplacement(sb, m.group()); else try { int idx = Integer.parseInt(modifier); if (args == null || idx >= args.size()) throw new SyntaxException("Missing argument @%d", idx); m.appendReplacement(sb, args.get(idx).toString()); } catch (NumberFormatException e) { m.appendReplacement(sb, m.group()); } } m.appendTail(sb); return sb.toString(); } private static void registerAll() { try { for (Field field : ScriptArguments.class.getDeclaredFields()) if (ScriptArgument.class.isAssignableFrom(field.getType()) && Modifier.isStatic(field.getModifiers())) add(field.getName().toLowerCase(), (ScriptArgument) field.get(null)); } catch (IllegalArgumentException | IllegalAccessException e) { throw new RuntimeException(e); } } public static ScriptArgument sender = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (sender == null) throw new MissingPlayerException(); return sender.getCommandSenderName(); } @Override public String getHelp() { return "Command sender name"; } }; public static ScriptArgument player = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (sender == null) throw new MissingPlayerException(); return sender.getCommandSenderName(); } @Override public String getHelp() { return "Player name"; } }; public static ScriptArgument uuid = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return ((EntityPlayerMP) sender).getPersistentID().toString(); } @Override public String getHelp() { return "Player UUID"; } }; public static ScriptArgument x = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Integer.toString((int) ((EntityPlayerMP) sender).posX); } @Override public String getHelp() { return "Player X position (as integer)"; } }; public static ScriptArgument y = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Integer.toString((int) ((EntityPlayerMP) sender).posY); } @Override public String getHelp() { return "Player Y position (as integer)"; } }; public static ScriptArgument z = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Integer.toString((int) ((EntityPlayerMP) sender).posZ); } @Override public String getHelp() { return "Player Z position (as integer)"; } }; public static ScriptArgument xd = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Double.toString(((EntityPlayerMP) sender).posX); } @Override public String getHelp() { return "Player X position (as floating point number)"; } }; public static ScriptArgument yd = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Double.toString(((EntityPlayerMP) sender).posY); } @Override public String getHelp() { return "Player Y position (as floating point number)"; } }; public static ScriptArgument zd = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Double.toString(((EntityPlayerMP) sender).posZ); } @Override public String getHelp() { return "Player Z position (as floating point number)"; } }; public static ScriptArgument dim = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Integer.toString(((EntityPlayerMP) sender).dimension); } @Override public String getHelp() { return "Player dimension"; } }; public static ScriptArgument gm = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); if (((EntityPlayerMP) sender).theItemInWorldManager.getGameType().isCreative()) return ChatConfig.gamemodeCreative; if (((EntityPlayerMP) sender).theItemInWorldManager.getGameType().isAdventure()) return ChatConfig.gamemodeAdventure; return ChatConfig.gamemodeSurvival; } @Override public String getHelp() { return "Player gamemode"; } }; public static ScriptArgument health = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Float.toString(((EntityPlayerMP) sender).getHealth()); } @Override public String getHelp() { return "Player health"; } }; public static ScriptArgument healthcolor = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); float health = ((EntityPlayerMP) sender).getHealth(); if (health <= 6) return EnumChatFormatting.RED.toString(); if (health < 16) return EnumChatFormatting.YELLOW.toString(); return EnumChatFormatting.GREEN.toString(); } @Override public String getHelp() { return "Insert color code based on player health"; } }; public static ScriptArgument hunger = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Integer.toString(((EntityPlayerMP) sender).getFoodStats().getFoodLevel()); } @Override public String getHelp() { return "Player hunger level"; } }; public static ScriptArgument hungercolor = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); float hunger = ((EntityPlayerMP) sender).getFoodStats().getFoodLevel(); if (hunger <= 6) return EnumChatFormatting.RED.toString(); if (hunger < 12) return EnumChatFormatting.YELLOW.toString(); return EnumChatFormatting.GREEN.toString(); } @Override public String getHelp() { return "Insert color code based on player hunger level"; } }; public static ScriptArgument saturation = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Float.toString(((EntityPlayerMP) sender).getFoodStats().getSaturationLevel()); } @Override public String getHelp() { return "Player (food) saturation level"; } }; public static ScriptArgument saturationcolor = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); float hunger = ((EntityPlayerMP) sender).getFoodStats().getSaturationLevel(); if (hunger <= 0) return EnumChatFormatting.RED.toString(); if (hunger <= 1.5) return EnumChatFormatting.YELLOW.toString(); return EnumChatFormatting.GREEN.toString(); } @Override public String getHelp() { return "Insert color code based on player saturation level"; } }; public static ScriptArgument zone = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return APIRegistry.perms.getServerZone().getZoneAt(new WorldPoint(((EntityPlayerMP) sender))).getName(); } @Override public String getHelp() { return "Get name of the zone the player is in"; } }; public static ScriptArgument zoneId = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); return Integer.toString(APIRegistry.perms.getServerZone().getZoneAt(new WorldPoint(((EntityPlayerMP) sender))).getId()); } @Override public String getHelp() { return "Get ID of the zone the player is in"; } }; public static ScriptArgument group = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); EntityPlayerMP _player = ((EntityPlayerMP) sender); return APIRegistry.perms.getServerZone().getPlayerGroups(UserIdent.get(_player)).first().getGroup(); } @Override public String getHelp() { return "Get name of the zone the player is in"; } }; public static ScriptArgument timePlayed = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); EntityPlayerMP _player = ((EntityPlayerMP) sender); return ChatOutputHandler.formatTimeDurationReadable(PlayerInfo.get(_player).getTimePlayed() / 1000, true); } @Override public String getHelp() { return "Get total time a player played on the server" + ""; } }; public static ScriptArgument lastLogout = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); EntityPlayerMP _player = ((EntityPlayerMP) sender); return FEConfig.FORMAT_DATE_TIME.format(PlayerInfo.get(_player).getLastLogout()); } @Override public String getHelp() { return "Get the time a player logged out last time"; } }; public static ScriptArgument lastLogin = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); EntityPlayerMP _player = ((EntityPlayerMP) sender); return FEConfig.FORMAT_DATE_TIME.format(PlayerInfo.get(_player).getLastLogin()); } @Override public String getHelp() { return "Get the time a player logged in last time"; } }; public static ScriptArgument sinceLastLogout = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); EntityPlayerMP _player = ((EntityPlayerMP) sender); return ChatOutputHandler.formatTimeDurationReadable((new Date().getTime() - PlayerInfo.get(_player).getLastLogout().getTime()) / 1000, true); } @Override public String getHelp() { return "Get the time since a player logged out last time"; } }; public static ScriptArgument sinceLastLogin = new ScriptArgument() { @Override public String process(ICommandSender sender) { if (!(sender instanceof EntityPlayerMP)) throw new MissingPlayerException(); EntityPlayerMP _player = ((EntityPlayerMP) sender); return ChatOutputHandler.formatTimeDurationReadable((new Date().getTime() - PlayerInfo.get(_player).getLastLogin().getTime()) / 1000, true); } @Override public String getHelp() { return "Get the time since a player logged in last time"; } }; public static ScriptArgument tps = new ScriptArgument() { @Override public String process(ICommandSender sender) { return new DecimalFormat("#").format(Math.min(20, ServerUtil.getTPS())); } @Override public String getHelp() { return "Ticks per second"; } }; public static ScriptArgument realTime = new ScriptArgument() { @Override public String process(ICommandSender sender) { return FEConfig.FORMAT_TIME.format(new Date()); } @Override public String getHelp() { return "Current real time"; } }; public static ScriptArgument realDate = new ScriptArgument() { @Override public String process(ICommandSender sender) { return FEConfig.FORMAT_DATE.format(new Date()); } @Override public String getHelp() { return "Current real date"; } }; public static ScriptArgument worldTime = new ScriptArgument() { @Override public String process(ICommandSender sender) { return new DecimalFormat("#").format(MinecraftServer.getServer().getEntityWorld().getWorldTime()); } @Override public String getHelp() { return "Current MC world time"; } }; public static ScriptArgument totalWorldTime = new ScriptArgument() { @Override public String process(ICommandSender sender) { return new DecimalFormat("#").format(MinecraftServer.getServer().getEntityWorld().getTotalWorldTime()); } @Override public String getHelp() { return "MC time passed since map creation"; } }; public static ScriptArgument serverUptime = new ScriptArgument() { @Override public String process(ICommandSender sender) { RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean(); return ChatOutputHandler.formatTimeDurationReadable(rb.getUptime() / 1000, true); } @Override public String getHelp() { return "Time since server start"; } }; public static ScriptArgument onlinePlayers = new ScriptArgument() { @Override public String process(ICommandSender sender) { int online = 0; try { online = MinecraftServer.getServer().getCurrentPlayerCount(); } catch (Exception e) { } return Integer.toString(online); } @Override public String getHelp() { return "Number of players that are online right now"; } }; public static ScriptArgument uniquePlayers = new ScriptArgument() { @Override public String process(ICommandSender sender) { return Integer.toString(APIRegistry.perms.getServerZone().getKnownPlayers().size()); } @Override public String getHelp() { return "Number of unique players on the server at all time"; } }; static { registerAll(); add("p", player); } }