Refactored Scripts to use Groovy instead of JavaScript

This commit is contained in:
Waverunner
2017-05-08 20:23:54 -04:00
parent b9e5cfb511
commit c0a80a175c
12 changed files with 184 additions and 118 deletions
Binary file not shown.
+5
View File
@@ -53,6 +53,11 @@
<artifactId>lz4</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>2.4.11</version>
</dependency>
</dependencies>
<build>
+15
View File
@@ -0,0 +1,15 @@
import intents.chat.ChatAvatarRequestIntent
import resources.objects.SWGObject
import resources.player.Player
import services.galaxy.GalacticManager
static def execute(GalacticManager galacticManager, Player player, SWGObject target, String args) {
if (args == null)
return
def name = args.split(" ")[0].toLowerCase(Locale.ENGLISH)
if (name == null)
return
new ChatAvatarRequestIntent(player, name, ChatAvatarRequestIntent.RequestType.FRIEND_ADD_TARGET).broadcast()
}
+32
View File
@@ -0,0 +1,32 @@
import resources.commands.ICmdCallback
import resources.objects.SWGObject
import resources.player.AccessLevel
import resources.player.Player
import services.galaxy.GalacticManager
import utilities.IntentFactory
class CmdTip implements ICmdCallback {
void execute(GalacticManager galacticManager, Player player, SWGObject target, String args) {
if (player.getAccessLevel() == AccessLevel.PLAYER) {
IntentFactory.sendSystemMessage(player, "Unable to access /tip command - currently reserved for admins")
return
}
def argSplit = args.split(" ")
if (argSplit.length < 2) {
IntentFactory.sendSystemMessage(player, "Invalid Arguments: " + args)
return
}
def creature = player.getCreatureObject()
if (argSplit[0] == "bank")
creature.setBankBalance(creature.getBankBalance() + Long.valueOf(argSplit[1]))
else if (argSplit[0] == "cash")
creature.setCashBalance(creature.getCashBalance() + Long.valueOf(argSplit[1]))
else
IntentFactory.sendSystemMessage(player, "Unknown Destination: " + argSplit[0])
}
}
def execute(GalacticManager galacticManager, Player player, SWGObject target, String args) {
println("Hello World!")
new CmdTip().execute(galacticManager, player, target, args)
}
+12 -13
View File
@@ -27,6 +27,18 @@
***********************************************************************************/
package main;
import com.projectswg.common.concurrency.Delay;
import com.projectswg.common.control.IntentManager;
import com.projectswg.common.debug.Log;
import com.projectswg.common.debug.Log.LogLevel;
import com.projectswg.common.debug.log_wrapper.ConsoleLogWrapper;
import com.projectswg.common.debug.log_wrapper.FileLogWrapper;
import intents.server.ServerStatusIntent;
import resources.Galaxy.GalaxyStatus;
import resources.control.ServerStatus;
import resources.server_info.DataManager;
import services.CoreManager;
import java.io.File;
import java.io.IOException;
import java.lang.Thread.State;
@@ -36,19 +48,6 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import com.projectswg.common.concurrency.Delay;
import com.projectswg.common.control.IntentManager;
import com.projectswg.common.debug.Log;
import com.projectswg.common.debug.Log.LogLevel;
import com.projectswg.common.debug.log_wrapper.ConsoleLogWrapper;
import com.projectswg.common.debug.log_wrapper.FileLogWrapper;
import intents.server.ServerStatusIntent;
import resources.Galaxy.GalaxyStatus;
import resources.control.ServerStatus;
import resources.server_info.DataManager;
import services.CoreManager;
public class ProjectSWG {
private static ProjectSWG server;
+1 -1
View File
@@ -32,5 +32,5 @@ import resources.player.Player;
import services.galaxy.GalacticManager;
public interface ICmdCallback {
public void execute(GalacticManager galacticManager, Player player, SWGObject target, String args);
void execute(GalacticManager galacticManager, Player player, SWGObject target, String args);
}
@@ -27,13 +27,11 @@
package resources.commands.callbacks;
import java.io.FileNotFoundException;
import java.util.Map;
import com.projectswg.common.data.location.Location;
import com.projectswg.common.data.location.Terrain;
import com.projectswg.common.debug.Log;
import groovy.util.ResourceException;
import groovy.util.ScriptException;
import intents.chat.ChatBroadcastIntent;
import intents.experience.ExperienceIntent;
import intents.network.CloseConnectionIntent;
@@ -58,6 +56,8 @@ import services.objects.StaticItemService.ObjectCreationHandler;
import services.player.PlayerManager;
import utilities.Scripts;
import java.util.Map;
/**
* Created by Waverunner on 8/19/2015
*/
@@ -94,7 +94,7 @@ public class QaToolCmdCallback implements ICmdCallback {
case "details":
try {
Scripts.invoke("commands/helper/qatool/details", "sendDetails", player, target, args.split(" "));
} catch (FileNotFoundException ex) {
} catch (ResourceException | ScriptException e) {
Log.e("sendDetails qatool script not found!");
}
break;
+7 -7
View File
@@ -27,16 +27,16 @@
***********************************************************************************/
package resources.radial;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.debug.Log;
import groovy.util.ResourceException;
import groovy.util.ScriptException;
import resources.objects.SWGObject;
import resources.player.Player;
import utilities.Scripts;
import java.util.ArrayList;
import java.util.List;
public class Radials {
private static final String SCRIPT_PREFIX = "radial/";
@@ -45,7 +45,7 @@ public class Radials {
List<RadialOption> options = new ArrayList<>();
try {
Scripts.invoke(SCRIPT_PREFIX + script, "getOptions", options, player, target, args);
} catch (FileNotFoundException ex) {
} catch (ResourceException | ScriptException e) {
Log.w("Couldn't retrieve radial options from %s for object %s because the script couldn't be found", SCRIPT_PREFIX + script, target);
}
return options;
@@ -54,7 +54,7 @@ public class Radials {
public static void handleSelection(String script, Player player, SWGObject target, RadialItem selection, Object ... args) {
try {
Scripts.invoke(SCRIPT_PREFIX + script, "handleSelection", player, target, selection, args);
} catch (FileNotFoundException ex) {
} catch (ResourceException | ScriptException e) {
Log.w("Can't handle selection %s on object %s because the script couldn't be found");
}
}
+10 -10
View File
@@ -27,20 +27,13 @@
***********************************************************************************/
package services.commands;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import com.projectswg.common.concurrency.PswgBasicScheduledThread;
import com.projectswg.common.control.Service;
import com.projectswg.common.data.CRC;
import com.projectswg.common.debug.Assert;
import com.projectswg.common.debug.Log;
import groovy.util.ResourceException;
import groovy.util.ScriptException;
import intents.BuffIntent;
import intents.PlayerEventIntent;
import intents.SkillModIntent;
@@ -54,6 +47,13 @@ import services.commands.buff.BuffData;
import services.commands.buff.BuffMap;
import utilities.Scripts;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
public class BuffService extends Service {
/*
@@ -326,7 +326,7 @@ public class BuffService extends Service {
} else {
try {
Scripts.invoke("buffs/callback" + callback, callback, creature);
} catch (FileNotFoundException ex) {
} catch (ResourceException | ScriptException e) {
Log.w("Callback script %s doesn't exist - buff %s won't behave as expected", callback, buffData.getName());
}
}
+12 -9
View File
@@ -27,15 +27,10 @@
***********************************************************************************/
package services.commands;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import com.projectswg.common.concurrency.PswgScheduledThreadPool;
import com.projectswg.common.debug.Log;
import groovy.util.ResourceException;
import groovy.util.ScriptException;
import intents.chat.ChatBroadcastIntent;
import intents.chat.ChatCommandIntent;
import network.packets.swg.zone.object_controller.CommandQueueDequeue;
@@ -52,6 +47,11 @@ import resources.server_info.DataManager;
import services.galaxy.GalacticManager;
import utilities.Scripts;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
public class CommandLauncher {
private final Map<Player, Queue<EnqueuedCommand>> combatQueueMap;
@@ -180,8 +180,11 @@ public class CommandLauncher {
}
} else {
try {
Scripts.invoke("commands/generic/" + command.getDefaultScriptCallback(), "executeCommand", enqueued.getGalacticManager(), player, enqueued.getTarget(), enqueued.getRequest().getArguments());
} catch (FileNotFoundException ex) {
Scripts.invoke("commands/generic/" + command.getDefaultScriptCallback(), "execute", enqueued.getGalacticManager(), player, enqueued.getTarget(), enqueued.getRequest().getArguments());
} catch (ResourceException e) {
// Script doesn't exist
} catch (ScriptException e) {
Log.a(e);
}
}
}
+9 -9
View File
@@ -27,16 +27,10 @@
***********************************************************************************/
package services.sui;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.projectswg.common.control.Service;
import com.projectswg.common.debug.Log;
import groovy.util.ResourceException;
import groovy.util.ScriptException;
import intents.network.GalacticPacketIntent;
import intents.sui.SuiWindowIntent;
import network.packets.Packet;
@@ -51,6 +45,12 @@ import resources.sui.SuiComponent;
import resources.sui.SuiEvent;
import utilities.Scripts;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SuiService extends Service {
private final Map<Long, List<SuiBaseWindow>> windows;
@@ -135,7 +135,7 @@ public class SuiService extends Service {
String script = window.getCallbackScript(callback);
try {
Scripts.invoke(script, callback, player, player.getCreatureObject(), event, parameters);
} catch (FileNotFoundException ex) {
} catch (ResourceException | ScriptException e) {
Log.e("Callback script %s not found", script);
}
} else if (window.hasJavaCallback(callback)) {
+76 -64
View File
@@ -27,71 +27,83 @@
***********************************************************************************/
package utilities;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import groovy.lang.Binding;
import groovy.lang.Script;
import groovy.util.GroovyScriptEngine;
import groovy.util.ResourceException;
import groovy.util.ScriptException;
import main.ProjectSWG;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import com.projectswg.common.debug.Log;
import java.io.IOException;
public class Scripts {
private static final String SCRIPTS;
private static final String EXTENSION;
private static final ScriptEngine ENGINE;
private static final Invocable INVOCABLE;
static {
ScriptEngineManager engineManager = new ScriptEngineManager();
SCRIPTS = "scripts/";
EXTENSION = ".js";
ENGINE = engineManager.getEngineByName("nashorn");
INVOCABLE = (Invocable) ENGINE;
if (ENGINE == null) {
Log.e("ScriptEngine is null!");
} else {
try {
ENGINE.put("intentFactory", new IntentFactory());
ENGINE.eval("var RadialOption = Java.type('resources.radial.RadialOption')");
ENGINE.eval("var RadialItem = Java.type('resources.radial.RadialItem')");
ENGINE.eval("var Log = Java.type('com.projectswg.common.debug.Log')");
ENGINE.eval("var SuiWindow = Java.type('resources.sui.SuiWindow')");
ENGINE.eval("var SuiButtons = Java.type('resources.sui.SuiButtons')");
ENGINE.eval("var SuiEvent = Java.type('resources.sui.SuiEvent')");
} catch (Throwable t) {
Log.e(t);
}
}
}
// Prevents instantiation.
private Scripts() {}
/**
* @param script name of the script, relative to the scripts folder.
* @param function name of the specific function within the script.
* @param args to pass to the function.
* @return whatever the function returns. If the function doesn't have a return statement, this method returns {@code null}.
* If an exception occurs, {@code null} is returned.
* @throws java.io.FileNotFoundException if the script file wasn't found
*/
@SuppressWarnings("unchecked")
public static <T> T invoke(String script, String function, Object... args) throws FileNotFoundException {
try {
ENGINE.eval(new InputStreamReader(new FileInputStream(SCRIPTS + script + EXTENSION), StandardCharsets.UTF_8));
return (T) INVOCABLE.invokeFunction(function, args);
} catch (ScriptException | NoSuchMethodException t) {
Log.e("Error invoking script: " + script + " with function: " + function);
Log.e(" Args: " + Arrays.toString(args));
Log.e(t);
return null;
}
}
private static GroovyScriptEngine groovyEngine;
static {
try {
groovyEngine = new GroovyScriptEngine("scripts/");
} catch (IOException e) {
e.printStackTrace();
}
if (groovyEngine == null)
throw new ProjectSWG.CoreException("Could not load the Groovy Script Engine!");
}
/**
* Invokes a method from the provided Groovy Script.
* @param scriptName name of the script, relative to the scripts folder.
* @param method name of the specific method within the script.
* @param args to pass to the method.
* @return expected return type of the script. If the method doesn't have a return statement, this method returns {@code null}.
* If an exception occurs, {@code null} is returned.
* @throws java.io.FileNotFoundException if the script file wasn't found
*/
@SuppressWarnings("unchecked")
public static <T> T invoke(String scriptName, String method, Object... args) throws ResourceException, ScriptException {
Script script = getScript(formatScriptName(scriptName));
return (script != null) ? (T) script.invokeMethod(method, args) : null;
}
/**
* Creates a binding from an array of variables. The name of the variable should lead the instance. An example would be:
* <br>&nbsp&nbsp{@code setupScriptVariables("variableNameOne", variableOne, "variableNameTwo", variableTwo);}
* @param variables an array of variables. Variable names should lead the instance of the variable.
*/
public static Binding createBindings(Object... variables) {
Binding binding = new Binding();
for (int i = 0; i < variables.length; i++) {
if (!(variables[i] instanceof String))
continue;
binding.setVariable((String) variables[i], variables[i++]);
}
return binding;
}
/**
* Creates the Groovy Script and returns it. The method uses the {@link GroovyScriptEngine}'s createScript method.
* A new {@link Binding} is passed to the created {@link Script} to ensure thread safety, providing a new instance of the generated {@link Script} for the accessing thread.
* @param scriptName Name of the script to load
* @return a unique instance of {@link Script}
*/
public static Script getScript(String scriptName) throws ResourceException, ScriptException {
return getScript(scriptName, new Binding());
}
/**
* Creates the Groovy Script and returns it. The method uses the {@link GroovyScriptEngine}'s createScript method.
* @param scriptName name of the script to load
* @param binding the binding instance to use
* @return an instance of the obtained Groovy Script
*/
public static Script getScript(String scriptName, Binding binding) throws ResourceException, ScriptException {
return groovyEngine.createScript(formatScriptName(scriptName), binding);
}
private static String formatScriptName(String name) {
return name.endsWith(".groovy") ? name : name + ".groovy";
}
}