2018-09-13 12:03:28 -04:00
|
|
|
package noppes.npcs.controllers;
|
|
|
|
|
|
2023-01-12 21:33:06 -05:00
|
|
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
2024-02-27 21:18:53 -06:00
|
|
|
import jdk.nashorn.api.scripting.ClassFilter;
|
|
|
|
|
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
|
2021-09-30 01:48:54 -05:00
|
|
|
import net.minecraft.entity.player.EntityPlayer;
|
2018-09-13 12:03:28 -04:00
|
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
|
|
|
import net.minecraft.nbt.NBTTagList;
|
|
|
|
|
import net.minecraft.nbt.NBTTagString;
|
|
|
|
|
import net.minecraft.server.MinecraftServer;
|
|
|
|
|
import net.minecraftforge.event.world.WorldEvent;
|
|
|
|
|
import noppes.npcs.CustomNpcs;
|
|
|
|
|
import noppes.npcs.LogWriter;
|
2023-11-16 15:19:32 -05:00
|
|
|
import noppes.npcs.config.ConfigScript;
|
2021-10-11 06:49:30 -05:00
|
|
|
import noppes.npcs.controllers.data.ForgeDataScript;
|
2023-03-16 04:27:19 -05:00
|
|
|
import noppes.npcs.controllers.data.GlobalNPCDataScript;
|
2021-10-11 06:49:30 -05:00
|
|
|
import noppes.npcs.controllers.data.PlayerDataScript;
|
2018-09-13 12:03:28 -04:00
|
|
|
import noppes.npcs.entity.EntityNPCInterface;
|
|
|
|
|
import noppes.npcs.scripted.ScriptWorld;
|
2021-09-30 01:48:54 -05:00
|
|
|
import noppes.npcs.util.JsonException;
|
2018-09-13 12:03:28 -04:00
|
|
|
import noppes.npcs.util.NBTJsonUtil;
|
2023-01-12 21:33:06 -05:00
|
|
|
|
2023-06-26 16:02:15 -05:00
|
|
|
import javax.script.ScriptContext;
|
2023-01-12 21:33:06 -05:00
|
|
|
import javax.script.ScriptEngine;
|
|
|
|
|
import javax.script.ScriptEngineFactory;
|
|
|
|
|
import javax.script.ScriptEngineManager;
|
2025-02-20 21:40:39 -05:00
|
|
|
import java.io.BufferedReader;
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.FileReader;
|
|
|
|
|
import java.io.IOException;
|
2023-06-26 16:02:15 -05:00
|
|
|
import java.util.*;
|
2018-09-13 12:03:28 -04:00
|
|
|
|
2024-04-04 18:53:53 -04:00
|
|
|
import static noppes.npcs.util.CustomNPCsThreader.customNPCThread;
|
|
|
|
|
|
2018-09-13 12:03:28 -04:00
|
|
|
public class ScriptController {
|
2021-10-19 02:49:46 -05:00
|
|
|
|
2025-03-13 17:14:45 -04:00
|
|
|
public static ScriptController Instance;
|
|
|
|
|
public static boolean HasStart = false;
|
|
|
|
|
private final ScriptEngineManager manager;
|
|
|
|
|
private ScriptEngineFactory nashornFactory;
|
|
|
|
|
public Map<String, String> languages = new HashMap<String, String>();
|
|
|
|
|
public Map<String, String> scripts = new HashMap<String, String>();
|
|
|
|
|
public long lastLoaded = 0;
|
|
|
|
|
public File dir;
|
|
|
|
|
public NBTTagCompound compound = new NBTTagCompound();
|
|
|
|
|
|
|
|
|
|
public boolean shouldSave = false;
|
|
|
|
|
public PlayerDataScript playerScripts = new PlayerDataScript((EntityPlayer) null);
|
|
|
|
|
public long lastPlayerUpdate = 0L;
|
|
|
|
|
|
|
|
|
|
public ForgeDataScript forgeScripts = new ForgeDataScript();
|
|
|
|
|
public long lastForgeUpdate = 0L;
|
|
|
|
|
|
|
|
|
|
public GlobalNPCDataScript globalNpcScripts = new GlobalNPCDataScript((EntityNPCInterface) null);
|
|
|
|
|
public long lastGlobalNpcUpdate = 0L;
|
|
|
|
|
|
|
|
|
|
public ScriptController() {
|
|
|
|
|
Instance = this;
|
|
|
|
|
manager = new ScriptEngineManager();
|
|
|
|
|
if (!ConfigScript.ScriptingEnabled)
|
|
|
|
|
return;
|
|
|
|
|
LogWriter.info("Script Engines Available:");
|
|
|
|
|
|
|
|
|
|
ScriptEngine engine = manager.getEngineByName("nashorn");
|
|
|
|
|
if (engine != null) {
|
|
|
|
|
this.nashornFactory = engine.getFactory();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (ScriptEngineFactory fac : manager.getEngineFactories()) {
|
|
|
|
|
if (fac.getExtensions().isEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
ScriptEngine scriptEngine = fac.getScriptEngine();
|
|
|
|
|
try {
|
|
|
|
|
scriptEngine.put("$RunTest", null);
|
|
|
|
|
String ext = "." + fac.getExtensions().get(0).toLowerCase();
|
|
|
|
|
LogWriter.info("Engine " + fac.getEngineName() + " running " + fac.getLanguageName() + " with extension: " + ext);
|
|
|
|
|
languages.put(fac.getLanguageName(), ext);
|
|
|
|
|
} catch (Exception ignored) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private File forgeScriptsFile() {
|
|
|
|
|
return new File(this.dir, "forge_scripts.json");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean loadForgeScripts() {
|
|
|
|
|
this.forgeScripts.clear();
|
|
|
|
|
File file = this.forgeScriptsFile();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (!file.exists()) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
this.forgeScripts.readFromNBT(NBTJsonUtil.LoadFile(file));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception var3) {
|
|
|
|
|
LogWriter.error("Error loading: " + file.getAbsolutePath(), var3);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void saveForgeScripts() {
|
|
|
|
|
File file = this.forgeScriptsFile();
|
|
|
|
|
try {
|
|
|
|
|
NBTJsonUtil.SaveFile(file, this.forgeScripts.writeToNBT(new NBTTagCompound()));
|
|
|
|
|
this.forgeScripts.lastInited = -1L;
|
|
|
|
|
} catch (IOException | JsonException var4) {
|
|
|
|
|
var4.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private File playerScriptsFile() {
|
|
|
|
|
return new File(dir, "player_scripts.json");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private File npcScriptsFile() {
|
|
|
|
|
return new File(dir, "npc_scripts.json");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean loadPlayerScripts() {
|
|
|
|
|
this.playerScripts.clear();
|
|
|
|
|
File file = this.playerScriptsFile();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (!file.exists()) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
this.playerScripts.readFromNBT(NBTJsonUtil.LoadFile(file));
|
|
|
|
|
shouldSave = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception var3) {
|
|
|
|
|
LogWriter.error("Error loading: " + file.getAbsolutePath(), var3);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void savePlayerScripts() {
|
|
|
|
|
File file = this.playerScriptsFile();
|
|
|
|
|
try {
|
|
|
|
|
NBTJsonUtil.SaveFile(file, this.playerScripts.writeToNBT(new NBTTagCompound()));
|
|
|
|
|
this.playerScripts.lastInited = -1L;
|
|
|
|
|
} catch (IOException | JsonException var4) {
|
|
|
|
|
var4.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean loadGlobalNPCScripts() {
|
|
|
|
|
this.globalNpcScripts.clear();
|
|
|
|
|
File file = this.npcScriptsFile();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (!file.exists()) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
this.globalNpcScripts.readFromNBT(NBTJsonUtil.LoadFile(file));
|
|
|
|
|
shouldSave = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception var3) {
|
|
|
|
|
LogWriter.error("Error loading: " + file.getAbsolutePath(), var3);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void saveGlobalNpcScripts() {
|
|
|
|
|
File file = this.npcScriptsFile();
|
|
|
|
|
try {
|
|
|
|
|
NBTJsonUtil.SaveFile(file, this.globalNpcScripts.writeToNBT(new NBTTagCompound()));
|
|
|
|
|
this.globalNpcScripts.lastInited = -1L;
|
|
|
|
|
} catch (IOException | JsonException var4) {
|
|
|
|
|
var4.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized void saveForgeScriptsSync() {
|
2024-04-04 18:53:53 -04:00
|
|
|
customNPCThread.execute(this::saveForgeScripts);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-13 17:14:45 -04:00
|
|
|
public synchronized void savePlayerScriptsSync() {
|
2024-04-04 18:53:53 -04:00
|
|
|
customNPCThread.execute(() -> {
|
|
|
|
|
File file = this.playerScriptsFile();
|
|
|
|
|
try {
|
|
|
|
|
NBTJsonUtil.SaveFile(file, this.playerScripts.writeToNBT(new NBTTagCompound()));
|
|
|
|
|
this.playerScripts.lastInited = -1L;
|
|
|
|
|
} catch (IOException | JsonException var4) {
|
|
|
|
|
var4.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-13 17:14:45 -04:00
|
|
|
public synchronized void saveGlobalScriptsSync() {
|
2024-04-04 18:53:53 -04:00
|
|
|
customNPCThread.execute(this::saveGlobalNpcScripts);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-13 17:14:45 -04:00
|
|
|
public void loadCategories() {
|
|
|
|
|
dir = new File(CustomNpcs.getWorldSaveDirectory(), "scripts");
|
|
|
|
|
if (!dir.exists())
|
|
|
|
|
dir.mkdir();
|
|
|
|
|
if (!getSavedFile().exists())
|
|
|
|
|
shouldSave = true;
|
|
|
|
|
new ScriptWorld(null).clearTempData();
|
|
|
|
|
scripts.clear();
|
|
|
|
|
for (String language : languages.keySet()) {
|
|
|
|
|
String ext = languages.get(language);
|
|
|
|
|
File scriptDir = new File(dir, language.toLowerCase());
|
|
|
|
|
if (!scriptDir.exists())
|
|
|
|
|
scriptDir.mkdir();
|
|
|
|
|
else
|
|
|
|
|
loadDir(scriptDir, "", ext);
|
|
|
|
|
}
|
|
|
|
|
lastLoaded = System.currentTimeMillis();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void loadDir(File dir, String name, String ext) {
|
|
|
|
|
for (File file : dir.listFiles()) {
|
|
|
|
|
String filename = name + file.getName().toLowerCase();
|
|
|
|
|
if (file.isDirectory()) {
|
|
|
|
|
loadDir(file, filename + "/", ext);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!filename.endsWith(ext))
|
|
|
|
|
continue;
|
|
|
|
|
try {
|
|
|
|
|
scripts.put(filename, readFile(file));
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean loadStoredData() {
|
|
|
|
|
loadCategories();
|
|
|
|
|
File file = getSavedFile();
|
|
|
|
|
try {
|
|
|
|
|
if (!file.exists())
|
|
|
|
|
return false;
|
|
|
|
|
this.compound = NBTJsonUtil.LoadFile(file);
|
|
|
|
|
shouldSave = false;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogWriter.error("Error loading: " + file.getAbsolutePath(), e);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private File getSavedFile() {
|
|
|
|
|
return new File(dir, "world_data.json");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String readFile(File file) throws IOException {
|
|
|
|
|
BufferedReader br = new BufferedReader(new FileReader(file));
|
|
|
|
|
try {
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
String line = br.readLine();
|
|
|
|
|
|
|
|
|
|
while (line != null) {
|
|
|
|
|
sb.append(line);
|
|
|
|
|
sb.append("\n");
|
|
|
|
|
line = br.readLine();
|
|
|
|
|
}
|
|
|
|
|
return sb.toString();
|
|
|
|
|
} finally {
|
|
|
|
|
br.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final List<String> nashornNames = immutableList("nashorn", "Nashorn", "js", "JS", "JavaScript", "javascript", "ECMAScript", "ecmascript");
|
|
|
|
|
|
|
|
|
|
public ScriptEngine getEngineByName(String language) {
|
|
|
|
|
if (nashornNames.contains(language) && this.nashornFactory != null) {
|
2024-02-27 21:18:53 -06:00
|
|
|
ScriptEngine scriptEngine;
|
2025-03-13 17:14:45 -04:00
|
|
|
if (ConfigScript.EnableBannedClasses) {
|
2024-02-29 20:23:42 -05:00
|
|
|
try {
|
|
|
|
|
ClassFilter filter = s -> {
|
|
|
|
|
for (String className : ConfigScript.BannedClasses) {
|
|
|
|
|
if (s.compareTo(className) == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2024-02-27 21:18:53 -06:00
|
|
|
}
|
2024-02-29 20:23:42 -05:00
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
NashornScriptEngineFactory nashornScriptEngineFactory = (NashornScriptEngineFactory) this.nashornFactory;
|
|
|
|
|
scriptEngine = nashornScriptEngineFactory.getScriptEngine(filter);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
scriptEngine = this.nashornFactory.getScriptEngine();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2024-02-27 21:18:53 -06:00
|
|
|
scriptEngine = this.nashornFactory.getScriptEngine();
|
|
|
|
|
}
|
2025-03-13 17:14:45 -04:00
|
|
|
scriptEngine.setBindings(this.manager.getBindings(), ScriptContext.GLOBAL_SCOPE);
|
|
|
|
|
return scriptEngine;
|
|
|
|
|
}
|
|
|
|
|
return manager.getEngineByName(language);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static List<String> immutableList(String... elements) {
|
|
|
|
|
return Collections.unmodifiableList(Arrays.asList(elements));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public NBTTagList nbtLanguages() {
|
|
|
|
|
NBTTagList list = new NBTTagList();
|
|
|
|
|
for (String language : languages.keySet()) {
|
|
|
|
|
NBTTagCompound compound = new NBTTagCompound();
|
|
|
|
|
NBTTagList scripts = new NBTTagList();
|
|
|
|
|
for (String script : getScripts(language)) {
|
|
|
|
|
scripts.appendTag(new NBTTagString(script));
|
|
|
|
|
}
|
|
|
|
|
compound.setTag("Scripts", scripts);
|
|
|
|
|
compound.setString("Language", language);
|
|
|
|
|
list.appendTag(compound);
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<String> getScripts(String language) {
|
|
|
|
|
List<String> list = new ArrayList<String>();
|
|
|
|
|
String ext = languages.get(language);
|
|
|
|
|
if (ext == null)
|
|
|
|
|
return list;
|
|
|
|
|
for (String script : scripts.keySet()) {
|
|
|
|
|
if (script.endsWith(ext)) {
|
|
|
|
|
list.add(script);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SubscribeEvent
|
|
|
|
|
public void invoke(WorldEvent.Save event) {
|
|
|
|
|
if (!shouldSave || event.world.isRemote || event.world != MinecraftServer.getServer().worldServers[0])
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
NBTJsonUtil.SaveFile(getSavedFile(), compound);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LogWriter.except(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shouldSave = false;
|
|
|
|
|
}
|
2024-02-27 21:18:53 -06:00
|
|
|
}
|