Update #44 - WebAssembly GC support, fix more WebRTC bugs

This commit is contained in:
lax1dude 2024-12-03 23:38:28 -08:00
parent 919014b4df
commit 70b52bbf7a
216 changed files with 34358 additions and 91 deletions

75
CREDITS
View file

@ -784,6 +784,81 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Project Name: Emscripten
Project Author: Emscripten authors
Project URL: https://emscripten.org/
Used For: Compiling the WASM runtime's loader.wasm program
* Emscripten is available under 2 licenses, the MIT license and the
* University of Illinois/NCSA Open Source License.
*
* Copyright (c) 2010-2014 Emscripten authors, see AUTHORS file.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Project Name: XZ Embedded
Project Author: Lasse Collin (Larhzu)
Project URL: https://tukaani.org/xz/embedded.html
Used For: Decompressing the WASM runtime
* Copyright (C) The XZ Embedded authors and contributors
*
* Permission to use, copy, modify, and/or distribute this
* software for any purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Project Name: XZ for Java
Project Author: Lasse Collin (Larhzu)
Project URL: https://tukaani.org/xz/java.html
Used For: Compression in the MakeWASMClientBundle command
* Copyright (C) The XZ for Java authors and contributors
*
* Permission to use, copy, modify, and/or distribute this
* software for any purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Make sure you also update the copy of this file in "sources/resources/assets/eagler/CREDITS.txt" Make sure you also update the copy of this file in "sources/resources/assets/eagler/CREDITS.txt"

View file

@ -21,14 +21,14 @@
## Getting Started: ## Getting Started:
### To compile the latest version of the client, on Windows: ### To compile the latest version of the JavaScript client, on Windows:
1. Make sure you have at least Java 11 installed and added to your PATH, it is recommended to use Java 17 1. Make sure you have at least Java 11 installed and added to your PATH, it is recommended to use Java 17
2. Download (clone) this repository to your computer 2. Download (clone) this repository to your computer
3. Double click `CompileLatestClient.bat`, a GUI resembling a classic windows installer should open 3. Double click `CompileLatestClient.bat`, a GUI resembling a classic windows installer should open
4. Follow the steps shown to you in the new window to finish compiling 4. Follow the steps shown to you in the new window to finish compiling
### To compile the latest version of the client, on Linux/macOS: ### To compile the latest version of the JavaScript client, on Linux/macOS:
1. Make sure you have at least Java 11 installed, it is recommended to use Java 17 1. Make sure you have at least Java 11 installed, it is recommended to use Java 17
2. Download (clone) this repository to your computer 2. Download (clone) this repository to your computer
@ -37,9 +37,21 @@
5. Type `./CompileLatestClient.sh` and hit enter, a GUI resembling a classic windows installer should open 5. Type `./CompileLatestClient.sh` and hit enter, a GUI resembling a classic windows installer should open
6. Follow the steps shown to you in the new window to finish compiling 6. Follow the steps shown to you in the new window to finish compiling
### To set up the development environment
1. Prepare the required files in the mcp918 folder ([readme](mcp918/readme.txt))
2. Run the `build_init` script
3. Run the `build_make_workspace` script
## Browser Compatibility ## Browser Compatibility
EaglercraftX 1.8 is currently known to work on browsers as old as Chrome 38 on Windows XP, the game supports both WebGL 1.0 and WebGL 2.0 however features such as dynamic lighting and PBR shaders require WebGL 2.0. The game also supports mobile browsers that don't have a keyboard or mouse, the game will enter touch screen mode automatically when touch input is detected. The game also includes an embedded OGG codec (JOrbis) for loading audio files on iOS where the browsers don't support loading OGG files in an AudioContext. The JavaScript runtime of EaglercraftX 1.8 is currently known to work on browsers as old as Chrome 38 on Windows XP, the game supports both WebGL 1.0 and WebGL 2.0 however features such as dynamic lighting and PBR shaders require WebGL 2.0. The game also supports mobile browsers that don't have a keyboard or mouse, the game will enter touch screen mode automatically when touch input is detected. The game also includes an embedded OGG codec (JOrbis) for loading audio files on iOS where the browsers don't support loading OGG files in an AudioContext.
## WebAssembly GC Support
EaglercraftX 1.8 also has an experimental WebAssembly GC (WASM-GC) runtime, almost all of the features supported on the JavaScript runtime are also supported on the WebAssembly GC runtime, however it is still incompatible with several major browsers (especially Safari) and will not run in Chrome unless you can access the `chrome://flags` menu or request an origin trial token from Google for your website. Its based on experimental technology and may still crash sometimes due to browser bugs or unresolved issues in the Java to WASM compiler. Hopefully in the coming months the required feature (JSPI, WebAssembly JavaScript Promise Integration) will become enabled by default on the Chrome browser. It performs significantly better than the JavaScript client, around 50% more FPS and TPS in some cases, and will hopefully replace it someday. Just make sure you enable VSync when you play it, otherwise the game will run "too fast" and choke the browser's event loop, causing input lag.
You can compile the WebAssembly GC runtime by creating a development environment (workspace) and reading the README in the "wasm_gc_teavm" folder.
## Singleplayer ## Singleplayer
@ -200,6 +212,7 @@ The default eaglercraftXOpts values is this:
- `ramdiskMode:` if worlds and resource packs should be stored in RAM instead of IndexedDB - `ramdiskMode:` if worlds and resource packs should be stored in RAM instead of IndexedDB
- `singleThreadMode:` if the game should run the client and integrated server in the same context instead of creating a worker object - `singleThreadMode:` if the game should run the client and integrated server in the same context instead of creating a worker object
- `enableEPKVersionCheck:` if the game should attempt to bypass the browser's cache and retry downloading assets.epk when its outdated - `enableEPKVersionCheck:` if the game should attempt to bypass the browser's cache and retry downloading assets.epk when its outdated
- `enforceVSync:` (WASM only) if the game should automatically re-enable VSync at launch if its disabled
- `hooks:` can be used to define JavaScript callbacks for certain events - `hooks:` can be used to define JavaScript callbacks for certain events
* `localStorageSaved:` JavaScript callback to save local storage keys (key, data) * `localStorageSaved:` JavaScript callback to save local storage keys (key, data)
* `localStorageLoaded:` JavaScript callback to load local storage keys (key) returns data * `localStorageLoaded:` JavaScript callback to load local storage keys (key) returns data

Binary file not shown.

View file

