Compare commits
	
		
			3 Commits
		
	
	
		
			14f4607c47
			...
			f2877edf37
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | f2877edf37 | ||
|  | 0c554d1598 | ||
|  | da28d13d61 | 
							
								
								
									
										10
									
								
								assets/Scenes/defaultLevel_2/scene.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								assets/Scenes/defaultLevel_2/scene.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | { | ||||||
|  |     "entities" : [], | ||||||
|  |     "scriptPaths" : [], | ||||||
|  |     "initScriptPath" : "/Scenes/defaultLevel_2/scene.ts", | ||||||
|  |     "realmDescriptor" : { | ||||||
|  |         "type" : "gridded", | ||||||
|  |         "griddedRealmSize" : 2 | ||||||
|  |     }, | ||||||
|  |     "createSaveInstance" : true | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								assets/Scenes/defaultLevel_2/scene.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								assets/Scenes/defaultLevel_2/scene.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | 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,119 +1,479 @@ | |||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * The map of all source files to their content and compiled value |  * @description The compiler object | ||||||
|  */ |  */ | ||||||
| let COMPILER_fileMap = { } | let COMPILER = { | ||||||
| 
 | 
 | ||||||
| /** |     //
 | ||||||
|  * The compiled program |     //
 | ||||||
|  */ |     //    VIRTUAL FILE SYSTEM
 | ||||||
| let COMPILER_emitted_value = '' |     //
 | ||||||
|  |     //
 | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The map of all source files to their content and compiled value | ||||||
|  |      */ | ||||||
|  |     fileMap: { }, | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The list of all source files to compile | ||||||
|  |      */ | ||||||
|  |     sourceFiles: [ ], | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 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 | ||||||
|  |      */ | ||||||
|  |     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, | ||||||
|  |             content: content, | ||||||
|  |             version: 0, | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |         //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 {*} languageVersion The language version | ||||||
|  |      * @returns The file if it exists, null otherwise | ||||||
|  |      */ | ||||||
|  |     getSourceFile: (fileName, languageVersion) => { | ||||||
|  |         if(!!COMPILER.fileMap[fileName]){ | ||||||
|  |             return COMPILER.fileMap[fileName].tsSourceFile | ||||||
|  |         } else { | ||||||
|  |             return null | ||||||
|  |         } | ||||||
|  |     }, | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** |     //
 | ||||||
|  * Registers a file with the compiler |     //
 | ||||||
|  * @param {*} fileName The file's name |     //   COMPILATION
 | ||||||
|  * @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 compiler options | ||||||
|  |      */ | ||||||
|  |     compilerOptions: { }, | ||||||
| 
 | 
 | ||||||
| /** |     /** | ||||||
|  * The callback invoked when the compiler host tries to read a file |      * Tracks whether the compiler has run or not | ||||||
|  * @param {*} fileName The name of the file |      */ | ||||||
|  * @param {*} languageVersion The language version |     compilerHasRun: false, | ||||||
|  * @returns The file if it exists, null otherwise | 
 | ||||||
|  */ |     /** | ||||||
| const COMPILER_getSourceFile = (fileName, languageVersion) => { |      * The typescript compiler host definition | ||||||
|     if(!!COMPILER_fileMap[fileName]){ |      */ | ||||||
|         return COMPILER_fileMap[fileName].compiled |     customCompilerHost: null, | ||||||
|     } else { | 
 | ||||||
|         return 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 |  * Constructs the compiler host | ||||||
|  * https://www.typescriptlang.org/tsconfig/#compilerOptions
 |  * https://www.typescriptlang.org/tsconfig/#compilerOptions
 | ||||||
|  |  *  | ||||||
|  |  * Examples: | ||||||
|  |  * https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API
 | ||||||
|  |  *  | ||||||
|  */ |  */ | ||||||
| const COMPILER_customCompilerHost = { | COMPILER.customCompilerHost = { | ||||||
|     getSourceFile: COMPILER_getSourceFile, |     getSourceFile: COMPILER.getSourceFile, | ||||||
|     writeFile: (fileName, data) => { |     writeFile: (fileName, data) => { | ||||||
|         let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName) |         loggerScripts.INFO("EMIT FILE " + fileName) | ||||||
|         loggerScripts.INFO("EMIT FILE " + normalizedFilePath) |         //wrap in require logic
 | ||||||
|         let finalData =  |         let finalData =  | ||||||
|         "let exports = { }\n" + |         "let exports = { }\n" + | ||||||
|         data + "\n" + |         data + "\n" + | ||||||
|         "return exports" |         "return exports" | ||||||
|         // COMPILER_emitted_value = data
 | 
 | ||||||
|         COMPILER_fileMap[normalizedFilePath] = { |         //create file
 | ||||||
|  |         COMPILER.createFile(fileName,finalData) | ||||||
|  |          | ||||||
|  |         //register in file map
 | ||||||
|  |         COMPILER.fileMap[fileName] = { | ||||||
|             content: data, //to be eval'd from top level
 |             content: data, //to be eval'd from top level
 | ||||||
|             moduleContent: finalData, //to be eval'd from require()
 |             moduleContent: finalData, //to be eval'd from require()
 | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|     getDefaultLibFileName: () => "lib.d.ts", |     getDefaultLibFileName: ts.getDefaultLibFileName, | ||||||
|     useCaseSensitiveFileNames: () => false, |     useCaseSensitiveFileNames: () => false, | ||||||
|     getCanonicalFileName: filename => filename, |     getCanonicalFileName: filename => filename, | ||||||
|     getCurrentDirectory: () => "", |     getCurrentDirectory: () => "/", | ||||||
|     getNewLine: () => "\n", |     getNewLine: () => "\n", | ||||||
|     getDirectories: () => [], |     getDirectories: (path) => { | ||||||
|     fileExists: () => true, |         loggerScripts.DEBUG('[ts] getDirectories ' + path) | ||||||
|     readFile: () => "" |         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, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | //initialized CWD
 | ||||||
|  * Instructs Typescript to emit the final compiled value | COMPILER.currentDirectory = COMPILER.topLevelDirectory | ||||||
|  */ |  | ||||||
| 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') |         fileName = fileName.replace('.ts','.js') | ||||||
|     } |     } | ||||||
|     if(fileName.startsWith('/Scripts')){ |     if(fileName.startsWith('/Scripts')){ | ||||||
|         fileName = fileName.replace('/Scripts','') |         // fileName = fileName.replace('/Scripts','')
 | ||||||
|     } |     } | ||||||
|     if(fileName.startsWith('Scripts/')){ |     if(fileName.startsWith('Scripts')){ | ||||||
|         fileName = fileName.replace('Scripts/','/') |         fileName = fileName.replace('Scripts','/Scripts') | ||||||
|     } |     } | ||||||
|     if(isJavascript && !fileName.endsWith(".js")){ |     if(isJavascript && !fileName.endsWith(".js")){ | ||||||
|         fileName = fileName + ".js" |         fileName = fileName + ".js" | ||||||
|  | |||||||
| @ -8,14 +8,14 @@ let HOST_ACCESS = { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //fake require
 | //fake require
 | ||||||
| REQUIRE_CACHE["/compiler/host_access.js"] = { | REQUIRE_CACHE["/Scripts/compiler/host_access.js"] = { | ||||||
|     exports: { |     exports: { | ||||||
|         'HOST_ACCESS': HOST_ACCESS, |         'HOST_ACCESS': HOST_ACCESS, | ||||||
|         'loggerScripts': loggerScripts, |         'loggerScripts': loggerScripts, | ||||||
|     }, |     }, | ||||||
|     exportedValues: [ |     exportedValues: [ | ||||||
|         'HOST_ACCESS', |         'HOST_ACCESS', | ||||||
|         'loggerScripts' |         'loggerScripts', | ||||||
|     ], |     ], | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,13 +16,24 @@ let exports = { } | |||||||
|  * @param {*} cwd The current working directory |  * @param {*} cwd The current working directory | ||||||
|  */ |  */ | ||||||
| const require = (path) => { | const require = (path) => { | ||||||
|  |     //get the path
 | ||||||
|     loggerScripts.DEBUG('Require path ' + path) |     loggerScripts.DEBUG('Require path ' + path) | ||||||
|     let normalizedFilePath = FILE_RESOLUTION_getFilePath(path) |     let normalizedFilePath = FILE_RESOLUTION_getFilePath(path) | ||||||
|  | 
 | ||||||
|  |     //actually require
 | ||||||
|     if(!!REQUIRE_CACHE[normalizedFilePath]){ |     if(!!REQUIRE_CACHE[normalizedFilePath]){ | ||||||
|  |         //return if has already been required
 | ||||||
|         return REQUIRE_CACHE[normalizedFilePath].exports |         return REQUIRE_CACHE[normalizedFilePath].exports | ||||||
|     } else if(!!COMPILER_fileMap[normalizedFilePath]?.content) { |     } else if(!!COMPILER.fileMap[normalizedFilePath]?.content) { | ||||||
|         const code = COMPILER_fileMap[normalizedFilePath].moduleContent |         //require if it is already registered
 | ||||||
|  |         const code = COMPILER.fileMap[normalizedFilePath].moduleContent | ||||||
|         loggerScripts.DEBUG('Module code ' + JSON.stringify(code)) |         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)() |         let exports = new Function(code)() | ||||||
|         //create module object
 |         //create module object
 | ||||||
|         const module = { |         const module = { | ||||||
| @ -33,6 +44,7 @@ const require = (path) => { | |||||||
|         loggerScripts.INFO("[require] CREATE MODULE " + normalizedFilePath) |         loggerScripts.INFO("[require] CREATE MODULE " + normalizedFilePath) | ||||||
|         return module.exports |         return module.exports | ||||||
|     } else { |     } else { | ||||||
|  |         //fail if it doesn't exist from host's view
 | ||||||
|         const errorMsg = "FAILED TO REQUIRE FILE " + normalizedFilePath |         const errorMsg = "FAILED TO REQUIRE FILE " + normalizedFilePath | ||||||
|         loggerScripts.WARNING(errorMsg) |         loggerScripts.WARNING(errorMsg) | ||||||
|         loggerScripts.WARNING('Module value:') |         loggerScripts.WARNING('Module value:') | ||||||
| @ -41,7 +53,19 @@ const require = (path) => { | |||||||
|         loggerScripts.WARNING('Require cache contents:') |         loggerScripts.WARNING('Require cache contents:') | ||||||
|         loggerScripts.WARNING(Object.keys(REQUIRE_CACHE) + '') |         loggerScripts.WARNING(Object.keys(REQUIRE_CACHE) + '') | ||||||
|         loggerScripts.WARNING('File cache contents:') |         loggerScripts.WARNING('File cache contents:') | ||||||
|         loggerScripts.WARNING(Object.keys(COMPILER_fileMap) + '') |         loggerScripts.WARNING(Object.keys(COMPILER.fileMap) + '') | ||||||
|         throw new Error(errorMsg) |         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,7 +1,8 @@ | |||||||
| import { Engine } from '/Scripts/engine/engine-interface' | import { Engine } from '/Scripts/engine/engine-interface' | ||||||
| import { loggerScripts } from '/Scripts/compiler/host_access' | import { loggerScripts } from '/Scripts/compiler/host_access' | ||||||
| import { Client, NamespaceClient } from '/Scripts/client/client' | import { Client, NamespaceClient } from '/Scripts/client/client' | ||||||
| import { HookManager } from '/Scripts/engine/hook-manager' | import { HookManager } from '/Scripts/engine/hooks/hook-manager' | ||||||
|  | import { SceneLoader } from '/Scripts/engine/scene/scene-loader' | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * The core engine values |  * The core engine values | ||||||
| @ -10,6 +11,7 @@ export const engine: Engine = { | |||||||
|     classes: [], |     classes: [], | ||||||
|     singletons: [], |     singletons: [], | ||||||
|     hookManager: new HookManager(), |     hookManager: new HookManager(), | ||||||
|  |     sceneLoader: new SceneLoader(), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -20,6 +22,7 @@ export const ENGINE_onInit = () => { | |||||||
| 
 | 
 | ||||||
|     //load namespaces
 |     //load namespaces
 | ||||||
|     let client: NamespaceClient = Client |     let client: NamespaceClient = Client | ||||||
|  |     engine.sceneLoader.hookManager = engine.hookManager | ||||||
| 
 | 
 | ||||||
|     loggerScripts.INFO('Script Engine Initialized') |     loggerScripts.INFO('Script Engine Initialized') | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| import { HookManager } from "/Scripts/engine/hook-manager"; | import { HookManager } from "/Scripts/engine/hooks/hook-manager"; | ||||||
|  | import { SceneLoader } from "/Scripts/engine/scene/scene-loader"; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -21,4 +22,9 @@ export interface Engine { | |||||||
|      */ |      */ | ||||||
|     hookManager: HookManager, |     hookManager: HookManager, | ||||||
|      |      | ||||||
|  |     /** | ||||||
|  |      * Tracks and loads scenes | ||||||
|  |      */ | ||||||
|  |     sceneLoader: SceneLoader, | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
|  | import { TrackedScene } from "/Scripts/engine/scene/scene-loader" | ||||||
| import { Hook } from "/Scripts/types/hook" | import { Hook } from "/Scripts/types/hook" | ||||||
| import { Scene } from "/Scripts/types/scene" | import { Scene } from "/Scripts/types/scene" | ||||||
| 
 | 
 | ||||||
| @ -15,7 +16,7 @@ export enum HookScope { | |||||||
| /** | /** | ||||||
|  * A hook that is tracked by the manager |  * A hook that is tracked by the manager | ||||||
|  */ |  */ | ||||||
| interface TrackedHook extends Hook { | export interface TrackedHook extends Hook { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * The scope that this hook was defined at |      * The scope that this hook was defined at | ||||||
| @ -29,23 +30,6 @@ 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 |  * Manages hooks for the engine | ||||||
|  */ |  */ | ||||||
| @ -56,11 +40,6 @@ export class HookManager { | |||||||
|      */ |      */ | ||||||
|     hooks: Array<TrackedHook> = [] |     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 |      * A map of engine signal to the list of hooks that should be called when that signal fires | ||||||
|      */ |      */ | ||||||
| @ -69,57 +48,7 @@ export class HookManager { | |||||||
|     /** |     /** | ||||||
|      * The list of all scenes tracked by the manager |      * The list of all scenes tracked by the manager | ||||||
|      */ |      */ | ||||||
|     trackedScenes: Array<{ sceneId: number, scene: Scene }> = [] |     trackedScenes: Array<TrackedScene> = [] | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 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 |      * Registers a hook | ||||||
| @ -139,10 +68,19 @@ export class HookManager { | |||||||
|         const signalArray: Array<TrackedHook> = this.signalHookMap?.[hookSignal] ? this.signalHookMap?.[hookSignal] : [] |         const signalArray: Array<TrackedHook> = this.signalHookMap?.[hookSignal] ? this.signalHookMap?.[hookSignal] : [] | ||||||
|         signalArray.push(trackedHook) |         signalArray.push(trackedHook) | ||||||
|         this.signalHookMap[hookSignal] = signalArray |         this.signalHookMap[hookSignal] = signalArray | ||||||
|         //add to scene array
 |         //
 | ||||||
|         const sceneArray: Array<TrackedHook> = this.sceneHookMap?.[scene.sceneId] ? this.sceneHookMap?.[scene.sceneId] : [] |         //Scene related structures
 | ||||||
|         sceneArray.push(trackedHook) |         //
 | ||||||
|         this.sceneHookMap[scene.sceneId] = sceneArray |         //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 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -159,7 +97,7 @@ export class HookManager { | |||||||
|      * @param signal The signal |      * @param signal The signal | ||||||
|      * @param value The value associated with the signal |      * @param value The value associated with the signal | ||||||
|      */ |      */ | ||||||
|     fireSignal(signal: string, value: any){ |     fireSignal(instanceId: number, signal: string, value: any){ | ||||||
|         const hooks: Array<TrackedHook> = this.signalHookMap[signal] |         const hooks: Array<TrackedHook> = this.signalHookMap[signal] | ||||||
|         hooks.forEach(trackedHook => { |         hooks.forEach(trackedHook => { | ||||||
|             trackedHook.callback(value) |             trackedHook.callback(value) | ||||||
							
								
								
									
										137
									
								
								assets/Scripts/engine/scene/scene-loader.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								assets/Scripts/engine/scene/scene-loader.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,137 @@ | |||||||
|  | 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,3 +1,4 @@ | |||||||
|  | import { TrackedScene } from "/Scripts/engine/scene/scene-loader"; | ||||||
| import { Hook } from "/Scripts/types/hook"; | import { Hook } from "/Scripts/types/hook"; | ||||||
| import { Namespace } from "/Scripts/types/namespace"; | import { Namespace } from "/Scripts/types/namespace"; | ||||||
| 
 | 
 | ||||||
| @ -26,4 +27,9 @@ export interface Scene extends Namespace { | |||||||
|      */ |      */ | ||||||
|     hooks?: Array<Hook> |     hooks?: Array<Hook> | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Invoked when the scene is created | ||||||
|  |      */ | ||||||
|  |     onCreate?: (instanceId: number) => void | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,8 @@ | |||||||
| @page dungeonsindex Dungeons | @page dungeonsindex Dungeons | ||||||
| 
 | 
 | ||||||
|  | [TOC] | ||||||
|  | - @subpage dungeonslayout | ||||||
|  | 
 | ||||||
| Enforce slower walking speed in dungeons (to give movement a more deliberate and weighty feel) | 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 |  - 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 | Have the engine generate different types of shortcuts to allow you to quickly navigate up/down to the uncleared floors | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								docs/src/highlevel-design/dungeons/dungeonslayout.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								docs/src/highlevel-design/dungeons/dungeonslayout.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | @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)); |             SaveUtils.createOrOverwriteSave(saveName, SceneGenerator.createProceduralSceneFile(saveName)); | ||||||
|         } |         } | ||||||
|         //load just-created save |         //load just-created save | ||||||
|         SaveUtils.loadSave(saveName); |         SaveUtils.loadSave(saveName, false); | ||||||
|         //initialize the "virtual" objects simulation |         //initialize the "virtual" objects simulation | ||||||
|         LoadingUtils.initMacroSimulation(); |         LoadingUtils.initMacroSimulation(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -53,7 +53,7 @@ public class LevelEditorLoading { | |||||||
|             SaveUtils.createOrOverwriteSave(saveName,sceneFile); |             SaveUtils.createOrOverwriteSave(saveName,sceneFile); | ||||||
|         } |         } | ||||||
|         //load just-created save |         //load just-created save | ||||||
|         SaveUtils.loadSave(saveName); |         SaveUtils.loadSave(saveName, true); | ||||||
| 
 | 
 | ||||||
|         LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT); |         LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT); | ||||||
|         //init authentication |         //init authentication | ||||||
|  | |||||||
| @ -34,7 +34,7 @@ public class LevelLoading { | |||||||
|         loadingWindow.setVisible(true); |         loadingWindow.setVisible(true); | ||||||
| 
 | 
 | ||||||
|         //load save |         //load save | ||||||
|         SaveUtils.loadSave(saveName); |         SaveUtils.loadSave(saveName, false); | ||||||
| 
 | 
 | ||||||
|         LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT); |         LoggerInterface.loggerEngine.INFO("run server: " + Globals.RUN_SERVER + " run client: " + Globals.RUN_CLIENT); | ||||||
|         //init authentication |         //init authentication | ||||||
|  | |||||||
| @ -95,4 +95,12 @@ public class SceneFile { | |||||||
|         return createSaveInstance; |         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 |      * Loads a scene file on the server | ||||||
|      * @param path The name of the save to look for a scene file within |      * @param path The name of the save to look for a scene file within | ||||||
|      */ |      */ | ||||||
|     public static void serverInstantiateSaveSceneFile(String saveName, ServerWorldData serverWorldData){ |     public static void serverInstantiateSaveSceneFile(String saveName, ServerWorldData serverWorldData, boolean isLevelEditor){ | ||||||
|         //load scene file |         //load scene file | ||||||
|         SceneFile file = FileUtils.loadObjectFromSavePath(saveName, "/scene.json", SceneFile.class); |         SceneFile file = FileUtils.loadObjectFromSavePath(saveName, "/scene.json", SceneFile.class); | ||||||
|         //instantiate scene data |         //instantiate scene data | ||||||
|         serverInstantiateSceneFile(file,serverWorldData); |         serverInstantiateSceneFile(file,serverWorldData,isLevelEditor); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Loads a scene file on the server |      * Loads a scene file on the server | ||||||
|      * @param path The name of the scene in the assets/scenes folder |      * @param path The name of the scene in the assets/scenes folder | ||||||
|      */ |      */ | ||||||
|     public static void serverInstantiateAssetSceneFile(String sceneName, ServerWorldData serverWorldData){ |     public static void serverInstantiateAssetSceneFile(String sceneName, ServerWorldData serverWorldData, boolean isLevelEditor){ | ||||||
|         //load scene file |         //load scene file | ||||||
|         String sanitizedPath = FileUtils.sanitizeFilePath("/Scenes/" + sceneName + "/scene.json"); |         String sanitizedPath = FileUtils.sanitizeFilePath("/Scenes/" + sceneName + "/scene.json"); | ||||||
|         SceneFile file = FileUtils.loadObjectFromAssetPath(sanitizedPath, SceneFile.class); |         SceneFile file = FileUtils.loadObjectFromAssetPath(sanitizedPath, SceneFile.class); | ||||||
|         //instantiate scene data |         //instantiate scene data | ||||||
|         serverInstantiateSceneFile(file,serverWorldData); |         serverInstantiateSceneFile(file,serverWorldData,isLevelEditor); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -47,7 +47,7 @@ public class SceneLoader { | |||||||
|      * @param path The path in the assets directory to a scene file |      * @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 |      * @param isSave if true, will try to load scene from save file instead of asset file | ||||||
|      */ |      */ | ||||||
|     private static void serverInstantiateSceneFile(SceneFile file, ServerWorldData serverWorldData){ |     private static void serverInstantiateSceneFile(SceneFile file, ServerWorldData serverWorldData, boolean isLevelEditor){ | ||||||
| 
 | 
 | ||||||
|         // |         // | ||||||
|         //Content manager |         //Content manager | ||||||
| @ -103,6 +103,9 @@ public class SceneLoader { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         //load scripts |         //load scripts | ||||||
|  |         if(!isLevelEditor && file.getInitScriptPath() != null){ | ||||||
|  |             Globals.scriptEngine.initScene(file.getInitScriptPath()); | ||||||
|  |         } | ||||||
|         //TODO: integrate scripts for client side of scenes |         //TODO: integrate scripts for client side of scenes | ||||||
|         // for(String scriptPath : file.getScriptPaths()){ |         // for(String scriptPath : file.getScriptPaths()){ | ||||||
|         //     Globals.scriptEngine.loadScript(scriptPath); |         //     Globals.scriptEngine.loadScript(scriptPath); | ||||||
|  | |||||||
| @ -59,7 +59,7 @@ public class MenuGenerators { | |||||||
|                         serverThread.start(); |                         serverThread.start(); | ||||||
|                         clientThread.start(); |                         clientThread.start(); | ||||||
|                     } else { |                     } else { | ||||||
|                         SaveUtils.loadSave(saveName.toLowerCase()); |                         SaveUtils.loadSave(saveName.toLowerCase(), false); | ||||||
|                         WindowUtils.replaceMainMenuContents(MenuGenerators.createSaveCreationMenu()); |                         WindowUtils.replaceMainMenuContents(MenuGenerators.createSaveCreationMenu()); | ||||||
|                     } |                     } | ||||||
|                     return false; |                     return false; | ||||||
|  | |||||||
| @ -179,6 +179,11 @@ public class MenuGeneratorsLevelEditor { | |||||||
|                 }, DEFAULT_GRID_SIZE / (float)GriddedDataCellManager.MAX_GRID_SIZE) |                 }, DEFAULT_GRID_SIZE / (float)GriddedDataCellManager.MAX_GRID_SIZE) | ||||||
|             ); |             ); | ||||||
|             sceneFile.getRealmDescriptor().setGriddedRealmSize(DEFAULT_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); |         rVal.addChild(griddedRealmControls); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -191,7 +191,7 @@ public class ToggleInput extends StandardDrawableElement implements ClickableEle | |||||||
|             } else { |             } else { | ||||||
|                 Globals.elementManager.focusElement(this); |                 Globals.elementManager.focusElement(this); | ||||||
|                 this.value = !this.value; |                 this.value = !this.value; | ||||||
|                 Globals.elementManager.fireEventNoPosition(new ValueChangeEvent(absoluteX), this); |                 Globals.elementManager.fireEventNoPosition(new ValueChangeEvent(this.value), this); | ||||||
|                 propagate = false; |                 propagate = false; | ||||||
|             } |             } | ||||||
|         } else if(event instanceof ValueChangeEvent){ |         } else if(event instanceof ValueChangeEvent){ | ||||||
|  | |||||||
| @ -119,6 +119,9 @@ public class InputMacros { | |||||||
|         //the actual input |         //the actual input | ||||||
|         ToggleInput toggleInput = ToggleInput.createToggleInput(); |         ToggleInput toggleInput = ToggleInput.createToggleInput(); | ||||||
|         toggleInput.setValue(defaultValue); |         toggleInput.setValue(defaultValue); | ||||||
|  |         toggleInput.setOnValueChangeCallback(new ValueChangeEventCallback() {public void execute(ValueChangeEvent event) { | ||||||
|  |             onChange.accept(event); | ||||||
|  |         }}); | ||||||
|         rVal.addChild(toggleInput); |         rVal.addChild(toggleInput); | ||||||
| 
 | 
 | ||||||
|         return rVal; |         return rVal; | ||||||
|  | |||||||
| @ -42,6 +42,9 @@ public class ScriptEngine { | |||||||
|     //the object that contains all host values accessible to javascript land |     //the object that contains all host values accessible to javascript land | ||||||
|     Value hostObject; |     Value hostObject; | ||||||
| 
 | 
 | ||||||
|  |     //the engine object | ||||||
|  |     Value engineObject; | ||||||
|  | 
 | ||||||
|     //The files that are loaded on init to bootstrap the script engine |     //The files that are loaded on init to bootstrap the script engine | ||||||
|     static final String[] filesToLoadOnInit = new String[]{ |     static final String[] filesToLoadOnInit = new String[]{ | ||||||
|         //polyfills |         //polyfills | ||||||
| @ -56,12 +59,6 @@ public class ScriptEngine { | |||||||
|         "Scripts/compiler/host_access.js", |         "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 |     //The classes that will be provided to the scripting engine | ||||||
|     //https://stackoverflow.com/a/65942034 |     //https://stackoverflow.com/a/65942034 | ||||||
|     static final Object[][] staticClasses = new Object[][]{ |     static final Object[][] staticClasses = new Object[][]{ | ||||||
| @ -103,15 +100,15 @@ public class ScriptEngine { | |||||||
|         defineHostMembers(); |         defineHostMembers(); | ||||||
| 
 | 
 | ||||||
|         //register engine files |         //register engine files | ||||||
|         for(String folderToRegister : foldersToLoadOnInit){ |         registerFile("/Scripts/engine/engine-init.ts"); | ||||||
|             registerScriptDirectory(folderToRegister,FileUtils.getAssetFile(folderToRegister)); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         //compile |         //compile | ||||||
|         compile(); |         compile(); | ||||||
| 
 | 
 | ||||||
|         //run script for engine init |         //run script for engine init | ||||||
|         requireModule("/Scripts/engine/engine-init.ts"); |         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"); |         invokeModuleFunction("/Scripts/engine/engine-init.ts","ENGINE_onInit"); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -160,6 +157,7 @@ public class ScriptEngine { | |||||||
|         return topLevelValue.removeMember(valueName); |         return topLevelValue.removeMember(valueName); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Deprecated | ||||||
|     /** |     /** | ||||||
|      * Reads the scripts directory |      * Reads the scripts directory | ||||||
|      * @param path The  |      * @param path The  | ||||||
| @ -186,7 +184,7 @@ 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 loadDependency(String path){ |     void loadDependency(String path){ | ||||||
|         String content; |         String content; | ||||||
|         Source source = null; |         Source source = null; | ||||||
|         try { |         try { | ||||||
| @ -205,44 +203,59 @@ 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 |      * Prints the content of a file | ||||||
|      * @param path The filepath of the script |      * @param path The filepath of the script | ||||||
|      */ |      */ | ||||||
|     public void printScriptSource(String path){ |     public void printScriptSource(String path){ | ||||||
|         invokeFunction("COMPILER_printSource", path); |         invokeMemberFunction("COMPILER", "printSource", path); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Registers a file with the scripting engine to be compiled into the full binary |      * Registers a file with the scripting engine to be compiled into the full binary | ||||||
|      * @param path The path to the script file |      * @param path The path to the script file | ||||||
|      */ |      */ | ||||||
|     private void registerFile(String path){ |     private boolean registerFile(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)); | ||||||
|             invokeFunction("COMPILER_registerFile",path,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); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } catch (IOException e) { |         } catch (IOException e) { | ||||||
|             LoggerInterface.loggerScripts.ERROR("FAILED TO LOAD SCRIPT", e); |             LoggerInterface.loggerScripts.ERROR("FAILED TO LOAD SCRIPT", e); | ||||||
|  |             return false; | ||||||
|         } |         } | ||||||
|  |         return true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Compiles the project |      * Compiles the project | ||||||
|      */ |      */ | ||||||
|     private void compile(){ |     private void compile(){ | ||||||
|         invokeFunction("COMPILER_run"); |         invokeMemberFunction("COMPILER", "run"); | ||||||
|         Value compiledCode = topLevelValue.getMember("COMPILER_emitted_value"); |     } | ||||||
|         context.eval("js",compiledCode.asString()); | 
 | ||||||
|  |     /** | ||||||
|  |      * 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); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -252,6 +265,7 @@ public class ScriptEngine { | |||||||
|      * @param args The arguments |      * @param args The arguments | ||||||
|      */ |      */ | ||||||
|     public Value invokeFunction(String functionName, Object... args){ |     public Value invokeFunction(String functionName, Object... args){ | ||||||
|  |         LoggerInterface.loggerScripts.DEBUG("Host execute: " + functionName); | ||||||
|         Value function = topLevelValue.getMember(functionName); |         Value function = topLevelValue.getMember(functionName); | ||||||
|         if(function != null){ |         if(function != null){ | ||||||
|             return function.execute(args); |             return function.execute(args); | ||||||
| @ -261,6 +275,25 @@ public class ScriptEngine { | |||||||
|         return null; |         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 |      * Invokes a function defined in a file | ||||||
|      * @param filePath The file the function is defined in |      * @param filePath The file the function is defined in | ||||||
| @ -298,6 +331,8 @@ public class ScriptEngine { | |||||||
|         for(Object[] currentClass : staticClasses){ |         for(Object[] currentClass : staticClasses){ | ||||||
|             classes.putMember((String)currentClass[0], currentClass[1]); |             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 |      * @param saveName The name of the save | ||||||
|      * @return true always |      * @return true always | ||||||
|      */ |      */ | ||||||
|     public static boolean loadSave(String saveName){ |     public static boolean loadSave(String saveName, boolean isLevelEditor){ | ||||||
|         String dirPath = deriveSaveDirectoryPath(saveName); |         String dirPath = deriveSaveDirectoryPath(saveName); | ||||||
| 
 | 
 | ||||||
|         //load save file |         //load save file | ||||||
| @ -200,11 +200,11 @@ public class SaveUtils { | |||||||
|         if(FileUtils.checkSavePathExists(saveName, "/scene.json")){ |         if(FileUtils.checkSavePathExists(saveName, "/scene.json")){ | ||||||
|             //load from save itself |             //load from save itself | ||||||
|             LoggerInterface.loggerEngine.INFO("Load scene data from save " + saveName); |             LoggerInterface.loggerEngine.INFO("Load scene data from save " + saveName); | ||||||
|             SceneLoader.serverInstantiateSaveSceneFile(saveName, serverWorldData); |             SceneLoader.serverInstantiateSaveSceneFile(saveName, serverWorldData, isLevelEditor); | ||||||
|         } else if(FileUtils.checkFileExists("/Scenes/" + saveName)){ |         } else if(FileUtils.getAssetFile("/Scenes/" + saveName + "/scene.json").exists()){ | ||||||
|             //load from defined scene |             //load from defined scene | ||||||
|             LoggerInterface.loggerEngine.INFO("Load scene data from scene " + saveName); |             LoggerInterface.loggerEngine.INFO("Load scene data from scene " + saveName); | ||||||
|             SceneLoader.serverInstantiateAssetSceneFile(saveName, serverWorldData); |             SceneLoader.serverInstantiateAssetSceneFile(saveName, serverWorldData, isLevelEditor); | ||||||
|         } else { |         } else { | ||||||
|             //The scene is neither defined in the save itself nor in the assets scene files |             //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!"); |             throw new IllegalStateException("Trying to load a save that does not contain a scene!"); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user