Compare commits
	
		
			No commits in common. "f2877edf376354ab7bb9adc498b9abb59730724d" and "14f4607c47b4504efcd7bd5e82bb392f7ca4fa84" have entirely different histories.
		
	
	
		
			f2877edf37
			...
			14f4607c47
		
	
		
| @ -1,10 +0,0 @@ | ||||
| { | ||||
|     "entities" : [], | ||||
|     "scriptPaths" : [], | ||||
|     "initScriptPath" : "/Scenes/defaultLevel_2/scene.ts", | ||||
|     "realmDescriptor" : { | ||||
|         "type" : "gridded", | ||||
|         "griddedRealmSize" : 2 | ||||
|     }, | ||||
|     "createSaveInstance" : true | ||||
| } | ||||
| @ -1,18 +0,0 @@ | ||||
| import { TrackedScene } from "/Scripts/engine/scene/scene-loader"; | ||||
| import { Scene } from "/Scripts/types/scene"; | ||||
| 
 | ||||
| /** | ||||
|  * The main scene interface | ||||
|  */ | ||||
| const TestScene1: Scene = { | ||||
|      | ||||
|     onCreate: (instanceId: number) => { | ||||
|         console.log('Hello from the scene! My ID is ' + instanceId) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * The scene to export | ||||
|  */ | ||||
| export default TestScene1 | ||||
| @ -1,479 +1,119 @@ | ||||
| 
 | ||||
| /** | ||||
|  * @description The compiler object | ||||
|  */ | ||||
| let COMPILER = { | ||||
| 
 | ||||
|     //
 | ||||
|     //
 | ||||
|     //    VIRTUAL FILE SYSTEM
 | ||||
|     //
 | ||||
|     //
 | ||||
| 
 | ||||
|     /** | ||||
|  * The map of all source files to their content and compiled value | ||||
|  */ | ||||
|     fileMap: { }, | ||||
| let COMPILER_fileMap = { } | ||||
| 
 | ||||
|     /** | ||||
|      * The list of all source files to compile | ||||
| /** | ||||
|  * The compiled program | ||||
|  */ | ||||
|     sourceFiles: [ ], | ||||
| let COMPILER_emitted_value = '' | ||||
| 
 | ||||
|     /** | ||||
|      * The top level directory, "/" | ||||
|      */ | ||||
|     topLevelDirectory: { | ||||
|         //as required by our framework
 | ||||
|         Scripts: { | ||||
|             compiler: { | ||||
|                 "host_access.js": { | ||||
|                     content: "", | ||||
|                     version: 0, | ||||
|                 }, | ||||
|                 version: 0, | ||||
|                 isDir: true, | ||||
|             }, | ||||
|             version: 0, | ||||
|             isDir: true, | ||||
|         }, | ||||
|         //as required by language service
 | ||||
|         node_modules: { | ||||
|             "@types": { | ||||
|                 "lib.d.ts": { | ||||
|                     content: "", | ||||
|                     version: 0, | ||||
|                     isDir: false, | ||||
|                 }, | ||||
|                 version: 0, | ||||
|                 isDir: true, | ||||
|             }, | ||||
|             version: 0, | ||||
|             isDir: true, | ||||
|         }, | ||||
|         version: 0, | ||||
|         isDir: true, | ||||
|     }, | ||||
| 
 | ||||
|     /** | ||||
|      * The current directory, "/" | ||||
|      */ | ||||
|     currentDirectory : { }, | ||||
| 
 | ||||
|     /** | ||||
| /** | ||||
|  * Registers a file with the compiler | ||||
|      * @param {string} fileName The file's name | ||||
|      * @param {string} content The content of the file | ||||
|      * @returns {string[]} The list of all files that still need to be registered by the host | ||||
|  * @param {*} fileName The file's name | ||||
|  * @param {*} content The content of the file | ||||
|  */ | ||||
|     registerFile: (fileName, content) => { | ||||
| 
 | ||||
|         //the list of files that are imported by this file
 | ||||
|         let dependentFiles = [] | ||||
|      | ||||
|         loggerScripts.INFO('REGISTER FILE ' + fileName) | ||||
|         if(!COMPILER.fileMap[fileName]){ | ||||
|             //create the virtual file
 | ||||
|             COMPILER.fileMap[fileName] = COMPILER.createFile(fileName,content) | ||||
|             //register the file itself
 | ||||
|             COMPILER.fileMap[fileName].tsSourceFile = ts.createSourceFile( | ||||
|                 fileName, | ||||
|                 content, | ||||
|                 ts.ScriptTarget.Latest, | ||||
|             ) | ||||
|             COMPILER.sourceFiles.push(fileName) | ||||
|             /** | ||||
|              * The preprocessed info about the file | ||||
|              * { | ||||
|              *   referencedFiles: ?, | ||||
|              *   typeReferenceDirectives: ?, | ||||
|              *   libReferenceDirectives: ?, | ||||
|              *   importedFiles: Array<{ | ||||
|              *     fileName: string, //the path (without file ending) of the file that is imported by this file
 | ||||
|              *     pos: ?, | ||||
|              *     end: ?, | ||||
|              *   }>, | ||||
|              *   isLibFile: boolean, | ||||
|              *   ambientExternalModules: ?, | ||||
|              * } | ||||
|              */ | ||||
|             const fileInfo = ts.preProcessFile(content) | ||||
|             loggerScripts.INFO('==========================') | ||||
|             loggerScripts.INFO(fileName) | ||||
|             loggerScripts.INFO('Registered file depends on:') | ||||
|             fileInfo.importedFiles.forEach(module => { | ||||
|                 let extension = ".ts" | ||||
|                 /** | ||||
|                  * { | ||||
|                  *   resolvedModule: ?, | ||||
|                  *   failedLookupLocations: Array<string>, | ||||
|                  *   affectingLocations: ?, | ||||
|                  *   resolutionDiagnostics: ?, | ||||
|                  *   alternateResult: ?, | ||||
|                  * } | ||||
|                  */ | ||||
|                 const resolvedImport = ts.resolveModuleName(module.fileName,fileName,COMPILER.compilerOptions,COMPILER.customCompilerHost) | ||||
|                 if(resolvedImport?.resolvedModule){ | ||||
|                     /** | ||||
|                      * undefined | ||||
|                      * OR | ||||
|                      * { | ||||
|                      *   resolvedFileName: ?, | ||||
|                      *   originalPath: ?, | ||||
|                      *   extension: string, (ie ".js", ".ts", etc) | ||||
|                      *   isExternalLibraryImport: boolean, | ||||
|                      *   packageId: ?, | ||||
|                      *   resolvedUsingTsExtension: boolean, | ||||
|                      * } | ||||
|                      */ | ||||
|                     const module = resolvedImport.resolvedModule | ||||
|                     extension = module.extension | ||||
|                 } | ||||
|                 //am assuming we're always importing typescript for the time being
 | ||||
|                 const dependentFile = module.fileName + extension | ||||
|                 const normalizedDependentFilePath = FILE_RESOLUTION_getFilePath(dependentFile,false) | ||||
|                 if(!COMPILER.fileMap[normalizedDependentFilePath]){ | ||||
|                     dependentFiles.push(normalizedDependentFilePath) | ||||
|                     loggerScripts.INFO(" - " + normalizedDependentFilePath) | ||||
|                 } | ||||
|             }) | ||||
|      | ||||
|             //If the compiler has already run once, run the language service against only this file
 | ||||
|             if(!!COMPILER.compilerHasRun){ | ||||
|                 COMPILER.emitFile(fileName) | ||||
|             } | ||||
|         } | ||||
|         return dependentFiles; | ||||
|     }, | ||||
| 
 | ||||
|     /** | ||||
|      * Creates a file object for a given path | ||||
|      * @param string} fileName The name of the file | ||||
|      * @param {string} content The content of the file | ||||
|      * @returns The file object | ||||
|      */ | ||||
|     createFile: (fileName, content) => { | ||||
|         //get the file path array
 | ||||
|         const filePathArray = COMPILER.getPath(fileName) | ||||
|         let mutableArray = filePathArray | ||||
|      | ||||
|         //the current folder as we recursively create folders to populate this file
 | ||||
|         let currentFolder = COMPILER.topLevelDirectory | ||||
|      | ||||
|         //recursively create directories until our file is written
 | ||||
|         while(mutableArray.length > 1){ | ||||
|             let nextDirName = mutableArray.shift() | ||||
|             if(!currentFolder?.[nextDirName]){ | ||||
|                 //create directory
 | ||||
|                 currentFolder[nextDirName] = { | ||||
|                     isDir: true, | ||||
|                     "..": currentFolder, | ||||
|                 } | ||||
|             } | ||||
|             currentFolder = currentFolder?.[nextDirName] | ||||
|         } | ||||
|      | ||||
|         //create the actual file
 | ||||
|         currentFolder[mutableArray[0]] = { | ||||
|             isDir: false, | ||||
|             dir: currentFolder, | ||||
| const COMPILER_registerFile = (fileName, content) => { | ||||
|     let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName,false) | ||||
|     loggerScripts.INFO('REGISTER FILE ' + normalizedFilePath) | ||||
|     COMPILER_fileMap[normalizedFilePath] = { | ||||
|         content: content, | ||||
|             version: 0, | ||||
|         compiled: ts.createSourceFile( | ||||
|             normalizedFilePath, content, ts.ScriptTarget.Latest | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|         //return the file
 | ||||
|         return currentFolder[mutableArray[0]] | ||||
|     }, | ||||
| 
 | ||||
|     /** | ||||
|      * Gets the path for the file | ||||
|      * @param {string} fullyQualifiedFilePath The fully qualified file path | ||||
|      * @returns {string[]} The array of directories ending with the name of the file | ||||
|      */ | ||||
|     getPath: (fullyQualifiedFilePath) => { | ||||
|         let modifiedFileName = fullyQualifiedFilePath | ||||
|         //remove leading "/"
 | ||||
|         if(modifiedFileName.startsWith("/")){ | ||||
|             modifiedFileName = modifiedFileName.substring(1) | ||||
|         } | ||||
|         //split
 | ||||
|         return modifiedFileName.split("/") | ||||
|     }, | ||||
| 
 | ||||
|     /** | ||||
|      * Gets the path for the file | ||||
|      * @param {stringp[]} filePathArray The fully qualified file path | ||||
|      * @returns The array of directories ending with the name of the file | ||||
|      */ | ||||
|     getFileByPath: (filePathArray) => { | ||||
|         let currentFolder = COMPILER.topLevelDirectory | ||||
|         let mutableArray = filePathArray | ||||
|      | ||||
|         //illegal state
 | ||||
|         if(mutableArray?.length < 1){ | ||||
|             throw new Error("Trying to get a file with a path array of length 0!") | ||||
|         } | ||||
|      | ||||
|         while(mutableArray?.length > 1){ | ||||
|             let nextDirName = mutableArray.shift() | ||||
|             currentFolder = currentFolder?.[nextDirName] | ||||
|             if(!currentFolder){ | ||||
|                 let errorMessage = "Trying to get file in directory that doesn't exist! \n" + | ||||
|                 nextDirName | ||||
|                 throw new Error(errorMessage) | ||||
|             } | ||||
|         } | ||||
|         return currentFolder[mutableArray?.[0]] | ||||
|     }, | ||||
| 
 | ||||
|     /** | ||||
|      * Checks if a file exists | ||||
|      * @param {string[]} filePathArray The file path array | ||||
|      * @returns true if it exists, false otherwise | ||||
|      */ | ||||
|     fileExists: (filePathArray) => { | ||||
|         let currentFolder = COMPILER.topLevelDirectory | ||||
|         let mutableArray = filePathArray | ||||
|      | ||||
|         //illegal state
 | ||||
|         if(mutableArray?.length < 1){ | ||||
|             throw new Error("Trying to get a file with a path array of length 0!") | ||||
|         } | ||||
|      | ||||
|         while(mutableArray.length > 1){ | ||||
|             let nextDirName = mutableArray.shift() | ||||
|             currentFolder = currentFolder?.[nextDirName] | ||||
|             if(!currentFolder){ | ||||
|                 return false | ||||
|             } | ||||
|         } | ||||
|         return !!currentFolder?.[mutableArray[0]] | ||||
|     }, | ||||
| 
 | ||||
|     /** | ||||
| /** | ||||
|  * The callback invoked when the compiler host tries to read a file | ||||
|      * @param {string} fileName The name of the file | ||||
|  * @param {*} fileName The name of the file | ||||
|  * @param {*} languageVersion The language version | ||||
|  * @returns The file if it exists, null otherwise | ||||
|  */ | ||||
|     getSourceFile: (fileName, languageVersion) => { | ||||
|         if(!!COMPILER.fileMap[fileName]){ | ||||
|             return COMPILER.fileMap[fileName].tsSourceFile | ||||
| const COMPILER_getSourceFile = (fileName, languageVersion) => { | ||||
|     if(!!COMPILER_fileMap[fileName]){ | ||||
|         return COMPILER_fileMap[fileName].compiled | ||||
|     } else { | ||||
|         return null | ||||
|     } | ||||
|     }, | ||||
| 
 | ||||
| 
 | ||||
|     //
 | ||||
|     //
 | ||||
|     //   COMPILATION
 | ||||
|     //
 | ||||
|     //
 | ||||
| 
 | ||||
|     /** | ||||
|      * The compiler options | ||||
|      */ | ||||
|     compilerOptions: { }, | ||||
| 
 | ||||
|     /** | ||||
|      * Tracks whether the compiler has run or not | ||||
|      */ | ||||
|     compilerHasRun: false, | ||||
| 
 | ||||
|     /** | ||||
|      * The typescript compiler host definition | ||||
|      */ | ||||
|     customCompilerHost: null, | ||||
| 
 | ||||
|     /** | ||||
|      * The typescript program | ||||
|      */ | ||||
|     program: null, | ||||
| 
 | ||||
|     /** | ||||
|      * Emits a file | ||||
|      * @param {string} fileName The name of the file | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     emitFile: (fileName) => { | ||||
|         loggerScripts.DEBUG('Compiler evaluating source path ' + fileName) | ||||
|         /** | ||||
|          * { | ||||
|          *   outputFiles: [ ], | ||||
|          *   emitSkipped: boolean, | ||||
|          *   diagnostics: { }, | ||||
|          * } | ||||
|          */ | ||||
|         const output = COMPILER.program.getEmitOutput(fileName) | ||||
|         if (!output.emitSkipped) { | ||||
|             output.outputFiles.forEach(outputFile => { | ||||
|                 loggerScripts.DEBUG(`[ts] Emitting ${outputFile}`); | ||||
|                 COMPILER.customCompilerHost.writeFile(outputFile.name, outputFile.text) | ||||
|             }) | ||||
|         } else { | ||||
|             loggerScripts.DEBUG(`[ts] Emitting ${fileName} failed`); | ||||
|             COMPILER.logEmitError(fileName); | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|     /** | ||||
|      * Logs errors raised during emission of files | ||||
|      * @param {string} fileName The name of the file to log errors about | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     logEmitError: (fileName) => { | ||||
|         loggerScripts.DEBUG('[ts] logErrors ' + fileName) | ||||
|         let allDiagnostics = services | ||||
|             .getCompilerOptionsDiagnostics() | ||||
|             .concat(services.getSyntacticDiagnostics(fileName)) | ||||
|             .concat(services.getSemanticDiagnostics(fileName)); | ||||
|      | ||||
|         allDiagnostics.forEach(diagnostic => { | ||||
|             let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); | ||||
|             if (diagnostic.file) { | ||||
|                 let { line, character } = diagnostic.file.getLineAndCharacterOfPosition( | ||||
|                     diagnostic.start | ||||
|                 ); | ||||
|                 loggerScripts.DEBUG(`[ts]  Error ${diagnostic.file.fileName} (${line + 1},${character +1}): ${message}`); | ||||
|             } else { | ||||
|                 loggerScripts.DEBUG(`[ts]  Error: ${message}`); | ||||
|             } | ||||
|         }); | ||||
|     }, | ||||
| 
 | ||||
|     /** | ||||
|      * Instructs Typescript to emit the final compiled value | ||||
|      */ | ||||
|     run: () => { | ||||
|         loggerScripts.INFO('COMPILE ALL REGISTERED FILES') | ||||
|      | ||||
|         if(!COMPILER.program){ | ||||
|             COMPILER.program = ts.createLanguageService(COMPILER.customCompilerHost, ts.createDocumentRegistry()); | ||||
|         } | ||||
|      | ||||
|         //Emit all currently known files
 | ||||
|         COMPILER.sourceFiles.forEach(sourcePath => { | ||||
|             COMPILER.emitFile(sourcePath) | ||||
|         }) | ||||
|      | ||||
|         //flag that the compiler has run (ie only incrementally compile when new files are added, now)
 | ||||
|         COMPILER.compilerHasRun = true | ||||
|     }, | ||||
| 
 | ||||
|     /** | ||||
|      * Loads a file | ||||
|      * @param {*} fileName The name of the file to load (preferably already has .ts at the end) | ||||
|      */ | ||||
|     runFile: (fileName) => { | ||||
|         let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName) | ||||
|         if(!!COMPILER.fileMap[normalizedFilePath]){ | ||||
|             loggerScripts.INFO('RUN FILE ' + normalizedFilePath) | ||||
|             eval(COMPILER.fileMap[normalizedFilePath].content) | ||||
|         } else { | ||||
|             const message = 'FAILED TO RESOLVE FILE ' + normalizedFilePath | ||||
|             loggerScripts.WARNING(message) | ||||
|             throw new Error(message) | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|     /** | ||||
|      * Loads a file | ||||
|      * @param {*} fileName The name of the file to load (preferably already has .ts at the end) | ||||
|      */ | ||||
|     printSource: (fileName) => { | ||||
|         let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName) | ||||
|         if(!!COMPILER.fileMap[normalizedFilePath]){ | ||||
|             loggerScripts.INFO('FILE CONTENT ' + normalizedFilePath) | ||||
|         } else { | ||||
|             const message = 'FAILED TO RESOLVE FILE ' + normalizedFilePath | ||||
|             loggerScripts.WARNING(message) | ||||
|             loggerScripts.WARNING('file map content:') | ||||
|             loggerScripts.WARNING(OBject.keys(COMPILER.fileMap) + "") | ||||
|             throw new Error(message) | ||||
|         } | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Constructs the compiler host | ||||
|  * https://www.typescriptlang.org/tsconfig/#compilerOptions
 | ||||
|  *  | ||||
|  * Examples: | ||||
|  * https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API
 | ||||
|  *  | ||||
|  */ | ||||
| COMPILER.customCompilerHost = { | ||||
|     getSourceFile: COMPILER.getSourceFile, | ||||
| const COMPILER_customCompilerHost = { | ||||
|     getSourceFile: COMPILER_getSourceFile, | ||||
|     writeFile: (fileName, data) => { | ||||
|         loggerScripts.INFO("EMIT FILE " + fileName) | ||||
|         //wrap in require logic
 | ||||
|         let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName) | ||||
|         loggerScripts.INFO("EMIT FILE " + normalizedFilePath) | ||||
|         let finalData =  | ||||
|         "let exports = { }\n" + | ||||
|         data + "\n" + | ||||
|         "return exports" | ||||
| 
 | ||||
|         //create file
 | ||||
|         COMPILER.createFile(fileName,finalData) | ||||
|          | ||||
|         //register in file map
 | ||||
|         COMPILER.fileMap[fileName] = { | ||||
|         // 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: ts.getDefaultLibFileName, | ||||
|     getDefaultLibFileName: () => "lib.d.ts", | ||||
|     useCaseSensitiveFileNames: () => false, | ||||
|     getCanonicalFileName: filename => filename, | ||||
|     getCurrentDirectory: () => "/", | ||||
|     getCurrentDirectory: () => "", | ||||
|     getNewLine: () => "\n", | ||||
|     getDirectories: (path) => { | ||||
|         loggerScripts.DEBUG('[ts] getDirectories ' + path) | ||||
|         const dirs = Object.keys(COMPILER.getFileByPath(COMPILER.getPath(path))) | ||||
|         loggerScripts.DEBUG('[ts] dirs: ' + dirs) | ||||
|         return dirs | ||||
|     }, | ||||
|     directoryExists: (path) => { | ||||
|         let exists = COMPILER.fileExists(COMPILER.getPath(path)) | ||||
|         if(exists){ | ||||
|             exists = COMPILER.getFileByPath(COMPILER.getPath(path))?.isDir | ||||
|         } | ||||
|         loggerScripts.DEBUG('[ts] directoryExists ' + path + " - " + exists) | ||||
|         return false | ||||
|     }, | ||||
|     fileExists: (path) => { | ||||
|         const exists = COMPILER.fileExists(COMPILER.getPath(path)) | ||||
|         loggerScripts.DEBUG('[ts] fileExists ' + path + " - " + exists) | ||||
|         return exists | ||||
|     }, | ||||
|     readFile: (path) => { | ||||
|         loggerScripts.DEBUG('[ts] readFile ' + path) | ||||
|         const file = COMPILER.getFileByPath(COMPILER.getPath(path)) | ||||
|         loggerScripts.DEBUG('[ts] readFile (content): ' + file.content) | ||||
|         return file.content | ||||
|     }, | ||||
|     getScriptFileNames: () => { | ||||
|         loggerScripts.DEBUG('[ts] getScriptFileNames') | ||||
|         return COMPILER.sourceFiles | ||||
|     }, | ||||
|     getScriptVersion: (fileName) => { | ||||
|         loggerScripts.DEBUG('[ts] getScriptVersion: ' + fileName) | ||||
|         const file = COMPILER.getFileByPath(COMPILER.getPath(fileName)) | ||||
|         return file?.version | ||||
|     }, | ||||
|     //https://github.com/microsoft/TypeScript/wiki/Using-the-Language-Service-API#scriptsnapshot
 | ||||
|     getScriptSnapshot: (fileName) => { | ||||
|         loggerScripts.DEBUG('[ts] getScriptSnapshot: ' + fileName) | ||||
|         const file = COMPILER.getFileByPath(COMPILER.getPath(fileName)) | ||||
|         if(file){ | ||||
|             return ts.ScriptSnapshot.fromString(file.content) | ||||
|         } else { | ||||
|             return undefined | ||||
|         } | ||||
|     }, | ||||
|     getCompilationSettings: () => COMPILER.compilerOptions, | ||||
|     getDirectories: () => [], | ||||
|     fileExists: () => true, | ||||
|     readFile: () => "" | ||||
| } | ||||
| 
 | ||||
| //initialized CWD
 | ||||
| COMPILER.currentDirectory = COMPILER.topLevelDirectory | ||||
| /** | ||||
|  * 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 { | ||||
|         const message = 'FAILED TO RESOLVE FILE ' + normalizedFilePath | ||||
|         loggerScripts.WARNING(message) | ||||
|         throw new Error(message) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 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 { | ||||
|         const message = 'FAILED TO RESOLVE FILE ' + normalizedFilePath | ||||
|         loggerScripts.WARNING(message) | ||||
|         loggerScripts.WARNING('file map content:') | ||||
|         loggerScripts.WARNING(OBject.keys(COMPILER_fileMap) + "") | ||||
|         throw new Error(message) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -10,10 +10,10 @@ const FILE_RESOLUTION_getFilePath = (rawFilePath, isJavascript = true) => { | ||||
|         fileName = fileName.replace('.ts','.js') | ||||
|     } | ||||
|     if(fileName.startsWith('/Scripts')){ | ||||
|         // fileName = fileName.replace('/Scripts','')
 | ||||
|         fileName = fileName.replace('/Scripts','') | ||||
|     } | ||||
|     if(fileName.startsWith('Scripts')){ | ||||
|         fileName = fileName.replace('Scripts','/Scripts') | ||||
|     if(fileName.startsWith('Scripts/')){ | ||||
|         fileName = fileName.replace('Scripts/','/') | ||||
|     } | ||||
|     if(isJavascript && !fileName.endsWith(".js")){ | ||||
|         fileName = fileName + ".js" | ||||
|  | ||||
| @ -8,14 +8,14 @@ let HOST_ACCESS = { | ||||
| } | ||||
| 
 | ||||
| //fake require
 | ||||
| REQUIRE_CACHE["/Scripts/compiler/host_access.js"] = { | ||||
| REQUIRE_CACHE["/compiler/host_access.js"] = { | ||||
|     exports: { | ||||
|         'HOST_ACCESS': HOST_ACCESS, | ||||
|         'loggerScripts': loggerScripts, | ||||
|     }, | ||||
|     exportedValues: [ | ||||
|         'HOST_ACCESS', | ||||
|         'loggerScripts', | ||||
|         'loggerScripts' | ||||
|     ], | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -16,24 +16,13 @@ let exports = { } | ||||
|  * @param {*} cwd The current working directory | ||||
|  */ | ||||
| const require = (path) => { | ||||
|     //get the path
 | ||||
|     loggerScripts.DEBUG('Require path ' + path) | ||||
|     let normalizedFilePath = FILE_RESOLUTION_getFilePath(path) | ||||
| 
 | ||||
|     //actually require
 | ||||
|     if(!!REQUIRE_CACHE[normalizedFilePath]){ | ||||
|         //return if has already been required
 | ||||
|         return REQUIRE_CACHE[normalizedFilePath].exports | ||||
|     } else if(!!COMPILER.fileMap[normalizedFilePath]?.content) { | ||||
|         //require if it is already registered
 | ||||
|         const code = COMPILER.fileMap[normalizedFilePath].moduleContent | ||||
|     } else if(!!COMPILER_fileMap[normalizedFilePath]?.content) { | ||||
|         const code = COMPILER_fileMap[normalizedFilePath].moduleContent | ||||
|         loggerScripts.DEBUG('Module code ' + JSON.stringify(code)) | ||||
|         //create dummy prior to fully evaluating code so that we don't recurse infinitely
 | ||||
|         REQUIRE_CACHE[normalizedFilePath] = { | ||||
|             exports: {}, | ||||
|             exportedValues: [], | ||||
|         } | ||||
|         //evaluate script for exports
 | ||||
|         let exports = new Function(code)() | ||||
|         //create module object
 | ||||
|         const module = { | ||||
| @ -44,7 +33,6 @@ const require = (path) => { | ||||
|         loggerScripts.INFO("[require] CREATE MODULE " + normalizedFilePath) | ||||
|         return module.exports | ||||
|     } else { | ||||
|         //fail if it doesn't exist from host's view
 | ||||
|         const errorMsg = "FAILED TO REQUIRE FILE " + normalizedFilePath | ||||
|         loggerScripts.WARNING(errorMsg) | ||||
|         loggerScripts.WARNING('Module value:') | ||||
| @ -53,19 +41,7 @@ const require = (path) => { | ||||
|         loggerScripts.WARNING('Require cache contents:') | ||||
|         loggerScripts.WARNING(Object.keys(REQUIRE_CACHE) + '') | ||||
|         loggerScripts.WARNING('File cache contents:') | ||||
|         loggerScripts.WARNING(Object.keys(COMPILER.fileMap) + '') | ||||
|         loggerScripts.WARNING(Object.keys(COMPILER_fileMap) + '') | ||||
|         throw new Error(errorMsg) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| //Add require to its own cache
 | ||||
| REQUIRE_CACHE["/Scripts/compiler/require_polyfill.js"] = { | ||||
|     exports: { | ||||
|         'require': require, | ||||
|         'exports': exports, | ||||
|     }, | ||||
|     exportedValues: [ | ||||
|         'require', | ||||
|         'exports', | ||||
|     ], | ||||
| } | ||||
|  | ||||
| @ -1,8 +1,7 @@ | ||||
| import { Engine } from '/Scripts/engine/engine-interface' | ||||
| import { loggerScripts } from '/Scripts/compiler/host_access' | ||||
| import { Client, NamespaceClient } from '/Scripts/client/client' | ||||
| import { HookManager } from '/Scripts/engine/hooks/hook-manager' | ||||
| import { SceneLoader } from '/Scripts/engine/scene/scene-loader' | ||||
| import { HookManager } from '/Scripts/engine/hook-manager' | ||||
| 
 | ||||
| /** | ||||
|  * The core engine values | ||||
| @ -11,7 +10,6 @@ export const engine: Engine = { | ||||
|     classes: [], | ||||
|     singletons: [], | ||||
|     hookManager: new HookManager(), | ||||
|     sceneLoader: new SceneLoader(), | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| @ -22,7 +20,6 @@ export const ENGINE_onInit = () => { | ||||
| 
 | ||||
|     //load namespaces
 | ||||
|     let client: NamespaceClient = Client | ||||
|     engine.sceneLoader.hookManager = engine.hookManager | ||||
| 
 | ||||
|     loggerScripts.INFO('Script Engine Initialized') | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| import { HookManager } from "/Scripts/engine/hooks/hook-manager"; | ||||
| import { SceneLoader } from "/Scripts/engine/scene/scene-loader"; | ||||
| import { HookManager } from "/Scripts/engine/hook-manager"; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
| @ -22,9 +21,4 @@ export interface Engine { | ||||
|      */ | ||||
|     hookManager: HookManager, | ||||
|      | ||||
|     /** | ||||
|      * Tracks and loads scenes | ||||
|      */ | ||||
|     sceneLoader: SceneLoader, | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| import { TrackedScene } from "/Scripts/engine/scene/scene-loader" | ||||
| import { Hook } from "/Scripts/types/hook" | ||||
| import { Scene } from "/Scripts/types/scene" | ||||
| 
 | ||||
| @ -16,7 +15,7 @@ export enum HookScope { | ||||
| /** | ||||
|  * A hook that is tracked by the manager | ||||
|  */ | ||||
| export interface TrackedHook extends Hook { | ||||
| interface TrackedHook extends Hook { | ||||
| 
 | ||||
|     /** | ||||
|      * The scope that this hook was defined at | ||||
| @ -30,6 +29,23 @@ export interface TrackedHook extends Hook { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * A scene being tracked by the manager | ||||
|  */ | ||||
| interface TrackedScene { | ||||
| 
 | ||||
|     /** | ||||
|      * The id assigned to the scene | ||||
|      */ | ||||
|     sceneId: number, | ||||
| 
 | ||||
|     /** | ||||
|      * The scene itself | ||||
|      */ | ||||
|     scene: Scene, | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Manages hooks for the engine | ||||
|  */ | ||||
| @ -40,6 +56,11 @@ export class HookManager { | ||||
|      */ | ||||
|     hooks: Array<TrackedHook> = [] | ||||
| 
 | ||||
|     /** | ||||
|      * A map of a scene to all hooks related to the scene | ||||
|      */ | ||||
|     sceneHookMap: Record<number,Array<TrackedHook>> = { } | ||||
| 
 | ||||
|     /** | ||||
|      * A map of engine signal to the list of hooks that should be called when that signal fires | ||||
|      */ | ||||
| @ -48,7 +69,57 @@ export class HookManager { | ||||
|     /** | ||||
|      * The list of all scenes tracked by the manager | ||||
|      */ | ||||
|     trackedScenes: Array<TrackedScene> = [] | ||||
|     trackedScenes: Array<{ sceneId: number, scene: Scene }> = [] | ||||
| 
 | ||||
|     /** | ||||
|      * A scene  | ||||
|      */ | ||||
|     sceneIdIncrementer: number = 0 | ||||
| 
 | ||||
|     /** | ||||
|      * Registers all hooks in a scene to the hook manager | ||||
|      * @param scene The scene | ||||
|      */ | ||||
|     registerScene(scene: Scene, isServerScene: boolean){ | ||||
|         const shouldRegister: boolean = !this.containsScene(scene) | ||||
|         if(shouldRegister){ | ||||
| 
 | ||||
|             //add to the list of tracked scenes
 | ||||
|             const trackedScene: TrackedScene = { | ||||
|                 sceneId: this.sceneIdIncrementer++, | ||||
|                 scene: scene, | ||||
|             } | ||||
|             this.trackedScenes.push(trackedScene) | ||||
| 
 | ||||
|             //load all hooks from the scene
 | ||||
|             scene.hooks.forEach((hook: Hook) => { | ||||
|                 this.registerHook(trackedScene,hook,isServerScene) | ||||
|             }) | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Deregisters all hooks in a scene from the hook manager | ||||
|      * @param scene The scene | ||||
|      */ | ||||
|     deregisterScene(scene: Scene){ | ||||
|         throw new Error("Unsupported Operation!") | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Checks if the manager is tracking a given scene | ||||
|      * @param scene The scene | ||||
|      * @returns true if it is being tracked already, false otherwise | ||||
|      */ | ||||
|     containsScene(scene: Scene): boolean { | ||||
|         this.trackedScenes.forEach(trackedScene => { | ||||
|             if(trackedScene.scene === scene){ | ||||
|                 return true | ||||
|             } | ||||
|         }) | ||||
|         return false | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Registers a hook | ||||
| @ -68,19 +139,10 @@ export class HookManager { | ||||
|         const signalArray: Array<TrackedHook> = this.signalHookMap?.[hookSignal] ? this.signalHookMap?.[hookSignal] : [] | ||||
|         signalArray.push(trackedHook) | ||||
|         this.signalHookMap[hookSignal] = signalArray | ||||
|         //
 | ||||
|         //Scene related structures
 | ||||
|         //
 | ||||
|         //track scene if it isn't already being tracked
 | ||||
|         let filteredArr = this.trackedScenes.filter(trackedScene => trackedScene.instanceId === scene.instanceId) | ||||
|         if(filteredArr.length < 1){ | ||||
|             this.trackedScenes.push(scene) | ||||
|         } | ||||
|         //add to scene tracking structures
 | ||||
|         scene.sceneHooks.push(trackedHook) | ||||
|         const sceneSignalArray: Array<TrackedHook> = scene.signalHookMap?.[hookSignal] ? scene.signalHookMap?.[hookSignal] : [] | ||||
|         sceneSignalArray.push(trackedHook) | ||||
|         scene.signalHookMap[hookSignal] = sceneSignalArray | ||||
|         //add to scene array
 | ||||
|         const sceneArray: Array<TrackedHook> = this.sceneHookMap?.[scene.sceneId] ? this.sceneHookMap?.[scene.sceneId] : [] | ||||
|         sceneArray.push(trackedHook) | ||||
|         this.sceneHookMap[scene.sceneId] = sceneArray | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -97,7 +159,7 @@ export class HookManager { | ||||
|      * @param signal The signal | ||||
|      * @param value The value associated with the signal | ||||
|      */ | ||||
|     fireSignal(instanceId: number, signal: string, value: any){ | ||||
|     fireSignal(signal: string, value: any){ | ||||
|         const hooks: Array<TrackedHook> = this.signalHookMap[signal] | ||||
|         hooks.forEach(trackedHook => { | ||||
|             trackedHook.callback(value) | ||||
| @ -1,137 +0,0 @@ | ||||
| import { engine } from "/Scripts/engine/engine-init"; | ||||
| import { HookManager, TrackedHook } from "/Scripts/engine/hooks/hook-manager"; | ||||
| import { Hook } from "/Scripts/types/hook"; | ||||
| import { Scene } from "/Scripts/types/scene"; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * A scene being tracked by the manager | ||||
|  */ | ||||
| export interface TrackedScene { | ||||
| 
 | ||||
|     /** | ||||
|      * The id assigned to the scene | ||||
|      */ | ||||
|     instanceId: number, | ||||
| 
 | ||||
|     /** | ||||
|      * The scene itself | ||||
|      */ | ||||
|     scene: Scene, | ||||
| 
 | ||||
|     /** | ||||
|      * A map of a scene to all hooks related to the scene | ||||
|      */ | ||||
|     sceneHooks: Array<TrackedHook> | ||||
| 
 | ||||
|     /** | ||||
|      * A map of engine signal to the list of hooks that should be called when that signal fires | ||||
|      */ | ||||
|     signalHookMap: Record<string,Array<TrackedHook>> | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Loads scenes | ||||
|  */ | ||||
| export class SceneLoader { | ||||
| 
 | ||||
| 
 | ||||
|      | ||||
|     /** | ||||
|      * The hook manager | ||||
|      */ | ||||
|     hookManager: HookManager | ||||
| 
 | ||||
|     /** | ||||
|      * The list of loaded scenes | ||||
|      */ | ||||
|     loadedScenes: TrackedScene[] = [ ] | ||||
| 
 | ||||
|     /** | ||||
|      * A record of tracked scene id to tracked scene object | ||||
|      */ | ||||
|     sceneIdMap: Record<number,TrackedScene> = { } | ||||
| 
 | ||||
|     /** | ||||
|      * A scene  | ||||
|      */ | ||||
|     sceneIdIncrementer: number = 0 | ||||
| 
 | ||||
|     /** | ||||
|      * Loads a scene | ||||
|      * @param sceneName The scene to load | ||||
|      * @returns The id assigned to the instance of the scene | ||||
|      */ | ||||
|     loadScene(sceneName: string): number { | ||||
|         //@ts-ignore
 | ||||
|         const scene: Scene = require(sceneName).default | ||||
| 
 | ||||
|         //creates an instance of the scene
 | ||||
|         let sceneInstanceId: number = this.createInstance(scene,true) | ||||
| 
 | ||||
|         //call on init for scene
 | ||||
|         if(scene.onCreate){ | ||||
|             scene.onCreate(sceneInstanceId) | ||||
|         } | ||||
| 
 | ||||
|         return sceneInstanceId | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Registers all hooks in a scene to the hook manager | ||||
|      * @param scene The scene | ||||
|      * @returns The id assigned to the instance of the scene | ||||
|      */ | ||||
|     createInstance(scene: Scene, isServerScene: boolean): number{ | ||||
|         //add to the list of tracked scenes
 | ||||
|         const trackedScene: TrackedScene = { | ||||
|             instanceId: this.sceneIdIncrementer++, | ||||
|             scene: scene, | ||||
|             sceneHooks: [], | ||||
|             signalHookMap: { }, | ||||
|         } | ||||
|         this.loadedScenes.push(trackedScene) | ||||
|         this.sceneIdMap[trackedScene.instanceId] = trackedScene | ||||
| 
 | ||||
|         //load all hooks from the scene
 | ||||
|         scene?.hooks?.forEach((hook: Hook) => { | ||||
|             engine.hookManager.registerHook(trackedScene,hook,isServerScene) | ||||
|         }) | ||||
| 
 | ||||
|         return trackedScene.instanceId | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Deregisters all hooks in a scene from the hook manager | ||||
|      * @param scene The scene | ||||
|      */ | ||||
|     deregisterScene(scene: Scene){ | ||||
|         throw new Error("Unsupported Operation!") | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Checks if the manager is tracking a given scene | ||||
|      * @param scene The scene | ||||
|      * @returns true if it is being tracked already, false otherwise | ||||
|      */ | ||||
|     containsScene(scene: Scene): boolean { | ||||
|         this.loadedScenes.forEach(trackedScene => { | ||||
|             if(trackedScene.scene === scene){ | ||||
|                 return true | ||||
|             } | ||||
|         }) | ||||
|         return false | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets a tracked scene by its id | ||||
|      * @param sceneId The tracked scene | ||||
|      * @returns The tracked scene if it exists, null otherwise | ||||
|      */ | ||||
|     getScene(sceneId: number){ | ||||
|         return this.sceneIdMap[sceneId] | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -1,4 +1,3 @@ | ||||
| import { TrackedScene } from "/Scripts/engine/scene/scene-loader"; | ||||
| import { Hook } from "/Scripts/types/hook"; | ||||
| import { Namespace } from "/Scripts/types/namespace"; | ||||
| 
 | ||||
| @ -27,9 +26,4 @@ export interface Scene extends Namespace { | ||||
|      */ | ||||
|     hooks?: Array<Hook> | ||||
| 
 | ||||
|     /** | ||||
|      * Invoked when the scene is created | ||||
|      */ | ||||
|     onCreate?: (instanceId: number) => void | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -1,8 +1,5 @@ | ||||
| @page dungeonsindex Dungeons | ||||
| 
 | ||||
| [TOC] | ||||
| - @subpage dungeonslayout | ||||
| 
 | ||||
| Enforce slower walking speed in dungeons (to give movement a more deliberate and weighty feel) | ||||
|  - Slower movement will also help with weapons feel more impactful | ||||
| Have the engine generate different types of shortcuts to allow you to quickly navigate up/down to the uncleared floors | ||||
|  | ||||
| @ -1,11 +0,0 @@ | ||||
| @page dungeonslayout Dungeon Layout | ||||
| 
 | ||||
| Procedural generation works better the more levers you have to tweak the generation with. | ||||
| Ideas for levers with respect to layout of dungeon templates: | ||||
|  - "Themes" of floors. IE having a spider themed floor, a magma/fire themed floor, etc | ||||
|  - "Navigation Lines". Having specific templates that are used to make easily identifiable highways through the dungeon that guide the player between highest level points of interest | ||||
|  - Color coordinating within floors | ||||
|  - Puzzle subsections of floors | ||||
|   - Working off of puzzles, have a central mechanism with explicit rooms around the mechanism (think a pillar that raises/lowers, a water level, etc) | ||||
|   - Generate rooms connecting all of these explicit rooms | ||||
|   - Don't necessarily want to connect them optimally. Players enjoy having to remember the location of other rooms earlier in the dungeon metroidvania style. | ||||
| @ -33,7 +33,7 @@ public class DebugSPWorldLoading { | ||||
|             SaveUtils.createOrOverwriteSave(saveName, SceneGenerator.createProceduralSceneFile(saveName)); | ||||
|         } | ||||
|         //load just-created save | ||||
|         SaveUtils.loadSave(saveName, false); | ||||
|         SaveUtils.loadSave(saveName); | ||||
|         //initialize the "virtual" objects simulation | ||||
|         LoadingUtils.initMacroSimulation(); | ||||
| 
 | ||||
|  | ||||
| @ -53,7 +53,7 @@ public class LevelEditorLoading { | ||||
|             SaveUtils.createOrOverwriteSave(saveName,sceneFile); | ||||
|         } | ||||
|         //load just-created save | ||||
|         SaveUtils.loadSave(saveName, true); | ||||
|         SaveUtils.loadSave(saveName); | ||||
| 
 | ||||
|         LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT); | ||||
|         //init authentication | ||||
|  | ||||
| @ -34,7 +34,7 @@ public class LevelLoading { | ||||
|         loadingWindow.setVisible(true); | ||||
| 
 | ||||
|         //load save | ||||
|         SaveUtils.loadSave(saveName, false); | ||||
|         SaveUtils.loadSave(saveName); | ||||
| 
 | ||||
|         LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT); | ||||
|         //init authentication | ||||
|  | ||||
| @ -95,12 +95,4 @@ public class SceneFile { | ||||
|         return createSaveInstance; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Sets whether the save utils will store a copy of the scene file in the save or not | ||||
|      * @param createSaveInstancetrue if should create instance of scene file in save, false otherwise | ||||
|      */ | ||||
|     public void setCreateSaveInstance(boolean createSaveInstance){ | ||||
|         this.createSaveInstance = createSaveInstance; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -23,23 +23,23 @@ public class SceneLoader { | ||||
|      * Loads a scene file on the server | ||||
|      * @param path The name of the save to look for a scene file within | ||||
|      */ | ||||
|     public static void serverInstantiateSaveSceneFile(String saveName, ServerWorldData serverWorldData, boolean isLevelEditor){ | ||||
|     public static void serverInstantiateSaveSceneFile(String saveName, ServerWorldData serverWorldData){ | ||||
|         //load scene file | ||||
|         SceneFile file = FileUtils.loadObjectFromSavePath(saveName, "/scene.json", SceneFile.class); | ||||
|         //instantiate scene data | ||||
|         serverInstantiateSceneFile(file,serverWorldData,isLevelEditor); | ||||
|         serverInstantiateSceneFile(file,serverWorldData); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Loads a scene file on the server | ||||
|      * @param path The name of the scene in the assets/scenes folder | ||||
|      */ | ||||
|     public static void serverInstantiateAssetSceneFile(String sceneName, ServerWorldData serverWorldData, boolean isLevelEditor){ | ||||
|     public static void serverInstantiateAssetSceneFile(String sceneName, ServerWorldData serverWorldData){ | ||||
|         //load scene file | ||||
|         String sanitizedPath = FileUtils.sanitizeFilePath("/Scenes/" + sceneName + "/scene.json"); | ||||
|         SceneFile file = FileUtils.loadObjectFromAssetPath(sanitizedPath, SceneFile.class); | ||||
|         //instantiate scene data | ||||
|         serverInstantiateSceneFile(file,serverWorldData,isLevelEditor); | ||||
|         serverInstantiateSceneFile(file,serverWorldData); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -47,7 +47,7 @@ public class SceneLoader { | ||||
|      * @param path The path in the assets directory to a scene file | ||||
|      * @param isSave if true, will try to load scene from save file instead of asset file | ||||
|      */ | ||||
|     private static void serverInstantiateSceneFile(SceneFile file, ServerWorldData serverWorldData, boolean isLevelEditor){ | ||||
|     private static void serverInstantiateSceneFile(SceneFile file, ServerWorldData serverWorldData){ | ||||
| 
 | ||||
|         // | ||||
|         //Content manager | ||||
| @ -103,9 +103,6 @@ public class SceneLoader { | ||||
|             } | ||||
|         } | ||||
|         //load scripts | ||||
|         if(!isLevelEditor && file.getInitScriptPath() != null){ | ||||
|             Globals.scriptEngine.initScene(file.getInitScriptPath()); | ||||
|         } | ||||
|         //TODO: integrate scripts for client side of scenes | ||||
|         // for(String scriptPath : file.getScriptPaths()){ | ||||
|         //     Globals.scriptEngine.loadScript(scriptPath); | ||||
|  | ||||
| @ -59,7 +59,7 @@ public class MenuGenerators { | ||||
|                         serverThread.start(); | ||||
|                         clientThread.start(); | ||||
|                     } else { | ||||
|                         SaveUtils.loadSave(saveName.toLowerCase(), false); | ||||
|                         SaveUtils.loadSave(saveName.toLowerCase()); | ||||
|                         WindowUtils.replaceMainMenuContents(MenuGenerators.createSaveCreationMenu()); | ||||
|                     } | ||||
|                     return false; | ||||
|  | ||||
| @ -179,11 +179,6 @@ public class MenuGeneratorsLevelEditor { | ||||
|                 }, DEFAULT_GRID_SIZE / (float)GriddedDataCellManager.MAX_GRID_SIZE) | ||||
|             ); | ||||
|             sceneFile.getRealmDescriptor().setGriddedRealmSize(DEFAULT_GRID_SIZE); | ||||
| 
 | ||||
|             griddedRealmControls.addChild(InputMacros.createToggle("Create Scene File", false, (ValueChangeEvent event) -> { | ||||
|                 sceneFile.setCreateSaveInstance(event.getAsBoolean()); | ||||
|                 System.out.println(sceneFile.getCreateSaveInstance()); | ||||
|             })); | ||||
|         } | ||||
|         rVal.addChild(griddedRealmControls); | ||||
| 
 | ||||
|  | ||||
| @ -191,7 +191,7 @@ public class ToggleInput extends StandardDrawableElement implements ClickableEle | ||||
|             } else { | ||||
|                 Globals.elementManager.focusElement(this); | ||||
|                 this.value = !this.value; | ||||
|                 Globals.elementManager.fireEventNoPosition(new ValueChangeEvent(this.value), this); | ||||
|                 Globals.elementManager.fireEventNoPosition(new ValueChangeEvent(absoluteX), this); | ||||
|                 propagate = false; | ||||
|             } | ||||
|         } else if(event instanceof ValueChangeEvent){ | ||||
|  | ||||
| @ -119,9 +119,6 @@ public class InputMacros { | ||||
|         //the actual input | ||||
|         ToggleInput toggleInput = ToggleInput.createToggleInput(); | ||||
|         toggleInput.setValue(defaultValue); | ||||
|         toggleInput.setOnValueChangeCallback(new ValueChangeEventCallback() {public void execute(ValueChangeEvent event) { | ||||
|             onChange.accept(event); | ||||
|         }}); | ||||
|         rVal.addChild(toggleInput); | ||||
| 
 | ||||
|         return rVal; | ||||
|  | ||||
| @ -42,9 +42,6 @@ public class ScriptEngine { | ||||
|     //the object that contains all host values accessible to javascript land | ||||
|     Value hostObject; | ||||
| 
 | ||||
|     //the engine object | ||||
|     Value engineObject; | ||||
| 
 | ||||
|     //The files that are loaded on init to bootstrap the script engine | ||||
|     static final String[] filesToLoadOnInit = new String[]{ | ||||
|         //polyfills | ||||
| @ -59,6 +56,12 @@ public class ScriptEngine { | ||||
|         "Scripts/compiler/host_access.js", | ||||
|     }; | ||||
| 
 | ||||
|     //folders that should be loaded once we have bootstrapped the compiler | ||||
|     static final String[] foldersToLoadOnInit = new String[]{ | ||||
|         "Scripts/engine", | ||||
|         "Scripts/client", | ||||
|     }; | ||||
| 
 | ||||
|     //The classes that will be provided to the scripting engine | ||||
|     //https://stackoverflow.com/a/65942034 | ||||
|     static final Object[][] staticClasses = new Object[][]{ | ||||
| @ -100,15 +103,15 @@ public class ScriptEngine { | ||||
|         defineHostMembers(); | ||||
| 
 | ||||
|         //register engine files | ||||
|         registerFile("/Scripts/engine/engine-init.ts"); | ||||
|         for(String folderToRegister : foldersToLoadOnInit){ | ||||
|             registerScriptDirectory(folderToRegister,FileUtils.getAssetFile(folderToRegister)); | ||||
|         } | ||||
| 
 | ||||
|         //compile | ||||
|         compile(); | ||||
| 
 | ||||
|         //run script for engine init | ||||
|         requireModule("/Scripts/engine/engine-init.ts"); | ||||
|         //get the engine object | ||||
|         engineObject = topLevelValue.getMember("REQUIRE_CACHE").getMember("/Scripts/engine/engine-init.js").getMember("exports").getMember("engine"); | ||||
|         invokeModuleFunction("/Scripts/engine/engine-init.ts","ENGINE_onInit"); | ||||
| 
 | ||||
| 
 | ||||
| @ -157,7 +160,6 @@ public class ScriptEngine { | ||||
|         return topLevelValue.removeMember(valueName); | ||||
|     } | ||||
| 
 | ||||
|     @Deprecated | ||||
|     /** | ||||
|      * Reads the scripts directory | ||||
|      * @param path The  | ||||
| @ -184,7 +186,7 @@ public class ScriptEngine { | ||||
|      * Loads a script from disk | ||||
|      * @param path The path to the script file | ||||
|      */ | ||||
|     void loadDependency(String path){ | ||||
|     public void loadDependency(String path){ | ||||
|         String content; | ||||
|         Source source = null; | ||||
|         try { | ||||
| @ -203,59 +205,44 @@ public class ScriptEngine { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Runs a script | ||||
|      * @param path The filepath of the script | ||||
|      */ | ||||
|     public void runScript(String path){ | ||||
|         invokeFunction("COMPILER_runFile", path); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Prints the content of a file | ||||
|      * @param path The filepath of the script | ||||
|      */ | ||||
|     public void printScriptSource(String path){ | ||||
|         invokeMemberFunction("COMPILER", "printSource", 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 boolean registerFile(String path){ | ||||
|     private void registerFile(String path){ | ||||
|         String content; | ||||
|         try { | ||||
|             content = FileUtils.getAssetFileAsString(path); | ||||
|             sourceMap.put(path,Source.create("js",content)); | ||||
|             Value dependentFilesValue = invokeMemberFunction("COMPILER", "registerFile",path,content); | ||||
|             // | ||||
|             //register dependent files if necessary | ||||
|             long dependentFilesCount = dependentFilesValue.getArraySize(); | ||||
|             if(dependentFilesCount > 0){ | ||||
|                 for(int i = 0; i < dependentFilesCount; i++){ | ||||
|                     String dependentFilePath = dependentFilesValue.getArrayElement(i).asString(); | ||||
|                     LoggerInterface.loggerScripts.INFO("[HOST - Script Engine] Should register file " + dependentFilePath); | ||||
|                     registerFile(dependentFilePath); | ||||
|                 } | ||||
|             } | ||||
|             invokeFunction("COMPILER_registerFile",path,content); | ||||
|         } catch (IOException e) { | ||||
|             LoggerInterface.loggerScripts.ERROR("FAILED TO LOAD SCRIPT", e); | ||||
|             return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Compiles the project | ||||
|      */ | ||||
|     private void compile(){ | ||||
|         invokeMemberFunction("COMPILER", "run"); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Initializes a scene script | ||||
|      * @param scenePath The scene's init script path | ||||
|      */ | ||||
|     public void initScene(String scenePath){ | ||||
|         //add files to virtual filesystem in script engine | ||||
|         registerFile(scenePath); | ||||
|         //load scene from javascript side | ||||
|         Value sceneLoader = this.engineObject.getMember("sceneLoader"); | ||||
|         Value loadFunc = sceneLoader.getMember("loadScene"); | ||||
|         loadFunc.execute(scenePath); | ||||
|         invokeFunction("COMPILER_run"); | ||||
|         Value compiledCode = topLevelValue.getMember("COMPILER_emitted_value"); | ||||
|         context.eval("js",compiledCode.asString()); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| @ -265,7 +252,6 @@ public class ScriptEngine { | ||||
|      * @param args The arguments | ||||
|      */ | ||||
|     public Value invokeFunction(String functionName, Object... args){ | ||||
|         LoggerInterface.loggerScripts.DEBUG("Host execute: " + functionName); | ||||
|         Value function = topLevelValue.getMember(functionName); | ||||
|         if(function != null){ | ||||
|             return function.execute(args); | ||||
| @ -275,25 +261,6 @@ public class ScriptEngine { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Calls a function on a child of the top level member | ||||
|      * @param memberName The name of the child | ||||
|      * @param functionName The name of the function | ||||
|      * @param args The arguments for the function | ||||
|      * @return The value from the function call | ||||
|      */ | ||||
|     public Value invokeMemberFunction(String memberName, String functionName, Object ... args){ | ||||
|         LoggerInterface.loggerScripts.DEBUG("Host execute: " + functionName); | ||||
|         Value childMember = topLevelValue.getMember(memberName); | ||||
|         Value function = childMember.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 | ||||
| @ -331,8 +298,6 @@ public class ScriptEngine { | ||||
|         for(Object[] currentClass : staticClasses){ | ||||
|             classes.putMember((String)currentClass[0], currentClass[1]); | ||||
|         } | ||||
|         //give access to script engine instance | ||||
|         hostObject.putMember("scriptEngine", this); | ||||
|     } | ||||
|      | ||||
|      | ||||
|  | ||||
| @ -174,7 +174,7 @@ public class SaveUtils { | ||||
|      * @param saveName The name of the save | ||||
|      * @return true always | ||||
|      */ | ||||
|     public static boolean loadSave(String saveName, boolean isLevelEditor){ | ||||
|     public static boolean loadSave(String saveName){ | ||||
|         String dirPath = deriveSaveDirectoryPath(saveName); | ||||
| 
 | ||||
|         //load save file | ||||
| @ -200,11 +200,11 @@ public class SaveUtils { | ||||
|         if(FileUtils.checkSavePathExists(saveName, "/scene.json")){ | ||||
|             //load from save itself | ||||
|             LoggerInterface.loggerEngine.INFO("Load scene data from save " + saveName); | ||||
|             SceneLoader.serverInstantiateSaveSceneFile(saveName, serverWorldData, isLevelEditor); | ||||
|         } else if(FileUtils.getAssetFile("/Scenes/" + saveName + "/scene.json").exists()){ | ||||
|             SceneLoader.serverInstantiateSaveSceneFile(saveName, serverWorldData); | ||||
|         } else if(FileUtils.checkFileExists("/Scenes/" + saveName)){ | ||||
|             //load from defined scene | ||||
|             LoggerInterface.loggerEngine.INFO("Load scene data from scene " + saveName); | ||||
|             SceneLoader.serverInstantiateAssetSceneFile(saveName, serverWorldData, isLevelEditor); | ||||
|             SceneLoader.serverInstantiateAssetSceneFile(saveName, serverWorldData); | ||||
|         } else { | ||||
|             //The scene is neither defined in the save itself nor in the assets scene files | ||||
|             throw new IllegalStateException("Trying to load a save that does not contain a scene!"); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user