@ -72,6 +72,11 @@ public class PullRequestTask {
File originalSourceTeaVMC = new File(EaglerBuildTools.repositoryRoot, "sources/teavmc-classpath/resources"); File originalSourceTeaVMC = new File(EaglerBuildTools.repositoryRoot, "sources/teavmc-classpath/resources");
File originalSourceBootMenu = new File(EaglerBuildTools.repositoryRoot, "sources/teavm-boot-menu/java"); File originalSourceBootMenu = new File(EaglerBuildTools.repositoryRoot, "sources/teavm-boot-menu/java");
File originalSourceLWJGL = new File(EaglerBuildTools.repositoryRoot, "sources/lwjgl/java"); File originalSourceLWJGL = new File(EaglerBuildTools.repositoryRoot, "sources/lwjgl/java");
File originalSourceWASMGCTeaVMJava = new File(EaglerBuildTools.repositoryRoot, "sources/wasm-gc-teavm/java");
File originalSourceWASMGCTeaVMJS = new File(EaglerBuildTools.repositoryRoot, "sources/wasm-gc-teavm/js");
File originalSourceWASMGCTeaVMBootstrapJS = new File(EaglerBuildTools.repositoryRoot, "sources/wasm-gc-teavm-bootstrap/js");
File originalSourceWASMGCTeaVMLoaderC = new File(EaglerBuildTools.repositoryRoot, "sources/wasm-gc-teavm-loader/c");
File originalSourceWASMGCTeaVMLoaderJS = new File(EaglerBuildTools.repositoryRoot, "sources/wasm-gc-teavm-loader/js");
File originalUnpatchedSourceResourcesJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_res.jar"); File originalUnpatchedSourceResourcesJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_res.jar");
File originalSourceResourcesJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_res_patch.jar"); File originalSourceResourcesJar = new File(EaglerBuildToolsConfig.getTemporaryDirectory(), "MinecraftSrc/minecraft_res_patch.jar");
File originalSourceResources = new File(EaglerBuildTools.repositoryRoot, "sources/resources"); File originalSourceResources = new File(EaglerBuildTools.repositoryRoot, "sources/resources");
@ -83,6 +88,11 @@ public class PullRequestTask {
File diffFromBootMenu = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/teavm-boot-menu/java"); File diffFromBootMenu = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/teavm-boot-menu/java");
File diffFromTeaVMC = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/teavmc-classpath/resources"); File diffFromTeaVMC = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/teavmc-classpath/resources");
File diffFromLWJGL = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/lwjgl/java"); File diffFromLWJGL = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/lwjgl/java");
File diffFromWASMGCTeaVMJava = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/wasm-gc-teavm/java");
File diffFromWASMGCTeaVMJS = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/wasm-gc-teavm/js");
File diffFromWASMGCTeaVMBootstrapJS = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/wasm-gc-teavm-bootstrap/js");
File diffFromWASMGCTeaVMLoaderC = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/wasm-gc-teavm-loader/c");
File diffFromWASMGCTeaVMLoaderJS = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/wasm-gc-teavm-loader/js");
File diffFromResources = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "desktopRuntime/resources"); File diffFromResources = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "desktopRuntime/resources");
File pullRequestTo = new File(EaglerBuildTools.repositoryRoot, "pullrequest"); File pullRequestTo = new File(EaglerBuildTools.repositoryRoot, "pullrequest");
@ -163,6 +173,36 @@ public class PullRequestTask {
} }
System.out.println("Found " + i + " changed files in /src/lwjgl/java/"); System.out.println("Found " + i + " changed files in /src/lwjgl/java/");
i = copyAllModified(diffFromWASMGCTeaVMJava, originalSourceWASMGCTeaVMJava);
if(i > 0) {
flag = true;
}
System.out.println("Found " + i + " changed files in /src/wasm-gc-teavm/java/");
i = copyAllModified(diffFromWASMGCTeaVMJS, originalSourceWASMGCTeaVMJS);
if(i > 0) {
flag = true;
}
System.out.println("Found " + i + " changed files in /src/wasm-gc-teavm/js/");
i = copyAllModified(diffFromWASMGCTeaVMBootstrapJS, originalSourceWASMGCTeaVMBootstrapJS);
if(i > 0) {
flag = true;
}
System.out.println("Found " + i + " changed files in /src/wasm-gc-teavm-bootstrap/js/");
i = copyAllModified(diffFromWASMGCTeaVMLoaderC, originalSourceWASMGCTeaVMLoaderC);
if(i > 0) {
flag = true;
}
System.out.println("Found " + i + " changed files in /src/wasm-gc-teavm-loader/c/");
i = copyAllModified(diffFromWASMGCTeaVMLoaderJS, originalSourceWASMGCTeaVMLoaderJS);
if(i > 0) {
flag = true;
}
System.out.println("Found " + i + " changed files in /src/wasm-gc-teavm-loader/js/");
i = createDiffFiles(null, minecraftJavadocTmp, originalUnpatchedSourceMainJar, i = createDiffFiles(null, minecraftJavadocTmp, originalUnpatchedSourceMainJar,
originalSourceMainJar, diffFromGame, pullRequestToMain, true); originalSourceMainJar, diffFromGame, pullRequestToMain, true);
if(i > 0) { if(i > 0) {

View file

@ -129,6 +129,11 @@ public class SetupWorkspace {
File repoSourcesProtoRelay = new File(repoSources, "protocol-relay/java"); File repoSourcesProtoRelay = new File(repoSources, "protocol-relay/java");
File repoSourcesBootMenu = new File(repoSources, "teavm-boot-menu/java"); File repoSourcesBootMenu = new File(repoSources, "teavm-boot-menu/java");
File repoSourcesTeavmCRes = new File(repoSources, "teavmc-classpath/resources"); File repoSourcesTeavmCRes = new File(repoSources, "teavmc-classpath/resources");
File repoSourcesWASMGCTeaVMJava = new File(repoSources, "wasm-gc-teavm/java");
File repoSourcesWASMGCTeaVMJS = new File(repoSources, "wasm-gc-teavm/js");
File repoSourcesWASMGCTeaVMBootstrapJS = new File(repoSources, "wasm-gc-teavm-bootstrap/js");
File repoSourcesWASMGCTeaVMLoaderC = new File(repoSources, "wasm-gc-teavm-loader/c");
File repoSourcesWASMGCTeaVMLoaderJS = new File(repoSources, "wasm-gc-teavm-loader/js");
File repoSourcesResources = new File(repoSources, "resources"); File repoSourcesResources = new File(repoSources, "resources");
File srcMainJava = new File(workspaceDirectory, "src/main/java"); File srcMainJava = new File(workspaceDirectory, "src/main/java");
File srcGameJava = new File(workspaceDirectory, "src/game/java"); File srcGameJava = new File(workspaceDirectory, "src/game/java");
@ -138,6 +143,11 @@ public class SetupWorkspace {
File srcProtoRelay = new File(workspaceDirectory, "src/protocol-relay/java"); File srcProtoRelay = new File(workspaceDirectory, "src/protocol-relay/java");
File srcBootMenu = new File(workspaceDirectory, "src/teavm-boot-menu/java"); File srcBootMenu = new File(workspaceDirectory, "src/teavm-boot-menu/java");
File srcTeavmCRes = new File(workspaceDirectory, "src/teavmc-classpath/resources"); File srcTeavmCRes = new File(workspaceDirectory, "src/teavmc-classpath/resources");
File srcWASMGCTeaVMJava = new File(workspaceDirectory, "src/wasm-gc-teavm/java");
File srcWASMGCTeaVMJS = new File(workspaceDirectory, "src/wasm-gc-teavm/js");
File srcWASMGCTeaVMBootstrapJS = new File(workspaceDirectory, "src/wasm-gc-teavm-bootstrap/js");
File srcWASMGCTeaVMLoaderC = new File(workspaceDirectory, "src/wasm-gc-teavm-loader/c");
File srcWASMGCTeaVMLoaderJS = new File(workspaceDirectory, "src/wasm-gc-teavm-loader/js");
File resourcesExtractTo = new File(workspaceDirectory, "desktopRuntime/resources"); File resourcesExtractTo = new File(workspaceDirectory, "desktopRuntime/resources");
File mcLanguagesZip = new File(mcTmpDirectory, "minecraft_languages.zip"); File mcLanguagesZip = new File(mcTmpDirectory, "minecraft_languages.zip");
File mcLanguagesExtractTo = new File(workspaceDirectory, "javascript/lang"); File mcLanguagesExtractTo = new File(workspaceDirectory, "javascript/lang");
@ -165,6 +175,11 @@ public class SetupWorkspace {
System.err.println("ERROR: Could not rename \".gitignore.default\" to \".gitignore\" in the workspace directory!"); System.err.println("ERROR: Could not rename \".gitignore.default\" to \".gitignore\" in the workspace directory!");
} }
existingGi = new File(workspaceDirectory, "wasm_gc_teavm/.gitignore");
if((existingGi.exists() && !existingGi.delete()) || !(new File(workspaceDirectory, "wasm_gc_teavm/.gitignore.default").renameTo(existingGi))) {
System.err.println("ERROR: Could not rename \"wasm_gc_teavm/.gitignore.default\" to \"wasm_gc_teavm/.gitignore\" in the workspace directory!");
}
if(repoSourcesTeaVM.isDirectory()) { if(repoSourcesTeaVM.isDirectory()) {
System.out.println("Copying files from \"/sources/teavm/java/\" to workspace..."); System.out.println("Copying files from \"/sources/teavm/java/\" to workspace...");
@ -183,6 +198,10 @@ public class SetupWorkspace {
System.out.println("Copying files from \"/sources/main/java/\" to workspace..."); System.out.println("Copying files from \"/sources/main/java/\" to workspace...");
try { try {
if(!srcMainJava.isDirectory() && !srcMainJava.mkdirs()) {
System.err.println("ERROR: Could not create destination directory!");
return false;
}
FileUtils.copyDirectory(repoSourcesMain, srcMainJava); FileUtils.copyDirectory(repoSourcesMain, srcMainJava);
}catch(IOException ex) { }catch(IOException ex) {
System.err.println("ERROR: could not copy \"/sources/main/java/\" to \"" + srcMainJava.getAbsolutePath() + "\"!"); System.err.println("ERROR: could not copy \"/sources/main/java/\" to \"" + srcMainJava.getAbsolutePath() + "\"!");
@ -193,6 +212,10 @@ public class SetupWorkspace {
System.out.println("Copying files from \"/sources/protocol-game/java/\" to workspace..."); System.out.println("Copying files from \"/sources/protocol-game/java/\" to workspace...");
try { try {
if(!srcProtoGame.isDirectory() && !srcProtoGame.mkdirs()) {
System.err.println("ERROR: Could not create destination directory!");
return false;
}
FileUtils.copyDirectory(repoSourcesProtoGame, srcProtoGame); FileUtils.copyDirectory(repoSourcesProtoGame, srcProtoGame);
}catch(IOException ex) { }catch(IOException ex) {
System.err.println("ERROR: could not copy \"/sources/protocol-game/java/\" to \"" + srcProtoGame.getAbsolutePath() + "\"!"); System.err.println("ERROR: could not copy \"/sources/protocol-game/java/\" to \"" + srcProtoGame.getAbsolutePath() + "\"!");
@ -204,6 +227,10 @@ public class SetupWorkspace {
System.out.println("Copying files from \"/sources/protocol-relay/java/\" to workspace..."); System.out.println("Copying files from \"/sources/protocol-relay/java/\" to workspace...");
try { try {
if(!srcProtoRelay.isDirectory() && !srcProtoRelay.mkdirs()) {
System.err.println("ERROR: Could not create destination directory!");
return false;
}
FileUtils.copyDirectory(repoSourcesProtoRelay, srcProtoRelay); FileUtils.copyDirectory(repoSourcesProtoRelay, srcProtoRelay);
}catch(IOException ex) { }catch(IOException ex) {
System.err.println("ERROR: could not copy \"/sources/protocol-relay/java/\" to \"" + srcProtoRelay.getAbsolutePath() + "\"!"); System.err.println("ERROR: could not copy \"/sources/protocol-relay/java/\" to \"" + srcProtoRelay.getAbsolutePath() + "\"!");
@ -215,6 +242,10 @@ public class SetupWorkspace {
System.out.println("Copying files from \"/sources/teavmc-classpath/resources/\" to workspace..."); System.out.println("Copying files from \"/sources/teavmc-classpath/resources/\" to workspace...");
try { try {
if(!srcTeavmCRes.isDirectory() && !srcTeavmCRes.mkdirs()) {
System.err.println("ERROR: Could not create destination directory!");
return false;
}
FileUtils.copyDirectory(repoSourcesTeavmCRes, srcTeavmCRes); FileUtils.copyDirectory(repoSourcesTeavmCRes, srcTeavmCRes);
}catch(IOException ex) { }catch(IOException ex) {
System.err.println("ERROR: could not copy \"/sources/teavmc-classpath/resources/\" to \"" + srcTeavmCRes.getAbsolutePath() + "\"!"); System.err.println("ERROR: could not copy \"/sources/teavmc-classpath/resources/\" to \"" + srcTeavmCRes.getAbsolutePath() + "\"!");
@ -226,6 +257,10 @@ public class SetupWorkspace {
System.out.println("Copying files from \"/sources/teavm-boot-menu/java/\" to workspace..."); System.out.println("Copying files from \"/sources/teavm-boot-menu/java/\" to workspace...");
try { try {
if(!srcBootMenu.isDirectory() && !srcBootMenu.mkdirs()) {
System.err.println("ERROR: Could not create destination directory!");
return false;
}
FileUtils.copyDirectory(repoSourcesBootMenu, srcBootMenu); FileUtils.copyDirectory(repoSourcesBootMenu, srcBootMenu);
}catch(IOException ex) { }catch(IOException ex) {
System.err.println("ERROR: could not copy \"/sources/teavm-boot-menu/java/\" to \"" + srcBootMenu.getAbsolutePath() + "\"!"); System.err.println("ERROR: could not copy \"/sources/teavm-boot-menu/java/\" to \"" + srcBootMenu.getAbsolutePath() + "\"!");
@ -247,6 +282,81 @@ public class SetupWorkspace {
throw ex; throw ex;
} }
} }
if(repoSourcesWASMGCTeaVMJava.isDirectory()) {
System.out.println("Copying files from \"/sources/wasm-gc-teavm/java/\" to workspace...");
try {
if(!srcWASMGCTeaVMJava.isDirectory() && !srcWASMGCTeaVMJava.mkdirs()) {
System.err.println("ERROR: Could not create destination directory!");
return false;
}
FileUtils.copyDirectory(repoSourcesWASMGCTeaVMJava, srcWASMGCTeaVMJava);
}catch(IOException ex) {
System.err.println("ERROR: could not copy \"/sources/wasm-gc-teavm/java/\" to \"" + srcWASMGCTeaVMJava.getAbsolutePath() + "\"!");
throw ex;
}
}
if(repoSourcesWASMGCTeaVMJS.isDirectory()) {
System.out.println("Copying files from \"/sources/wasm-gc-teavm/js/\" to workspace...");
try {
if(!srcWASMGCTeaVMJS.isDirectory() && !srcWASMGCTeaVMJS.mkdirs()) {
System.err.println("ERROR: Could not create destination directory!");
return false;
}
FileUtils.copyDirectory(repoSourcesWASMGCTeaVMJS, srcWASMGCTeaVMJS);
}catch(IOException ex) {
System.err.println("ERROR: could not copy \"/sources/wasm-gc-teavm/js/\" to \"" + srcWASMGCTeaVMJS.getAbsolutePath() + "\"!");
throw ex;
}
}
if(repoSourcesWASMGCTeaVMBootstrapJS.isDirectory()) {
System.out.println("Copying files from \"/sources/wasm-gc-teavm-bootstrap/js/\" to workspace...");
try {
if(!srcWASMGCTeaVMBootstrapJS.isDirectory() && !srcWASMGCTeaVMBootstrapJS.mkdirs()) {
System.err.println("ERROR: Could not create destination directory!");
return false;
}
FileUtils.copyDirectory(repoSourcesWASMGCTeaVMBootstrapJS, srcWASMGCTeaVMBootstrapJS);
}catch(IOException ex) {
System.err.println("ERROR: could not copy \"/sources/wasm-gc-teavm-bootstrap/js/\" to \"" + srcWASMGCTeaVMBootstrapJS.getAbsolutePath() + "\"!");
throw ex;
}
}
if(repoSourcesWASMGCTeaVMLoaderC.isDirectory()) {
System.out.println("Copying files from \"/sources/wasm-gc-teavm-loader/c/\" to workspace...");
try {
if(!srcWASMGCTeaVMLoaderC.isDirectory() && !srcWASMGCTeaVMLoaderC.mkdirs()) {
System.err.println("ERROR: Could not create destination directory!");
return false;
}
FileUtils.copyDirectory(repoSourcesWASMGCTeaVMLoaderC, srcWASMGCTeaVMLoaderC);
}catch(IOException ex) {
System.err.println("ERROR: could not copy \"/sources/wasm-gc-teavm-loader/c/\" to \"" + srcWASMGCTeaVMLoaderC.getAbsolutePath() + "\"!");
throw ex;
}
}
if(repoSourcesWASMGCTeaVMLoaderJS.isDirectory()) {
System.out.println("Copying files from \"/sources/wasm-gc-teavm-loader/js/\" to workspace...");
try {
if(!srcWASMGCTeaVMLoaderJS.isDirectory() && !srcWASMGCTeaVMLoaderJS.mkdirs()) {
System.err.println("ERROR: Could not create destination directory!");
return false;
}
FileUtils.copyDirectory(repoSourcesWASMGCTeaVMLoaderJS, srcWASMGCTeaVMLoaderJS);
}catch(IOException ex) {
System.err.println("ERROR: could not copy \"/sources/wasm-gc-teavm-loader/js/\" to \"" + srcWASMGCTeaVMLoaderJS.getAbsolutePath() + "\"!");
throw ex;
}
}
System.out.println("Copying files from \"/sources/resources/\" to workspace..."); System.out.println("Copying files from \"/sources/resources/\" to workspace...");

View file

@ -1 +1 @@
u43 u44

View file

@ -1,4 +1,4 @@
# 145 files to delete: # 146 files to delete:
net/minecraft/client/renderer/VertexBufferUploader.java net/minecraft/client/renderer/VertexBufferUploader.java
net/minecraft/realms/DisconnectedRealmsScreen.java net/minecraft/realms/DisconnectedRealmsScreen.java
net/minecraft/client/stream/Metadata.java net/minecraft/client/stream/Metadata.java
@ -99,6 +99,7 @@ net/minecraft/realms/RealmsAnvilLevelStorageSource.java
net/minecraft/realms/RealmsSliderButton.java net/minecraft/realms/RealmsSliderButton.java
net/minecraft/world/storage/ThreadedFileIOBase.java net/minecraft/world/storage/ThreadedFileIOBase.java
net/minecraft/client/renderer/vertex/VertexBuffer.java net/minecraft/client/renderer/vertex/VertexBuffer.java
net/minecraft/world/MinecraftException.java
net/minecraft/network/rcon/RConConsoleSource.java net/minecraft/network/rcon/RConConsoleSource.java
net/minecraft/world/chunk/storage/AnvilSaveHandler.java net/minecraft/world/chunk/storage/AnvilSaveHandler.java
net/minecraft/realms/RealmsVertexFormatElement.java net/minecraft/realms/RealmsVertexFormatElement.java

View file

@ -18,7 +18,7 @@
> DELETE 1 @ 1 : 4 > DELETE 1 @ 1 : 4
> CHANGE 1 : 74 @ 1 : 4 > CHANGE 1 : 75 @ 1 : 4
~ ~
~ import net.lax1dude.eaglercraft.v1_8.ClientUUIDLoadingCache; ~ import net.lax1dude.eaglercraft.v1_8.ClientUUIDLoadingCache;
@ -52,6 +52,7 @@
~ import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerFontRenderer; ~ import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerFontRenderer;
~ import net.lax1dude.eaglercraft.v1_8.minecraft.EnumInputEvent; ~ import net.lax1dude.eaglercraft.v1_8.minecraft.EnumInputEvent;
~ import net.lax1dude.eaglercraft.v1_8.minecraft.GuiScreenGenericErrorMessage; ~ import net.lax1dude.eaglercraft.v1_8.minecraft.GuiScreenGenericErrorMessage;
~ import net.lax1dude.eaglercraft.v1_8.minecraft.GuiScreenVSyncReEnabled;
~ import net.lax1dude.eaglercraft.v1_8.minecraft.GuiScreenVideoSettingsWarning; ~ import net.lax1dude.eaglercraft.v1_8.minecraft.GuiScreenVideoSettingsWarning;
~ import net.lax1dude.eaglercraft.v1_8.notifications.ServerNotificationRenderer; ~ import net.lax1dude.eaglercraft.v1_8.notifications.ServerNotificationRenderer;
~ import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader; ~ import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader;
@ -359,12 +360,6 @@
~ mainMenu = new GuiConnecting(mainMenu, this, this.serverName, this.serverPort); ~ mainMenu = new GuiConnecting(mainMenu, this, this.serverName, this.serverPort);
> CHANGE 2 : 5 @ 2 : 7
~ int vidIssues = gameSettings.checkBadVideoSettings();
~ if (vidIssues != 0) {
~ mainMenu = new GuiScreenVideoSettingsWarning(mainMenu, vidIssues);
> CHANGE 2 : 6 @ 2 : 7 > CHANGE 2 : 6 @ 2 : 7
~ mainMenu = new GuiScreenEditProfile(mainMenu); ~ mainMenu = new GuiScreenEditProfile(mainMenu);
@ -372,8 +367,25 @@
~ if (!EagRuntime.getConfiguration().isForceProfanityFilter() && !gameSettings.hasShownProfanityFilter) { ~ if (!EagRuntime.getConfiguration().isForceProfanityFilter() && !gameSettings.hasShownProfanityFilter) {
~ mainMenu = new GuiScreenContentWarning(mainMenu); ~ mainMenu = new GuiScreenContentWarning(mainMenu);
> CHANGE 2 : 14 @ 2 : 3 > CHANGE 2 : 7 @ 2 : 7
~ boolean vsyncScreen = false;
~ if (EagRuntime.getConfiguration().isEnforceVSync() && Display.isVSyncSupported() && !gameSettings.enableVsync) {
~ gameSettings.enableVsync = true;
~ gameSettings.saveOptions();
~ vsyncScreen = true;
> CHANGE 2 : 23 @ 2 : 3
~ int vidIssues = gameSettings.checkBadVideoSettings();
~ if (vidIssues != 0) {
~ mainMenu = new GuiScreenVideoSettingsWarning(mainMenu, vidIssues);
~ }
~
~ if (vsyncScreen) {
~ mainMenu = new GuiScreenVSyncReEnabled(mainMenu);
~ }
~
~ this.displayGuiScreen(mainMenu); ~ this.displayGuiScreen(mainMenu);
~ ~
~ this.renderEngine.deleteTexture(this.mojangLogo); ~ this.renderEngine.deleteTexture(this.mojangLogo);

View file

@ -345,7 +345,7 @@
> CHANGE 8 : 36 @ 8 : 25 > CHANGE 8 : 36 @ 8 : 25
~ ArrayList arraylist; ~ ArrayList arraylist;
~ if (EagRuntime.getPlatformType() != EnumPlatformType.JAVASCRIPT) { ~ if (EagRuntime.getPlatformType() == EnumPlatformType.DESKTOP) {
~ long i = EagRuntime.maxMemory(); ~ long i = EagRuntime.maxMemory();
~ long j = EagRuntime.totalMemory(); ~ long j = EagRuntime.totalMemory();
~ long k = EagRuntime.freeMemory(); ~ long k = EagRuntime.freeMemory();

View file

@ -85,7 +85,7 @@
+ long millis = EagRuntime.steadyTimeMillis(); + long millis = EagRuntime.steadyTimeMillis();
+ long closeKeyTimeout = millis - showingCloseKey; + long closeKeyTimeout = millis - showingCloseKey;
+ if (closeKeyTimeout < 3000l) { + if (closeKeyTimeout < 3000l && showingCloseKey != 0l) {
+ int alpha1 = 0xC0000000; + int alpha1 = 0xC0000000;
+ int alpha2 = 0xFF000000; + int alpha2 = 0xFF000000;
+ if (closeKeyTimeout > 2500l) { + if (closeKeyTimeout > 2500l) {

View file

@ -168,7 +168,154 @@
> DELETE 3 @ 3 : 4 > DELETE 3 @ 3 : 4
> DELETE 105 @ 105 : 106 > CHANGE 3 : 7 @ 3 : 5
~ Entity object = null;
~ boolean b = false;
~ switch (packetIn.getType()) {
~ case 10:
> CHANGE 2 : 5 @ 2 : 3
~ break;
~ case 90:
~ b = true;
> CHANGE 4 : 6 @ 4 : 7
~ break;
~ case 60:
> CHANGE 1 : 3 @ 1 : 2
~ break;
~ case 61:
> CHANGE 1 : 4 @ 1 : 2
~ break;
~ case 71:
~ b = true;
> CHANGE 3 : 6 @ 3 : 5
~ break;
~ case 77:
~ b = true;
> CHANGE 2 : 4 @ 2 : 4
~ break;
~ case 65:
> CHANGE 1 : 3 @ 1 : 2
~ break;
~ case 72:
> CHANGE 1 : 3 @ 1 : 2
~ break;
~ case 76:
> CHANGE 1 : 4 @ 1 : 2
~ break;
~ case 63:
~ b = true;
> CHANGE 3 : 6 @ 3 : 5
~ break;
~ case 64:
~ b = true;
> CHANGE 3 : 6 @ 3 : 5
~ break;
~ case 66:
~ b = true;
> CHANGE 3 : 5 @ 3 : 5
~ break;
~ case 62:
> CHANGE 1 : 4 @ 1 : 2
~ break;
~ case 73:
~ b = true;
> CHANGE 1 : 4 @ 1 : 3
~ break;
~ case 75:
~ b = true;
> CHANGE 1 : 3 @ 1 : 3
~ break;
~ case 1:
> CHANGE 1 : 3 @ 1 : 2
~ break;
~ case 50:
> CHANGE 1 : 3 @ 1 : 2
~ break;
~ case 78:
> CHANGE 1 : 3 @ 1 : 2
~ break;
~ case 51:
> CHANGE 1 : 3 @ 1 : 2
~ break;
~ case 2:
> CHANGE 1 : 4 @ 1 : 2
~ break;
~ case 70:
~ b = true;
> INSERT 2 : 7 @ 2
+ break;
+ }
+
+ if (b) {
+ // fix for compiler bug
> CHANGE 4 : 10 @ 4 : 10
~ object.serverPosX = packetIn.getX();
~ object.serverPosY = packetIn.getY();
~ object.serverPosZ = packetIn.getZ();
~ object.rotationPitch = (float) (packetIn.getPitch() * 360) / 256.0F;
~ object.rotationYaw = (float) (packetIn.getYaw() * 360) / 256.0F;
~ Entity[] aentity = object.getParts();
> CHANGE 1 : 2 @ 1 : 2
~ int i = packetIn.getEntityID() - object.getEntityId();
> CHANGE 6 : 8 @ 6 : 8
~ object.setEntityId(packetIn.getEntityID());
~ this.clientWorldController.addEntityToWorld(packetIn.getEntityID(), object);
> CHANGE 8 : 10 @ 8 : 10
~ object.setVelocity((double) packetIn.getSpeedX() / 8000.0D, (double) packetIn.getSpeedY() / 8000.0D,
~ (double) packetIn.getSpeedZ() / 8000.0D);
> DELETE 6 @ 6 : 7
> DELETE 12 @ 12 : 13 > DELETE 12 @ 12 : 13

View file

@ -18,7 +18,39 @@
~ public void renderBlockDamage(IBlockState state, BlockPos pos, EaglerTextureAtlasSprite texture, ~ public void renderBlockDamage(IBlockState state, BlockPos pos, EaglerTextureAtlasSprite texture,
> CHANGE 55 : 59 @ 55 : 61 > INSERT 15 : 16 @ 15
+ boolean res;
> CHANGE 2 : 3 @ 2 : 3
~ res = false;
> CHANGE 3 : 5 @ 3 : 4
~ res = this.fluidRenderer.renderFluid(blockAccess, state, pos, worldRendererIn);
~ break;
> CHANGE 1 : 3 @ 1 : 2
~ res = false;
~ break;
> CHANGE 2 : 4 @ 2 : 3
~ res = this.blockModelRenderer.renderModel(blockAccess, ibakedmodel, state, pos, worldRendererIn);
~ break;
> CHANGE 1 : 3 @ 1 : 2
~ res = false;
~ break;
> INSERT 2 : 3 @ 2
+ return res;
> CHANGE 24 : 28 @ 24 : 30
~ ~
~ try { ~ try {

View file

@ -26,13 +26,19 @@
~ private String[] stacktrace; ~ private String[] stacktrace;
> INSERT 4 : 5 @ 4 > INSERT 2 : 5 @ 2
+ if (causeThrowable == null) {
+ throw new NullPointerException("Crash report created for null throwable!");
+ }
> INSERT 2 : 3 @ 2
+ this.stacktrace = EagRuntime.getStackTraceElements(causeThrowable); + this.stacktrace = EagRuntime.getStackTraceElements(causeThrowable);
> CHANGE 26 : 37 @ 26 : 54 > CHANGE 26 : 37 @ 26 : 54
~ if (EagRuntime.getPlatformType() != EnumPlatformType.JAVASCRIPT) { ~ if (EagRuntime.getPlatformType() == EnumPlatformType.DESKTOP) {
~ this.theReportCategory.addCrashSectionCallable("Memory", new Callable<String>() { ~ this.theReportCategory.addCrashSectionCallable("Memory", new Callable<String>() {
~ public String call() { ~ public String call() {
~ long i = EagRuntime.maxMemory(); ~ long i = EagRuntime.maxMemory();

View file

@ -7,12 +7,14 @@
> DELETE 2 @ 2 : 4 > DELETE 2 @ 2 : 4
> CHANGE 4 : 11 @ 4 : 8 > CHANGE 4 : 13 @ 4 : 8
~ ~
~ import com.google.common.collect.Lists; ~ import com.google.common.collect.Lists;
~ import com.google.common.collect.Maps; ~ import com.google.common.collect.Maps;
~ ~
~ import net.lax1dude.eaglercraft.v1_8.EagRuntime;
~ import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformType;
~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; ~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
~ import net.lax1dude.eaglercraft.v1_8.log4j.Logger; ~ import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
~ import net.lax1dude.eaglercraft.v1_8.minecraft.EntityConstructor; ~ import net.lax1dude.eaglercraft.v1_8.minecraft.EntityConstructor;
@ -126,7 +128,22 @@
~ Set<String> set = stringToClassMapping.keySet(); ~ Set<String> set = stringToClassMapping.keySet();
> CHANGE 29 : 97 @ 29 : 91 > CHANGE 2 : 9 @ 2 : 6
~ // TODO: Eventually TeaVM will support getModifiers
~ if (EagRuntime.getPlatformType() != EnumPlatformType.WASM_GC) {
~ for (String s : set) {
~ Class oclass = (Class) stringToClassMapping.get(s);
~ if ((oclass.getModifiers() & 1024) != 1024) {
~ arraylist.add(s);
~ }
> INSERT 1 : 3 @ 1
+ } else {
+ arraylist.addAll(set);
> CHANGE 22 : 90 @ 22 : 84
~ addMapping(EntityItem.class, EntityItem::new, "Item", 1); ~ addMapping(EntityItem.class, EntityItem::new, "Item", 1);
~ addMapping(EntityXPOrb.class, EntityXPOrb::new, "XPOrb", 2); ~ addMapping(EntityXPOrb.class, EntityXPOrb::new, "XPOrb", 2);

View file

@ -38,7 +38,9 @@
> DELETE 7 @ 7 : 8 > DELETE 7 @ 7 : 8
> CHANGE 10 : 11 @ 10 : 12 > DELETE 4 @ 4 : 5
> CHANGE 5 : 6 @ 5 : 7
~ import net.minecraft.world.chunk.Chunk; ~ import net.minecraft.world.chunk.Chunk;
@ -195,7 +197,11 @@
~ for (int i = 0; i < this.worldServers.length; ++i) { ~ for (int i = 0; i < this.worldServers.length; ++i) {
~ WorldServer worldserver = this.worldServers[i]; ~ WorldServer worldserver = this.worldServers[i];
> DELETE 20 @ 20 : 23 > CHANGE 6 : 7 @ 6 : 11
~ worldserver.saveAllChunks(true, (IProgressUpdate) null);
> DELETE 9 @ 9 : 12
> CHANGE 16 : 22 @ 16 : 21 > CHANGE 16 : 22 @ 16 : 21

View file

@ -314,7 +314,9 @@
~ public EntityPlayer getPlayerEntityByUUID(EaglercraftUUID uuid) { ~ public EntityPlayer getPlayerEntityByUUID(EaglercraftUUID uuid) {
> CHANGE 197 : 198 @ 197 : 198 > DELETE 13 @ 13 : 17
> CHANGE 180 : 181 @ 180 : 181
~ public EaglercraftRandom setRandomSeed(int parInt1, int parInt2, int parInt3) { ~ public EaglercraftRandom setRandomSeed(int parInt1, int parInt2, int parInt3) {

View file

@ -108,13 +108,21 @@
~ EaglercraftRandom random = new EaglercraftRandom(this.getSeed()); ~ EaglercraftRandom random = new EaglercraftRandom(this.getSeed());
> CHANGE 62 : 65 @ 62 : 63 > CHANGE 49 : 50 @ 49 : 50
~ public void saveAllChunks(boolean progressCallback, IProgressUpdate parIProgressUpdate) {
> CHANGE 12 : 15 @ 12 : 13
~ List<Chunk> lst = Lists.newArrayList(this.theChunkProviderServer.func_152380_a()); ~ List<Chunk> lst = Lists.newArrayList(this.theChunkProviderServer.func_152380_a());
~ for (int i = 0, l = lst.size(); i < l; ++i) { ~ for (int i = 0, l = lst.size(); i < l; ++i) {
~ Chunk chunk = lst.get(i); ~ Chunk chunk = lst.get(i);
> CHANGE 79 : 82 @ 79 : 80 > CHANGE 14 : 15 @ 14 : 16
~ protected void saveLevel() {
> CHANGE 63 : 66 @ 63 : 64
~ List<EntityPlayer> lst = this.playerEntities; ~ List<EntityPlayer> lst = this.playerEntities;
~ for (int i = 0, l = lst.size(); i < l; ++i) { ~ for (int i = 0, l = lst.size(); i < l; ++i) {

View file

@ -14,4 +14,6 @@
~ public WorldServerMulti(MinecraftServer server, ISaveHandler saveHandlerIn, int dimensionId, WorldServer delegate) { ~ public WorldServerMulti(MinecraftServer server, ISaveHandler saveHandlerIn, int dimensionId, WorldServer delegate) {
~ super(server, saveHandlerIn, new DerivedWorldInfo(delegate.getWorldInfo()), dimensionId); ~ super(server, saveHandlerIn, new DerivedWorldInfo(delegate.getWorldInfo()), dimensionId);
> DELETE 32 @ 32 : 35
> EOF > EOF

View file

@ -0,0 +1,14 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> DELETE 3 @ 3 : 4
> CHANGE 6 : 7 @ 6 : 7
~ void saveChunk(World var1, Chunk var2) throws IOException;
> EOF

View file

@ -9,7 +9,9 @@
+ import net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer; + import net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer;
> CHANGE 14 : 17 @ 14 : 16 > DELETE 6 @ 6 : 7
> CHANGE 7 : 10 @ 7 : 9
~ import net.lax1dude.eaglercraft.v1_8.HString; ~ import net.lax1dude.eaglercraft.v1_8.HString;
~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; ~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
@ -46,17 +48,14 @@
+ ++EaglerMinecraftServer.counterChunkWrite; + ++EaglerMinecraftServer.counterChunkWrite;
> CHANGE 1 : 3 @ 1 : 2 > CHANGE 1 : 3 @ 1 : 5
~ logger.error("Couldn\'t save chunk"); ~ logger.error("Couldn\'t save chunk");
~ logger.error(ioexception); ~ logger.error(ioexception);
> CHANGE 1 : 3 @ 1 : 3 > DELETE 1 @ 1 : 2
~ logger.error("Couldn\'t save chunk; already in use by another instance of Minecraft?"); > CHANGE 29 : 30 @ 29 : 30
~ logger.error(minecraftexception);
> CHANGE 31 : 32 @ 31 : 32
~ for (int j = 0, l = arraylist.size(); j < l; ++j) { ~ for (int j = 0, l = arraylist.size(); j < l; ++j) {

View file

@ -7,13 +7,15 @@
> DELETE 2 @ 2 : 3 > DELETE 2 @ 2 : 3
> INSERT 1 : 2 @ 1 > CHANGE 1 : 2 @ 1 : 2
+ import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2; ~ import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
> DELETE 3 @ 3 : 5 > DELETE 2 @ 2 : 4
> CHANGE 16 : 17 @ 16 : 17 > DELETE 4 @ 4 : 6
> CHANGE 10 : 11 @ 10 : 11
~ VFile2 getWorldDirectory(); ~ VFile2 getWorldDirectory();

View file

@ -12,7 +12,9 @@
~ import java.util.List; ~ import java.util.List;
~ ~
> CHANGE 7 : 11 @ 7 : 12 > DELETE 4 @ 4 : 5
> CHANGE 2 : 6 @ 2 : 7
~ import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2; ~ import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; ~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
@ -40,9 +42,9 @@
~ public VFile2 getWorldDirectory() { ~ public VFile2 getWorldDirectory() {
> DELETE 4 @ 4 : 19 > DELETE 3 @ 3 : 21
> CHANGE 3 : 4 @ 3 : 4 > CHANGE 1 : 2 @ 1 : 2
~ throw new RuntimeException("eagler"); ~ throw new RuntimeException("eagler");

View file

@ -9,9 +9,11 @@
~ import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2; ~ import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
> DELETE 4 @ 4 : 7 > DELETE 1 @ 1 : 2
> DELETE 9 @ 9 : 13 > DELETE 2 @ 2 : 5
> DELETE 6 @ 6 : 13
> CHANGE 13 : 19 @ 13 : 14 > CHANGE 13 : 19 @ 13 : 14

View file

@ -257,7 +257,7 @@
+ eaglercraft.command.clientStub=This command is client side! + eaglercraft.command.clientStub=This command is client side!
+ +
> INSERT 163 : 561 @ 163 > INSERT 163 : 568 @ 163
+ eaglercraft.singleplayer.busy.killTask=Cancel Task + eaglercraft.singleplayer.busy.killTask=Cancel Task
+ eaglercraft.singleplayer.busy.cancelWarning=Are you sure? + eaglercraft.singleplayer.busy.cancelWarning=Are you sure?
@ -657,6 +657,13 @@
+ eaglercraft.options.badVideoSettingsDetected.continueAnyway=Continue Anyway + eaglercraft.options.badVideoSettingsDetected.continueAnyway=Continue Anyway
+ eaglercraft.options.badVideoSettingsDetected.doNotShowAgain=Do Not Show Again + eaglercraft.options.badVideoSettingsDetected.doNotShowAgain=Do Not Show Again
+ +
+ eaglercraft.options.vsyncReEnabled.title=Issues Detected
+ eaglercraft.options.vsyncReEnabled.0=You are using the WASM-GC client
+ eaglercraft.options.vsyncReEnabled.1=VSync has been automatically re-enabled
+ eaglercraft.options.vsyncReEnabled.2=Using the WASM-GC version of EaglercraftX without
+ eaglercraft.options.vsyncReEnabled.3=VSync enabled causes bad input lag, sorry!
+ eaglercraft.options.vsyncReEnabled.continue=Continue
+
> INSERT 18 : 19 @ 18 > INSERT 18 : 19 @ 18

View file

@ -198,6 +198,11 @@ public class DesktopClientConfigAdapter implements IClientConfigAdapter {
return false; return false;
} }
@Override
public boolean isEnforceVSync() {
return false;
}
@Override @Override
public IClientConfigAdapterHooks getHooks() { public IClientConfigAdapterHooks getHooks() {
return hooks; return hooks;

View file

@ -10,6 +10,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.IEaglerFilesystem;
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData; import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC; import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.DesktopClientConfigAdapter; import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.DesktopClientConfigAdapter;
import net.lax1dude.eaglercraft.v1_8.sp.server.IWASMCrashCallback;
import net.lax1dude.eaglercraft.v1_8.sp.server.internal.lwjgl.MemoryConnection; import net.lax1dude.eaglercraft.v1_8.sp.server.internal.lwjgl.MemoryConnection;
/** /**
@ -91,4 +92,8 @@ public class ServerPlatformSingleplayer {
return false; return false;
} }
public static void setCrashCallbackWASM(IWASMCrashCallback callback) {
}
} }

View file

@ -99,4 +99,9 @@ public class EagUtils {
return EaglercraftUUID.nameUUIDFromBytes(("EaglercraftXClientOld:" + name).getBytes(StandardCharsets.UTF_8)); return EaglercraftUUID.nameUUIDFromBytes(("EaglercraftXClientOld:" + name).getBytes(StandardCharsets.UTF_8));
} }
public static void sleepPrint(String string) {
System.out.println(string);
PlatformRuntime.sleep(500);
}
} }

View file

@ -10,7 +10,7 @@ public class EaglercraftVersion {
/// Customize these to fit your fork: /// Customize these to fit your fork:
public static final String projectForkName = "EaglercraftX"; public static final String projectForkName = "EaglercraftX";
public static final String projectForkVersion = "u43"; public static final String projectForkVersion = "u44";
public static final String projectForkVendor = "lax1dude"; public static final String projectForkVendor = "lax1dude";
public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8";
@ -20,20 +20,20 @@ public class EaglercraftVersion {
public static final String projectOriginName = "EaglercraftX"; public static final String projectOriginName = "EaglercraftX";
public static final String projectOriginAuthor = "lax1dude"; public static final String projectOriginAuthor = "lax1dude";
public static final String projectOriginRevision = "1.8"; public static final String projectOriginRevision = "1.8";
public static final String projectOriginVersion = "u43"; public static final String projectOriginVersion = "u44";
public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace
// EPK Version Identifier // EPK Version Identifier
public static final String EPKVersionIdentifier = "u43"; // Set to null to disable EPK version check public static final String EPKVersionIdentifier = "u44"; // Set to null to disable EPK version check
// Updating configuration // Updating configuration
public static final boolean enableUpdateService = true; public static final boolean enableUpdateService = true;
public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client"; public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client";
public static final int updateBundlePackageVersionInt = 43; public static final int updateBundlePackageVersionInt = 44;
public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName; public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName;
@ -52,8 +52,8 @@ public class EaglercraftVersion {
// Miscellaneous variables: // Miscellaneous variables:
public static final String mainMenuStringA = "Minecraft 1.8.8"; public static final String mainMenuStringA = "Minecraft 1.8.8";
public static final String mainMenuStringB = projectOriginName + " " + public static final String mainMenuStringB = projectOriginName + " " + projectOriginRevision + "-"
projectOriginRevision + "-" + projectOriginVersion + " ultimate"; + projectOriginVersion + " ultimate [" + EagRuntime.getPlatformType().getName() + "]";
public static final String mainMenuStringC = ""; public static final String mainMenuStringC = "";
public static final String mainMenuStringD = "Resources Copyright Mojang AB"; public static final String mainMenuStringD = "Resources Copyright Mojang AB";
@ -63,6 +63,9 @@ public class EaglercraftVersion {
public static final String mainMenuStringG = "Collector's Edition"; public static final String mainMenuStringG = "Collector's Edition";
public static final String mainMenuStringH = "PBR Shaders"; public static final String mainMenuStringH = "PBR Shaders";
public static final String screenRecordingFilePrefix = projectOriginName + " "
+ projectOriginRevision + "-" + projectOriginVersion;
public static final long demoWorldSeed = (long) "North Carolina".hashCode(); public static final long demoWorldSeed = (long) "North Carolina".hashCode();
public static final boolean mainMenuEnableGithubButton = false; public static final boolean mainMenuEnableGithubButton = false;

View file

@ -16,7 +16,7 @@ package net.lax1dude.eaglercraft.v1_8.internal;
* *
*/ */
public enum EnumPlatformType { public enum EnumPlatformType {
DESKTOP("Desktop"), JAVASCRIPT("JavaScript"), WASM_GC("ASM"); DESKTOP("Desktop"), JAVASCRIPT("JS"), WASM_GC("WASM-GC");
private final String name; private final String name;

View file

@ -98,6 +98,8 @@ public interface IClientConfigAdapter {
boolean isRamdiskMode(); boolean isRamdiskMode();
boolean isEnforceVSync();
IClientConfigAdapterHooks getHooks(); IClientConfigAdapterHooks getHooks();
} }

View file

@ -39,11 +39,9 @@ class VFileOutputStream extends EaglerOutputStream {
try { try {
copyBuffer.put(buf, 0, count); copyBuffer.put(buf, 0, count);
copyBuffer.flip(); copyBuffer.flip();
try { vfsFile.getFS().eaglerWrite(vfsFile.path, copyBuffer);
vfsFile.getFS().eaglerWrite(vfsFile.path, copyBuffer); }catch(Throwable t) {
}catch(Throwable t) { throw new IOException("Could not write stream contents to file!", t);
throw new IOException("Could not write stream contents to file!", t);
}
}finally { }finally {
PlatformRuntime.freeByteBuffer(copyBuffer); PlatformRuntime.freeByteBuffer(copyBuffer);
} }

View file

@ -159,6 +159,10 @@ public class Logger {
} }
private void logExcp(final Level level, String h, Throwable msg) { private void logExcp(final Level level, String h, Throwable msg) {
if(msg == null) {
log(level, "{}: <null>", h);
return;
}
log(level, "{}: {}", h, msg.toString()); log(level, "{}: {}", h, msg.toString());
EagRuntime.getStackTrace(msg, (e) -> log(level, " at {}", e)); EagRuntime.getStackTrace(msg, (e) -> log(level, " at {}", e));
PlatformRuntime.printJSExceptionIfBrowser(msg); PlatformRuntime.printJSExceptionIfBrowser(msg);

View file

@ -189,11 +189,15 @@ public class EaglerFontRenderer extends FontRenderer {
if(hasStrike) { if(hasStrike) {
GlStateManager.color(0.25f, 0.25f, 0.25f, 1.0f); GlStateManager.color(0.25f, 0.25f, 0.25f, 1.0f);
GlStateManager.translate(1.0f, 1.0f, 0.0f); GlStateManager.translate(1.0f, 1.0f, 0.0f);
GlStateManager.disableTexture2D();
tessellator.draw(); tessellator.draw();
GlStateManager.translate(-1.0f, -1.0f, 0.0f); GlStateManager.translate(-1.0f, -1.0f, 0.0f);
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
GlStateManager.enableTexture2D();
InstancedFontRenderer.render(8, 8, texScale, texScale, true); InstancedFontRenderer.render(8, 8, texScale, texScale, true);
GlStateManager.disableTexture2D();
EaglercraftGPU.renderAgain(); EaglercraftGPU.renderAgain();
GlStateManager.enableTexture2D();
}else { }else {
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
InstancedFontRenderer.render(8, 8, texScale, texScale, true); InstancedFontRenderer.render(8, 8, texScale, texScale, true);
@ -201,7 +205,9 @@ public class EaglerFontRenderer extends FontRenderer {
}else { }else {
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
if(hasStrike) { if(hasStrike) {
GlStateManager.disableTexture2D();
tessellator.draw(); tessellator.draw();
GlStateManager.enableTexture2D();
} }
InstancedFontRenderer.render(8, 8, texScale, texScale, false); InstancedFontRenderer.render(8, 8, texScale, texScale, false);
} }

View file

@ -0,0 +1,51 @@
package net.lax1dude.eaglercraft.v1_8.minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public class GuiScreenVSyncReEnabled extends GuiScreen {
private GuiScreen cont;
public GuiScreenVSyncReEnabled(GuiScreen cont) {
this.cont = cont;
}
public void initGui() {
this.buttonList.clear();
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 6 + 136, I18n.format("options.vsyncReEnabled.continue")));
}
public void drawScreen(int par1, int par2, float par3) {
this.drawDefaultBackground();
this.drawCenteredString(fontRendererObj, I18n.format("options.vsyncReEnabled.title"), this.width / 2, 70, 11184810);
this.drawCenteredString(fontRendererObj, I18n.format("options.vsyncReEnabled.0"), this.width / 2, 95, 16777215);
this.drawCenteredString(fontRendererObj, I18n.format("options.vsyncReEnabled.1"), this.width / 2, 120, 16777215);
this.drawCenteredString(fontRendererObj, I18n.format("options.vsyncReEnabled.2"), this.width / 2, 145, 16777215);
this.drawCenteredString(fontRendererObj, I18n.format("options.vsyncReEnabled.3"), this.width / 2, 160, 16777215);
super.drawScreen(par1, par2, par3);
}
protected void actionPerformed(GuiButton par1GuiButton) {
if(par1GuiButton.id == 0) {
this.mc.displayGuiScreen(cont);
}
}
}

View file

@ -65,7 +65,7 @@ class ServerQueryImpl implements IServerQuery {
IWebSocketFrame frame = lst.get(i); IWebSocketFrame frame = lst.get(i);
alive = true; alive = true;
if(pingTimer == -1) { if(pingTimer == -1) {
pingTimer = PlatformRuntime.steadyTimeMillis() - pingStart; pingTimer = frame.getTimestamp() - pingStart;
if(pingTimer < 1) { if(pingTimer < 1) {
pingTimer = 1; pingTimer = 1;
} }

View file

@ -15,6 +15,7 @@ import org.apache.commons.lang3.StringUtils;
import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.EnumEaglerConnectionState; import net.lax1dude.eaglercraft.v1_8.internal.EnumEaglerConnectionState;
import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformType;
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData; import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication; import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
@ -84,6 +85,7 @@ public class SingleplayerServerController implements ISaveFormat {
issuesDetected.clear(); issuesDetected.clear();
statusState = IntegratedServerState.WORLD_WORKER_BOOTING; statusState = IntegratedServerState.WORLD_WORKER_BOOTING;
loggingState = true; loggingState = true;
callFailed = false;
boolean singleThreadSupport = ClientPlatformSingleplayer.isSingleThreadModeSupported(); boolean singleThreadSupport = ClientPlatformSingleplayer.isSingleThreadModeSupported();
if(!singleThreadSupport && forceSingleThread) { if(!singleThreadSupport && forceSingleThread) {
throw new UnsupportedOperationException("Single thread mode is not supported!"); throw new UnsupportedOperationException("Single thread mode is not supported!");
@ -294,10 +296,12 @@ public class SingleplayerServerController implements ISaveFormat {
} }
} }
boolean logWindowState = PlatformApplication.isShowingDebugConsole(); if(EagRuntime.getPlatformType() == EnumPlatformType.JAVASCRIPT) {
if(loggingState != logWindowState) { boolean logWindowState = PlatformApplication.isShowingDebugConsole();
loggingState = logWindowState; if(loggingState != logWindowState) {
sendIPCPacket(new IPCPacket1BEnableLogging(logWindowState)); loggingState = logWindowState;
sendIPCPacket(new IPCPacket1BEnableLogging(logWindowState));
}
} }
if(ClientPlatformSingleplayer.isRunningSingleThreadMode()) { if(ClientPlatformSingleplayer.isRunningSingleThreadMode()) {

View file

@ -41,6 +41,8 @@ class LANClientPeer {
protected long startTime; protected long startTime;
protected String localICECandidate = null;
protected LANClientPeer(String clientId) { protected LANClientPeer(String clientId) {
this.clientId = clientId; this.clientId = clientId;
this.startTime = EagRuntime.steadyTimeMillis(); this.startTime = EagRuntime.steadyTimeMillis();
@ -50,7 +52,13 @@ class LANClientPeer {
protected void handleICECandidates(String candidates) { protected void handleICECandidates(String candidates) {
if(state == SENT_DESCRIPTION) { if(state == SENT_DESCRIPTION) {
PlatformWebRTC.serverLANPeerICECandidates(clientId, candidates); PlatformWebRTC.serverLANPeerICECandidates(clientId, candidates);
state = RECEIVED_ICE_CANDIDATE; if(localICECandidate != null) {
LANServerController.lanRelaySocket.writePacket(new RelayPacket03ICECandidate(clientId, localICECandidate));
localICECandidate = null;
state = SENT_ICE_CANDIDATE;
}else {
state = RECEIVED_ICE_CANDIDATE;
}
}else { }else {
logger.error("Relay [{}] unexpected IPacket03ICECandidate for '{}'", LANServerController.lanRelaySocket.getURI(), clientId); logger.error("Relay [{}] unexpected IPacket03ICECandidate for '{}'", LANServerController.lanRelaySocket.getURI(), clientId);
} }
@ -100,6 +108,12 @@ class LANClientPeer {
disconnect(); disconnect();
}else { }else {
switch(state) { switch(state) {
case SENT_DESCRIPTION:{
if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
localICECandidate = ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates;
continue read_loop;
}
}
case RECEIVED_ICE_CANDIDATE: { case RECEIVED_ICE_CANDIDATE: {
if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) { if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
LANServerController.lanRelaySocket.writePacket(new RelayPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates)); LANServerController.lanRelaySocket.writePacket(new RelayPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates));
@ -136,7 +150,7 @@ class LANClientPeer {
} }
} }
if(state != CLOSED) { if(state != CLOSED) {
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName()); logger.error("LAN client '{}' had an accident: {} (state {})", clientId, evt.getClass().getSimpleName(), state);
} }
disconnect(); disconnect();
return; return;

View file

@ -82,7 +82,7 @@ public class LANServerController {
} }
} }
EagUtils.sleep(50); EagUtils.sleep(50);
}while(EagRuntime.steadyTimeMillis() - millis < 1000l); }while(EagRuntime.steadyTimeMillis() - millis < 2500l);
logger.info("Relay [{}] relay provide ICE servers timeout", sock.getURI()); logger.info("Relay [{}] relay provide ICE servers timeout", sock.getURI());
closeLAN(); closeLAN();
return null; return null;

View file

@ -8,7 +8,6 @@ import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger; import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.MinecraftException;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.AnvilChunkLoader; import net.minecraft.world.chunk.storage.AnvilChunkLoader;
@ -88,7 +87,7 @@ public class EaglerChunkLoader extends AnvilChunkLoader {
} }
@Override @Override
public void saveChunk(World var1, Chunk var2) throws IOException, MinecraftException { public void saveChunk(World var1, Chunk var2) throws IOException {
NBTTagCompound chunkData = new NBTTagCompound(); NBTTagCompound chunkData = new NBTTagCompound();
this.writeChunkToNBT(var2, var1, chunkData); this.writeChunkToNBT(var2, var1, chunkData);
NBTTagCompound fileData = new NBTTagCompound(); NBTTagCompound fileData = new NBTTagCompound();

View file

@ -485,6 +485,8 @@ public class EaglerIntegratedServerWorker {
// signal thread startup successful // signal thread startup successful
sendIPCPacket(new IPCPacketFFProcessKeepAlive(0xFF)); sendIPCPacket(new IPCPacketFFProcessKeepAlive(0xFF));
ServerPlatformSingleplayer.setCrashCallbackWASM(EaglerIntegratedServerWorker::sendIntegratedServerCrashWASMCB);
while(true) { while(true) {
mainLoop(false); mainLoop(false);
ServerPlatformSingleplayer.immediateContinue(); ServerPlatformSingleplayer.immediateContinue();
@ -525,4 +527,11 @@ public class EaglerIntegratedServerWorker {
mainLoop(true); mainLoop(true);
} }
public static void sendIntegratedServerCrashWASMCB(String stringValue, boolean terminated) {
sendIPCPacket(new IPCPacket15Crashed(stringValue));
if(terminated) {
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacketFFProcessKeepAlive.EXITED));
}
}
} }

View file

@ -0,0 +1,22 @@
package net.lax1dude.eaglercraft.v1_8.sp.server;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public interface IWASMCrashCallback {
void callback(String crashReport, boolean terminated);
}

View file

@ -139,14 +139,24 @@ public class IntegratedVoiceService {
} }
public void handleVoiceSignalPacketTypeConnect(EntityPlayerMP sender) { public void handleVoiceSignalPacketTypeConnect(EntityPlayerMP sender) {
if (voicePlayers.containsKey(sender.getUniqueID())) { EaglercraftUUID senderUuid = sender.getUniqueID();
if (voicePlayers.containsKey(senderUuid)) {
return; return;
} }
boolean hasNoOtherPlayers = voicePlayers.isEmpty(); boolean hasNoOtherPlayers = voicePlayers.isEmpty();
voicePlayers.put(sender.getUniqueID(), sender); voicePlayers.put(senderUuid, sender);
if (hasNoOtherPlayers) { if (hasNoOtherPlayers) {
return; return;
} }
GameMessagePacket v3p = null;
GameMessagePacket v4p = null;
for(EntityPlayerMP conn : voicePlayers.values()) {
if(conn.playerNetServerHandler.getEaglerMessageProtocol().ver <= 3) {
conn.playerNetServerHandler.sendEaglerMessage(v3p == null ? (v3p = new SPacketVoiceSignalConnectV3EAG(senderUuid.msb, senderUuid.lsb, true, false)) : v3p);
} else {
conn.playerNetServerHandler.sendEaglerMessage(v4p == null ? (v4p = new SPacketVoiceSignalConnectAnnounceV4EAG(senderUuid.msb, senderUuid.lsb)) : v4p);
}
}
Collection<SPacketVoiceSignalGlobalEAG.UserData> userDatas = new ArrayList<>(voicePlayers.size()); Collection<SPacketVoiceSignalGlobalEAG.UserData> userDatas = new ArrayList<>(voicePlayers.size());
for(EntityPlayerMP player : voicePlayers.values()) { for(EntityPlayerMP player : voicePlayers.values()) {
EaglercraftUUID uuid = player.getUniqueID(); EaglercraftUUID uuid = player.getUniqueID();

View file

@ -94,13 +94,16 @@ public class VoiceClientController {
} }
public static void handleVoiceSignalPacketTypeGlobalNew(Collection<SPacketVoiceSignalGlobalEAG.UserData> voicePlayers) { public static void handleVoiceSignalPacketTypeGlobalNew(Collection<SPacketVoiceSignalGlobalEAG.UserData> voicePlayers) {
boolean isGlobal = voiceChannel == EnumVoiceChannelType.GLOBAL;
uuidToNameLookup.clear(); uuidToNameLookup.clear();
for (SPacketVoiceSignalGlobalEAG.UserData player : voicePlayers) { for (SPacketVoiceSignalGlobalEAG.UserData player : voicePlayers) {
EaglercraftUUID uuid = new EaglercraftUUID(player.uuidMost, player.uuidLeast); EaglercraftUUID uuid = new EaglercraftUUID(player.uuidMost, player.uuidLeast);
if(player.username != null) { if(player.username != null) {
uuidToNameLookup.put(uuid, player.username); uuidToNameLookup.put(uuid, player.username);
} }
sendPacketRequestIfNeeded(uuid); if (isGlobal) {
sendPacketRequestIfNeeded(uuid);
}
} }
} }
@ -138,7 +141,7 @@ public class VoiceClientController {
} }
public static void handleVoiceSignalPacketTypeConnectAnnounce(EaglercraftUUID user) { public static void handleVoiceSignalPacketTypeConnectAnnounce(EaglercraftUUID user) {
if (voiceChannel != EnumVoiceChannelType.NONE) sendPacketRequest(user); if (voiceChannel != EnumVoiceChannelType.NONE && (voiceChannel == EnumVoiceChannelType.GLOBAL || listeningSet.contains(user))) sendPacketRequest(user);
} }
public static void handleVoiceSignalPacketTypeDisconnect(EaglercraftUUID user) { public static void handleVoiceSignalPacketTypeDisconnect(EaglercraftUUID user) {

View file

@ -1 +1 @@
u43 u44

View file

@ -785,3 +785,78 @@
* THE SOFTWARE. * THE SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Project Name: Emscripten
Project Author: Emscripten authors
Project URL: https://emscripten.org/
Used For: Compiling the WASM runtime's loader.wasm program
* Emscripten is available under 2 licenses, the MIT license and the
* University of Illinois/NCSA Open Source License.
*
* Copyright (c) 2010-2014 Emscripten authors, see AUTHORS file.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Project Name: XZ Embedded
Project Author: Lasse Collin (Larhzu)
Project URL: https://tukaani.org/xz/embedded.html
Used For: Decompressing the WASM runtime
* Copyright (C) The XZ Embedded authors and contributors
*
* Permission to use, copy, modify, and/or distribute this
* software for any purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Project Name: XZ for Java
Project Author: Lasse Collin (Larhzu)
Project URL: https://tukaani.org/xz/java.html
Used For: Compression in the MakeWASMClientBundle command
* Copyright (C) The XZ for Java authors and contributors
*
* Permission to use, copy, modify, and/or distribute this
* software for any purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -1 +1 @@
{"pluginName":"EaglercraftXBungee","pluginVersion":"1.3.3","pluginButton":"Download \"EaglerXBungee-1.3.3.jar\"","pluginFilename":"EaglerXBungee.zip"} {"pluginName":"EaglercraftXBungee","pluginVersion":"1.3.4","pluginButton":"Download \"EaglerXBungee-1.3.4.jar\"","pluginFilename":"EaglerXBungee.zip"}

View file

@ -0,0 +1,12 @@
.gradle
.settings
.classpath
.project
build
bin
javascript/eagruntime.js
javascript/classes.wasm
javascript/classes.wasm.teadbg
javascript/assets.epk
javascript_dist/assets.epw
javascript_dist/EaglercraftX_1.8_*

View file

@ -0,0 +1,6 @@
@echo off
title CompileEPWBootstrapJS
set srcFolder=../src/wasm-gc-teavm-bootstrap/js
echo Compiling %srcFolder%
java -jar buildtools/closure-compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --assume_function_wrapper --emit_use_strict --isolation_mode IIFE --js "%srcFolder%/externs.js" "%srcFolder%/main.js" --js_output_file javascript_dist/bootstrap.js
pause

View file

@ -0,0 +1,4 @@
#!/bin/sh
srcFolder=../src/wasm-gc-teavm-bootstrap/js
echo Compiling $srcFolder
java -jar buildtools/closure-compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --assume_function_wrapper --emit_use_strict --isolation_mode IIFE --js $srcFolder/externs.js $srcFolder/main.js --js_output_file javascript_dist/bootstrap.js

View file

@ -0,0 +1,6 @@
@echo off
title epkcompiler
echo compiling, please wait...
java -jar "../desktopRuntime/CompileEPK.jar" "../desktopRuntime/resources" "javascript/assets.epk" none
echo finished compiling epk
pause

View file

@ -0,0 +1,2 @@
#!/bin/sh
java -jar "../desktopRuntime/CompileEPK.jar" "../desktopRuntime/resources" "javascript/assets.epk" none

View file

@ -0,0 +1,6 @@
@echo off
title CompileEagRuntimeJS
set srcFolder=../src/wasm-gc-teavm/js
echo Compiling %srcFolder%
java -jar buildtools/closure-compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --assume_function_wrapper --emit_use_strict --isolation_mode IIFE --js "%srcFolder%/externs.js" "%srcFolder%/eagruntime_util.js" "%srcFolder%/eagruntime_main.js" "%srcFolder%/platformApplication.js" "%srcFolder%/platformAssets.js" "%srcFolder%/platformAudio.js" "%srcFolder%/platformFilesystem.js" "%srcFolder%/platformInput.js" "%srcFolder%/platformNetworking.js" "%srcFolder%/platformOpenGL.js" "%srcFolder%/platformRuntime.js" "%srcFolder%/platformScreenRecord.js" "%srcFolder%/platformVoiceClient.js" "%srcFolder%/platformWebRTC.js" "%srcFolder%/platformWebView.js" "%srcFolder%/clientPlatformSingleplayer.js" "%srcFolder%/serverPlatformSingleplayer.js" "%srcFolder%/WASMGCBufferAllocator.js" "%srcFolder%/fix-webm-duration.js" "%srcFolder%/teavm_runtime.js" "%srcFolder%/eagruntime_entrypoint.js" --js_output_file javascript/eagruntime.js
pause

View file

@ -0,0 +1,4 @@
#!/bin/sh
srcFolder=../src/wasm-gc-teavm/js
echo Compiling $srcFolder
java -jar buildtools/closure-compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --assume_function_wrapper --emit_use_strict --isolation_mode IIFE --js $srcFolder/externs.js $srcFolder/eagruntime_util.js $srcFolder/eagruntime_main.js $srcFolder/platformApplication.js $srcFolder/platformAssets.js $srcFolder/platformAudio.js $srcFolder/platformFilesystem.js $srcFolder/platformInput.js $srcFolder/platformNetworking.js $srcFolder/platformOpenGL.js $srcFolder/platformRuntime.js $srcFolder/platformScreenRecord.js $srcFolder/platformVoiceClient.js $srcFolder/platformWebRTC.js $srcFolder/platformWebView.js $srcFolder/clientPlatformSingleplayer.js $srcFolder/serverPlatformSingleplayer.js $srcFolder/WASMGCBufferAllocator.js $srcFolder/fix-webm-duration.js $srcFolder/teavm_runtime.js $srcFolder/eagruntime_entrypoint.js --js_output_file javascript/eagruntime.js

View file

@ -0,0 +1,9 @@
@echo off
title CompileLoaderWASM
mkdir "bin/emscripten"
call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/main.c -o bin/emscripten/main.o
call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_crc32.c -o bin/emscripten/xz_crc32.o
call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_lzma2.c -o bin/emscripten/xz_dec_lzma2.o
call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_stream.c -o bin/emscripten/xz_dec_stream.o
call emcc -O3 -sMALLOC=dlmalloc -sALLOW_MEMORY_GROWTH -sINITIAL_HEAP=16777216 -sMAXIMUM_MEMORY=67108864 --pre-js ../src/wasm-gc-teavm-loader/js/pre.js --js-library ../src/wasm-gc-teavm-loader/js/library.js bin/emscripten/main.o bin/emscripten/xz_crc32.o bin/emscripten/xz_dec_lzma2.o bin/emscripten/xz_dec_stream.o -o javascript/loader.js
pause

View file

@ -0,0 +1,7 @@
#!/bin/sh
mkdir -p bin/emscripten
emcc -c -O3 ../src/wasm-gc-teavm-loader/c/main.c -o bin/emscripten/main.o
emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_crc32.c -o bin/emscripten/xz_crc32.o
emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_lzma2.c -o bin/emscripten/xz_dec_lzma2.o
emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_stream.c -o bin/emscripten/xz_dec_stream.o
emcc -O3 -sMALLOC=dlmalloc -sALLOW_MEMORY_GROWTH -sINITIAL_HEAP=16777216 -sMAXIMUM_MEMORY=67108864 --pre-js ../src/wasm-gc-teavm-loader/js/pre.js --js-library ../src/wasm-gc-teavm-loader/js/library.js bin/emscripten/main.o bin/emscripten/xz_crc32.o bin/emscripten/xz_dec_lzma2.o bin/emscripten/xz_dec_stream.o -o javascript/loader.js

View file

@ -0,0 +1,4 @@
@echo off
title gradlew generateWasmGC
call gradlew generateWasmGC
pause

View file

@ -0,0 +1,3 @@
#!/bin/sh
chmod +x gradlew
./gradlew generateWasmGC

View file

@ -0,0 +1,5 @@
@echo off
title MakeWASMClientBundle
cd javascript
java -cp "../buildtools/org.tukanni.xz.jar;../buildtools/MakeWASMClientBundle.jar;../../desktopRuntime/CompileEPK.jar;../../desktopRuntime/MakeOfflineDownload.jar" net.lax1dude.eaglercraft.v1_8.buildtools.workspace.MakeWASMClientBundle epw_src.txt epw_meta.txt "../javascript_dist"
pause

View file

@ -0,0 +1,3 @@
#!/bin/sh
cd javascript
java -cp "../buildtools/org.tukanni.xz.jar:../buildtools/MakeWASMClientBundle.jar:../../desktopRuntime/CompileEPK.jar:../../desktopRuntime/MakeOfflineDownload.jar" net.lax1dude.eaglercraft.v1_8.buildtools.workspace.MakeWASMClientBundle epw_src.txt epw_meta.txt "../javascript_dist"

View file

@ -0,0 +1,25 @@
# EaglercraftX WASM-GC Runtime
This folder contains the Gradle project for compiling the EaglercraftX 1.8 client to WASM. This requires a special fork of TeaVM that has been modified for Eaglercraft. The `settings.gradle` and `build.gradle` are set up to download the binaries automatically but if you would like to build the TeaVM fork yourself you can use the TeaVM fork's `publishToMavenLocal` gradle task and replace the URL maven repository declarations in the gradle build scripts with `mavenLocal()` instead.
**TeaVM Fork: [https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm/tree/eagler-r1](https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm/tree/eagler-r1)**
### To compile the client:
1. Run `CompileEPK` to compile the assets.epk file
2. Run `CompileWASM` to compile the classes.wasm file
3. Run `CompileEagRuntimeJS` to compile the eagruntime.js file
4. Run `MakeWASMClientBundle` to bundle the client into an EPW file
The final assets.epw and offline download will be in the "javascript_dist" folder
### Optional Steps:
- Run `CompileBootstrapJS` to recompile bootstrap.js in the javascript_dist folder
- Run `CompileLoaderWASM`to recompile loader.js and loader.wasm (requires emscripten)
### Potential issues when porting:
- Disabling VSync causes bad input lag, the solution to this problem is to remove the vsync option and force people to play with vsync enabled, like all other browser games
- TeaVM's WASM GC backend is still under development and will sometimes generate broken code with nested try/finally statements in a try/catch block, or other strange runtime glitches
- Fewer reflection features are supported in WASM GC than the JavaScript backend (so far)
- Do not use `@Async` or any sort of callback (like addEventListener) in your Java, you must implement async functions in JavaScript in `../src/wasm-gc-teavm/js`, using JSPI to suspend/resume the thread for promises, or by pushing events into a queue that you can poll from your Java for event handlers.
- Functions imported via the `@Import` will not catch exceptions, if you want proper exception handling you must call the imported function through the JSO

View file

@ -0,0 +1,56 @@
import org.teavm.gradle.api.OptimizationLevel
import org.teavm.gradle.api.WasmDebugInfoLocation
import org.teavm.gradle.api.WasmDebugInfoLevel
plugins {
id "java"
id "eclipse"
id "org.teavm" version "0.11.0-EAGLER-R1"
}
sourceSets {
main {
java {
srcDirs(
"../src/main/java",
"../src/game/java",
"../src/protocol-game/java",
"../src/protocol-relay/java",
"../src/wasm-gc-teavm/java"
)
}
}
}
repositories {
maven {
url = uri("https://eaglercraft-teavm-fork.github.io/maven/")
}
mavenCentral()
}
dependencies {
compileOnly "org.teavm:teavm-core:0.11.0-EAGLER-R1" // workaround for a few hacks
}
def folder = "javascript"
def name = "classes.wasm"
teavm.wasmGC {
targetFileName = "../" + name
optimization = OptimizationLevel.AGGRESSIVE
outOfProcess = false
fastGlobalAnalysis = false
processMemory = 512
mainClass = "net.lax1dude.eaglercraft.v1_8.internal.wasm_gc_teavm.MainClass"
outputDir = file(folder)
properties = [ "java.util.TimeZone.autodetect": "true" ]
debugInformation = true
debugInfoLocation = WasmDebugInfoLocation.EXTERNAL;
debugInfoLevel = WasmDebugInfoLevel.DEOBFUSCATION;
directMallocSupport = true
minHeapSize = 32
maxHeapSize = 384
disassembly = true
}

View file

@ -0,0 +1 @@
org.gradle.jvmargs=-Xmx4G -Xms4G

View file

@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View file

@ -0,0 +1,249 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

View file

@ -0,0 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View file

@ -0,0 +1,104 @@
<!DOCTYPE html>
<!--
This file is from ${date}, there is no official eagler download link anymore, check the websites and discords of your favorite eagler servers for new versions
Be aware that some server owners are lazy and do not update their client regularly
This is the WASM-GC version of EaglercraftX and may not be compatible with outdated browsers
-->
<html style="width:100%;height:100%;background-color:black;">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
<meta name="description" content="EaglercraftX 1.8 WASM-GC Offline" />
<meta name="keywords" content="eaglercraft, eaglercraftx, minecraft, 1.8, 1.8.8" />
<title>EaglercraftX 1.8 WASM-GC</title>
<meta property="og:locale" content="en-US" />
<meta property="og:type" content="website" />
<meta property="og:title" content="EaglercraftX 1.8 WASM-GC Offline" />
<meta property="og:description" content="this file is not a website, whoever uploaded it to this URL is a dumbass" />
<script type="text/javascript">
"use strict";
var relayId = Math.floor(Math.random() * 3);
// %%%%%%%%% launch options %%%%%%%%%%%%
window.eaglercraftXOpts = {
container: "game_frame",
worldsDB: "worlds",
relays: [
{ addr: "wss://relay.deev.is/", comment: "lax1dude relay #1", primary: relayId == 0 },
{ addr: "wss://relay.lax1dude.net/", comment: "lax1dude relay #2", primary: relayId == 1 },
{ addr: "wss://relay.shhnowisnottheti.me/", comment: "ayunami relay #1", primary: relayId == 2 }
]
};
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
</script>
<script type="text/javascript">
"use strict";
if(typeof window !== "undefined") window.eaglercraftXClientScriptElement = document.currentScript;
${classes_js}
</script>
<script type="text/javascript">
"use strict";
(function(){
window.eaglercraftXOpts.assetsURI = ${assets_epk};
var launchInterval = -1;
var launchCounter = 1;
var launchCountdownNumberElement = null;
var launchCountdownProgressElement = null;
var launchSkipCountdown = false;
var launchTick = function() {
launchCountdownNumberElement.innerText = "" + Math.floor(6.0 - launchCounter * 0.06);
launchCountdownProgressElement.style.width = "" + launchCounter + "%";
if(++launchCounter > 100 || launchSkipCountdown) {
clearInterval(launchInterval);
setTimeout(function() { document.body.removeChild(document.getElementById("launch_countdown_screen")); document.body.style.backgroundColor = "black"; main(); }, 50);
}
};
window.addEventListener("load", function() {
launchCountdownNumberElement = document.getElementById("launchCountdownNumber");
launchCountdownProgressElement = document.getElementById("launchCountdownProgress");
launchInterval = setInterval(launchTick, 50);
document.getElementById("skipCountdown").addEventListener("click", function() {
launchSkipCountdown = true;
});
});
})();
</script>
<link type="image/png" rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAR/SURBVEhLtZXZK3ZRFMYPcqXc+gv413DHxVuGIpIhkciQWaRccCNjSCkligwXSOZ5nmfv9zvn2e8+58V753sudmuvvdZ61l5r7XOc8H+GS/D19aUNkPz5+aktQH5/f//4+LBKZKuRkpUtQjCUYG5gD2T38vLy/PwsDfL9/f3Dw8PT05M0b29vnKLhCKCBT4L4gvBLBIei4//4+Hh1dUVEQutUuLu7E83FxQUGnKLBWKfQaA3S+AREVxaEOD8/Pzk50XpzcyMDcH19zdZG3N3d3dzc3Nvb01aX5pQUpQGGQJxcQpfNysoKhUIdHR1o1tbWbInYAgxIPDMzMy8vLzc3FxqOdMoRqwJK8G8ALUYIhHMiSEhIwI6CyIb0qQzC4eGhsXCc1tZWnZIEKzdQJQSXgKxfX18RCM3Z5eWlcfVAxKOjo+Pj49PTU88lTOk2NjbMsePc3t6SAfcgFdszOyMuAdeBg0CQi2lhYUHOeOLDCisN8FzcPFZXV3t7ezHY3t5GQ+6it+2xMASsKhEEWKsmRLRBBUpPvpJ/TpFKFBwKYAiITmicsbYhdHfJAltqhUCVsCQhwslmeXmZxiBQT9c0Ar9E2O3v72sYSE0N1yQArkKy0kBMXLqlZqIZHR3t6empqqqSDcBdhXEJSJ/bUc3q6uq+vj629GB9fR1WsLW1NTs7u7S0RN2locMjIyOEm5ubQ7+4uJienk4/+vv77Y1hwhLBEKhwWHitdVFfX9/Y2Gg2HuLi4owUAysrK8yCG97rh0+ApP5Q2ZycHFlPTExUVFRIBvn5+WhKSkp2dnaMKhptbW2426GgQ/rwuAQCZ1hwFayLiork9hMFBQV1dXVmE0BLS4vqw3QFB8kn4IAxoGPkYpxi4FeDmpqas7Mz4pClAgqGwD48rjY2NmacYqC0tJQ1KSlJWyE5OZkpUKkBAxZVIntAoZh04+Q48fHxPNGBgYHExMT29naj9cBodnZ2mo3jlJWVMeW2OGQck4B1amqqoaGhqamJjx2lGxwcpL0mUgR8fJhsWqJtSkoKU2SbHHUDpkhPBujd8xuQG6PJRM/Pz09PT7O1NNnZ2Tw3fgZkXVhYKCUlUhBATP+hCVyKZGky17RV0g04laayslJ6hlVeFHB4eFhKaogGd0LxtmTgE+hbhKDnPjMzgw8E3qGL2tpaBWpubjYqj2BoaEj6rq4uNATRZ0ZwCbiL6gXEzINk5vCBQJ9rMD4+rkA8QNK036uDg4Py8vLu7m680KjIBNR3zBDoWQM1g98snyB+VSoRW8C/UwR81/SvhgNj9JOTkwwVERUdRBEI0BAdLRVERkhLS8vIyEDQlrsTPTU1lVFhKxARvZgUlFLbegCf4BvIsbi4mIg4E5EogIHhiKCMtU0WUFiVy06j5fAJIDdSBDQw+PegDfBRcbOPwH4F9LuFWIIQdQNKwWqzIE0aoFUaBsw+SQuFw0uNtC9A+F4i3QNrbg3IDn+SAsHh+wYiEpeyBEMLv/cAO6KzAijxxB+Y4wisBhssJUhjEbPJf4Nw+B+JXqLW3bw+wQAAAABJRU5ErkJggg==" />
</head>
<body style="margin:0px;width:100%;height:100%;overflow:hidden;background-color:white;" id="game_frame">
<div style="margin:0px;width:100%;height:100%;font-family:sans-serif;display:flex;align-items:center;user-select:none;" id="launch_countdown_screen">
<div style="margin:auto;text-align:center;">
<h1>This file is from <span style="color:#AA0000;">${date}</span></h1>
<h2>Game will launch in <span id="launchCountdownNumber">5</span>...</h2>
<div style="border:2px solid black;width:100%;height:15px;padding:1px;margin-bottom:20vh;"><div id="launchCountdownProgress" style="background-color:#555555;width:0%;height:100%;"></div>
<p style="margin-top:30px;"><button id="skipCountdown" autofocus>Skip Countdown</button></p></div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
client-version-integer=44
client-package-name=net.lax1dude.eaglercraft.v1_8.client
client-origin-name=EaglercraftX
client-origin-version=u44
client-origin-vendor=lax1dude
client-fork-name=EaglercraftX
client-fork-version=u44
client-fork-vendor=lax1dude

View file

@ -0,0 +1,22 @@
loader-js-file=loader.js
loader-wasm-file=loader.wasm
eagruntime-js-file=eagruntime.js
classes-wasm-file=classes.wasm
classes-deobf-teadbg-file=classes.wasm.teadbg
classes-deobf-wasm-file=classes.wasm-deobfuscator.wasm
assets-epk-0-file=assets.epk
assets-epk-0-path=/
assets-epk-1-file=../../javascript/lang
assets-epk-1-path=/assets/minecraft/lang/
splash-logo-image-file=splash.png
splash-logo-image-mime=image/png
press-any-key-image-file=pressAnyKey.png
press-any-key-image-mime=image/png
crash-logo-image-file=crashLogo.png
crash-logo-image-mime=image/png
favicon-image-file=favicon.png
favicon-image-mime=image/png
jspi-unavailable-file=enableJSPIScreen.html
offline-download-template=OfflineDownloadTemplate.txt
offline-download-script=../javascript_dist/bootstrap.js
offline-download-name=EaglercraftX_1.8_WASM-GC_Offline_Download.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html style="width:100%;height:100%;background-color:black;">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
<meta name="description" content="EaglercraftX 1.8 WASM-GC test directory HTML page" />
<meta name="keywords" content="eaglercraft, eaglercraftx, minecraft, 1.8, 1.8.8" />
<title>EaglercraftX 1.8 WASM-GC</title>
<meta property="og:locale" content="en-US" />
<meta property="og:type" content="website" />
<meta property="og:title" content="EaglercraftX 1.8 WASM-GC" />
<meta property="og:description" content="test directory HTML page" />
<link type="image/png" rel="shortcut icon" href="favicon.png" />
<script type="text/javascript">
"use strict";
window.addEventListener("load", async function() {
if(window.location.href.indexOf("file:") === 0) {
alert("HTTP please, do not open this file locally, run a local HTTP server and load it via HTTP");
}else if(typeof WebAssembly.Suspending === "undefined") {
alert("JSPI is not enabled, please enable it in chrome://flags");
}else {
const splash = document.createElement("div");
splash.style.width = "100%";
splash.style.height = "100%";
splash.style.imageRendering = "pixelated";
splash.style.background = "center / contain no-repeat url(splash.png), 0px 0px / 1000000% 1000000% no-repeat url(splash.png) white";
document.body.appendChild(splash);
console.log("Downloading assets.epk...");
var assetsEPK;
try {
assetsEPK = new Uint8Array(await fetch("assets.epk").then(resp => resp.arrayBuffer()));
}catch(ex) {
alert("Could not download assets.epk!");
console.error("Could not download assets.epk!");
console.error(ex);
return;
}
console.log("Downloaded " + assetsEPK.length + " byte file");
const relayId = Math.floor(Math.random() * 3);
const eaglercraftXOpts = {
demoMode: false,
localesURI: "lang/",
worldsDB: "worlds",
servers: [
{ addr: "ws://localhost:8081/", name: "Local test server" }
],
relays: [
{ addr: "wss://relay.deev.is/", comment: "lax1dude relay #1", primary: relayId === 0 },
{ addr: "wss://relay.lax1dude.net/", comment: "lax1dude relay #2", primary: relayId === 1 },
{ addr: "wss://relay.shhnowisnottheti.me/", comment: "ayunami relay #1", primary: relayId === 2 }
]
};
window.__eaglercraftXLoaderContext = {
getEaglercraftXOpts: function() {
return eaglercraftXOpts;
},
getEagRuntimeJSURL: function() {
return "eagruntime.js";
},
getClassesWASMURL: function() {
return "classes.wasm";
},
getClassesDeobfWASMURL: function() {
return "classes.wasm-deobfuscator.wasm";
},
getClassesTEADBGURL: function() {
return "classes.wasm.teadbg";
},
getEPKFiles: function() {
return [{
name: "assets.epk",
path: "",
data: assetsEPK
}];
},
getRootElement: function() {
return document.body;
},
getMainArgs: function() {
return [];
},
getImageURL: function(idx) {
switch(idx) {
case 0:
return "splash.png";
case 1:
return "pressAnyKey.png";
case 2:
return "crashLogo.png";
case 3:
return "favicon.png";
default:
return null;
}
},
runMain: function(fn) {
setTimeout(fn, 10);
}
};
var q = window.location.search;
if((typeof q === "string") && q[0] === "?" && (typeof URLSearchParams !== "undefined")) {
q = new URLSearchParams(q);
var s = q.get("server");
if(s) eaglercraftXOpts.joinServer = s;
}
const scriptElement = document.createElement("script");
scriptElement.type = "text/javascript";
scriptElement.src = "eagruntime.js";
document.head.appendChild(scriptElement);
}
});
</script>
</head>
<body style="margin:0px;width:100%;height:100%;overflow:hidden;background-color:black;" id="game_frame"></body>
</html>

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -0,0 +1,12 @@
(function(){'use strict';function g(a){console.log("LoaderBootstrap: [INFO] "+a)}function n(a){console.error("LoaderBootstrap: [ERROR] "+a)}var q=null;
function r(){const a=[];for(var c=0;64>c;++c)a["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charCodeAt(c)]=c;a[45]=62;a[95]=63;return function(b,d){var e=b.length-d;if(0<e%4)throw Error("Invalid string. Length must be a multiple of 4");var f=b.indexOf("=",d);f=-1===f?e:f-d;e=[f,f===e?0:4-f%4];var l=e[0];e=e[1];f=new Uint8Array(3*(l+e)/4-e);var h=0;l=(0<e?l-4:l)+d;var k;for(k=d;k<l;k+=4)d=a[b.charCodeAt(k)]<<18|a[b.charCodeAt(k+1)]<<12|a[b.charCodeAt(k+2)]<<6|a[b.charCodeAt(k+
3)],f[h++]=d>>16&255,f[h++]=d>>8&255,f[h++]=d&255;2===e?(d=a[b.charCodeAt(k)]<<2|a[b.charCodeAt(k+1)]>>4,f[h++]=d&255):1===e&&(d=a[b.charCodeAt(k)]<<10|a[b.charCodeAt(k+1)]<<4|a[b.charCodeAt(k+2)]>>2,f[h++]=d>>8&255,f[h++]=d&255);return f.buffer}}function u(){return new Promise(function(a){setTimeout(a,20)})}function v(a){return new Promise(function(c){fetch(a,{cache:"force-cache"}).then(function(b){return b.arrayBuffer()}).then(c).catch(function(b){n("Failed to fetch URL! "+b);c(null)})})}
function w(a){return a.startsWith("data:application/octet-stream;base64,")?new Promise(function(c){v(a).then(function(b){if(b)c(b);else{console.log("LoaderBootstrap: [WARN] Failed to decode base64 via fetch, doing it the slow way instead...");try{q||=r();var d=q(a,37);c(d)}catch(e){n("Failed to decode base64! "+e),c(null)}}})}):v(a)}
function x(a,c){const b=document.createElement("h2");b.style.color="#AA0000";b.style.padding="25px";b.style.fontFamily="sans-serif";b.style.marginBlock="0px";b.appendChild(document.createTextNode(c));a.appendChild(b);c=document.createElement("h4");c.style.color="#AA0000";c.style.padding="25px";c.style.fontFamily="sans-serif";c.style.marginBlock="0px";c.appendChild(document.createTextNode("Try again later"));a.style.backgroundColor="white";a.appendChild(c)}
window.main=async function(){if("undefined"===typeof window.eaglercraftXOpts)n("window.eaglercraftXOpts is not defined!"),alert("window.eaglercraftXOpts is not defined!");else{var a=window.eaglercraftXOpts.container;if("string"!==typeof a)n("window.eaglercraftXOpts.container is not a string!"),alert("window.eaglercraftXOpts.container is not a string!");else{var c=window.eaglercraftXOpts.assetsURI;if("string"!==typeof c)if("object"===typeof c&&"object"===typeof c[0]&&"string"===typeof c[0].url)c=c[0].url;
else{n("window.eaglercraftXOpts.assetsURI is not a string!");alert("window.eaglercraftXOpts.assetsURI is not a string!");return}var b=document.getElementById(a);if(b){for(;a=b.lastChild;)b.removeChild(a);a=document.createElement("div");a.style.width="100%";a.style.height="100%";a.style.setProperty("image-rendering","pixelated");a.style.background='center / contain no-repeat url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMAAAADACAAAAAB3tzPbAAAACXBIWXMAAC4jAAAuIwF4pT92AAAG+UlEQVR42u2cy23jOhRATwbTwGwFvAJoF6BFGjColcGkASNuIPA6C68DN+BADZiCVxLSQBYqIGYBAbSdEvwWkvUzZWfymwlwCQwQUZeXPOT9URPkYs/3bj8QAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAH4x9vPvzFpAhAzM98UILmqfjDf1YT0N/cBk+71v+wDSczHmDeJ6TqO+SIfyD7IvC9g33Yc7dP6CQDxB+q62Hc2xnyJD2Sf5vuzL3Hi5MM0WbCN51u/Y/30ryEGmDVHlhwsY9Y7xlq0CuzVc4lh2n7NkGsnQ1nB7IefmrY/araJcbrq6Ryk9YqW4l3J/dHww1jdej+8kte042EW0Nba1hyWdl+9irq/FNXaD6BbQoexuvf+tQC2vX1+AFvP0kxiuyidfWwEbOtQtK0n0r6xbYCKsLcM21+pLZX3u4984Kq2xlnWDimllRudAXEpkGSHfqMzsmxfWnLWNf9aQznW4wMZWOMJxvGs/Ff5X+yPcD0g3dqZesdsI2f7Z2/73W2JSok9Gqu7P1q/I2qtj0qn/ZkTaCPWO2a0VyjrxY7sNUG1LxRlaE90MpDpGVeAxpaGobN2XPWH0aQVE1stfXPAj0+XzUmcob3aTRdVZ2+tRv+gMNBDaTkZ4k6uhtYPaK7iUkUcx9lgij92gZ6aXmxoDeK8D1hPfm18oBvTfPGwXoVG+4VfXcwl8dEOtCJS7De9M0VTqTA2p081O3kJ+uk5cU/RVN8C262Ms9HMlLHSmhNFTcc9u1uQRX4jMhqyNIk1GRk69a6hb0IDZ3pITnbfNqFuJWE9gbYrfmSqen/SiKy27G0VS20VWc+UEn59/YDPkc+0EunrAXQ/JXucYL+3VutyAqvP5wFvtEoyQPsMJMpKc3v7/Su9ALLkhAJDPCObGTDmonfNHAij3sg5866fmTHGnFt/crroh6vEv/Rq6vhEoP7hWWb2ylSQZP5zOVrDqVxSZnm/xL6OFnZwF3/4JoyGjyXu1X3n0rEFyE5Jzc5KEDfT7s2ZYs52s5e1HU88hB17nKTqAroXWPpXiHbN7R3Q8fVDbjzU6vb8hUbX67FWN8Xo4U5SIWjbukr1knY9XrcwS30aOuTatqa0vkA6cI05dyPrzWBbj7ZZrPUT2O7pdpKFtp4rph0E0AxtfN0u9kNVg25d4BPiDF0+R83dPol7/l4m4yQmQzdX+ISewqTnc8ngp94yaCan4vT+Hc228q8/T35+e8+XueSqCaPmEz9ofdbX6eSqE5iN/m4A8Qd9w/1bAEl2fPmafT3Axdv/ytlFeXUwTZyyf+NA3hWDGPrm+HXtHSdQ7nrz7fvv+MPFe/9Q3nAS+iYA3zcKCYAACIAACIAACIAACIAACIAACIAA1C2Komh++r9cogdv90M0+GoZAVHkSiGSaFmOmJdTRdESiKJ5Je4eovnSldoGNJ44gTBNbx+XH7tDYxwOniAPgEdygGWxTm/jBCAHV0u7xa90PV64IW0uOWdCapK7t600vfF2j4Ad5FCE4IopCSWMSg0Q4NgRVNKrwIBJ1ZDGxXO/5+fxhDvFQ87EsHxZMy9Sli/raMbjf9eqMpiciQG3yYOJwW1eQoBoesNBzG3yKdvqNwie1HMwiXFcwo7L7aMBtlSrC7c79RzyUm5w0f66Gk1vcJs8vFYHxUvy/u8leJz4N8t8vX5ccl04Chz5BOLR+mVVWXX5lsU4ncSOFevL7WFsJbYiPfQpcvJwhNsBxKiwcHDPNnoojzp8Jh8PnusiSMcLd1B8R5i+Igq5/BZKU3IEO8cIpoqw6L5NR8kjuOIaFR6GlmKdvmnhuFTsfqNwTBnzBOo+ZFua+jh3jAZtnksMu/b850wIfh1sVwVPhMEzKK9lz/+7Hi3Kx8CjOajVbVCEz3kIT1wyYnsD6s5t8tUaGLFpTfC7q2TH4rjzHMCoGgqTOJiMFi/TY5kduOJWHfzdtzdFrS4PYBwzhi0LAKcAdTcvKhur+VWQ3/TWcq/+LJG5VahUsILHUDGiGCmKy26cOrxlxwZUsMHlvVDW7lMQwghGOGZpmt6zcdFD47EhtQVyWySQRHUgVDzhmkeClyZFlGmiA5BH0WpyB+twPp/cgQpQBH0Lqt6qaTwfs+OW6Kl/RrdET/WqQi5BgWLDqNxmdV/Mo1X1QX5Ms0Pq/jmaP7d2/b6IVq3HW+a9qT7v6/TDNv2+tVA0hzz8klroc07AbXKmN98YQMppARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCAD2//A2iD9ZsgY5XpAAAAAElFTkSuQmCC") white';
b.appendChild(a);c.startsWith("data:")?(g('Downloading EPW file "<data: '+c.length+' chars>"...'),c=await w(c)):(g('Downloading EPW file "'+c+'"...'),c=await v(c));var d=!1;c?384>c.byteLength&&(n("The EPW file is too short"),d=!0):d=!0;if(d)b.removeChild(a),x(b,"Failed to download EPW file!"),n("Failed to download EPW file!");else{var e=new DataView(c);if(608649541!==e.getUint32(0,!0)||1297301847!==e.getUint32(4,!0))n("The file is not an EPW file"),d=!0;var f=c.byteLength;e.getUint32(8,!0)!==f&&(n("The EPW file is the wrong length"),
d=!0);if(d)b.removeChild(a),x(b,"EPW file is invalid!"),n("EPW file is invalid!");else{var l=new TextDecoder("utf-8"),h=e.getUint32(100,!0),k=e.getUint32(104,!0),m=e.getUint32(108,!0),p=e.getUint32(112,!0);if(0>h||h+k>f||0>m||m+p>f)n("The EPW file contains an invalid offset (component: splash)"),d=!0;if(d)b.removeChild(a),x(b,"EPW file is invalid!"),n("EPW file is invalid!");else{h=new Uint8Array(c,h,k);m=new Uint8Array(c,m,p);l=URL.createObjectURL(new Blob([h],{type:l.decode(m)}));g("Loaded splash img: "+
l);a.style.background='center / contain no-repeat url("'+l+'"), 0px 0px / 1000000% 1000000% no-repeat url("'+l+'") white';await u();p=e.getUint32(164,!0);h=e.getUint32(168,!0);m=e.getUint32(180,!0);e=e.getUint32(184,!0);if(0>p||p+h>f||0>m||m+e>f)n("The EPW file contains an invalid offset (component: loader)"),d=!0;if(d)b.removeChild(a),x(b,"EPW file is invalid!"),n("EPW file is invalid!");else{a=new Uint8Array(c,p,h);a=URL.createObjectURL(new Blob([a],{type:"text/javascript;charset=utf-8"}));g("Loaded loader.js: "+
l);d=new Uint8Array(c,m,e);d=URL.createObjectURL(new Blob([d],{type:"application/wasm"}));g("Loaded loader.wasm: "+d);f={};for(const [t,y]of Object.entries(window.eaglercraftXOpts))"container"!==t&&"assetsURI"!==t&&(f[t]=y);window.__eaglercraftXLoaderContextPre={rootElement:b,eaglercraftXOpts:f,theEPWFileBuffer:c,loaderWASMURL:d,splashURL:l};g("Appending loader.js to document...");b=document.createElement("script");b.type="text/javascript";b.src=a;document.head.appendChild(b)}}}}}else b='window.eaglercraftXOpts.container "'+
a+'" is not a known element id!',n(b),alert(b)}}};}).call(this);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html style="width:100%;height:100%;background-color:black;">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
<meta name="description" content="Play minecraft 1.8 in your browser" />
<meta name="keywords" content="eaglercraft, eaglercraftx, minecraft, 1.8, 1.8.8" />
<title>EaglercraftX 1.8 WASM-GC</title>
<meta property="og:locale" content="en-US" />
<meta property="og:type" content="website" />
<meta property="og:title" content="EaglercraftX 1.8 WASM-GC" />
<meta property="og:description" content="Play minecraft 1.8 in your browser" />
<meta property="og:image" content="favicon.png" />
<link type="image/png" rel="shortcut icon" href="favicon.png" />
<script type="text/javascript" src="bootstrap.js"></script>
<script type="text/javascript">
"use strict";
window.addEventListener("load", function() {
if(window.location.href.indexOf("file:") === 0) {
alert("HTTP please, do not open this file locally, run a local HTTP server and load it via HTTP");
}else {
// %%%%%%%%% launch options %%%%%%%%%%%%
var relayId = Math.floor(Math.random() * 3);
window.eaglercraftXOpts = {
demoMode: false,
container: "game_frame",
assetsURI: "assets.epw",
worldsDB: "worlds",
servers: [
/* example: { addr: "ws://localhost:8081/", name: "Local test server" } */
],
relays: [
{ addr: "wss://relay.deev.is/", comment: "lax1dude relay #1", primary: relayId == 0 },
{ addr: "wss://relay.lax1dude.net/", comment: "lax1dude relay #2", primary: relayId == 1 },
{ addr: "wss://relay.shhnowisnottheti.me/", comment: "ayunami relay #1", primary: relayId == 2 }
]
};
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
var q = window.location.search;
if((typeof q === "string") && q[0] === "?" && (typeof window.URLSearchParams !== "undefined")) {
q = new window.URLSearchParams(q);
var s = q.get("server");
if(s) window.eaglercraftXOpts.joinServer = s;
}
main();
}
});
</script>
</head>
<body style="margin:0px;width:100%;height:100%;overflow:hidden;background-color:black;" id="game_frame"></body>
</html>

View file

@ -0,0 +1,19 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user manual at https://docs.gradle.org/6.0/userguide/multi_project_builds.html
*/
pluginManagement {
repositories {
maven {
url = uri("https://eaglercraft-teavm-fork.github.io/maven/")
}
mavenCentral()
}
}
rootProject.name = 'eagler-workspace-wasm-gc-teavm'

View file

@ -48,11 +48,13 @@ public class BootMenuEntryPoint {
private static native void setHasAlreadyBooted(); private static native void setHasAlreadyBooted();
public static boolean checkShouldLaunchFlag(Window win) { public static boolean checkShouldLaunchFlag(Window win) {
wasManuallyInvoked = false;
int flag = BootMenuDataManager.getBootMenuFlags(win); int flag = BootMenuDataManager.getBootMenuFlags(win);
if(flag == -1) { if(flag == -1) {
return IBootMenuConfigAdapter.instance.isShowBootMenuOnLaunch() && !getHasAlreadyBooted(); return IBootMenuConfigAdapter.instance.isShowBootMenuOnLaunch() && !getHasAlreadyBooted();
} }
if((flag & 2) != 0) { if((flag & 2) != 0) {
wasManuallyInvoked = true;
BootMenuDataManager.setBootMenuFlags(win, flag & ~2); BootMenuDataManager.setBootMenuFlags(win, flag & ~2);
setHasAlreadyBooted(); setHasAlreadyBooted();
return true; return true;
@ -63,6 +65,7 @@ public class BootMenuEntryPoint {
private static boolean hasInit = false; private static boolean hasInit = false;
private static byte[] signatureData = null; private static byte[] signatureData = null;
private static byte[] bundleData = null; private static byte[] bundleData = null;
public static boolean wasManuallyInvoked = false;
public static void launchMenu(Window parentWindow, HTMLElement parentElement) { public static void launchMenu(Window parentWindow, HTMLElement parentElement) {
signatureData = PlatformUpdateSvc.getClientSignatureData(); signatureData = PlatformUpdateSvc.getClientSignatureData();

View file

@ -144,7 +144,7 @@ public class BootMenuMain {
bootMenuFatOfflineLoader = new BootMenuFatOfflineLoader(parentWindow.getDocument().getHead()); bootMenuFatOfflineLoader = new BootMenuFatOfflineLoader(parentWindow.getDocument().getHead());
logger.info("Entering boot menu display state"); logger.info("Entering boot menu display state");
eventQueue.clear(); eventQueue.clear();
changeState(new MenuStateBoot(true)); changeState(new MenuStateBoot(!BootMenuEntryPoint.wasManuallyInvoked));
enterUpdateLoop(); enterUpdateLoop();
} }

View file

@ -74,6 +74,12 @@ public class OfflineDownloadParser {
logger.info("Detected format: EAGLERCRAFTX_1_8_OFFLINE (International)"); logger.info("Detected format: EAGLERCRAFTX_1_8_OFFLINE (International)");
return EnumOfflineParseType.EAGLERCRAFTX_1_8_OFFLINE; return EnumOfflineParseType.EAGLERCRAFTX_1_8_OFFLINE;
} }
if(foundWithin(offlineDownloadData.indexOf(StringUtils.reverse("]OFNI[ :partstooBredaoL")), 0, 16384)) {
if(offlineDownloadData.indexOf(StringUtils.reverse(",46esab;maerts-tetco/noitacilppa:atad\" = IRUstessa.stpOXtfarcrelgae.wodniw")) != -1) {
logger.info("Detected format: EAGLERCRAFTX_1_8_OFFLINE (WASM-GC)");
return EnumOfflineParseType.EAGLERCRAFTX_1_8_OFFLINE;
}
}
if(foundWithin(offlineDownloadData.indexOf(StringUtils.reverse("{ = stpOtfarcrelgae.wodniw")), 32, 2048) && foundWithin(offlineDownloadData.indexOf(StringUtils.reverse(">\"rekrow_ps\"=di \"rekrowrelgae/txet\"=epyt tpircs<")), 4194304, offlineDownloadData.length() - 1048576)) { if(foundWithin(offlineDownloadData.indexOf(StringUtils.reverse("{ = stpOtfarcrelgae.wodniw")), 32, 2048) && foundWithin(offlineDownloadData.indexOf(StringUtils.reverse(">\"rekrow_ps\"=di \"rekrowrelgae/txet\"=epyt tpircs<")), 4194304, offlineDownloadData.length() - 1048576)) {
logger.info("Detected format: EAGLERCRAFTX_1_5_NEW_OFFLINE"); logger.info("Detected format: EAGLERCRAFTX_1_5_NEW_OFFLINE");
return EnumOfflineParseType.EAGLERCRAFT_1_5_NEW_OFFLINE; return EnumOfflineParseType.EAGLERCRAFT_1_5_NEW_OFFLINE;

View file

@ -1569,7 +1569,7 @@ public class PlatformInput {
isOnMobilePressAnyKey = true; isOnMobilePressAnyKey = true;
setupAnyKeyScreenMobile(allowBootMenu); setupAnyKeyScreenMobile(allowBootMenu);
if(pressAnyKeyScreenMobile() && allowBootMenu) { if(pressAnyKeyScreenMobile() && allowBootMenu) {
PlatformRuntime.enterBootMenu(); PlatformRuntime.enterBootMenu(true);
} }
}finally { }finally {
isOnMobilePressAnyKey = false; isOnMobilePressAnyKey = false;

View file

@ -185,8 +185,7 @@ public class PlatformRuntime {
} }
CSSStyleDeclaration style = root.getStyle(); CSSStyleDeclaration style = root.getStyle();
style.setProperty("overflowX", "hidden"); style.setProperty("overflow", "hidden");
style.setProperty("overflowY", "hidden");
TeaVMClientConfigAdapter teavmCfg = (TeaVMClientConfigAdapter) getClientConfigAdapter(); TeaVMClientConfigAdapter teavmCfg = (TeaVMClientConfigAdapter) getClientConfigAdapter();
boolean allowBootMenu = teavmCfg.isAllowBootMenu(); boolean allowBootMenu = teavmCfg.isAllowBootMenu();
@ -241,8 +240,7 @@ public class PlatformRuntime {
style.setProperty("position", "relative"); style.setProperty("position", "relative");
style.setProperty("width", "100%"); style.setProperty("width", "100%");
style.setProperty("height", "100%"); style.setProperty("height", "100%");
style.setProperty("overflowX", "hidden"); style.setProperty("overflow", "hidden");
style.setProperty("overflowY", "hidden");
root.appendChild(parent); root.appendChild(parent);
ClientMain.configRootElement = parent; // hack ClientMain.configRootElement = parent; // hack
@ -421,7 +419,7 @@ public class PlatformRuntime {
Collections.sort(exts); Collections.sort(exts);
logger.info("Unlocked the following OpenGL ES extensions:"); logger.info("Unlocked the following OpenGL ES extensions:");
for(int i = 0, l = exts.size(); i < l; ++i) { for(int i = 0, l = exts.size(); i < l; ++i) {
logger.info(" - " + exts.get(i)); logger.info(" - {}", exts.get(i));
} }
} }
@ -443,7 +441,7 @@ public class PlatformRuntime {
if(allowBootMenu && BootMenuEntryPoint.checkShouldLaunchFlag(win)) { if(allowBootMenu && BootMenuEntryPoint.checkShouldLaunchFlag(win)) {
logger.info("Boot menu enable flag is set, entering boot menu..."); logger.info("Boot menu enable flag is set, entering boot menu...");
enterBootMenu(); enterBootMenu(BootMenuEntryPoint.wasManuallyInvoked);
} }
byte[] finalLoadScreen = PlatformAssets.getResourceBytes("/assets/eagler/eagtek.png"); byte[] finalLoadScreen = PlatformAssets.getResourceBytes("/assets/eagler/eagtek.png");
@ -1134,7 +1132,7 @@ public class PlatformRuntime {
if(PlatformInput.keyboardGetEventKeyState()) { if(PlatformInput.keyboardGetEventKeyState()) {
int key = PlatformInput.keyboardGetEventKey(); int key = PlatformInput.keyboardGetEventKey();
if(key == KeyboardConstants.KEY_DELETE || key == KeyboardConstants.KEY_BACK) { if(key == KeyboardConstants.KEY_DELETE || key == KeyboardConstants.KEY_BACK) {
enterBootMenu(); enterBootMenu(true);
} }
} }
} }
@ -1143,7 +1141,7 @@ public class PlatformRuntime {
@JSBody(params = {}, script = "delete __isEaglerX188Running;") @JSBody(params = {}, script = "delete __isEaglerX188Running;")
private static native void clearRunningFlag(); private static native void clearRunningFlag();
static void enterBootMenu() { static void enterBootMenu(boolean manual) {
if(!getClientConfigAdapter().isAllowBootMenu()) { if(!getClientConfigAdapter().isAllowBootMenu()) {
throw new IllegalStateException("Boot menu is disabled"); throw new IllegalStateException("Boot menu is disabled");
} }
@ -1170,7 +1168,7 @@ public class PlatformRuntime {
immediateContinueChannel = null; immediateContinueChannel = null;
clearRunningFlag(); clearRunningFlag();
logger.info("Firing boot menu escape signal..."); logger.info("Firing boot menu escape signal...");
throw new TeaVMEnterBootMenuException(); throw new TeaVMEnterBootMenuException(manual);
} }
public static void postCreate() { public static void postCreate() {

View file

@ -188,7 +188,7 @@ public class PlatformScreenRecord {
TeaVMUtils.addEventListener(mediaRec, "dataavailable", new EventListener<DataAvailableEvent>() { TeaVMUtils.addEventListener(mediaRec, "dataavailable", new EventListener<DataAvailableEvent>() {
@Override @Override
public void handleEvent(DataAvailableEvent evt) { public void handleEvent(DataAvailableEvent evt) {
final String fileName = EaglercraftVersion.mainMenuStringB + " - " + EaglerProfile.getName() + " - " + fmt.format(new Date()) + "." + params.codec.fileExt; final String fileName = EaglercraftVersion.screenRecordingFilePrefix + " - " + EaglerProfile.getName() + " - " + fmt.format(new Date()) + "." + params.codec.fileExt;
if("video/webm".equals(params.codec.container)) { if("video/webm".equals(params.codec.container)) {
FixWebMDurationJS.getRecUrl(evt, (int) (PlatformRuntime.steadyTimeMillis() - startTime), url -> { FixWebMDurationJS.getRecUrl(evt, (int) (PlatformRuntime.steadyTimeMillis() - startTime), url -> {
PlatformApplication.downloadURLWithNameTeaVM(fileName, url, () -> TeaVMUtils.freeDataURL(url)); PlatformApplication.downloadURLWithNameTeaVM(fileName, url, () -> TeaVMUtils.freeDataURL(url));

View file

@ -421,7 +421,7 @@ public class PlatformWebRTC {
final Object[] evtHandler = new Object[1]; final Object[] evtHandler = new Object[1];
evtHandler[0] = (EventListener<Event>) evt -> { evtHandler[0] = (EventListener<Event>) evt -> {
if (!iceCandidates.isEmpty()) { if (!iceCandidates.isEmpty()) {
Window.setTimeout(() -> ((EventListener<Event>)evtHandler[0]).handleEvent(evt), 1); Window.setTimeout(() -> ((EventListener<Event>)evtHandler[0]).handleEvent(evt), 10);
return; return;
} }
clientDataChannelClosed = false; clientDataChannelClosed = false;
@ -541,7 +541,7 @@ public class PlatformWebRTC {
final Object[] evtHandler = new Object[1]; final Object[] evtHandler = new Object[1];
evtHandler[0] = (EventListener<Event>) evt -> { evtHandler[0] = (EventListener<Event>) evt -> {
if (!iceCandidates.isEmpty()) { if (!iceCandidates.isEmpty()) {
Window.setTimeout(() -> ((EventListener<Event>)evtHandler[0]).handleEvent(evt), 1); Window.setTimeout(() -> ((EventListener<Event>)evtHandler[0]).handleEvent(evt), 10);
return; return;
} }
if (getChannel(evt) == null) return; if (getChannel(evt) == null) return;

View file

@ -200,7 +200,6 @@ public class PlatformWebView {
try { try {
List<String> sandboxArgs = new ArrayList<>(); List<String> sandboxArgs = new ArrayList<>();
sandboxArgs.add("allow-downloads"); sandboxArgs.add("allow-downloads");
sandboxArgs.add("allow-same-origin");
if(options.scriptEnabled) { if(options.scriptEnabled) {
sandboxArgs.add("allow-scripts"); sandboxArgs.add("allow-scripts");
sandboxArgs.add("allow-pointer-lock"); sandboxArgs.add("allow-pointer-lock");

View file

@ -202,6 +202,7 @@ public class ClientMain {
}catch(TeaVMEnterBootMenuException ee) { }catch(TeaVMEnterBootMenuException ee) {
try { try {
systemOut.println("ClientMain: [INFO] launching eaglercraftx boot menu"); systemOut.println("ClientMain: [INFO] launching eaglercraftx boot menu");
BootMenuEntryPoint.wasManuallyInvoked = ee.isManual;
BootMenuEntryPoint.launchMenu(Window.current(), configRootElement); BootMenuEntryPoint.launchMenu(Window.current(), configRootElement);
}catch(Throwable t) { }catch(Throwable t) {
showCrashScreen("Failed to enter boot menu!", t); showCrashScreen("Failed to enter boot menu!", t);
@ -550,6 +551,7 @@ public class ClientMain {
} }
if(el == null) { if(el == null) {
Window.alert("Compatibility error: " + t);
System.err.println("Compatibility error: " + t); System.err.println("Compatibility error: " + t);
return; return;
} }
@ -573,11 +575,9 @@ public class ClientMain {
+ "<p><br /><span style=\"font-size:1.1em;border-bottom:1px dashed #AAAAAA;padding-bottom:5px;\">Things you can try:</span></p>" + "<p><br /><span style=\"font-size:1.1em;border-bottom:1px dashed #AAAAAA;padding-bottom:5px;\">Things you can try:</span></p>"
+ "<ol>" + "<ol>"
+ "<li><span style=\"font-weight:bold;\">Just try using Eaglercraft on a different device</span>, it isn't a bug it's common sense</li>" + "<li><span style=\"font-weight:bold;\">Just try using Eaglercraft on a different device</span>, it isn't a bug it's common sense</li>"
+ "<li style=\"margin-top:7px;\">If you are on a mobile device, please try a proper desktop or a laptop computer</li>" + "<li style=\"margin-top:7px;\">If this screen just appeared randomly, try restarting your browser or device</li>"
+ "<li style=\"margin-top:7px;\">If you are using a device with no mouse cursor, please use a device with a mouse cursor</li>"
+ "<li style=\"margin-top:7px;\">If you are not using Chrome/Edge, try installing the latest Google Chrome</li>" + "<li style=\"margin-top:7px;\">If you are not using Chrome/Edge, try installing the latest Google Chrome</li>"
+ "<li style=\"margin-top:7px;\">If your browser is out of date, please update it to the latest version</li>" + "<li style=\"margin-top:7px;\">If your browser is out of date, please update it to the latest version</li>"
+ "<li style=\"margin-top:7px;\">If you are using an old OS such as Windows 7, please try Windows 10 or 11</li>"
+ "</ol>" + "</ol>"
+ "</div>"); + "</div>");

View file

@ -69,7 +69,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter, IBootMenu
private boolean openDebugConsoleOnLaunch = false; private boolean openDebugConsoleOnLaunch = false;
private boolean fixDebugConsoleUnloadListener = false; private boolean fixDebugConsoleUnloadListener = false;
private boolean forceWebViewSupport = false; private boolean forceWebViewSupport = false;
private boolean enableWebViewCSP = false; private boolean enableWebViewCSP = true;
private boolean autoFixLegacyStyleAttr = false; private boolean autoFixLegacyStyleAttr = false;
private boolean showBootMenuOnLaunch = false; private boolean showBootMenuOnLaunch = false;
private boolean bootMenuBlocksUnsignedClients = false; private boolean bootMenuBlocksUnsignedClients = false;
@ -77,7 +77,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter, IBootMenu
private boolean forceProfanityFilter = false; private boolean forceProfanityFilter = false;
private boolean forceWebGL1 = false; private boolean forceWebGL1 = false;
private boolean forceWebGL2 = false; private boolean forceWebGL2 = false;
private boolean allowExperimentalWebGL1 = false; private boolean allowExperimentalWebGL1 = true;
private boolean useWebGLExt = true; private boolean useWebGLExt = true;
private boolean useDelayOnSwap = false; private boolean useDelayOnSwap = false;
private boolean useJOrbisAudioDecoder = false; private boolean useJOrbisAudioDecoder = false;
@ -550,6 +550,11 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter, IBootMenu
return ramdiskMode; return ramdiskMode;
} }
@Override
public boolean isEnforceVSync() {
return false;
}
@Override @Override
public IClientConfigAdapterHooks getHooks() { public IClientConfigAdapterHooks getHooks() {
return hooks; return hooks;

View file

@ -17,4 +17,10 @@ package net.lax1dude.eaglercraft.v1_8.internal.teavm;
*/ */
public class TeaVMEnterBootMenuException extends RuntimeException { public class TeaVMEnterBootMenuException extends RuntimeException {
public final boolean isManual;
public TeaVMEnterBootMenuException(boolean manual) {
this.isManual = manual;
}
} }

View file

@ -35,6 +35,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils;
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2; import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger; import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.sp.server.IWASMCrashCallback;
/** /**
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved. * Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
@ -291,4 +292,8 @@ public class ServerPlatformSingleplayer {
} }
} }
public static void setCrashCallbackWASM(IWASMCrashCallback callback) {
}
} }

View file

@ -0,0 +1,45 @@
/**
* @fileoverview loader bootstrap externs
* @externs
*/
/*
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
window.main = function() {};
window.eaglercraftXOpts = {};
window.eaglercraftXOpts.assetsURI = "";
window.eaglercraftXOpts.container = "";
window.__eaglercraftXLoaderContextPre = {};
/** @type {!HTMLElement} */
window.__eaglercraftXLoaderContextPre.rootElement;
/** @type {!Object} */
window.__eaglercraftXLoaderContextPre.eaglercraftXOpts;
/** @type {!ArrayBuffer} */
window.__eaglercraftXLoaderContextPre.theEPWFileBuffer;
/** @type {string} */
window.__eaglercraftXLoaderContextPre.loaderWASMURL;
/** @type {string} */
window.__eaglercraftXLoaderContextPre.splashURL;

View file

@ -0,0 +1,377 @@
/*
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @param {*} msg
*/
function logInfo(msg) {
console.log("LoaderBootstrap: [INFO] " + msg);
}
/**
* @param {*} msg
*/
function logWarn(msg) {
console.log("LoaderBootstrap: [WARN] " + msg);
}
/**
* @param {*} msg
*/
function logError(msg) {
console.error("LoaderBootstrap: [ERROR] " + msg);
}
/** @type {function(string,number):ArrayBuffer|null} */
var decodeBase64Impl = null;
/**
* @return {function(string,number):ArrayBuffer}
*/
function createBase64Decoder() {
const revLookup = [];
const code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
for (var i = 0, len = code.length; i < len; ++i) {
revLookup[code.charCodeAt(i)] = i;
}
revLookup["-".charCodeAt(0)] = 62;
revLookup["_".charCodeAt(0)] = 63;
/**
* @param {string} b64
* @param {number} start
* @return {!Array<number>}
*/
function getLens(b64, start) {
const len = b64.length - start;
if (len % 4 > 0) {
throw new Error("Invalid string. Length must be a multiple of 4");
}
var validLen = b64.indexOf("=", start);
if (validLen === -1) {
validLen = len;
}else {
validLen -= start;
}
const placeHoldersLen = validLen === len ? 0 : 4 - (validLen % 4);
return [validLen, placeHoldersLen];
}
/**
* @param {string} b64
* @param {number} start
* @return {ArrayBuffer}
*/
function decodeImpl(b64, start) {
var tmp;
const lens = getLens(b64, start);
const validLen = lens[0];
const placeHoldersLen = lens[1];
const arr = new Uint8Array(((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen);
var curByte = 0;
const len = (placeHoldersLen > 0 ? validLen - 4 : validLen) + start;
var i;
for (i = start; i < len; i += 4) {
tmp = (revLookup[b64.charCodeAt(i)] << 18) |
(revLookup[b64.charCodeAt(i + 1)] << 12) |
(revLookup[b64.charCodeAt(i + 2)] << 6) |
revLookup[b64.charCodeAt(i + 3)]
arr[curByte++] = (tmp >> 16) & 0xFF
arr[curByte++] = (tmp >> 8) & 0xFF
arr[curByte++] = tmp & 0xFF
}
if (placeHoldersLen === 2) {
tmp = (revLookup[b64.charCodeAt(i)] << 2) |
(revLookup[b64.charCodeAt(i + 1)] >> 4)
arr[curByte++] = tmp & 0xFF
}else if (placeHoldersLen === 1) {
tmp = (revLookup[b64.charCodeAt(i)] << 10) |
(revLookup[b64.charCodeAt(i + 1)] << 4) |
(revLookup[b64.charCodeAt(i + 2)] >> 2)
arr[curByte++] = (tmp >> 8) & 0xFF
arr[curByte++] = tmp & 0xFF
}
return arr.buffer;
}
return decodeImpl;
}
/**
* @param {string} url
* @param {number} start
* @return {ArrayBuffer}
*/
function decodeBase64(url, start) {
if(!decodeBase64Impl) {
decodeBase64Impl = createBase64Decoder();
}
return decodeBase64Impl(url, start);
}
/**
* @param {number} ms
* @return {!Promise}
*/
function asyncSleep(ms) {
return new Promise(function(resolve) {
setTimeout(resolve, ms);
});
}
/**
* @param {string} url
* @return {!Promise<ArrayBuffer>}
*/
function downloadURL(url) {
return new Promise(function(resolve) {
fetch(url, { "cache": "force-cache" })
.then(function(res) {
return res.arrayBuffer();
})
.then(resolve)
.catch(function(ex) {
logError("Failed to fetch URL! " + ex);
resolve(null);
});
});
}
/**
* @param {string} url
* @return {!Promise<ArrayBuffer>}
*/
function downloadDataURL(url) {
if(!url.startsWith("data:application/octet-stream;base64,")) {
return downloadURL(url);
}else {
return new Promise(function(resolve) {
downloadURL(url).then(function(res) {
if(res) {
resolve(res);
}else {
logWarn("Failed to decode base64 via fetch, doing it the slow way instead...");
try {
resolve(decodeBase64(url, 37));
}catch(ex) {
logError("Failed to decode base64! " + ex);
resolve(null);
}
}
});
});
}
}
/**
* @param {HTMLElement} rootElement
* @param {string} msg
*/
function displayInvalidEPW(rootElement, msg) {
const downloadFailureMsg = /** @type {HTMLElement} */ (document.createElement("h2"));
downloadFailureMsg.style.color = "#AA0000";
downloadFailureMsg.style.padding = "25px";
downloadFailureMsg.style.fontFamily = "sans-serif";
downloadFailureMsg.style["marginBlock"] = "0px";
downloadFailureMsg.appendChild(document.createTextNode(msg));
rootElement.appendChild(downloadFailureMsg);
const downloadFailureMsg2 = /** @type {HTMLElement} */ (document.createElement("h4"));
downloadFailureMsg2.style.color = "#AA0000";
downloadFailureMsg2.style.padding = "25px";
downloadFailureMsg2.style.fontFamily = "sans-serif";
downloadFailureMsg2.style["marginBlock"] = "0px";
downloadFailureMsg2.appendChild(document.createTextNode("Try again later"));
rootElement.style.backgroundColor = "white";
rootElement.appendChild(downloadFailureMsg2);
}
window.main = async function() {
if(typeof window.eaglercraftXOpts === "undefined") {
const msg = "window.eaglercraftXOpts is not defined!";
logError(msg);
alert(msg);
return;
}
const containerId = window.eaglercraftXOpts.container;
if(typeof containerId !== "string") {
const msg = "window.eaglercraftXOpts.container is not a string!";
logError(msg);
alert(msg);
return;
}
var assetsURI = window.eaglercraftXOpts.assetsURI;
if(typeof assetsURI !== "string") {
if((typeof assetsURI === "object") && (typeof assetsURI[0] === "object") && (typeof assetsURI[0]["url"] === "string")) {
assetsURI = assetsURI[0]["url"];
}else {
const msg = "window.eaglercraftXOpts.assetsURI is not a string!";
logError(msg);
alert(msg);
return;
}
}
const rootElement = /** @type {HTMLElement} */ (document.getElementById(containerId));
if(!rootElement) {
const msg = "window.eaglercraftXOpts.container \"" + containerId + "\" is not a known element id!";
logError(msg);
alert(msg);
return;
}
var node;
while(node = rootElement.lastChild) {
rootElement.removeChild(node);
}
const splashElement = /** @type {HTMLElement} */ (document.createElement("div"));
splashElement.style.width = "100%";
splashElement.style.height = "100%";
splashElement.style.setProperty("image-rendering", "pixelated");
splashElement.style.background = "center / contain no-repeat url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMAAAADACAAAAAB3tzPbAAAACXBIWXMAAC4jAAAuIwF4pT92AAAG+UlEQVR42u2cy23jOhRATwbTwGwFvAJoF6BFGjColcGkASNuIPA6C68DN+BADZiCVxLSQBYqIGYBAbSdEvwWkvUzZWfymwlwCQwQUZeXPOT9URPkYs/3bj8QAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAH4x9vPvzFpAhAzM98UILmqfjDf1YT0N/cBk+71v+wDSczHmDeJ6TqO+SIfyD7IvC9g33Yc7dP6CQDxB+q62Hc2xnyJD2Sf5vuzL3Hi5MM0WbCN51u/Y/30ryEGmDVHlhwsY9Y7xlq0CuzVc4lh2n7NkGsnQ1nB7IefmrY/araJcbrq6Ryk9YqW4l3J/dHww1jdej+8kte042EW0Nba1hyWdl+9irq/FNXaD6BbQoexuvf+tQC2vX1+AFvP0kxiuyidfWwEbOtQtK0n0r6xbYCKsLcM21+pLZX3u4984Kq2xlnWDimllRudAXEpkGSHfqMzsmxfWnLWNf9aQznW4wMZWOMJxvGs/Ff5X+yPcD0g3dqZesdsI2f7Z2/73W2JSok9Gqu7P1q/I2qtj0qn/ZkTaCPWO2a0VyjrxY7sNUG1LxRlaE90MpDpGVeAxpaGobN2XPWH0aQVE1stfXPAj0+XzUmcob3aTRdVZ2+tRv+gMNBDaTkZ4k6uhtYPaK7iUkUcx9lgij92gZ6aXmxoDeK8D1hPfm18oBvTfPGwXoVG+4VfXcwl8dEOtCJS7De9M0VTqTA2p081O3kJ+uk5cU/RVN8C262Ms9HMlLHSmhNFTcc9u1uQRX4jMhqyNIk1GRk69a6hb0IDZ3pITnbfNqFuJWE9gbYrfmSqen/SiKy27G0VS20VWc+UEn59/YDPkc+0EunrAXQ/JXucYL+3VutyAqvP5wFvtEoyQPsMJMpKc3v7/Su9ALLkhAJDPCObGTDmonfNHAij3sg5866fmTHGnFt/crroh6vEv/Rq6vhEoP7hWWb2ylSQZP5zOVrDqVxSZnm/xL6OFnZwF3/4JoyGjyXu1X3n0rEFyE5Jzc5KEDfT7s2ZYs52s5e1HU88hB17nKTqAroXWPpXiHbN7R3Q8fVDbjzU6vb8hUbX67FWN8Xo4U5SIWjbukr1knY9XrcwS30aOuTatqa0vkA6cI05dyPrzWBbj7ZZrPUT2O7pdpKFtp4rph0E0AxtfN0u9kNVg25d4BPiDF0+R83dPol7/l4m4yQmQzdX+ISewqTnc8ngp94yaCan4vT+Hc228q8/T35+e8+XueSqCaPmEz9ofdbX6eSqE5iN/m4A8Qd9w/1bAEl2fPmafT3Axdv/ytlFeXUwTZyyf+NA3hWDGPrm+HXtHSdQ7nrz7fvv+MPFe/9Q3nAS+iYA3zcKCYAACIAACIAACIAACIAACIAACIAA1C2Komh++r9cogdv90M0+GoZAVHkSiGSaFmOmJdTRdESiKJ5Je4eovnSldoGNJ44gTBNbx+XH7tDYxwOniAPgEdygGWxTm/jBCAHV0u7xa90PV64IW0uOWdCapK7t600vfF2j4Ad5FCE4IopCSWMSg0Q4NgRVNKrwIBJ1ZDGxXO/5+fxhDvFQ87EsHxZMy9Sli/raMbjf9eqMpiciQG3yYOJwW1eQoBoesNBzG3yKdvqNwie1HMwiXFcwo7L7aMBtlSrC7c79RzyUm5w0f66Gk1vcJs8vFYHxUvy/u8leJz4N8t8vX5ccl04Chz5BOLR+mVVWXX5lsU4ncSOFevL7WFsJbYiPfQpcvJwhNsBxKiwcHDPNnoojzp8Jh8PnusiSMcLd1B8R5i+Igq5/BZKU3IEO8cIpoqw6L5NR8kjuOIaFR6GlmKdvmnhuFTsfqNwTBnzBOo+ZFua+jh3jAZtnksMu/b850wIfh1sVwVPhMEzKK9lz/+7Hi3Kx8CjOajVbVCEz3kIT1wyYnsD6s5t8tUaGLFpTfC7q2TH4rjzHMCoGgqTOJiMFi/TY5kduOJWHfzdtzdFrS4PYBwzhi0LAKcAdTcvKhur+VWQ3/TWcq/+LJG5VahUsILHUDGiGCmKy26cOrxlxwZUsMHlvVDW7lMQwghGOGZpmt6zcdFD47EhtQVyWySQRHUgVDzhmkeClyZFlGmiA5BH0WpyB+twPp/cgQpQBH0Lqt6qaTwfs+OW6Kl/RrdET/WqQi5BgWLDqNxmdV/Mo1X1QX5Ms0Pq/jmaP7d2/b6IVq3HW+a9qT7v6/TDNv2+tVA0hzz8klroc07AbXKmN98YQMppARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCAD2//A2iD9ZsgY5XpAAAAAElFTkSuQmCC\") white";
rootElement.appendChild(splashElement);
/** @type {ArrayBuffer} */
var theEPWFileBuffer;
if(assetsURI.startsWith("data:")) {
logInfo("Downloading EPW file \"<data: " + assetsURI.length + " chars>\"...");
theEPWFileBuffer = await downloadDataURL(assetsURI);
}else {
logInfo("Downloading EPW file \"" + assetsURI + "\"...");
theEPWFileBuffer = await downloadURL(assetsURI);
}
var isInvalid = false;
if(!theEPWFileBuffer) {
isInvalid = true;
}else if(theEPWFileBuffer.byteLength < 384) {
logError("The EPW file is too short");
isInvalid = true;
}
if(isInvalid) {
rootElement.removeChild(splashElement);
const msg = "Failed to download EPW file!";
displayInvalidEPW(rootElement, msg);
logError(msg);
return;
}
const dataView = new DataView(theEPWFileBuffer);
if(dataView.getUint32(0, true) !== 608649541 || dataView.getUint32(4, true) !== 1297301847) {
logError("The file is not an EPW file");
isInvalid = true;
}
const phileLength = theEPWFileBuffer.byteLength;
if(dataView.getUint32(8, true) !== phileLength) {
logError("The EPW file is the wrong length");
isInvalid = true;
}
if(isInvalid) {
rootElement.removeChild(splashElement);
const msg = "EPW file is invalid!";
displayInvalidEPW(rootElement, msg);
logError(msg);
return;
}
const textDecoder = new TextDecoder("utf-8");
const splashDataOffset = dataView.getUint32(100, true);
const splashDataLength = dataView.getUint32(104, true);
const splashMIMEOffset = dataView.getUint32(108, true);
const splashMIMELength = dataView.getUint32(112, true);
if(splashDataOffset < 0 || splashDataOffset + splashDataLength > phileLength
|| splashMIMEOffset < 0 || splashMIMEOffset + splashMIMELength > phileLength) {
logError("The EPW file contains an invalid offset (component: splash)");
isInvalid = true;
}
if(isInvalid) {
rootElement.removeChild(splashElement);
const msg = "EPW file is invalid!";
displayInvalidEPW(rootElement, msg);
logError(msg);
return;
}
const splashBinSlice = new Uint8Array(theEPWFileBuffer, splashDataOffset, splashDataLength);
const splashMIMESlice = new Uint8Array(theEPWFileBuffer, splashMIMEOffset, splashMIMELength);
const splashURL = URL.createObjectURL(new Blob([ splashBinSlice ], { "type": textDecoder.decode(splashMIMESlice) }));
logInfo("Loaded splash img: " + splashURL);
splashElement.style.background = "center / contain no-repeat url(\"" + splashURL + "\"), 0px 0px / 1000000% 1000000% no-repeat url(\"" + splashURL + "\") white";
// allow the screen to update
await asyncSleep(20);
const loaderJSOffset = dataView.getUint32(164, true);
const loaderJSLength = dataView.getUint32(168, true);
const loaderWASMOffset = dataView.getUint32(180, true);
const loaderWASMLength = dataView.getUint32(184, true);
if(loaderJSOffset < 0 || loaderJSOffset + loaderJSLength > phileLength
|| loaderWASMOffset < 0 || loaderWASMOffset + loaderWASMLength > phileLength) {
logError("The EPW file contains an invalid offset (component: loader)");
isInvalid = true;
}
if(isInvalid) {
rootElement.removeChild(splashElement);
const msg = "EPW file is invalid!";
displayInvalidEPW(rootElement, msg);
logError(msg);
return;
}
const loaderJSSlice = new Uint8Array(theEPWFileBuffer, loaderJSOffset, loaderJSLength);
const loaderJSURL = URL.createObjectURL(new Blob([ loaderJSSlice ], { "type": "text/javascript;charset=utf-8" }));
logInfo("Loaded loader.js: " + splashURL);
const loaderWASMSlice = new Uint8Array(theEPWFileBuffer, loaderWASMOffset, loaderWASMLength);
const loaderWASMURL = URL.createObjectURL(new Blob([ loaderWASMSlice ], { "type": "application/wasm" }));
logInfo("Loaded loader.wasm: " + loaderWASMURL);
const optsObj = {};
for(const [key, value] of Object.entries(window.eaglercraftXOpts)) {
if(key !== "container" && key !== "assetsURI") {
optsObj[key] = value;
}
}
window.__eaglercraftXLoaderContextPre = {
"rootElement": rootElement,
"eaglercraftXOpts": optsObj,
"theEPWFileBuffer": theEPWFileBuffer,
"loaderWASMURL": loaderWASMURL,
"splashURL": splashURL
};
logInfo("Appending loader.js to document...");
const scriptElement = /** @type {HTMLScriptElement} */ (document.createElement("script"));
scriptElement.type = "text/javascript";
scriptElement.src = loaderJSURL;
document.head.appendChild(scriptElement);
};

Some files were not shown because too many files have changed in this diff Show more