package com.forgeessentials.scripting;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;
import org.apache.commons.io.FileUtils;
import com.forgeessentials.core.ForgeEssentials;
import com.forgeessentials.core.moduleLauncher.FEModule;
import com.forgeessentials.scripting.ScriptParser.MissingPermissionException;
import com.forgeessentials.scripting.ScriptParser.ScriptArgument;
import com.forgeessentials.scripting.ScriptParser.ScriptException;
import com.forgeessentials.scripting.ScriptParser.ScriptMethod;
import com.forgeessentials.scripting.command.CommandTimedTask;
import com.forgeessentials.scripting.command.PatternCommand;
import com.forgeessentials.util.output.ChatOutputHandler;
import com.forgeessentials.util.events.ConfigReloadEvent;
import com.forgeessentials.util.events.FEModuleEvent.FEModuleInitEvent;
import com.forgeessentials.util.events.FEModuleEvent.FEModuleServerInitEvent;
import com.forgeessentials.util.events.FEModuleEvent.FEModuleServerPostInitEvent;
import com.forgeessentials.util.events.FEModuleEvent.FEModuleServerStopEvent;
import com.forgeessentials.util.events.ServerEventHandler;
import com.forgeessentials.util.output.LoggingHandler;
import cpw.mods.fml.common.eventhandler.EventPriority;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.PlayerEvent;
@FEModule(name = "Scripting", parentMod = ForgeEssentials.class, isCore = false)
public class ModuleScripting extends ServerEventHandler
{
public static enum ServerEventType
{
START, STOP, LOGIN, LOGOUT;
}
@FEModule.ModuleDir
public static File moduleDir;
// Map < event name, List of scripts < lines of code > >
public Map<ServerEventType, Map<String, List<String>>> scripts = new HashMap<>();
@SubscribeEvent
public void load(FEModuleInitEvent event)
{
try (PrintWriter writer = new PrintWriter(new File(moduleDir, "arguments.txt")))
{
writer.println("# Script arguments");
writer.println();
for (Entry<String, ScriptArgument> item : ScriptArguments.getAll().entrySet())
{
writer.println("## @" + item.getKey());
writer.println(item.getValue().getHelp());
writer.println();
}
}
catch (FileNotFoundException e)
{
LoggingHandler.felog.info("Unable to write script arguments file");
}
try (PrintWriter writer = new PrintWriter(new File(moduleDir, "methods.txt")))
{
writer.println("# Script methods");
writer.println();
for (Entry<String, ScriptMethod> item : ScriptMethods.getAll().entrySet())
{
writer.println("## " + item.getKey());
writer.println(item.getValue().getHelp());
writer.println();
}
}
catch (FileNotFoundException e)
{
LoggingHandler.felog.info("Unable to write script arguments file");
}
}
public void loadScripts()
{
scripts = new HashMap<>();
for (ServerEventType eventType : ServerEventType.values())
{
Map<String, List<String>> scriptList = new HashMap<>();
scripts.put(eventType, scriptList);
File path = new File(moduleDir, eventType.toString().toLowerCase());
if (!path.exists())
{
path.mkdirs();
continue;
}
// File[] files = path.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String
// name) { return FilenameUtils.getExtension(name).equalsIgnoreCase("txt");}});
for (File file : path.listFiles())
{
List<String> script = new ArrayList<>();
try
{
for (String line : FileUtils.readLines(file))
script.add(line);
scriptList.put(file.getName(), script);
}
catch (IOException e1)
{
LoggingHandler.felog.error(String.format("Error reading script %s", file.getName()));
continue;
}
}
}
}
@SubscribeEvent
public void serverStarting(FEModuleServerInitEvent e)
{
new CommandTimedTask().register();
loadScripts();
PatternCommand.loadAll();
createDefaultPatternCommands();
PatternCommand.saveAll();
}
@SubscribeEvent
public void serverStarted(FEModuleServerPostInitEvent e)
{
runEventScripts(ServerEventType.START, null);
}
@SubscribeEvent
public void serverStopping(FEModuleServerStopEvent e)
{
runEventScripts(ServerEventType.STOP, null);
}
public static void createDefaultPatternCommands()
{
PatternCommand cmd;
if (!PatternCommand.patternCommands.containsKey("god"))
{
cmd = new PatternCommand("god", "/god on|off [player]", null);
cmd.getPatterns().put("on @p", Arrays.asList(new String[] { //
"permcheck fe.commands.god.others", "/p user @1 deny fe.protection.damageby.*", "/heal @player", "echo God mode turned ON for @1", }));
cmd.getPatterns().put("off @p", Arrays.asList(new String[] { //
"permcheck fe.commands.god.others", "/p user %@ clear fe.protection.damageby.*", "echo God mode turned OFF for @1", }));
cmd.getPatterns().put("on", Arrays.asList(new String[] { //
"permcheck fe.commands.god", "/p user @player deny fe.protection.damageby.*", "/heal", "echo God mode ON", }));
cmd.getPatterns().put("off", Arrays.asList(new String[] { //
"/p user @player clear fe.protection.damageby.*", "echo God mode OFF", }));
cmd.getPatterns().put("", Arrays.asList(new String[] { //
"echo Usage: /god on|off [player]", }));
}
}
@SubscribeEvent
public void reload(ConfigReloadEvent e)
{
loadScripts();
PatternCommand.loadAll();
createDefaultPatternCommands();
PatternCommand.saveAll();
}
public void runEventScripts(ServerEventType eventType, ICommandSender sender)
{
if (sender == null)
sender = MinecraftServer.getServer();
for (Entry<String, List<String>> script : scripts.get(eventType).entrySet())
{
try
{
ScriptParser.run(script.getValue(), sender);
}
catch (CommandException e)
{
ChatOutputHandler.chatError(sender, e.getMessage());
// ChatOutputHandler.felog.info(String.format("Error in script \"%s\": %s", script.getKey(),
// e.getMessage()));
}
catch (MissingPermissionException e)
{
if (!e.getMessage().isEmpty())
ChatOutputHandler.chatError(sender, e.getMessage());
}
catch (ScriptException e)
{
LoggingHandler.felog.error(String.format("Error in script \"%s\": %s", script.getKey(), e.getMessage()));
}
}
}
@SubscribeEvent(priority = EventPriority.LOWEST)
public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event)
{
runEventScripts(ServerEventType.LOGIN, event.player);
}
@SubscribeEvent(priority = EventPriority.LOWEST)
public void playerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent event)
{
runEventScripts(ServerEventType.LOGOUT, event.player);
}
}