script engine work
This commit is contained in:
parent
df4fe45dd5
commit
e5a187ce19
5
.gitignore
vendored
5
.gitignore
vendored
@ -44,4 +44,7 @@
|
|||||||
/docs/DoxygenWarningLog.txt
|
/docs/DoxygenWarningLog.txt
|
||||||
|
|
||||||
#imgui local layout
|
#imgui local layout
|
||||||
/imgui.ini
|
/imgui.ini
|
||||||
|
|
||||||
|
#script engine related
|
||||||
|
/assets/Scripts/compiler/typescript.js
|
||||||
|
|||||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -4,5 +4,7 @@
|
|||||||
"**/.git/objects/**": true,
|
"**/.git/objects/**": true,
|
||||||
"**/node_modules/**": true
|
"**/node_modules/**": true
|
||||||
},
|
},
|
||||||
"java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx2G -Xms100m -Xlog:disable"
|
"java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx2G -Xms100m -Xlog:disable",
|
||||||
|
"javascript.preferences.importModuleSpecifier": "non-relative",
|
||||||
|
"typescript.preferences.importModuleSpecifier": "non-relative"
|
||||||
}
|
}
|
||||||
113
assets/Scripts/compiler/compiler.js
Normal file
113
assets/Scripts/compiler/compiler.js
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* The map of all source files to their content and compiled value
|
||||||
|
*/
|
||||||
|
let COMPILER_fileMap = { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The compiled program
|
||||||
|
*/
|
||||||
|
let COMPILER_emitted_value = ''
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a file with the compiler
|
||||||
|
* @param {*} fileName The file's name
|
||||||
|
* @param {*} content The content of the file
|
||||||
|
*/
|
||||||
|
const COMPILER_registerFile = (fileName, content) => {
|
||||||
|
let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName,false)
|
||||||
|
loggerScripts.INFO('REGISTER FILE ' + normalizedFilePath)
|
||||||
|
COMPILER_fileMap[normalizedFilePath] = {
|
||||||
|
content: content,
|
||||||
|
compiled: ts.createSourceFile(
|
||||||
|
normalizedFilePath, content, ts.ScriptTarget.Latest
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The callback invoked when the compiler host tries to read a file
|
||||||
|
* @param {*} fileName The name of the file
|
||||||
|
* @param {*} languageVersion The language version
|
||||||
|
* @returns The file if it exists, null otherwise
|
||||||
|
*/
|
||||||
|
const COMPILER_getSourceFile = (fileName, languageVersion) => {
|
||||||
|
if(!!COMPILER_fileMap[fileName]){
|
||||||
|
return COMPILER_fileMap[fileName].compiled
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the compiler host
|
||||||
|
* https://www.typescriptlang.org/tsconfig/#compilerOptions
|
||||||
|
*/
|
||||||
|
const COMPILER_customCompilerHost = {
|
||||||
|
getSourceFile: COMPILER_getSourceFile,
|
||||||
|
writeFile: (fileName, data) => {
|
||||||
|
let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName)
|
||||||
|
loggerScripts.INFO("EMIT FILE " + normalizedFilePath)
|
||||||
|
let finalData =
|
||||||
|
"let exports = { }\n" +
|
||||||
|
data + "\n" +
|
||||||
|
"return exports"
|
||||||
|
// COMPILER_emitted_value = data
|
||||||
|
COMPILER_fileMap[normalizedFilePath] = {
|
||||||
|
content: data, //to be eval'd from top level
|
||||||
|
moduleContent: finalData, //to be eval'd from require()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getDefaultLibFileName: () => "lib.d.ts",
|
||||||
|
useCaseSensitiveFileNames: () => false,
|
||||||
|
getCanonicalFileName: filename => filename,
|
||||||
|
getCurrentDirectory: () => "",
|
||||||
|
getNewLine: () => "\n",
|
||||||
|
getDirectories: () => [],
|
||||||
|
fileExists: () => true,
|
||||||
|
readFile: () => ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instructs Typescript to emit the final compiled value
|
||||||
|
*/
|
||||||
|
const COMPILER_run = () => {
|
||||||
|
loggerScripts.INFO('COMPILE ALL REGISTERED FILES')
|
||||||
|
|
||||||
|
const compilerOptions = { }
|
||||||
|
|
||||||
|
const COMPILER_program = ts.createProgram(
|
||||||
|
Object.keys(COMPILER_fileMap), compilerOptions, COMPILER_customCompilerHost
|
||||||
|
)
|
||||||
|
COMPILER_program.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a file
|
||||||
|
* @param {*} fileName The name of the file to load (preferably already has .ts at the end)
|
||||||
|
*/
|
||||||
|
const COMPILER_runFile = (fileName) => {
|
||||||
|
let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName)
|
||||||
|
if(!!COMPILER_fileMap[normalizedFilePath]){
|
||||||
|
loggerScripts.INFO('RUN FILE ' + normalizedFilePath)
|
||||||
|
eval(COMPILER_fileMap[normalizedFilePath].content)
|
||||||
|
} else {
|
||||||
|
loggerScripts.WARNING('FAILED TO RESOLVE FILE ' + normalizedFilePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a file
|
||||||
|
* @param {*} fileName The name of the file to load (preferably already has .ts at the end)
|
||||||
|
*/
|
||||||
|
const COMPILER_printSource = (fileName) => {
|
||||||
|
let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName)
|
||||||
|
if(!!COMPILER_fileMap[normalizedFilePath]){
|
||||||
|
loggerScripts.INFO('FILE CONTENT ' + normalizedFilePath)
|
||||||
|
} else {
|
||||||
|
loggerScripts.WARNING('FAILED TO RESOLVE FILE ' + normalizedFilePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
23
assets/Scripts/compiler/file_resolution.js
Normal file
23
assets/Scripts/compiler/file_resolution.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes a file path
|
||||||
|
* @param {*} rawFilePath The raw file path
|
||||||
|
* @returns The normalized file path
|
||||||
|
*/
|
||||||
|
const FILE_RESOLUTION_getFilePath = (rawFilePath, isJavascript = true) => {
|
||||||
|
let fileName = rawFilePath
|
||||||
|
if(isJavascript && fileName.includes('.ts')){
|
||||||
|
fileName = fileName.replace('.ts','.js')
|
||||||
|
}
|
||||||
|
if(fileName.startsWith('/Scripts')){
|
||||||
|
fileName = fileName.replace('/Scripts','')
|
||||||
|
}
|
||||||
|
if(fileName.startsWith('Scripts/')){
|
||||||
|
fileName = fileName.replace('Scripts/','/')
|
||||||
|
}
|
||||||
|
if(isJavascript && !fileName.endsWith(".js")){
|
||||||
|
fileName = fileName + ".js"
|
||||||
|
}
|
||||||
|
return fileName
|
||||||
|
}
|
||||||
|
|
||||||
1
assets/Scripts/compiler/get_typescript.sh
Normal file
1
assets/Scripts/compiler/get_typescript.sh
Normal file
@ -0,0 +1 @@
|
|||||||
|
wget -O typescript.js https://unpkg.com/typescript@latest/lib/typescript.js
|
||||||
9
assets/Scripts/compiler/host_access.js
Normal file
9
assets/Scripts/compiler/host_access.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* The host context that contains the core engine functions
|
||||||
|
*/
|
||||||
|
export let HOST = {
|
||||||
|
classes: { }, //the classes available to the script engine
|
||||||
|
singletons: { }, //the singletons available to the script engine
|
||||||
|
}
|
||||||
|
|
||||||
36
assets/Scripts/compiler/require_polyfill.js
Normal file
36
assets/Scripts/compiler/require_polyfill.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches loaded modules
|
||||||
|
*/
|
||||||
|
let REQUIRE_CACHE = { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used if the module is directly executed instead of being require'd for some reason
|
||||||
|
*/
|
||||||
|
let exports = { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports a module
|
||||||
|
* @param {*} path The path of the module
|
||||||
|
* @param {*} cwd The current working directory
|
||||||
|
*/
|
||||||
|
const require = (path) => {
|
||||||
|
let normalizedFilePath = FILE_RESOLUTION_getFilePath(path)
|
||||||
|
if(REQUIRE_CACHE[path]){
|
||||||
|
return REQUIRE_CACHE[normalizedFilePath].exports
|
||||||
|
} else if(!!COMPILER_fileMap[normalizedFilePath]?.content) {
|
||||||
|
const code = COMPILER_fileMap[normalizedFilePath].moduleContent
|
||||||
|
let exports = new Function(code)()
|
||||||
|
//create module object
|
||||||
|
const module = {
|
||||||
|
exports: exports,
|
||||||
|
exportedValues: Object.keys(exports),
|
||||||
|
}
|
||||||
|
REQUIRE_CACHE[normalizedFilePath] = module
|
||||||
|
loggerScripts.INFO("[require] CREATE MODULE " + normalizedFilePath)
|
||||||
|
return module.exports
|
||||||
|
} else {
|
||||||
|
loggerScripts.WARNING("FAILED TO REQUIRE FILE " + normalizedFilePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
7
assets/Scripts/engine/engine-init.ts
Normal file
7
assets/Scripts/engine/engine-init.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the script engine first initializes
|
||||||
|
*/
|
||||||
|
export const ENGINE_onInit = () => {
|
||||||
|
console.log('Script Engine Init')
|
||||||
|
}
|
||||||
9
assets/Scripts/engine/engine-interface.ts
Normal file
9
assets/Scripts/engine/engine-interface.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The host context that contains all core engine functions
|
||||||
|
*/
|
||||||
|
export interface Host {
|
||||||
|
classes: any, //the host's view of the scripting engine
|
||||||
|
singletons: any, //the singletons available to the script engine
|
||||||
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
console.log("test")
|
|
||||||
@ -4,4 +4,5 @@
|
|||||||
- @subpage biomeideas
|
- @subpage biomeideas
|
||||||
- @subpage largelocationideas
|
- @subpage largelocationideas
|
||||||
- @subpage macrolocationideas
|
- @subpage macrolocationideas
|
||||||
- @subpage smalllocations
|
- @subpage smalllocations
|
||||||
|
- @subpage minidungeons
|
||||||
4
docs/src/highlevel-design/locations/minidungeons.md
Normal file
4
docs/src/highlevel-design/locations/minidungeons.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@page minidungeons Mini Dungeons
|
||||||
|
|
||||||
|
In certain levels, you can find premade characters that can join your party.
|
||||||
|
|
||||||
@ -21,7 +21,6 @@ Redo hitboxes to have capsules and also chaining between frames (but not between
|
|||||||
- Introduce block hitbox (blockbox) type
|
- Introduce block hitbox (blockbox) type
|
||||||
- Sour spot, sweet spot for damage hitboxes and hurtboxes
|
- Sour spot, sweet spot for damage hitboxes and hurtboxes
|
||||||
Enemy AI
|
Enemy AI
|
||||||
better scaffolding for scriptig engine with hooks for equipping items, spawning entities, pausing/resuming play, etc
|
|
||||||
Ability for private realms to have time start/stop based on the player's feedback <-- sync this up to tutorial ui via script
|
Ability for private realms to have time start/stop based on the player's feedback <-- sync this up to tutorial ui via script
|
||||||
Scene Message Service
|
Scene Message Service
|
||||||
- Can send arbitrary events and messages
|
- Can send arbitrary events and messages
|
||||||
|
|||||||
@ -406,6 +406,8 @@ Audio
|
|||||||
- Sword Hit Metal
|
- Sword Hit Metal
|
||||||
- Sword Hit Flesh
|
- Sword Hit Flesh
|
||||||
|
|
||||||
|
(06/02/2024)
|
||||||
|
better scaffolding for scripting engine with hooks for equipping items, spawning entities, pausing/resuming play, etc
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
@ -413,7 +415,7 @@ Audio
|
|||||||
BIG BIG BIG BIG IMMEDIATE TO DO:
|
BIG BIG BIG BIG IMMEDIATE TO DO:
|
||||||
always enforce opengl interface across all opengl calls jesus christ the bone uniform bug was impossible
|
always enforce opengl interface across all opengl calls jesus christ the bone uniform bug was impossible
|
||||||
|
|
||||||
|
Fix not all grass tiles update when updating a nearby voxel (ie it doesn't go into negative coordinates to scan for foliage updates)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -444,7 +444,6 @@ public class Globals {
|
|||||||
elementManager = new ElementManager();
|
elementManager = new ElementManager();
|
||||||
//script engine
|
//script engine
|
||||||
scriptEngine = new ScriptEngine();
|
scriptEngine = new ScriptEngine();
|
||||||
scriptEngine.init();
|
|
||||||
//ai manager
|
//ai manager
|
||||||
aiManager = new AIManager();
|
aiManager = new AIManager();
|
||||||
//realm & data cell manager
|
//realm & data cell manager
|
||||||
|
|||||||
@ -76,6 +76,9 @@ public class Main {
|
|||||||
//init global variables
|
//init global variables
|
||||||
Globals.initGlobals();
|
Globals.initGlobals();
|
||||||
|
|
||||||
|
//init scripting engine
|
||||||
|
Globals.scriptEngine.init();
|
||||||
|
|
||||||
//controls
|
//controls
|
||||||
if(Globals.RUN_CLIENT){
|
if(Globals.RUN_CLIENT){
|
||||||
initControlHandler();
|
initControlHandler();
|
||||||
|
|||||||
@ -56,10 +56,11 @@ public class SceneLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//load scripts
|
//load scripts
|
||||||
for(String scriptPath : file.getScriptPaths()){
|
//TODO: integrate scripts for client side of scenes
|
||||||
Globals.scriptEngine.loadScript(scriptPath);
|
// for(String scriptPath : file.getScriptPaths()){
|
||||||
}
|
// Globals.scriptEngine.loadScript(scriptPath);
|
||||||
Globals.scriptEngine.runScript(file.getInitScriptPath());
|
// }
|
||||||
|
// Globals.scriptEngine.runScript(file.getInitScriptPath());
|
||||||
|
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package electrosphere.logger;
|
package electrosphere.logger;
|
||||||
|
|
||||||
|
import org.graalvm.polyglot.HostAccess.Export;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A channel for logging messages
|
* A channel for logging messages
|
||||||
*/
|
*/
|
||||||
@ -56,6 +58,7 @@ public class Logger {
|
|||||||
* This should be used for messages that would have interest to someone running a server (ie specific network messages, account creation, etc)
|
* This should be used for messages that would have interest to someone running a server (ie specific network messages, account creation, etc)
|
||||||
* @param message The message to report
|
* @param message The message to report
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
public void INFO(String message){
|
public void INFO(String message){
|
||||||
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO){
|
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO){
|
||||||
System.out.println(message);
|
System.out.println(message);
|
||||||
@ -68,6 +71,7 @@ public class Logger {
|
|||||||
* This should be used for reporting events that happen in the engine that are concerning but don't mean the engine has failed to execute (ie a texture failed to load)
|
* This should be used for reporting events that happen in the engine that are concerning but don't mean the engine has failed to execute (ie a texture failed to load)
|
||||||
* @param message The message to report
|
* @param message The message to report
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
public void WARNING(String message){
|
public void WARNING(String message){
|
||||||
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO || level == LogLevel.WARNING){
|
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO || level == LogLevel.WARNING){
|
||||||
System.out.println(message);
|
System.out.println(message);
|
||||||
|
|||||||
@ -20,6 +20,7 @@ public class LoggerInterface {
|
|||||||
public static Logger loggerDB;
|
public static Logger loggerDB;
|
||||||
public static Logger loggerAudio;
|
public static Logger loggerAudio;
|
||||||
public static Logger loggerUI;
|
public static Logger loggerUI;
|
||||||
|
public static Logger loggerScripts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes all logic objects
|
* Initializes all logic objects
|
||||||
@ -35,6 +36,7 @@ public class LoggerInterface {
|
|||||||
loggerDB = new Logger(LogLevel.WARNING);
|
loggerDB = new Logger(LogLevel.WARNING);
|
||||||
loggerAudio = new Logger(LogLevel.WARNING);
|
loggerAudio = new Logger(LogLevel.WARNING);
|
||||||
loggerUI = new Logger(LogLevel.WARNING);
|
loggerUI = new Logger(LogLevel.WARNING);
|
||||||
|
loggerScripts = new Logger(LogLevel.WARNING);
|
||||||
loggerStartup.INFO("Initialized loggers");
|
loggerStartup.INFO("Initialized loggers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,11 +7,14 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.graalvm.polyglot.Context;
|
import org.graalvm.polyglot.Context;
|
||||||
import org.graalvm.polyglot.Engine;
|
import org.graalvm.polyglot.Engine;
|
||||||
|
import org.graalvm.polyglot.PolyglotException;
|
||||||
import org.graalvm.polyglot.Source;
|
import org.graalvm.polyglot.Source;
|
||||||
import org.graalvm.polyglot.Value;
|
import org.graalvm.polyglot.Value;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.util.FileUtils;
|
import electrosphere.util.FileUtils;
|
||||||
|
import electrosphere.util.MathUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for executing scripts in the game engine
|
* Interface for executing scripts in the game engine
|
||||||
@ -25,7 +28,37 @@ public class ScriptEngine {
|
|||||||
Map<String,Source> sourceMap;
|
Map<String,Source> sourceMap;
|
||||||
|
|
||||||
//the javascript object that stores values
|
//the javascript object that stores values
|
||||||
Value jsBindingsObject;
|
Value topLevelValue;
|
||||||
|
|
||||||
|
//the object that contains all host values accessible to javascript land
|
||||||
|
Value hostObject;
|
||||||
|
|
||||||
|
//The files that are loaded on init to bootstrap the script engine
|
||||||
|
static final String[] filesToLoadOnInit = new String[]{
|
||||||
|
//polyfills
|
||||||
|
"Scripts/compiler/require_polyfill.js",
|
||||||
|
|
||||||
|
//main typescript engine
|
||||||
|
"Scripts/compiler/typescript.js",
|
||||||
|
|
||||||
|
//compiler and utilities
|
||||||
|
"Scripts/compiler/file_resolution.js",
|
||||||
|
"Scripts/compiler/compiler.js",
|
||||||
|
"Scripts/compiler/host_access.js",
|
||||||
|
};
|
||||||
|
|
||||||
|
//The classes that will be provided to the scripting engine
|
||||||
|
//https://stackoverflow.com/a/65942034
|
||||||
|
static final Object[][] staticClasses = new Object[][]{
|
||||||
|
{"mathUtils",MathUtils.class},
|
||||||
|
};
|
||||||
|
|
||||||
|
//singletons from the host that are provided to the javascript context
|
||||||
|
static final Object[][] hostSingletops = new Object[][]{
|
||||||
|
{"timekeeper",Globals.timekeeper},
|
||||||
|
{"currentPlayer",Globals.clientPlayer},
|
||||||
|
{"loggerScripts",LoggerInterface.loggerScripts},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the engine
|
* Initializes the engine
|
||||||
@ -36,11 +69,42 @@ public class ScriptEngine {
|
|||||||
//create engine with flag to disable warning
|
//create engine with flag to disable warning
|
||||||
Engine engine = Engine.newBuilder().option("engine.WarnInterpreterOnly", "false").build();
|
Engine engine = Engine.newBuilder().option("engine.WarnInterpreterOnly", "false").build();
|
||||||
//create context
|
//create context
|
||||||
context = Context.newBuilder("js").engine(engine).build();
|
context = Context.newBuilder("js")
|
||||||
//read scripts into source map
|
.allowNativeAccess(false)
|
||||||
readScriptsDirectory("/src/main/sql", FileUtils.getAssetFile("/src/main/sql"));
|
.engine(engine)
|
||||||
|
.build();
|
||||||
//save the js bindings object
|
//save the js bindings object
|
||||||
jsBindingsObject = context.getBindings("js");
|
topLevelValue = context.getBindings("js");
|
||||||
|
|
||||||
|
//put host members into environment
|
||||||
|
putTopLevelValue("loggerScripts",LoggerInterface.loggerScripts);
|
||||||
|
|
||||||
|
//load all files required to start the engine
|
||||||
|
for(String fileToLoad : filesToLoadOnInit){
|
||||||
|
loadDependency(fileToLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
//define host members
|
||||||
|
defineHostMembers();
|
||||||
|
|
||||||
|
//register engine files
|
||||||
|
registerScriptDirectory("Scripts/engine",FileUtils.getAssetFile("Scripts/engine"));
|
||||||
|
|
||||||
|
//compile
|
||||||
|
compile();
|
||||||
|
|
||||||
|
//run script for engine init
|
||||||
|
requireModule("/Scripts/engine/engine-init.ts");
|
||||||
|
invokeModuleFunction("/Scripts/engine/engine-init.ts","ENGINE_onInit");
|
||||||
|
|
||||||
|
|
||||||
|
//call the engine initialization function
|
||||||
|
// invokeFunction("ENGINE_onInit");
|
||||||
|
|
||||||
|
System.exit(0);
|
||||||
|
|
||||||
|
//read scripts into source map
|
||||||
|
// readScriptsDirectory("/src/main/sql", FileUtils.getAssetFile("/src/main/sql"));
|
||||||
//create bindings
|
//create bindings
|
||||||
// try {
|
// try {
|
||||||
// String content = FileUtils.getAssetFileAsString("/Scripts/test.js");
|
// String content = FileUtils.getAssetFileAsString("/Scripts/test.js");
|
||||||
@ -59,7 +123,7 @@ public class ScriptEngine {
|
|||||||
* @param value The value that is stored at that variable
|
* @param value The value that is stored at that variable
|
||||||
*/
|
*/
|
||||||
public void putTopLevelValue(String valueName, Object value){
|
public void putTopLevelValue(String valueName, Object value){
|
||||||
jsBindingsObject.putMember(valueName, value);
|
topLevelValue.putMember(valueName, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,7 +132,16 @@ public class ScriptEngine {
|
|||||||
* @return The value of the variable
|
* @return The value of the variable
|
||||||
*/
|
*/
|
||||||
public Value getTopLevelValue(String valueName){
|
public Value getTopLevelValue(String valueName){
|
||||||
return jsBindingsObject.getMember(valueName);
|
return topLevelValue.getMember(valueName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a top level member from the javascript context
|
||||||
|
* @param valueName The name of the top level member
|
||||||
|
* @return true if successfully removed, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean removeTopLevelValue(String valueName){
|
||||||
|
return topLevelValue.removeMember(valueName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,17 +149,18 @@ public class ScriptEngine {
|
|||||||
* @param path The
|
* @param path The
|
||||||
* @param directory
|
* @param directory
|
||||||
*/
|
*/
|
||||||
void readScriptsDirectory(String path, File directory){
|
void registerScriptDirectory(String path, File directory){
|
||||||
if(directory.exists() && directory.isDirectory()){
|
if(directory.exists() && directory.isDirectory()){
|
||||||
File[] children = directory.listFiles();
|
File[] children = directory.listFiles();
|
||||||
for(File childFile : children){
|
for(File childFile : children){
|
||||||
String qualifiedName = path + "/" + childFile.getName();
|
String qualifiedName = path + "/" + childFile.getName();
|
||||||
if(childFile.isDirectory()){
|
if(childFile.isDirectory()){
|
||||||
readScriptsDirectory(qualifiedName,childFile);
|
registerScriptDirectory(qualifiedName,childFile);
|
||||||
} else {
|
} else {
|
||||||
//add to source map
|
//add to source map
|
||||||
String content = FileUtils.readFileToString(childFile);
|
registerFile(qualifiedName);
|
||||||
sourceMap.put(qualifiedName,Source.create("js",content));
|
// String content = FileUtils.readFileToString(childFile);
|
||||||
|
// sourceMap.put(qualifiedName,Source.create("js",content));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,15 +170,17 @@ public class ScriptEngine {
|
|||||||
* Loads a script from disk
|
* Loads a script from disk
|
||||||
* @param path The path to the script file
|
* @param path The path to the script file
|
||||||
*/
|
*/
|
||||||
public void loadScript(String path){
|
public void loadDependency(String path){
|
||||||
String content;
|
String content;
|
||||||
try {
|
try {
|
||||||
content = FileUtils.getAssetFileAsString(path);
|
content = FileUtils.getAssetFileAsString(path);
|
||||||
sourceMap.put(path,Source.create("js",content));
|
sourceMap.put(path,Source.create("js",content));
|
||||||
|
context.eval(sourceMap.get(path));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO Auto-generated catch block
|
LoggerInterface.loggerScripts.ERROR("FAILED TO LOAD SCRIPT", e);
|
||||||
|
} catch (PolyglotException e){
|
||||||
|
LoggerInterface.loggerScripts.ERROR("Script error", e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
LoggerInterface.loggerGameLogic.ERROR("FAILED TO LOAD SCRIPT", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,12 +189,96 @@ public class ScriptEngine {
|
|||||||
* @param path The filepath of the script
|
* @param path The filepath of the script
|
||||||
*/
|
*/
|
||||||
public void runScript(String path){
|
public void runScript(String path){
|
||||||
Source source = sourceMap.get(path);
|
invokeFunction("COMPILER_runFile", path);
|
||||||
if(source != null){
|
}
|
||||||
context.eval(source);
|
|
||||||
|
/**
|
||||||
|
* Prints the content of a file
|
||||||
|
* @param path The filepath of the script
|
||||||
|
*/
|
||||||
|
public void printScriptSource(String path){
|
||||||
|
invokeFunction("COMPILER_printSource", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a file with the scripting engine to be compiled into the full binary
|
||||||
|
* @param path The path to the script file
|
||||||
|
*/
|
||||||
|
private void registerFile(String path){
|
||||||
|
String content;
|
||||||
|
try {
|
||||||
|
content = FileUtils.getAssetFileAsString(path);
|
||||||
|
sourceMap.put(path,Source.create("js",content));
|
||||||
|
invokeFunction("COMPILER_registerFile",path,content);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LoggerInterface.loggerScripts.ERROR("FAILED TO LOAD SCRIPT", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the project
|
||||||
|
*/
|
||||||
|
private void compile(){
|
||||||
|
invokeFunction("COMPILER_run");
|
||||||
|
Value compiledCode = topLevelValue.getMember("COMPILER_emitted_value");
|
||||||
|
context.eval("js",compiledCode.asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls a function defined in the global scope with the arguments provided
|
||||||
|
* @param functionName The function name
|
||||||
|
* @param args The arguments
|
||||||
|
*/
|
||||||
|
public Value invokeFunction(String functionName, Object... args){
|
||||||
|
Value function = topLevelValue.getMember(functionName);
|
||||||
|
if(function != null){
|
||||||
|
return function.execute(args);
|
||||||
|
} else {
|
||||||
|
LoggerInterface.loggerScripts.WARNING("Failed to invoke function " + functionName);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes a function defined in a file
|
||||||
|
* @param filePath The file the function is defined in
|
||||||
|
* @param functionName The function's name
|
||||||
|
* @param args The args to pass into the function
|
||||||
|
*/
|
||||||
|
public void invokeModuleFunction(String filePath, String functionName, Object ... args){
|
||||||
|
Value filePathRaw = invokeFunction("FILE_RESOLUTION_getFilePath",filePath);
|
||||||
|
Value requireCache = topLevelValue.getMember("REQUIRE_CACHE");
|
||||||
|
Value module = requireCache.getMember(filePathRaw.asString());
|
||||||
|
Value exports = module.getMember("exports");
|
||||||
|
Value function = exports.getMember(functionName);
|
||||||
|
if(function != null && function.canExecute()){
|
||||||
|
function.execute(args);
|
||||||
|
} else {
|
||||||
|
LoggerInterface.loggerScripts.WARNING("Failed to invoke function " + functionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requires a module into the global space
|
||||||
|
* @param filePath The filepath of the module
|
||||||
|
*/
|
||||||
|
public void requireModule(String filePath){
|
||||||
|
invokeFunction("require", filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines host members within javascript context
|
||||||
|
*/
|
||||||
|
private void defineHostMembers(){
|
||||||
|
//remove top level members required for bootstrapping the engine
|
||||||
|
removeTopLevelValue("loggerScripts");
|
||||||
|
//give guest access to static classes
|
||||||
|
Value classes = hostObject.getMember("classes");
|
||||||
|
for(Object[] currentClass : staticClasses){
|
||||||
|
classes.putMember((String)currentClass[0], currentClass[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
9
tsconfig.json
Normal file
9
tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths" : {
|
||||||
|
"/*" : [
|
||||||
|
"./assets/Scripts/*"
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user