diff --git a/MakeOfflineDownload.bat b/MakeOfflineDownload.bat index 1ac0441..4b4efde 100644 --- a/MakeOfflineDownload.bat +++ b/MakeOfflineDownload.bat @@ -1,4 +1,4 @@ @echo off title MakeOfflineDownload -java -cp "resources/MakeOfflineDownload.jar;resources/CompileEPK.jar" net.lax1dude.eaglercraft.v1_8.buildtools.workspace.MakeOfflineDownload "javascript/OfflineDownloadTemplate.txt" "javascript/classes.js" "javascript/assets.epk" "javascript/EaglercraftL_1.9_Offline_en_US.html" "javascript/EaglercraftX_1.8_Offline_International.html" "javascript/lang" +java -cp "resources/MakeOfflineDownload.jar;resources/CompileEPK.jar" net.lax1dude.eaglercraft.v1_8.buildtools.workspace.MakeOfflineDownload "javascript/OfflineDownloadTemplate.txt" "javascript/classes.js" "javascript/assets.epk" "javascript/EaglercraftL_1.9_Offline_en_US.html" "javascript/EaglercraftL_1.9_Offline_International.html" "javascript/lang" pause \ No newline at end of file diff --git a/New Text Document.txt b/New Text Document.txt new file mode 100644 index 0000000..e69de29 diff --git a/javascript/EaglercraftL_1.9_Offline_International.html b/javascript/EaglercraftL_1.9_Offline_International.html new file mode 100644 index 0000000..616a79a --- /dev/null +++ b/javascript/EaglercraftL_1.9_Offline_International.html @@ -0,0 +1,45405 @@ + + + + + + + + + + + + + + + + + + + + + + + + +EaglercraftX 1.8 + + + + + + + + + + +
+
+

This file is from 06/02/2024

+

Game will launch in 5...

+
+
+
+ + diff --git a/javascript/web.zip b/javascript/web.zip new file mode 100644 index 0000000..523e025 Binary files /dev/null and b/javascript/web.zip differ diff --git a/javascript/web1.zip b/javascript/web1.zip new file mode 100644 index 0000000..36cd1ca Binary files /dev/null and b/javascript/web1.zip differ diff --git a/javascript/web2.zip b/javascript/web2.zip new file mode 100644 index 0000000..bdadebd Binary files /dev/null and b/javascript/web2.zip differ diff --git a/javascript/web4.zip b/javascript/web4.zip new file mode 100644 index 0000000..2ef5b63 Binary files /dev/null and b/javascript/web4.zip differ diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java index 76c62f5..0e68432 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java @@ -74,6 +74,10 @@ public class PlatformApplication { } public static void setLocalStorage(String name, byte[] data) { + setLocalStorage(name, data, true); + } + + public static void setLocalStorage(String name, byte[] data, boolean hooks) { if (data == null) { (new File("_eagstorage." + name + ".dat")).delete(); } else { @@ -86,6 +90,10 @@ public class PlatformApplication { } public static byte[] getLocalStorage(String data) { + return getLocalStorage(data, true); + } + + public static byte[] getLocalStorage(String data, boolean hooks) { File f = new File("_eagstorage." + data + ".dat"); if (!f.isFile()) { return null; diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java index ce3c9a6..462f52c 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java @@ -238,6 +238,10 @@ public class PlatformInput { glfwSwapBuffers(win); } + public static boolean isVSyncSupported() { + return true; + } + public static boolean wasResized() { boolean b = windowResized; windowResized = false; diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DesktopClientConfigAdapter.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DesktopClientConfigAdapter.java index eae9e86..2edc7f5 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DesktopClientConfigAdapter.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DesktopClientConfigAdapter.java @@ -8,19 +8,27 @@ import org.json.JSONObject; import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion; import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapter; +import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapterHooks; import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayEntry; /** * Copyright (c) 2022 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -31,6 +39,8 @@ public class DesktopClientConfigAdapter implements IClientConfigAdapter { public final List defaultServers = new ArrayList(); + private final DesktopClientConfigAdapterHooks hooks = new DesktopClientConfigAdapterHooks(); + @Override public String getDefaultLocale() { return "en_US"; @@ -128,4 +138,33 @@ public class DesktopClientConfigAdapter implements IClientConfigAdapter { public boolean isAllowVoiceClient() { return false; } + + @Override + public boolean isAllowFNAWSkins() { + return true; + } + + @Override + public String getLocalStorageNamespace() { + return EaglercraftVersion.localStorageNamespace; + } + + @Override + public IClientConfigAdapterHooks getHooks() { + return hooks; + } + + private static class DesktopClientConfigAdapterHooks implements IClientConfigAdapterHooks { + + @Override + public void callLocalStorageSavedHook(String key, String base64) { + + } + + @Override + public String callLocalStorageLoadHook(String key) { + return null; + } + + } } diff --git a/src/main/java/net/hoosiertransfer/Config.java b/src/main/java/net/hoosiertransfer/Config.java index a1beff3..5e0f894 100644 --- a/src/main/java/net/hoosiertransfer/Config.java +++ b/src/main/java/net/hoosiertransfer/Config.java @@ -15,16 +15,12 @@ public class Config { public static int tracingDistance = 128; public static Set blockEntityWhitelist = new HashSet<>(Arrays.asList("minecraft:beacon")); public static int SleepDuration = 10; - public static int hitboxLimit = 50; + public static int hitboxLimit = 50; public static boolean disableAlpha() { return Minecraft.getMinecraft().gameSettings.disableAlpha && !Minecraft.getMinecraft().gameSettings.shaders; } - public static boolean skipRenderUpdate() { - return Minecraft.getMinecraft().gameSettings.skipHandRender && !Minecraft.getMinecraft().gameSettings.shaders; - } - public static boolean audioEnabled() { return Minecraft.getMinecraft().gameSettings.enableSound; } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java index d7baaca..11b73cd 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java @@ -57,6 +57,10 @@ public class Display { PlatformInput.setVSync(enable); } + public static boolean isVSyncSupported() { + return PlatformInput.isVSyncSupported(); + } + public static void update() { PlatformInput.update(); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java index 6c72cc3..663d3b6 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java @@ -9,8 +9,8 @@ public class EaglercraftVersion { /// Customize these to fit your fork: public static final String projectForkName = "Eaglercraft Lambda"; - public static final String projectForkVersion = "0.3.1"; - public static final String projectForkVendor = "hoosiertransfer"; + public static final String projectForkVersion = "0.3.5"; + public static final String projectForkVendor = "HoosierTransfer"; public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; @@ -18,8 +18,8 @@ public class EaglercraftVersion { public static final String projectOriginName = "EaglercraftX"; public static final String projectOriginAuthor = "lax1dude"; - public static final String projectOriginRevision = "1.9"; - public static final String projectOriginVersion = "u29"; + public static final String projectOriginRevision = "1.9.4"; + public static final String projectOriginVersion = "u30"; public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace @@ -28,7 +28,7 @@ public class EaglercraftVersion { public static final boolean enableUpdateService = false; public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client"; - public static final int updateBundlePackageVersionInt = 29; + public static final int updateBundlePackageVersionInt = 30; public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName; @@ -38,7 +38,7 @@ public class EaglercraftVersion { // Miscellaneous variables: - public static final String mainMenuStringA = "Minecraft 1.8.8"; + public static final String mainMenuStringA = "Minecraft 1.9.4"; public static final String mainMenuStringB = projectOriginName + " " + projectOriginRevision + "-" + projectOriginVersion + " ultimate"; public static final String mainMenuStringC = ""; @@ -56,4 +56,6 @@ public class EaglercraftVersion { public static final boolean forceDemoMode = false; + public static final String localStorageNamespace = "_eaglercraftX"; + } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapter.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapter.java index 684275c..8af37d5 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapter.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapter.java @@ -8,14 +8,21 @@ import org.json.JSONObject; /** * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -69,4 +76,10 @@ public interface IClientConfigAdapter { boolean isEnableSignatureBadge(); boolean isAllowVoiceClient(); + + boolean isAllowFNAWSkins(); + + String getLocalStorageNamespace(); + + IClientConfigAdapterHooks getHooks(); } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRelaysArray.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapterHooks.java similarity index 61% rename from src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRelaysArray.java rename to src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapterHooks.java index c120824..9cedf14 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRelaysArray.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapterHooks.java @@ -1,30 +1,31 @@ -package net.lax1dude.eaglercraft.v1_8.internal.teavm.opts; - -import org.teavm.jso.JSIndexer; -import org.teavm.jso.JSObject; -import org.teavm.jso.JSProperty; +package net.lax1dude.eaglercraft.v1_8.internal; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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 JSEaglercraftXOptsRelaysArray extends JSObject { +public interface IClientConfigAdapterHooks { - @JSIndexer - JSEaglercraftXOptsRelay get(int idx); + void callLocalStorageSavedHook(String key, String base64); - @JSProperty - int getLength(); + String callLocalStorageLoadHook(String key); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BlockVertexIDs.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BlockVertexIDs.java index fd41992..49f1428 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BlockVertexIDs.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BlockVertexIDs.java @@ -13,11 +13,34 @@ import net.minecraft.client.resources.IResourceManager; import net.minecraft.client.resources.IResourceManagerReloadListener; import net.minecraft.util.ResourceLocation; +/** + * Copyright (c) 2023 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 BlockVertexIDs implements IResourceManagerReloadListener { private static final Logger logger = LogManager.getLogger("BlockVertexIDsCSV"); - public static final Map modelToID = new HashMap(); + public static final Map modelToID = new HashMap(); public static int builtin_water_still_vertex_id = 0; public static int builtin_water_flow_vertex_id = 0; @@ -31,41 +54,41 @@ public class BlockVertexIDs implements IResourceManagerReloadListener { modelToID.clear(); String line; boolean firstLine = true; - while((line = reader.readLine()) != null) { - if((line = line.trim()).length() > 0) { - if(firstLine) { + while ((line = reader.readLine()) != null) { + if ((line = line.trim()).length() > 0) { + if (firstLine) { firstLine = false; continue; } String[] split = line.split(","); - if(split.length == 2) { + if (split.length == 2) { try { int i = Integer.parseInt(split[1]); - if(i <= 0 || i > 254) { + if (i <= 0 || i > 254) { logger.error("Error: {}: Only IDs 1 to 254 are configurable!", split[0]); throw new NumberFormatException(); } i -= 127; modelToID.put(split[0], i); - switch(split[0]) { - case "eagler:builtin/water_still_vertex_id": - builtin_water_still_vertex_id = i; - break; - case "eagler:builtin/water_flow_vertex_id": - builtin_water_flow_vertex_id = i; - break; - default: - break; + switch (split[0]) { + case "eagler:builtin/water_still_vertex_id": + builtin_water_still_vertex_id = i; + break; + case "eagler:builtin/water_flow_vertex_id": + builtin_water_flow_vertex_id = i; + break; + default: + break; } continue; - }catch(NumberFormatException ex) { + } catch (NumberFormatException ex) { } } logger.error("Skipping bad vertex id entry: {}", line); } } } - }catch(Throwable t) { + } catch (Throwable t) { logger.error("Could not load list of vertex ids!"); logger.error(t); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/EaglerSkinTexture.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/EaglerSkinTexture.java index 59d1f73..56e5b94 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/EaglerSkinTexture.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/EaglerSkinTexture.java @@ -72,7 +72,8 @@ public class EaglerSkinTexture implements ITextureObject { } System.arraycopy(pixels, 0, this.pixels, 0, pixels.length); if (textureId != -1) { - TextureUtil.uploadTextureImageAllocate(textureId, new ImageData(width, height, pixels, true), false, false); + TextureUtil.uploadTextureImageSub(textureId, new ImageData(width, height, pixels, true), 0, 0, false, + false); } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditProfile.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditProfile.java index eecea58..2598187 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditProfile.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditProfile.java @@ -20,8 +20,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; import java.io.IOException; /** - * Copyright (c) 2022-2023 lax1dude, hoosiertransfer, ayunami2000. All Rights - * Reserved. + * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND @@ -83,14 +82,20 @@ public class GuiScreenEditProfile extends GuiScreen { } private void updateOptions() { + DefaultSkins[] arr = DefaultSkins.defaultSkinsMap; + if (!EagRuntime.getConfiguration().isAllowFNAWSkins()) { + DefaultSkins[] arrNoFNAW = new DefaultSkins[arr.length - 5]; + System.arraycopy(arr, 0, arrNoFNAW, 0, arrNoFNAW.length); + arr = arrNoFNAW; + } int numCustom = EaglerProfile.customSkins.size(); - String[] n = new String[numCustom + DefaultSkins.defaultSkinsMap.length]; + String[] n = new String[numCustom + arr.length]; for (int i = 0; i < numCustom; ++i) { n[i] = EaglerProfile.customSkins.get(i).name; } - int numDefault = DefaultSkins.defaultSkinsMap.length; + int numDefault = arr.length; for (int j = 0; j < numDefault; ++j) { - n[numCustom + j] = DefaultSkins.defaultSkinsMap[j].name; + n[numCustom + j] = arr[j].name; } dropDownOptions = n; } @@ -116,6 +121,10 @@ public class GuiScreenEditProfile extends GuiScreen { GlStateManager.translate(skinX + 2, skinY - 9, 0.0f); GlStateManager.scale(0.75f, 0.75f, 0.75f); + if (selectedSlot > dropDownOptions.length - 1) { + selectedSlot = 0; + } + int numberOfCustomSkins = EaglerProfile.customSkins.size(); int skid = selectedSlot - numberOfCustomSkins; SkinModel selectedSkinModel = skid < 0 ? EaglerProfile.customSkins.get(selectedSlot).model diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportExportProfile.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportExportProfile.java index e709d2d..8a87082 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportExportProfile.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportExportProfile.java @@ -12,14 +12,21 @@ 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 + * 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) + * 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. * @@ -34,35 +41,42 @@ public class GuiScreenImportExportProfile extends GuiScreen { } public void initGui() { - this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 40, I18n.format("settingsBackup.importExport.import"))); - this.buttonList.add(new GuiButton(2, this.width / 2 - 100, this.height / 4 + 65, I18n.format("settingsBackup.importExport.export"))); + this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 40, + I18n.format("settingsBackup.importExport.import"))); + this.buttonList.add(new GuiButton(2, this.width / 2 - 100, this.height / 4 + 65, + I18n.format("settingsBackup.importExport.export"))); this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 130, I18n.format("gui.cancel"))); } protected void actionPerformed(GuiButton par1GuiButton) { - if(par1GuiButton.id == 0) { + if (par1GuiButton.id == 0) { mc.displayGuiScreen(back); - }else if(par1GuiButton.id == 1) { + } else if (par1GuiButton.id == 1) { waitingForFile = true; EagRuntime.displayFileChooser(null, "epk"); - }else if(par1GuiButton.id == 2) { + } else if (par1GuiButton.id == 2) { mc.displayGuiScreen(new GuiScreenExportProfile(back)); } } public void updateScreen() { - if(waitingForFile && EagRuntime.fileChooserHasResult()) { + if (waitingForFile && EagRuntime.fileChooserHasResult()) { waitingForFile = false; FileChooserResult result = EagRuntime.getFileChooserResult(); - if(result != null) { + if (result != null) { mc.loadingScreen.eaglerShow(I18n.format("settingsBackup.importing.1"), "settingsBackup.importing.2"); + ProfileImporter importer = new ProfileImporter(result.fileData); try { - ProfileImporter importer = new ProfileImporter(result.fileData); importer.readHeader(); mc.displayGuiScreen(new GuiScreenImportProfile(importer, back)); - }catch(IOException ex) { + } catch (IOException ex) { + try { + importer.close(); + } catch (IOException e) { + } EagRuntime.debugPrintStackTrace(ex); - mc.displayGuiScreen(new GuiScreenGenericErrorMessage("settingsBackup.importing.failed.1", "settingsBackup.importing.failed.2", back)); + mc.displayGuiScreen(new GuiScreenGenericErrorMessage("settingsBackup.importing.failed.1", + "settingsBackup.importing.failed.2", back)); } } } @@ -70,9 +84,10 @@ public class GuiScreenImportExportProfile extends GuiScreen { public void drawScreen(int par1, int par2, float par3) { this.drawDefaultBackground(); - - this.drawCenteredString(this.fontRendererObj, I18n.format("settingsBackup.importExport.title"), this.width / 2, this.height / 4, 16777215); - + + this.drawCenteredString(this.fontRendererObj, I18n.format("settingsBackup.importExport.title"), this.width / 2, + this.height / 4, 16777215); + super.drawScreen(par1, par2, par3); } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportProfile.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportProfile.java index 7eecc81..e0a0a31 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportProfile.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportProfile.java @@ -14,14 +14,21 @@ 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 + * 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) + * 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. * @@ -50,30 +57,50 @@ public class GuiScreenImportProfile extends GuiScreen { } public void initGui() { - this.buttonList.add(importProfile = new GuiButton(2, this.width / 2 - 100, this.height / 4, I18n.format("settingsBackup.import.option.profile") + " " + I18n.format(doImportProfile ? "gui.yes" : "gui.no"))); + this.buttonList.add(importProfile = new GuiButton(2, this.width / 2 - 100, this.height / 4, + I18n.format("settingsBackup.import.option.profile") + " " + + I18n.format(doImportProfile ? "gui.yes" : "gui.no"))); importProfile.enabled = importer.hasProfile(); - this.buttonList.add(importSettings = new GuiButton(3, this.width / 2 - 100, this.height / 4 + 25, I18n.format("settingsBackup.import.option.settings") + " " + I18n.format(doImportSettings ? "gui.yes" : "gui.no"))); + this.buttonList.add(importSettings = new GuiButton(3, this.width / 2 - 100, this.height / 4 + 25, + I18n.format("settingsBackup.import.option.settings") + " " + + I18n.format(doImportSettings ? "gui.yes" : "gui.no"))); importSettings.enabled = importer.hasProfile(); - this.buttonList.add(importServers = new GuiButton(4, this.width / 2 - 100, this.height / 4 + 50, I18n.format("settingsBackup.import.option.servers") + " " + I18n.format(doImportServers ? "gui.yes" : "gui.no"))); + this.buttonList.add(importServers = new GuiButton(4, this.width / 2 - 100, this.height / 4 + 50, + I18n.format("settingsBackup.import.option.servers") + " " + + I18n.format(doImportServers ? "gui.yes" : "gui.no"))); importServers.enabled = importer.hasServers(); - this.buttonList.add(importResourcePacks = new GuiButton(5, this.width / 2 - 100, this.height / 4 + 75, I18n.format("settingsBackup.import.option.resourcePacks") + " " + I18n.format(doImportResourcePacks ? "gui.yes" : "gui.no"))); + this.buttonList.add(importResourcePacks = new GuiButton(5, this.width / 2 - 100, this.height / 4 + 75, + I18n.format("settingsBackup.import.option.resourcePacks") + " " + + I18n.format(doImportResourcePacks ? "gui.yes" : "gui.no"))); importResourcePacks.enabled = importer.hasResourcePacks() && EaglerFolderResourcePack.isSupported(); - this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 115, I18n.format("settingsBackup.import.option.import"))); + this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 115, + I18n.format("settingsBackup.import.option.import"))); this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 140, I18n.format("gui.cancel"))); } + @Override + public void onGuiClosed() { + try { + importer.close(); + } catch (IOException e) { + } + } + protected void actionPerformed(GuiButton par1GuiButton) { - if(par1GuiButton.id == 0) { - if(!doImportProfile && !doImportSettings && !doImportServers && !doImportResourcePacks) { + if (par1GuiButton.id == 0) { + if (!doImportProfile && !doImportSettings && !doImportServers && !doImportResourcePacks) { mc.displayGuiScreen(back); - }else { - mc.loadingScreen.eaglerShow(I18n.format("settingsBackup.importing.1"), I18n.format("settingsBackup.importing.2")); + } else { + mc.loadingScreen.eaglerShow(I18n.format("settingsBackup.importing.1"), + I18n.format("settingsBackup.importing.2")); try { - List list1 = new ArrayList(mc.gameSettings.resourcePacks); + List list1 = new ArrayList(mc.gameSettings.resourcePacks); List list2 = new ArrayList(mc.gameSettings.field_183018_l); - importer.importProfileAndSettings(doImportProfile, doImportSettings, doImportServers, doImportResourcePacks); - boolean resourcePacksChanged = !mc.gameSettings.resourcePacks.equals(list1) || !mc.gameSettings.field_183018_l.equals(list2); - if(resourcePacksChanged || (doImportResourcePacks && (list1.size() > 0 || list2.size() > 0))) { + importer.importProfileAndSettings(doImportProfile, doImportSettings, doImportServers, + doImportResourcePacks); + boolean resourcePacksChanged = !mc.gameSettings.resourcePacks.equals(list1) + || !mc.gameSettings.field_183018_l.equals(list2); + if (resourcePacksChanged || (doImportResourcePacks && (list1.size() > 0 || list2.size() > 0))) { mc.loadingScreen.eaglerShow(I18n.format("resourcePack.load.refreshing"), I18n.format("resourcePack.load.pleaseWait")); mc.getResourcePackRepository().reconstruct(mc.gameSettings); @@ -82,29 +109,35 @@ public class GuiScreenImportProfile extends GuiScreen { mc.displayGuiScreen(back); } catch (IOException e) { EagRuntime.debugPrintStackTrace(e); - mc.displayGuiScreen(new GuiScreenGenericErrorMessage("settingsBackup.importing.failed.1", "settingsBackup.importing.failed.2", back)); + mc.displayGuiScreen(new GuiScreenGenericErrorMessage("settingsBackup.importing.failed.1", + "settingsBackup.importing.failed.2", back)); } } - }else if(par1GuiButton.id == 1) { + } else if (par1GuiButton.id == 1) { mc.displayGuiScreen(back); - }else if(par1GuiButton.id == 2) { + } else if (par1GuiButton.id == 2) { doImportProfile = !doImportProfile; - importProfile.displayString = I18n.format("settingsBackup.import.option.profile") + " " + I18n.format(doImportProfile ? "gui.yes" : "gui.no"); - }else if(par1GuiButton.id == 3) { + importProfile.displayString = I18n.format("settingsBackup.import.option.profile") + " " + + I18n.format(doImportProfile ? "gui.yes" : "gui.no"); + } else if (par1GuiButton.id == 3) { doImportSettings = !doImportSettings; - importSettings.displayString = I18n.format("settingsBackup.import.option.settings") + " " + I18n.format(doImportSettings ? "gui.yes" : "gui.no"); - }else if(par1GuiButton.id == 4) { + importSettings.displayString = I18n.format("settingsBackup.import.option.settings") + " " + + I18n.format(doImportSettings ? "gui.yes" : "gui.no"); + } else if (par1GuiButton.id == 4) { doImportServers = !doImportServers; - importServers.displayString = I18n.format("settingsBackup.import.option.servers") + " " + I18n.format(doImportServers ? "gui.yes" : "gui.no"); - }else if(par1GuiButton.id == 5) { + importServers.displayString = I18n.format("settingsBackup.import.option.servers") + " " + + I18n.format(doImportServers ? "gui.yes" : "gui.no"); + } else if (par1GuiButton.id == 5) { doImportResourcePacks = !doImportResourcePacks; - importResourcePacks.displayString = I18n.format("settingsBackup.import.option.resourcePacks") + " " + I18n.format(doImportResourcePacks ? "gui.yes" : "gui.no"); + importResourcePacks.displayString = I18n.format("settingsBackup.import.option.resourcePacks") + " " + + I18n.format(doImportResourcePacks ? "gui.yes" : "gui.no"); } } public void drawScreen(int par1, int par2, float par3) { this.drawDefaultBackground(); - this.drawCenteredString(this.fontRendererObj, I18n.format("settingsBackup.import.title"), this.width / 2, this.height / 4 - 25, 16777215); + this.drawCenteredString(this.fontRendererObj, I18n.format("settingsBackup.import.title"), this.width / 2, + this.height / 4 - 25, 16777215); super.drawScreen(par1, par2, par3); } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileExporter.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileExporter.java index c309239..a56b0db 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileExporter.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileExporter.java @@ -26,14 +26,21 @@ import static net.lax1dude.eaglercraft.v1_8.sp.server.export.EPKCompiler.*; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -46,14 +53,16 @@ public class ProfileExporter { boolean doExportServers, boolean doExportResourcePacks) throws IOException { doExportResourcePacks &= EaglerFolderResourcePack.isSupported(); EaglerOutputStream osb = new EaglerOutputStream(); - osb.write(new byte[]{(byte)69,(byte)65,(byte)71,(byte)80,(byte)75,(byte)71,(byte)36,(byte)36}); // EAGPKG$$ - osb.write(new byte[]{(byte)6,(byte)118,(byte)101,(byte)114,(byte)50,(byte)46,(byte)48}); // 6 + ver2.0 + osb.write( + new byte[] { (byte) 69, (byte) 65, (byte) 71, (byte) 80, (byte) 75, (byte) 71, (byte) 36, (byte) 36 }); // EAGPKG$$ + osb.write(new byte[] { (byte) 6, (byte) 118, (byte) 101, (byte) 114, (byte) 50, (byte) 46, (byte) 48 }); // 6 + + // ver2.0 Date d = new Date(); - + byte[] filename = "profile.epk".getBytes(StandardCharsets.UTF_8); osb.write(filename.length); osb.write(filename); - + byte[] comment = ("\n\n # Eaglercraft profile backup - \"" + EaglerProfile.getName() + "\"" + "\n # Contains: " + (doExportProfile ? "profile " : "") + (doExportSettings ? "settings " : "") + (doExportServers ? "servers " : "") + (doExportResourcePacks ? "resourcePacks" : "") + "\n\n") @@ -62,116 +71,123 @@ public class ProfileExporter { osb.write((comment.length >> 8) & 255); osb.write(comment.length & 255); osb.write(comment); - + writeLong(d.getTime(), osb); - + int lengthIntegerOffset = osb.size(); - osb.write(new byte[]{(byte)255,(byte)255,(byte)255,(byte)255}); // this will be replaced with the file count - + osb.write(new byte[] { (byte) 255, (byte) 255, (byte) 255, (byte) 255 }); // this will be replaced with the file + // count + osb.write('G'); - OutputStream os = EaglerZLIB.newGZIPOutputStream(osb); - - os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD - os.write(new byte[]{(byte)9,(byte)102,(byte)105,(byte)108,(byte)101,(byte)45,(byte)116,(byte)121, - (byte)112,(byte)101}); // 9 + file-type - os.write(new byte[]{(byte)0,(byte)0,(byte)0,(byte)14,(byte)101,(byte)112,(byte)107,(byte)47,(byte)112,(byte)114,(byte)111, - (byte)102,(byte)105,(byte)108,(byte)101,(byte)49,(byte)56,(byte)56}); // 14 + epk/profile188 - os.write('>'); - - os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD - os.write(new byte[]{(byte)12,(byte)102,(byte)105,(byte)108,(byte)101,(byte)45,(byte)101,(byte)120, - (byte)112,(byte)111,(byte)114,(byte)116,(byte)115,(byte)0,(byte)0,(byte)0,(byte)1}); // 12 + file-exports + 1 - os.write((doExportProfile ? 1 : 0) | (doExportSettings ? 2 : 0) | (doExportServers ? 4 : 0) | (doExportResourcePacks ? 8 : 0)); - os.write('>'); - int fileCount = 2; - - if(doExportProfile) { - byte[] profileData = EaglerProfile.write(); - if(profileData == null) { - throw new IOException("Could not write profile data!"); - } - exportFileToEPK("_eaglercraftX.p", profileData, os); - ++fileCount; - } - - if(doExportSettings) { - logger.info("Exporting game settings..."); - byte[] gameSettings = Minecraft.getMinecraft().gameSettings.writeOptions(); - if(gameSettings == null) { - throw new IOException("Could not write game settings!"); - } - exportFileToEPK("_eaglercraftX.g", gameSettings, os); - ++fileCount; - logger.info("Exporting relay settings..."); - byte[] relays = RelayManager.relayManager.write(); - if(relays == null) { - throw new IOException("Could not write relay settings!"); - } - exportFileToEPK("_eaglercraftX.r", relays, os); - ++fileCount; - } - - if(doExportServers) { - logger.info("Exporting server list..."); - byte[] servers = ServerList.getServerList().writeServerList(); - if(servers == null) { - throw new IOException("Could not write server list!"); - } - exportFileToEPK("_eaglercraftX.s", servers, os); - ++fileCount; - } - - logger.info("Exporting certificates..."); - UpdateCertificate cert = UpdateService.getClientCertificate(); - if(cert != null) { - exportFileToEPK("certs/main.cert", cert.rawCertData, os); - ++fileCount; - } - Collection updatesExport = UpdateService.getAvailableUpdates(); - int cc = 0; - for(UpdateCertificate cert2 : updatesExport) { - exportFileToEPK("certs/c" + (cc++) + ".cert", cert2.rawCertData, os); - ++fileCount; - } - - if(doExportResourcePacks) { - logger.info("Exporting resource packs..."); - byte[] packManifest = (new VFile2(EaglerFolderResourcePack.RESOURCE_PACKS + "/manifest.json")).getAllBytes(); - if(packManifest != null) { - exportFileToEPK(EaglerFolderResourcePack.RESOURCE_PACKS + "/manifest.json", packManifest, os); + try (OutputStream os = EaglerZLIB.newGZIPOutputStream(osb)) { + os.write(new byte[] { (byte) 72, (byte) 69, (byte) 65, (byte) 68 }); // HEAD + os.write(new byte[] { (byte) 9, (byte) 102, (byte) 105, (byte) 108, (byte) 101, (byte) 45, (byte) 116, + (byte) 121, + (byte) 112, (byte) 101 }); // 9 + file-type + os.write(new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 14, (byte) 101, (byte) 112, (byte) 107, + (byte) 47, (byte) 112, (byte) 114, (byte) 111, + (byte) 102, (byte) 105, (byte) 108, (byte) 101, (byte) 49, (byte) 56, (byte) 56 }); // 14 + + // epk/profile188 + os.write('>'); + + os.write(new byte[] { (byte) 72, (byte) 69, (byte) 65, (byte) 68 }); // HEAD + os.write(new byte[] { (byte) 12, (byte) 102, (byte) 105, (byte) 108, (byte) 101, (byte) 45, (byte) 101, + (byte) 120, + (byte) 112, (byte) 111, (byte) 114, (byte) 116, (byte) 115, (byte) 0, (byte) 0, (byte) 0, + (byte) 1 }); // 12 + file-exports + 1 + os.write((doExportProfile ? 1 : 0) | (doExportSettings ? 2 : 0) | (doExportServers ? 4 : 0) + | (doExportResourcePacks ? 8 : 0)); + os.write('>'); + + if (doExportProfile) { + byte[] profileData = EaglerProfile.write(); + if (profileData == null) { + throw new IOException("Could not write profile data!"); + } + exportFileToEPK("_eaglercraftX.p", profileData, os); ++fileCount; - VFile2 baseDir = new VFile2(EaglerFolderResourcePack.RESOURCE_PACKS); - List files = baseDir.listFiles(true); - logger.info("({} files to export)", files.size()); - for(int i = 0, l = files.size(); i < l; ++i) { - VFile2 f = files.get(i); - if(f.getPath().equals(EaglerFolderResourcePack.RESOURCE_PACKS + "/manifest.json")) { - continue; - } - exportFileToEPK(f.getPath(), f.getAllBytes(), os); + } + + if (doExportSettings) { + logger.info("Exporting game settings..."); + byte[] gameSettings = Minecraft.getMinecraft().gameSettings.writeOptions(); + if (gameSettings == null) { + throw new IOException("Could not write game settings!"); + } + exportFileToEPK("_eaglercraftX.g", gameSettings, os); + ++fileCount; + logger.info("Exporting relay settings..."); + byte[] relays = RelayManager.relayManager.write(); + if (relays == null) { + throw new IOException("Could not write relay settings!"); + } + exportFileToEPK("_eaglercraftX.r", relays, os); + ++fileCount; + } + + if (doExportServers) { + logger.info("Exporting server list..."); + byte[] servers = ServerList.getServerList().writeServerList(); + if (servers == null) { + throw new IOException("Could not write server list!"); + } + exportFileToEPK("_eaglercraftX.s", servers, os); + ++fileCount; + } + + logger.info("Exporting certificates..."); + UpdateCertificate cert = UpdateService.getClientCertificate(); + if (cert != null) { + exportFileToEPK("certs/main.cert", cert.rawCertData, os); + ++fileCount; + } + Collection updatesExport = UpdateService.getAvailableUpdates(); + int cc = 0; + for (UpdateCertificate cert2 : updatesExport) { + exportFileToEPK("certs/c" + (cc++) + ".cert", cert2.rawCertData, os); + ++fileCount; + } + + if (doExportResourcePacks) { + logger.info("Exporting resource packs..."); + byte[] packManifest = (new VFile2(EaglerFolderResourcePack.RESOURCE_PACKS + "/manifest.json")) + .getAllBytes(); + if (packManifest != null) { + exportFileToEPK(EaglerFolderResourcePack.RESOURCE_PACKS + "/manifest.json", packManifest, os); ++fileCount; - if(i > 0 && i % 100 == 0) { - logger.info("Exported {} files", i); + VFile2 baseDir = new VFile2(EaglerFolderResourcePack.RESOURCE_PACKS); + List files = baseDir.listFiles(true); + logger.info("({} files to export)", files.size()); + for (int i = 0, l = files.size(); i < l; ++i) { + VFile2 f = files.get(i); + if (f.getPath().equals(EaglerFolderResourcePack.RESOURCE_PACKS + "/manifest.json")) { + continue; + } + exportFileToEPK(f.getPath(), f.getAllBytes(), os); + ++fileCount; + if (i > 0 && i % 100 == 0) { + logger.info("Exported {} files", i); + } } } } + + os.write(new byte[] { (byte) 69, (byte) 78, (byte) 68, (byte) 36 }); // END$ } - - os.write(new byte[]{(byte)69,(byte)78,(byte)68,(byte)36}); // END$ - os.close(); - - osb.write(new byte[]{(byte)58,(byte)58,(byte)58,(byte)89,(byte)69,(byte)69,(byte)58,(byte)62}); // :::YEE:> - + + osb.write( + new byte[] { (byte) 58, (byte) 58, (byte) 58, (byte) 89, (byte) 69, (byte) 69, (byte) 58, (byte) 62 }); // :::YEE:> + byte[] ret = osb.toByteArray(); - ret[lengthIntegerOffset] = (byte)((fileCount >> 24) & 0xFF); - ret[lengthIntegerOffset + 1] = (byte)((fileCount >> 16) & 0xFF); - ret[lengthIntegerOffset + 2] = (byte)((fileCount >> 8) & 0xFF); - ret[lengthIntegerOffset + 3] = (byte)(fileCount & 0xFF); - + ret[lengthIntegerOffset] = (byte) ((fileCount >> 24) & 0xFF); + ret[lengthIntegerOffset + 1] = (byte) ((fileCount >> 16) & 0xFF); + ret[lengthIntegerOffset + 2] = (byte) ((fileCount >> 8) & 0xFF); + ret[lengthIntegerOffset + 3] = (byte) (fileCount & 0xFF); + logger.info("Export complete!"); - + EagRuntime.downloadFileWithName(EaglerProfile.getName() + "-backup.epk", ret); } @@ -179,15 +195,15 @@ public class ProfileExporter { CRC32 checkSum = new CRC32(); checkSum.update(contents); long sum = checkSum.getValue(); - - os.write(new byte[]{(byte)70,(byte)73,(byte)76,(byte)69}); // FILE - + + os.write(new byte[] { (byte) 70, (byte) 73, (byte) 76, (byte) 69 }); // FILE + byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8); os.write(nameBytes.length); os.write(nameBytes); writeInt(contents.length + 5, os); - writeInt((int)sum, os); - + writeInt((int) sum, os); + os.write(contents); os.write(':'); os.write('>'); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileImporter.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileImporter.java index e626b69..99ed4ff 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileImporter.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileImporter.java @@ -1,5 +1,6 @@ package net.lax1dude.eaglercraft.v1_8.profile; +import java.io.Closeable; import java.io.IOException; import net.lax1dude.eaglercraft.v1_8.EagRuntime; @@ -17,19 +18,26 @@ import net.minecraft.client.multiplayer.ServerList; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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 ProfileImporter { +public class ProfileImporter implements Closeable { private static final Logger logger = LogManager.getLogger("ProfileImporter"); @@ -47,13 +55,13 @@ public class ProfileImporter { public void readHeader() throws IOException { logger.info("Reading EPK file header..."); epkDecompiler = new EPKDecompiler(data); - + FileEntry etr = epkDecompiler.readFile(); if (etr == null || !etr.type.equals("HEAD") || !etr.name.equals("file-type") || !EPKDecompiler.readASCII(etr.data).equals("epk/profile188")) { throw new IOException("EPK file is not a profile backup!"); } - + etr = epkDecompiler.readFile(); if (etr == null || !etr.type.equals("HEAD") || !etr.name.equals("file-exports") || etr.data.length != 1) { throw new IOException("EPK file is not a profile backup!"); @@ -91,61 +99,67 @@ public class ProfileImporter { doImportServers &= headerHasServers; doImportResourcePacks &= headerHasResourcePacks && EaglerFolderResourcePack.isSupported(); FileEntry etr; - vigg: while((etr = epkDecompiler.readFile()) != null) { - if(etr.type.equals("FILE")) { - switch(etr.name) { - case "_eaglercraftX.p": - if(doImportProfile) { - logger.info("Importing profile..."); - EaglerProfile.read(etr.data); - EagRuntime.setStorage("p", etr.data); - } - break; - case "_eaglercraftX.g": - if(doImportSettings) { - logger.info("Importing settings..."); - Minecraft.getMinecraft().gameSettings.loadOptions(etr.data); - EagRuntime.setStorage("g", etr.data); - } - break; - case "_eaglercraftX.r": - if(doImportSettings) { - logger.info("Importing relays..."); - RelayManager.relayManager.load(etr.data); - EagRuntime.setStorage("r", etr.data); - } - break; - case "_eaglercraftX.s": - if(doImportServers) { - logger.info("Importing servers..."); - ServerList.getServerList().loadServerList(etr.data); - EagRuntime.setStorage("s", etr.data); - } - break; - default: - if(etr.name.startsWith("certs/")) { - UpdateService.addCertificateToSet(etr.data); - }else if(etr.name.startsWith(EaglerFolderResourcePack.RESOURCE_PACKS + "/")) { - if(doImportResourcePacks) { - logger.info("Deleting old resource packs..."); - (new VFile2(EaglerFolderResourcePack.RESOURCE_PACKS)).listFiles(true).forEach(VFile2::delete); - logger.info("Importing resource packs..."); - int counter = 0; - do { - if(etr.name.startsWith(EaglerFolderResourcePack.RESOURCE_PACKS + "/")) { - (new VFile2(etr.name)).setAllBytes(etr.data); - if(++counter % 100 == 0) { - logger.info("Imported {} files", counter); - } - } - }while((etr = epkDecompiler.readFile()) != null); + vigg: while ((etr = epkDecompiler.readFile()) != null) { + if (etr.type.equals("FILE")) { + switch (etr.name) { + case "_eaglercraftX.p": + if (doImportProfile) { + logger.info("Importing profile..."); + EaglerProfile.read(etr.data); + EagRuntime.setStorage("p", etr.data); } - break vigg; - } - break; + break; + case "_eaglercraftX.g": + if (doImportSettings) { + logger.info("Importing settings..."); + Minecraft.getMinecraft().gameSettings.loadOptions(etr.data); + EagRuntime.setStorage("g", etr.data); + } + break; + case "_eaglercraftX.r": + if (doImportSettings) { + logger.info("Importing relays..."); + RelayManager.relayManager.load(etr.data); + EagRuntime.setStorage("r", etr.data); + } + break; + case "_eaglercraftX.s": + if (doImportServers) { + logger.info("Importing servers..."); + ServerList.getServerList().loadServerList(etr.data); + EagRuntime.setStorage("s", etr.data); + } + break; + default: + if (etr.name.startsWith("certs/")) { + UpdateService.addCertificateToSet(etr.data); + } else if (etr.name.startsWith(EaglerFolderResourcePack.RESOURCE_PACKS + "/")) { + if (doImportResourcePacks) { + logger.info("Deleting old resource packs..."); + (new VFile2(EaglerFolderResourcePack.RESOURCE_PACKS)).listFiles(true) + .forEach(VFile2::delete); + logger.info("Importing resource packs..."); + int counter = 0; + do { + if (etr.name.startsWith(EaglerFolderResourcePack.RESOURCE_PACKS + "/")) { + (new VFile2(etr.name)).setAllBytes(etr.data); + if (++counter % 100 == 0) { + logger.info("Imported {} files", counter); + } + } + } while ((etr = epkDecompiler.readFile()) != null); + } + break vigg; + } + break; } } } logger.info("Import complete!"); } + + @Override + public void close() throws IOException { + epkDecompiler.close(); + } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/RenderHighPoly.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/RenderHighPoly.java index a166472..4445b32 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/RenderHighPoly.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/RenderHighPoly.java @@ -27,14 +27,21 @@ import net.minecraft.util.MathHelper; /** * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -54,40 +61,43 @@ public class RenderHighPoly extends RenderPlayer { if (!abstractclientplayer.isUser() || this.renderManager.livingPlayer == abstractclientplayer) { double nameY = d1; HighPolySkin highPolySkin = abstractclientplayer.getEaglerSkinModel().highPoly; - - if(highPolySkin == null) { + + if (highPolySkin == null) { super.doRender(abstractclientplayer, d0, d1, d2, f, f1); return; - }else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) { + } else if (highPolySkin == HighPolySkin.LAXATIVE_DUDE) { nameY += 0.1; - }else if(highPolySkin == HighPolySkin.BABY_WINSTON) { + } else if (highPolySkin == HighPolySkin.BABY_WINSTON) { nameY -= 1.0; } - + GlStateManager.pushMatrix(); GlStateManager.disableCull(); - + try { Minecraft mc = Minecraft.getMinecraft(); - float f2 = this.interpolateRotation(abstractclientplayer.prevRenderYawOffset, abstractclientplayer.renderYawOffset, + float f2 = this.interpolateRotation(abstractclientplayer.prevRenderYawOffset, + abstractclientplayer.renderYawOffset, f1); - float f3 = this.interpolateRotation(abstractclientplayer.prevRotationYawHead, abstractclientplayer.rotationYawHead, + float f3 = this.interpolateRotation(abstractclientplayer.prevRotationYawHead, + abstractclientplayer.rotationYawHead, f1); float f4 = f3 - f2; if (abstractclientplayer.isRiding() && abstractclientplayer.ridingEntity instanceof EntityLivingBase) { EntityLivingBase entitylivingbase1 = (EntityLivingBase) abstractclientplayer.ridingEntity; - f2 = this.interpolateRotation(entitylivingbase1.prevRenderYawOffset, entitylivingbase1.renderYawOffset, + f2 = this.interpolateRotation(entitylivingbase1.prevRenderYawOffset, + entitylivingbase1.renderYawOffset, f1); f4 = f3 - f2; float f5 = MathHelper.wrapAngleTo180_float(f4); if (f5 < -85.0F) { f5 = -85.0F; } - + if (f5 >= 85.0F) { f5 = 85.0F; } - + f2 = f3 - f5; if (f5 * f5 > 2500.0F) { f2 += f5 * 0.2F; @@ -100,301 +110,326 @@ public class RenderHighPoly extends RenderPlayer { GlStateManager.enableRescaleNormal(); this.preRenderCallback(abstractclientplayer, f1); float f6 = 0.0625F; - GlStateManager.scale(HighPolySkin.highPolyScale, HighPolySkin.highPolyScale, HighPolySkin.highPolyScale); + GlStateManager.scale(HighPolySkin.highPolyScale, HighPolySkin.highPolyScale, + HighPolySkin.highPolyScale); mc.getTextureManager().bindTexture(highPolySkin.texture); - - if(abstractclientplayer.isPlayerSleeping()) { - if(highPolySkin == HighPolySkin.LAXATIVE_DUDE || highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { + + if (abstractclientplayer.isPlayerSleeping()) { + if (highPolySkin == HighPolySkin.LAXATIVE_DUDE || highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { GlStateManager.translate(0.0f, -3.7f, 0.0f); - }else if(highPolySkin == HighPolySkin.BABY_WINSTON) { + } else if (highPolySkin == HighPolySkin.BABY_WINSTON) { GlStateManager.translate(0.0f, -2.4f, 0.0f); - }else { + } else { GlStateManager.translate(0.0f, -3.0f, 0.0f); } } - - float var15 = abstractclientplayer.prevLimbSwingAmount + (abstractclientplayer.limbSwingAmount - abstractclientplayer.prevLimbSwingAmount) * f1; + + float var15 = abstractclientplayer.prevLimbSwingAmount + + (abstractclientplayer.limbSwingAmount - abstractclientplayer.prevLimbSwingAmount) * f1; float var16 = abstractclientplayer.limbSwing - abstractclientplayer.limbSwingAmount * (1.0F - f1); - - if(highPolySkin == HighPolySkin.LONG_ARMS) { + + if (highPolySkin == HighPolySkin.LONG_ARMS) { GlStateManager.rotate(MathHelper.sin(var16) * 20f * var15, 0.0f, 1.0f, 0.0f); GlStateManager.rotate(MathHelper.cos(var16) * 7f * var15, 0.0f, 0.0f, 1.0f); - }else if(highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { + } else if (highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { GlStateManager.rotate(MathHelper.sin(var16) * 7f * var15, 0.0f, 1.0f, 0.0f); GlStateManager.rotate(MathHelper.cos(var16) * 3f * var15, 0.0f, 0.0f, 1.0f); GlStateManager.rotate(-f3, 0.0f, 1.0f, 0.0f); - float xd = (float)(abstractclientplayer.posX - abstractclientplayer.prevPosX); + float xd = (float) (abstractclientplayer.posX - abstractclientplayer.prevPosX); GlStateManager.rotate(xd * 70.0f * var15, 0.0f, 0.0f, 1.0f); - float zd = (float)(abstractclientplayer.posZ - abstractclientplayer.prevPosZ); + float zd = (float) (abstractclientplayer.posZ - abstractclientplayer.prevPosZ); GlStateManager.rotate(zd * 70.0f * var15, 1.0f, 0.0f, 0.0f); GlStateManager.rotate(f3, 0.0f, 1.0f, 0.0f); - }else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) { + } else if (highPolySkin == HighPolySkin.LAXATIVE_DUDE) { GlStateManager.rotate(-f3, 0.0f, 1.0f, 0.0f); - float xd = (float)(abstractclientplayer.posX - abstractclientplayer.prevPosX); + float xd = (float) (abstractclientplayer.posX - abstractclientplayer.prevPosX); GlStateManager.rotate(-xd * 40.0f * var15, 0.0f, 0.0f, 1.0f); - float zd = (float)(abstractclientplayer.posZ - abstractclientplayer.prevPosZ); + float zd = (float) (abstractclientplayer.posZ - abstractclientplayer.prevPosZ); GlStateManager.rotate(-zd * 40.0f * var15, 1.0f, 0.0f, 0.0f); GlStateManager.rotate(f3, 0.0f, 1.0f, 0.0f); - }else if(highPolySkin == HighPolySkin.BABY_WINSTON) { + } else if (highPolySkin == HighPolySkin.BABY_WINSTON) { GlStateManager.translate(0.0f, (MathHelper.cos(f10 % 100000.0f) + 1.0f) * var15 * 0.2f, 0.0f); GlStateManager.rotate(MathHelper.sin(var16) * 5f * var15, 0.0f, 1.0f, 0.0f); GlStateManager.rotate(MathHelper.cos(var16) * 5f * var15, 0.0f, 0.0f, 1.0f); } - + if (abstractclientplayer.hurtTime > 0 || abstractclientplayer.deathTime > 0) { GlStateManager.color(1.2f, 0.8F, 0.8F, 1.0F); } - - if(DeferredStateManager.isInDeferredPass()) { + + if (DeferredStateManager.isInDeferredPass()) { DeferredStateManager.setDefaultMaterialConstants(); DeferredStateManager.setRoughnessConstant(0.5f); DeferredStateManager.setMetalnessConstant(0.05f); } - - if(highPolySkin.bodyModel != null) { + + if (highPolySkin.bodyModel != null) { EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.bodyModel)); } float jumpFactor = 0.0f; - - if(highPolySkin.headModel != null) { - if(highPolySkin == HighPolySkin.BABY_CHARLES) { + + if (highPolySkin.headModel != null) { + if (highPolySkin == HighPolySkin.BABY_CHARLES) { long millis = System.currentTimeMillis(); - float partialTicks = (float) ((millis - abstractclientplayer.eaglerHighPolyAnimationTick) * 0.02); - //long l50 = millis / 50l * 50l; - //boolean runTick = par1EntityPlayer.eaglerHighPolyAnimationTick < l50 && millis >= l50; + float partialTicks = (float) ((millis - abstractclientplayer.eaglerHighPolyAnimationTick) + * 0.02); + // long l50 = millis / 50l * 50l; + // boolean runTick = par1EntityPlayer.eaglerHighPolyAnimationTick < l50 && + // millis >= l50; abstractclientplayer.eaglerHighPolyAnimationTick = millis; - - if(partialTicks < 0.0f) { + + if (partialTicks < 0.0f) { partialTicks = 0.0f; } - if(partialTicks > 1.0f) { + if (partialTicks > 1.0f) { partialTicks = 1.0f; } - - float jumpFac = (float)(abstractclientplayer.posY - abstractclientplayer.prevPosY); - if(jumpFac < 0.0f && !abstractclientplayer.isCollidedVertically) { + + float jumpFac = (float) (abstractclientplayer.posY - abstractclientplayer.prevPosY); + if (jumpFac < 0.0f && !abstractclientplayer.isCollidedVertically) { jumpFac = -jumpFac; jumpFac *= 0.1f; } jumpFac -= 0.05f; - if(jumpFac > 0.1f && !abstractclientplayer.isCollidedVertically) { + if (jumpFac > 0.1f && !abstractclientplayer.isCollidedVertically) { jumpFac = 0.1f; - }else if(jumpFac < 0.0f) { + } else if (jumpFac < 0.0f) { jumpFac = 0.0f; - }else if(jumpFac > 0.1f && abstractclientplayer.isCollidedVertically) { + } else if (jumpFac > 0.1f && abstractclientplayer.isCollidedVertically) { jumpFac = 0.1f; - }else if(jumpFac > 0.4f) { + } else if (jumpFac > 0.4f) { jumpFac = 0.4f; } jumpFac *= 10.0f; - - abstractclientplayer.eaglerHighPolyAnimationFloat3 += (jumpFac / (jumpFac + 1.0f)) * 6.0f * partialTicks; - - if(Float.isInfinite(abstractclientplayer.eaglerHighPolyAnimationFloat3)) { + + abstractclientplayer.eaglerHighPolyAnimationFloat3 += (jumpFac / (jumpFac + 1.0f)) * 6.0f + * partialTicks; + + if (Float.isInfinite(abstractclientplayer.eaglerHighPolyAnimationFloat3)) { abstractclientplayer.eaglerHighPolyAnimationFloat3 = 1.0f; - }else if(abstractclientplayer.eaglerHighPolyAnimationFloat3 > 1.0f) { + } else if (abstractclientplayer.eaglerHighPolyAnimationFloat3 > 1.0f) { abstractclientplayer.eaglerHighPolyAnimationFloat3 = 1.0f; - }else if(abstractclientplayer.eaglerHighPolyAnimationFloat3 < -1.0f) { + } else if (abstractclientplayer.eaglerHighPolyAnimationFloat3 < -1.0f) { abstractclientplayer.eaglerHighPolyAnimationFloat3 = -1.0f; } - - abstractclientplayer.eaglerHighPolyAnimationFloat2 += abstractclientplayer.eaglerHighPolyAnimationFloat3 * partialTicks; - + + abstractclientplayer.eaglerHighPolyAnimationFloat2 += abstractclientplayer.eaglerHighPolyAnimationFloat3 + * partialTicks; + abstractclientplayer.eaglerHighPolyAnimationFloat5 += partialTicks; - while(abstractclientplayer.eaglerHighPolyAnimationFloat5 > 0.05f) { + while (abstractclientplayer.eaglerHighPolyAnimationFloat5 > 0.05f) { abstractclientplayer.eaglerHighPolyAnimationFloat5 -= 0.05f; abstractclientplayer.eaglerHighPolyAnimationFloat3 *= 0.99f; abstractclientplayer.eaglerHighPolyAnimationFloat2 *= 0.9f; } - - jumpFactor = abstractclientplayer.eaglerHighPolyAnimationFloat2; //(abstractclientplayer.eaglerHighPolyAnimationFloat1 - abstractclientplayer.eaglerHighPolyAnimationFloat2) * partialTicks + abstractclientplayer.eaglerHighPolyAnimationFloat2; + + jumpFactor = abstractclientplayer.eaglerHighPolyAnimationFloat2; // (abstractclientplayer.eaglerHighPolyAnimationFloat1 + // - + // abstractclientplayer.eaglerHighPolyAnimationFloat2) + // * partialTicks + + // abstractclientplayer.eaglerHighPolyAnimationFloat2; jumpFactor -= 0.12f; - if(jumpFactor < 0.0f) { + if (jumpFactor < 0.0f) { jumpFactor = 0.0f; } jumpFactor = jumpFactor / (jumpFactor + 2.0f); - if(jumpFactor > 1.0f) { + if (jumpFactor > 1.0f) { jumpFactor = 1.0f; } } - if(jumpFactor > 0.0f) { + if (jumpFactor > 0.0f) { GlStateManager.pushMatrix(); GlStateManager.translate(0.0f, jumpFactor * 3.0f, 0.0f); } - + EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.headModel)); - - if(jumpFactor > 0.0f) { + + if (jumpFactor > 0.0f) { GlStateManager.popMatrix(); } } - - if(highPolySkin.limbsModel != null && highPolySkin.limbsModel.length > 0) { - for(int i = 0; i < highPolySkin.limbsModel.length; ++i) { + + if (highPolySkin.limbsModel != null && highPolySkin.limbsModel.length > 0) { + for (int i = 0; i < highPolySkin.limbsModel.length; ++i) { DeferredStateManager.setRoughnessConstant(0.023f); DeferredStateManager.setMetalnessConstant(0.902f); float offset = 0.0f; - if(highPolySkin.limbsOffset != null) { - if(highPolySkin.limbsOffset.length == 1) { + if (highPolySkin.limbsOffset != null) { + if (highPolySkin.limbsOffset.length == 1) { offset = highPolySkin.limbsOffset[0]; - }else { + } else { offset = highPolySkin.limbsOffset[i]; } } - + GlStateManager.pushMatrix(); - - if(offset != 0.0f || highPolySkin.limbsInitialRotation != 0.0f) { - if(offset != 0.0f) { + + if (offset != 0.0f || highPolySkin.limbsInitialRotation != 0.0f) { + if (offset != 0.0f) { GlStateManager.translate(0.0f, offset, 0.0f); } - if(highPolySkin.limbsInitialRotation != 0.0f) { + if (highPolySkin.limbsInitialRotation != 0.0f) { GlStateManager.rotate(highPolySkin.limbsInitialRotation, 1.0f, 0.0f, 0.0f); } } - - if(highPolySkin == HighPolySkin.LONG_ARMS) { - if(abstractclientplayer.isSwingInProgress) { - float var17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f; + + if (highPolySkin == HighPolySkin.LONG_ARMS) { + if (abstractclientplayer.isSwingInProgress) { + float var17 = MathHelper + .cos(-abstractclientplayer.getSwingProgress(f1) * (float) Math.PI * 2.0f - 1.2f) + - 0.362f; var17 *= var17; GlStateManager.rotate(-var17 * 20.0f, 1.0f, 0.0f, 0.0f); } - }else if(highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { - if(abstractclientplayer.isSwingInProgress) { - float var17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f; + } else if (highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { + if (abstractclientplayer.isSwingInProgress) { + float var17 = MathHelper + .cos(-abstractclientplayer.getSwingProgress(f1) * (float) Math.PI * 2.0f - 1.2f) + - 0.362f; var17 *= var17; GlStateManager.rotate(var17 * 60.0f, 1.0f, 0.0f, 0.0f); } GlStateManager.rotate(40.0f * var15, 1.0f, 0.0f, 0.0f); - }else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) { + } else if (highPolySkin == HighPolySkin.LAXATIVE_DUDE) { float fff = (i == 0) ? 1.0f : -1.0f; float swing = (MathHelper.cos(f10 % 100000.0f) * fff + 0.2f) * var15; float swing2 = (MathHelper.cos(f10 % 100000.0f) * fff * 0.5f + 0.0f) * var15; GlStateManager.rotate(swing * 25.0f, 1.0f, 0.0f, 0.0f); - if(abstractclientplayer.isSwingInProgress) { - float var17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f; + if (abstractclientplayer.isSwingInProgress) { + float var17 = MathHelper + .cos(-abstractclientplayer.getSwingProgress(f1) * (float) Math.PI * 2.0f - 1.2f) + - 0.362f; var17 *= var17; GlStateManager.rotate(-var17 * 25.0f, 1.0f, 0.0f, 0.0f); } - + // shear matrix tmpMatrix.setIdentity(); tmpMatrix.m21 = swing2; tmpMatrix.m23 = swing2 * -0.2f; GlStateManager.multMatrix(tmpMatrix); } - - if(i != 0) { + + if (i != 0) { mc.getTextureManager().bindTexture(highPolySkin.texture); if (abstractclientplayer.hurtTime > 0 || abstractclientplayer.deathTime > 0) { GlStateManager.color(1.2f, 0.8F, 0.8F, 1.0F); - }else { + } else { GlStateManager.color(1.0f, 1.0F, 1.0F, 1.0F); } } EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.limbsModel[i])); - - if(i == 0) { + + if (i == 0) { GlStateManager.pushMatrix(); - + GlStateManager.translate(-0.287f, 0.05f, 0.0f); - - if(highPolySkin == HighPolySkin.LONG_ARMS) { + + if (highPolySkin == HighPolySkin.LONG_ARMS) { GlStateManager.translate(1.72f, 2.05f, -0.24f); ItemStack stk = abstractclientplayer.getHeldItem(); - if(stk != null) { + if (stk != null) { Item itm = stk.getItem(); - if(itm != null) { - if(itm == Items.bow) { + if (itm != null) { + if (itm == Items.bow) { GlStateManager.translate(-0.22f, 0.8f, 0.6f); GlStateManager.rotate(-90.0f, 1.0f, 0.0f, 0.0f); - }else if(itm instanceof ItemBlock && !((ItemBlock)itm).getBlock().isNormalCube()) { + } else if (itm instanceof ItemBlock + && !((ItemBlock) itm).getBlock().isNormalCube()) { GlStateManager.translate(0.0f, -0.1f, 0.13f); - }else if(!itm.isFull3D()) { + } else if (!itm.isFull3D()) { GlStateManager.translate(-0.08f, -0.1f, 0.16f); } } } - }else if(highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { + } else if (highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { GlStateManager.translate(-0.029f, 1.2f, -3f); GlStateManager.rotate(-5.0f, 0.0f, 1.0f, 0.0f); float var17 = -1.2f * var15; - if(abstractclientplayer.isSwingInProgress) { - float vvar17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f; + if (abstractclientplayer.isSwingInProgress) { + float vvar17 = MathHelper.cos( + -abstractclientplayer.getSwingProgress(f1) * (float) Math.PI * 2.0f - 1.2f) + - 0.362f; var17 = vvar17 < var17 ? vvar17 : var17; } GlStateManager.translate(-0.02f * var17, 0.42f * var17, var17 * 0.35f); GlStateManager.rotate(var17 * 30.0f, 1.0f, 0.0f, 0.0f); GlStateManager.rotate(110.0f, 1.0f, 0.0f, 0.0f); ItemStack stk = abstractclientplayer.getHeldItem(); - if(stk != null) { + if (stk != null) { Item itm = stk.getItem(); - if(itm != null) { - if(itm == Items.bow) { + if (itm != null) { + if (itm == Items.bow) { GlStateManager.translate(-0.18f, 1.0f, 0.4f); GlStateManager.rotate(-95.0f, 1.0f, 0.0f, 0.0f); - }else if(itm instanceof ItemBlock && !((ItemBlock)itm).getBlock().isNormalCube()) { + } else if (itm instanceof ItemBlock + && !((ItemBlock) itm).getBlock().isNormalCube()) { GlStateManager.translate(0.0f, -0.1f, 0.13f); - }else if(!itm.isFull3D()) { + } else if (!itm.isFull3D()) { GlStateManager.translate(-0.08f, -0.1f, 0.16f); } } } - }else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) { + } else if (highPolySkin == HighPolySkin.LAXATIVE_DUDE) { GlStateManager.translate(1.291f, 2.44f, -2.18f); GlStateManager.rotate(95.0f, 1.0f, 0.0f, 0.0f); ItemStack stk = abstractclientplayer.getHeldItem(); - if(stk != null) { + if (stk != null) { Item itm = stk.getItem(); - if(itm != null) { - if(itm == Items.bow) { + if (itm != null) { + if (itm == Items.bow) { GlStateManager.translate(-0.65f, 1.3f, -0.1f); GlStateManager.rotate(180.0f, 0.0f, 0.0f, 1.0f); GlStateManager.rotate(20.0f, 1.0f, 0.0f, 0.0f); - }else if(itm instanceof ItemBlock && !((ItemBlock)itm).getBlock().isNormalCube()) { + } else if (itm instanceof ItemBlock + && !((ItemBlock) itm).getBlock().isNormalCube()) { GlStateManager.translate(0.0f, -0.35f, 0.4f); - }else if(!itm.isFull3D()) { + } else if (!itm.isFull3D()) { GlStateManager.translate(-0.1f, -0.1f, 0.16f); } } } } - + DeferredStateManager.setDefaultMaterialConstants(); renderHeldItem(abstractclientplayer, f1); GlStateManager.popMatrix(); } - + GlStateManager.popMatrix(); } } - - if(highPolySkin.eyesModel != null && !DeferredStateManager.isEnableShadowRender()) { + + if (highPolySkin.eyesModel != null && !DeferredStateManager.isEnableShadowRender()) { float ff = 0.00416f; int brightness = abstractclientplayer.getBrightnessForRender(0.0f); float blockLight = (brightness % 65536) * ff; float skyLight = (brightness / 65536) * ff; - float sunCurve = (float)((abstractclientplayer.worldObj.getWorldTime() + 4000l) % 24000) / 24000.0f; - sunCurve = MathHelper.clamp_float(9.8f - MathHelper.abs(sunCurve * 5.0f + sunCurve * sunCurve * 45.0f - 14.3f) * 0.7f, 0.0f, 1.0f); + float sunCurve = (float) ((abstractclientplayer.worldObj.getWorldTime() + 4000l) % 24000) + / 24000.0f; + sunCurve = MathHelper.clamp_float( + 9.8f - MathHelper.abs(sunCurve * 5.0f + sunCurve * sunCurve * 45.0f - 14.3f) * 0.7f, 0.0f, + 1.0f); skyLight = skyLight * (sunCurve * 0.85f + 0.15f); blockLight = blockLight * (sunCurve * 0.3f + 0.7f); float eyeBrightness = blockLight; - if(skyLight > eyeBrightness) { + if (skyLight > eyeBrightness) { eyeBrightness = skyLight; } eyeBrightness += blockLight * 0.2f; eyeBrightness = 1.0f - eyeBrightness; eyeBrightness = MathHelper.clamp_float(eyeBrightness * 1.9f - 1.0f, 0.0f, 1.0f); - if(eyeBrightness > 0.1f) { - if(DeferredStateManager.isInDeferredPass()) { + if (eyeBrightness > 0.1f) { + if (DeferredStateManager.isInDeferredPass()) { GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); DeferredStateManager.setDefaultMaterialConstants(); DeferredStateManager.setEmissionConstant(eyeBrightness); - }else { + } else { GlStateManager.enableBlend(); GlStateManager.blendFunc(GL_ONE, GL_ONE); - GlStateManager.color(eyeBrightness * 7.0f, eyeBrightness * 7.0f, eyeBrightness * 7.0f, 1.0f); - if(jumpFactor > 0.0f) { + GlStateManager.color(eyeBrightness * 7.0f, eyeBrightness * 7.0f, eyeBrightness * 7.0f, + 1.0f); + if (jumpFactor > 0.0f) { GlStateManager.pushMatrix(); GlStateManager.translate(0.0f, jumpFactor * 3.0f, 0.0f); } @@ -402,22 +437,22 @@ public class RenderHighPoly extends RenderPlayer { GlStateManager.disableTexture2D(); GlStateManager.disableLighting(); GlStateManager.enableCull(); - + EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.eyesModel)); - + GlStateManager.enableTexture2D(); GlStateManager.enableLighting(); GlStateManager.disableCull(); - if(jumpFactor > 0.0f) { + if (jumpFactor > 0.0f) { GlStateManager.popMatrix(); } GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); - if(!DeferredStateManager.isInDeferredPass()) { + if (!DeferredStateManager.isInDeferredPass()) { GlStateManager.disableBlend(); } } } - }catch(Throwable t) { + } catch (Throwable t) { logger.error("Couldn\'t render entity"); logger.error(t); } @@ -433,11 +468,11 @@ public class RenderHighPoly extends RenderPlayer { } public void renderRightArm(AbstractClientPlayer clientPlayer) { - + } public void renderLeftArm(AbstractClientPlayer clientPlayer) { - + } protected void renderHeldItem(AbstractClientPlayer clientPlayer, float partialTicks) { @@ -468,4 +503,13 @@ public class RenderHighPoly extends RenderPlayer { GlStateManager.popMatrix(); } } + + public void renderLivingAt(AbstractClientPlayer abstractclientplayer, double d0, double d1, double d2) { + if (abstractclientplayer.isEntityAlive() && abstractclientplayer.isPlayerSleeping()) { + super.renderLivingAt(abstractclientplayer, d0 - (double) abstractclientplayer.renderOffsetX, + d1 - (double) abstractclientplayer.renderOffsetY, d2 - (double) abstractclientplayer.renderOffsetZ); + } else { + super.renderLivingAt(abstractclientplayer, d0, d1, d2); + } + } } \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinModel.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinModel.java index 82edd33..e2181f9 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinModel.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinModel.java @@ -54,7 +54,7 @@ public enum SkinModel { private SkinModel(int id, HighPolySkin highPoly) { this.id = id; this.width = 256; - this.height = 128; + this.height = 256; this.profileSkinType = "eagler"; this.sanitize = true; this.highPoly = highPoly; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java index 4ca34d9..28a6d8f 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java @@ -429,11 +429,6 @@ public class ConnectionHandshake { RateLimitTracker.registerLockOut(PlatformNetworking.getCurrentURI()); mc.displayGuiScreen(GuiDisconnected.createRateLimitKick(scr)); } else if (errorCode == HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE) { - if (IChatComponent.Serializer.jsonToComponent(errStr).getUnformattedText().toLowerCase() - .contains("banned from this server")) { - EaglerProfile.updateUsernameCookies(); - reloadPage(); - } if (IChatComponent.Serializer.jsonToComponent(errStr).getUnformattedText().toLowerCase() .contains("reload page")) { EaglerProfile.updateUsernameCookieFromLocalStorage(); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/EaglercraftNetworkManager.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/EaglercraftNetworkManager.java index f07167d..0c28ed2 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/EaglercraftNetworkManager.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/EaglercraftNetworkManager.java @@ -92,10 +92,6 @@ public class EaglercraftNetworkManager { } clientDisconnected = true; System.out.println("Closed channel: " + reason.getUnformattedText()); - if (reason.getUnformattedText().toLowerCase().contains("banned from this server")) { - EaglerProfile.updateUsernameCookies(); - reloadPage(); - } if (reason.getUnformattedText().toLowerCase().contains("reload page")) { EaglerProfile.updateUsernameCookieFromLocalStorage(); reloadPage(); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenNameWorldImport.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenNameWorldImport.java index eded766..2c0a3d4 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenNameWorldImport.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenNameWorldImport.java @@ -13,14 +13,21 @@ import net.minecraft.client.resources.I18n; /** * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -44,7 +51,7 @@ public class GuiScreenNameWorldImport extends GuiScreen { this.importFormat = format; this.world = world; this.name = world.fileName; - if(name.length() > 4 && (name.endsWith(".epk") || name.endsWith(".zip"))) { + if (name.length() > 4 && (name.endsWith(".epk") || name.endsWith(".zip"))) { name = name.substring(0, name.length() - 4); } } @@ -53,13 +60,17 @@ public class GuiScreenNameWorldImport extends GuiScreen { * Called from the main game loop to update the screen. */ public void updateScreen() { - if(!timeToImport) { + if (!timeToImport) { this.theGuiTextField.updateCursorCounter(); } - if(definetlyTimeToImport && !isImporting) { + if (definetlyTimeToImport && !isImporting) { isImporting = true; - SingleplayerServerController.importWorld(GuiCreateWorld.func_146317_a(mc.getSaveLoader(), this.theGuiTextField.getText().trim()), world.fileData, importFormat, (byte) ((loadSpawnChunks ? 2 : 0) | (enhancedGameRules ? 1 : 0))); - mc.displayGuiScreen(new GuiScreenIntegratedServerBusy(parentGuiScreen, "singleplayer.busy.importing." + (importFormat + 1), "singleplayer.failed.importing." + (importFormat + 1), SingleplayerServerController::isReady)); + SingleplayerServerController.importWorld( + GuiCreateWorld.func_146317_a(mc.getSaveLoader(), this.theGuiTextField.getText().trim()), + world.fileData, importFormat, (byte) ((loadSpawnChunks ? 2 : 0) | (enhancedGameRules ? 1 : 0))); + mc.displayGuiScreen(new GuiScreenIntegratedServerBusy(parentGuiScreen, + "singleplayer.busy.importing." + (importFormat + 1), + "singleplayer.failed.importing." + (importFormat + 1), SingleplayerServerController::isReady)); } } @@ -67,16 +78,23 @@ public class GuiScreenNameWorldImport extends GuiScreen { * Adds the buttons (and other controls) to the screen in question. */ public void initGui() { - if(!timeToImport) { + if (!timeToImport) { Keyboard.enableRepeatEvents(true); this.buttonList.clear(); - this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + 12, I18n.format("singleplayer.import.continue"))); - this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 120 + 12, I18n.format("gui.cancel"))); - this.theGuiTextField = new GuiTextField(2, this.fontRendererObj, this.width / 2 - 100, this.height / 4 + 3, 200, 20); + this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + 12, + I18n.format("singleplayer.import.continue"))); + this.buttonList + .add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 120 + 12, I18n.format("gui.cancel"))); + this.theGuiTextField = new GuiTextField(2, this.fontRendererObj, this.width / 2 - 100, this.height / 4 + 3, + 200, 20); this.theGuiTextField.setFocused(true); this.theGuiTextField.setText(name); - this.buttonList.add(loadSpawnChunksBtn = new GuiButton(2, this.width / 2 - 100, this.height / 4 + 24 + 12, I18n.format("singleplayer.import.loadSpawnChunks", loadSpawnChunks ? I18n.format("gui.yes") : I18n.format("gui.no")))); - this.buttonList.add(enhancedGameRulesBtn = new GuiButton(3, this.width / 2 - 100, this.height / 4 + 48 + 12, I18n.format("singleplayer.import.enhancedGameRules", enhancedGameRules ? I18n.format("gui.yes") : I18n.format("gui.no")))); + this.buttonList.add(loadSpawnChunksBtn = new GuiButton(2, this.width / 2 - 100, this.height / 4 + 24 + 12, + I18n.format("singleplayer.import.loadSpawnChunks", + loadSpawnChunks ? I18n.format("gui.yes") : I18n.format("gui.no")))); + this.buttonList.add(enhancedGameRulesBtn = new GuiButton(3, this.width / 2 - 100, this.height / 4 + 48 + 12, + I18n.format("singleplayer.import.enhancedGameRules", + enhancedGameRules ? I18n.format("gui.yes") : I18n.format("gui.no")))); } } @@ -101,10 +119,12 @@ public class GuiScreenNameWorldImport extends GuiScreen { timeToImport = true; } else if (par1GuiButton.id == 2) { loadSpawnChunks = !loadSpawnChunks; - loadSpawnChunksBtn.displayString = I18n.format("singleplayer.import.loadSpawnChunks", loadSpawnChunks ? I18n.format("gui.yes") : I18n.format("gui.no")); + loadSpawnChunksBtn.displayString = I18n.format("singleplayer.import.loadSpawnChunks", + loadSpawnChunks ? I18n.format("gui.yes") : I18n.format("gui.no")); } else if (par1GuiButton.id == 3) { enhancedGameRules = !enhancedGameRules; - enhancedGameRulesBtn.displayString = I18n.format("singleplayer.import.enhancedGameRules", enhancedGameRules ? I18n.format("gui.yes") : I18n.format("gui.no")); + enhancedGameRulesBtn.displayString = I18n.format("singleplayer.import.enhancedGameRules", + enhancedGameRules ? I18n.format("gui.yes") : I18n.format("gui.no")); } } } @@ -127,7 +147,7 @@ public class GuiScreenNameWorldImport extends GuiScreen { */ protected void mouseClicked(int par1, int par2, int par3) { super.mouseClicked(par1, par2, par3); - if(!timeToImport) { + if (!timeToImport) { this.theGuiTextField.mouseClicked(par1, par2, par3); } } @@ -137,16 +157,21 @@ public class GuiScreenNameWorldImport extends GuiScreen { */ public void drawScreen(int par1, int par2, float par3) { this.drawDefaultBackground(); - if(!timeToImport) { - this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.import.title"), this.width / 2, this.height / 4 - 60 + 20, 16777215); - this.drawString(this.fontRendererObj, I18n.format("singleplayer.import.enterName"), this.width / 2 - 100, this.height / 4 - 60 + 50, 10526880); - this.drawCenteredString(this.fontRendererObj, I18n.format("createWorld.seedNote"), this.width / 2, this.height / 4 + 90, -6250336); + if (!timeToImport) { + this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.import.title"), this.width / 2, + this.height / 4 - 60 + 20, 16777215); + this.drawString(this.fontRendererObj, I18n.format("singleplayer.import.enterName"), this.width / 2 - 100, + this.height / 4 - 60 + 50, 10526880); + this.drawCenteredString(this.fontRendererObj, I18n.format("createWorld.seedNote"), this.width / 2, + this.height / 4 + 90, -6250336); this.theGuiTextField.drawTextBox(); - }else { + } else { definetlyTimeToImport = true; long dots = (System.currentTimeMillis() / 500l) % 4l; String str = I18n.format("singleplayer.import.reading", world.fileName); - this.drawString(fontRendererObj, str + (dots > 0 ? "." : "") + (dots > 1 ? "." : "") + (dots > 2 ? "." : ""), (this.width - this.fontRendererObj.getStringWidth(str)) / 2, this.height / 3 + 10, 0xFFFFFF); + this.drawString(fontRendererObj, + str + (dots > 0 ? "." : "") + (dots > 1 ? "." : "") + (dots > 2 ? "." : ""), + (this.width - this.fontRendererObj.getStringWidth(str)) / 2, this.height / 3 + 10, 0xFFFFFF); } super.drawScreen(par1, par2, par3); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiShareToLan.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiShareToLan.java index b681a5c..f1b98cd 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiShareToLan.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiShareToLan.java @@ -165,7 +165,6 @@ public class GuiShareToLan extends GuiScreen { this.mc.ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(I18n.format("lanServer.opened") .replace("$relay$", LANServerController.getCurrentURI()).replace("$code$", code))); } else { - SingleplayerServerController.configureLAN(mc.theWorld.getWorldInfo().getGameType(), false); this.mc.displayGuiScreen(new GuiScreenNoRelays(this, "noRelay.titleFail")); } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/lan/LANClientNetworkManager.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/lan/LANClientNetworkManager.java index 2c56484..69a1d1d 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/lan/LANClientNetworkManager.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/lan/LANClientNetworkManager.java @@ -25,8 +25,7 @@ import java.util.ArrayList; import java.util.List; /** - * Copyright (c) 2022-2024 lax1dude, hoosiertransfer, ayunami2000. All Rights - * Reserved. + * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND @@ -358,9 +357,11 @@ public class LANClientNetworkManager extends EaglercraftNetworkManager { } EaglerInputStream bi = new EaglerInputStream(fullData); int i = (bi.read() << 24) | (bi.read() << 16) | (bi.read() << 8) | bi.read(); - InputStream inflaterInputStream = EaglerZLIB.newInflaterInputStream(bi); fullData = new byte[i]; - int r = IOUtils.readFully(inflaterInputStream, fullData); + int r; + try (InputStream inflaterInputStream = EaglerZLIB.newInflaterInputStream(bi)) { + r = IOUtils.readFully(inflaterInputStream, fullData); + } if (i != r) { logger.warn("Decompressed packet expected size {} differs from actual size {}!", i, r); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java index 9bd605e..d3617a2 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java @@ -501,7 +501,7 @@ public class EaglerIntegratedServerWorker { while (true) { mainLoop(); - EagUtils.sleep(1l); + EagUtils.sleep(0l); } } catch (Throwable tt) { if (tt instanceof ReportedException) { diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/EPKDecompiler.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/EPKDecompiler.java index 10f536e..c7f0c76 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/EPKDecompiler.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/EPKDecompiler.java @@ -1,6 +1,7 @@ package net.lax1dude.eaglercraft.v1_8.sp.server.export; import java.io.ByteArrayInputStream; +import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; @@ -12,170 +13,185 @@ import net.lax1dude.eaglercraft.v1_8.IOUtils; /** * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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 EPKDecompiler { +public class EPKDecompiler implements Closeable { public static class FileEntry { public final String type; public final String name; public final byte[] data; + protected FileEntry(String type, String name, byte[] data) { this.type = type; this.name = name; this.data = data; } } - + private ByteArrayInputStream in2; private InputStream zis; private CRC32 crc32; private int numFiles; private boolean isFinished = false; - + public EPKDecompiler(byte[] data) throws IOException { in2 = new ByteArrayInputStream(data); - + byte[] header = new byte[8]; IOUtils.readFully(in2, header); - - if(Arrays.equals(header, new byte[]{(byte)69,(byte)65,(byte)71,(byte)80,(byte)75,(byte)71,(byte)36,(byte)36})) { - byte[] endCode = new byte[] { (byte)':', (byte)':', (byte)':', (byte)'Y', - (byte)'E', (byte)'E', (byte)':', (byte)'>' }; - for(int i = 0; i < 8; ++i) { - if(data[data.length - 8 + i] != endCode[i]) { + + if (Arrays.equals(header, new byte[] { (byte) 69, (byte) 65, (byte) 71, (byte) 80, (byte) 75, (byte) 71, + (byte) 36, (byte) 36 })) { + byte[] endCode = new byte[] { (byte) ':', (byte) ':', (byte) ':', (byte) 'Y', + (byte) 'E', (byte) 'E', (byte) ':', (byte) '>' }; + for (int i = 0; i < 8; ++i) { + if (data[data.length - 8 + i] != endCode[i]) { throw new IOException("EPK file is missing EOF code (:::YEE:>)"); } } in2 = new ByteArrayInputStream(data, 8, data.length - 16); InputStream is = in2; - + String vers = readASCII(is); - if(!vers.startsWith("ver2.")) { + if (!vers.startsWith("ver2.")) { throw new IOException("Unknown or invalid EPK version: " + vers); } IOUtils.skipFully(is, is.read()); // skip filename IOUtils.skipFully(is, loadShort(is)); // skip comment IOUtils.skipFully(is, 8); // skip millis date - + numFiles = loadInt(is); - - char compressionType = (char)is.read(); - - switch(compressionType) { - case 'G': - zis = EaglerZLIB.newGZIPInputStream(is); - break; - case 'Z': - zis = EaglerZLIB.newInflaterInputStream(is); - break; - case '0': - zis = is; - break; - default: - throw new IOException("Invalid or unsupported EPK compression: " + compressionType); + + char compressionType = (char) is.read(); + + switch (compressionType) { + case 'G': + zis = EaglerZLIB.newGZIPInputStream(is); + break; + case 'Z': + zis = EaglerZLIB.newInflaterInputStream(is); + break; + case '0': + zis = is; + break; + default: + throw new IOException("Invalid or unsupported EPK compression: " + compressionType); } - + crc32 = new CRC32(); - }else if(Arrays.equals(header, new byte[]{(byte)69,(byte)65,(byte)71,(byte)80,(byte)75,(byte)71,(byte)33,(byte)33})) { + } else if (Arrays.equals(header, new byte[] { (byte) 69, (byte) 65, (byte) 71, (byte) 80, (byte) 75, (byte) 71, + (byte) 33, (byte) 33 })) { throw new IOException("FILE IS AN UNSUPPORTED LEGACY FORMAT!"); - }else { + } else { throw new IOException("FILE IS NOT AN EPK FILE!"); } - + } public FileEntry readFile() throws IOException { - if(isFinished) { + if (isFinished) { return null; } - + byte[] typeBytes = new byte[4]; IOUtils.readFully(zis, typeBytes); String type = readASCII(typeBytes); - - if(numFiles == 0) { - if(!"END$".equals(type)) { + + if (numFiles == 0) { + if (!"END$".equals(type)) { throw new IOException("EPK file is missing END code (END$)"); } isFinished = true; return null; - }else { - if("END$".equals(type)) { + } else { + if ("END$".equals(type)) { throw new IOException("Unexpected END when there are still " + numFiles + " files remaining"); - }else { + } else { String name = readASCII(zis); int len = loadInt(zis); byte[] data; - - if("FILE".equals(type)) { - if(len < 5) { + + if ("FILE".equals(type)) { + if (len < 5) { throw new IOException("File '" + name + "' is incomplete (no crc)"); } - + int loadedCrc = loadInt(zis); - + data = new byte[len - 5]; IOUtils.readFully(zis, data); - + crc32.reset(); crc32.update(data, 0, data.length); - if((int)crc32.getValue() != loadedCrc) { + if ((int) crc32.getValue() != loadedCrc) { throw new IOException("File '" + name + "' has an invalid checksum"); } - - if(zis.read() != ':') { + + if (zis.read() != ':') { throw new IOException("File '" + name + "' is incomplete"); } - }else { + } else { data = new byte[len]; IOUtils.readFully(zis, data); } - - if(zis.read() != '>') { + + if (zis.read() != '>') { throw new IOException("Object '" + name + "' is incomplete"); } - + --numFiles; return new FileEntry(type, name, data); } } } - + public static final int loadShort(InputStream is) throws IOException { return (is.read() << 8) | is.read(); } - + public static final int loadInt(InputStream is) throws IOException { return (is.read() << 24) | (is.read() << 16) | (is.read() << 8) | is.read(); } - + public static final String readASCII(byte[] bytesIn) throws IOException { char[] charIn = new char[bytesIn.length]; - for(int i = 0; i < bytesIn.length; ++i) { - charIn[i] = (char)((int)bytesIn[i] & 0xFF); - } - return new String(charIn); - } - - public static final String readASCII(InputStream bytesIn) throws IOException { - int len = bytesIn.read(); - char[] charIn = new char[len]; - for(int i = 0; i < len; ++i) { - charIn[i] = (char)(bytesIn.read() & 0xFF); + for (int i = 0; i < bytesIn.length; ++i) { + charIn[i] = (char) ((int) bytesIn[i] & 0xFF); } return new String(charIn); } + public static final String readASCII(InputStream bytesIn) throws IOException { + int len = bytesIn.read(); + char[] charIn = new char[len]; + for (int i = 0; i < len; ++i) { + charIn[i] = (char) (bytesIn.read() & 0xFF); + } + return new String(charIn); + } + + @Override + public void close() throws IOException { + zis.close(); + } + } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/WorldConverterEPK.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/WorldConverterEPK.java index dc8e7f4..cd3a4de 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/WorldConverterEPK.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/WorldConverterEPK.java @@ -14,8 +14,7 @@ import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; /** - * Copyright (c) 2022-2024 lax1dude, hoosiertransfer, ayunami2000. All Rights - * Reserved. + * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND @@ -48,44 +47,45 @@ public class WorldConverterEPK { folderName += "_"; worldDir = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory(); } - EPKDecompiler dc = new EPKDecompiler(archiveContents); - EPKDecompiler.FileEntry f = null; - int lastProgUpdate = 0; - int prog = 0; - String hasReadType = null; - boolean has152Format = false; - int cnt = 0; - while ((f = dc.readFile()) != null) { - byte[] b = f.data; - if (hasReadType == null) { - if (f.type.equals("HEAD") && f.name.equals("file-type") - && ((hasReadType = EPKDecompiler.readASCII(f.data)).equals("epk/world188") - || (has152Format = hasReadType.equals("epk/world152")))) { - if (has152Format) { - logger.warn("World type detected as 1.5.2, it will be converted to 1.8.8 format"); + try (EPKDecompiler dc = new EPKDecompiler(archiveContents)) { + EPKDecompiler.FileEntry f = null; + int lastProgUpdate = 0; + int prog = 0; + String hasReadType = null; + boolean has152Format = false; + int cnt = 0; + while ((f = dc.readFile()) != null) { + byte[] b = f.data; + if (hasReadType == null) { + if (f.type.equals("HEAD") && f.name.equals("file-type") + && ((hasReadType = EPKDecompiler.readASCII(f.data)).equals("epk/world188") + || (has152Format = hasReadType.equals("epk/world152")))) { + if (has152Format) { + logger.warn("World type detected as 1.5.2, it will be converted to 1.8.8 format"); + } + continue; + } else { + throw new IOException("file does not contain a singleplayer 1.5.2 or 1.8.8 world!"); } - continue; - } else { - throw new IOException("file does not contain a singleplayer 1.5.2 or 1.8.8 world!"); } - } - if (f.type.equals("FILE")) { - if (f.name.equals("level.dat") || f.name.equals("level.dat_old")) { - NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b)); - worldDatNBT.getCompoundTag("Data").setString("LevelName", newName); - worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis()); - EaglerOutputStream tmp = new EaglerOutputStream(); - CompressedStreamTools.writeCompressed(worldDatNBT, tmp); - b = tmp.toByteArray(); - } - VFile2 ff = new VFile2(worldDir, f.name); - ff.setAllBytes(b); - prog += b.length; - ++cnt; - if (prog - lastProgUpdate > 25000) { - lastProgUpdate = prog; - logger.info("Extracted {} files, {} bytes from EPK...", cnt, prog); - EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.1", prog); + if (f.type.equals("FILE")) { + if (f.name.equals("level.dat") || f.name.equals("level.dat_old")) { + NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b)); + worldDatNBT.getCompoundTag("Data").setString("LevelName", newName); + worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis()); + EaglerOutputStream tmp = new EaglerOutputStream(); + CompressedStreamTools.writeCompressed(worldDatNBT, tmp); + b = tmp.toByteArray(); + } + VFile2 ff = new VFile2(worldDir, f.name); + ff.setAllBytes(b); + prog += b.length; + ++cnt; + if (prog - lastProgUpdate > 25000) { + lastProgUpdate = prog; + logger.info("Extracted {} files, {} bytes from EPK...", cnt, prog); + EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.1", prog); + } } } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/WorldConverterMCA.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/WorldConverterMCA.java index b323868..05d6d98 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/WorldConverterMCA.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/WorldConverterMCA.java @@ -24,8 +24,7 @@ import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; /** - * Copyright (c) 2022-2024 lax1dude, hoosiertransfer, ayunami2000. All Rights - * Reserved. + * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND @@ -58,124 +57,126 @@ public class WorldConverterMCA { folderName += "_"; worldDir = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory(); } - ZipInputStream zis = new ZipInputStream(new EaglerInputStream(archiveContents)); - ZipEntry folderNameFile = null; List fileNames = new ArrayList<>(); - while ((folderNameFile = zis.getNextEntry()) != null) { - if (folderNameFile.getName().contains("__MACOSX/")) - continue; - if (folderNameFile.isDirectory()) - continue; - String lowerName = folderNameFile.getName().toLowerCase(); - if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") - || lowerName.endsWith(".mcr"))) - continue; - fileNames.add(folderNameFile.getName().toCharArray()); + try (ZipInputStream zis = new ZipInputStream(new EaglerInputStream(archiveContents))) { + ZipEntry folderNameFile = null; + while ((folderNameFile = zis.getNextEntry()) != null) { + if (folderNameFile.getName().contains("__MACOSX/")) + continue; + if (folderNameFile.isDirectory()) + continue; + String lowerName = folderNameFile.getName().toLowerCase(); + if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") + || lowerName.endsWith(".mcr"))) + continue; + fileNames.add(folderNameFile.getName().toCharArray()); + } } final int[] i = new int[] { 0 }; while (fileNames.get(0).length > i[0] && fileNames.stream().allMatch(w -> w[i[0]] == fileNames.get(0)[i[0]])) i[0]++; int folderPrefixOffset = i[0]; - zis = new ZipInputStream(new EaglerInputStream(archiveContents)); - ZipEntry f = null; - int lastProgUpdate = 0; - int prog = 0; - byte[] bb = new byte[16384]; - while ((f = zis.getNextEntry()) != null) { - if (f.getName().contains("__MACOSX/")) - continue; - if (f.isDirectory()) - continue; - String lowerName = f.getName().toLowerCase(); - if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") - || lowerName.endsWith(".mcr") || lowerName.endsWith(".bmp"))) - continue; - EaglerOutputStream baos = new EaglerOutputStream(); - int len; - while ((len = zis.read(bb)) != -1) { - baos.write(bb, 0, len); - } - baos.close(); - byte[] b = baos.toByteArray(); - String fileName = f.getName().substring(folderPrefixOffset); - if (fileName.equals("level.dat") || fileName.equals("level.dat_old")) { - NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b)); + try (ZipInputStream zis = new ZipInputStream(new EaglerInputStream(archiveContents))) { + ZipEntry f = null; + int lastProgUpdate = 0; + int prog = 0; + byte[] bb = new byte[16384]; + while ((f = zis.getNextEntry()) != null) { + if (f.getName().contains("__MACOSX/")) + continue; + if (f.isDirectory()) + continue; + String lowerName = f.getName().toLowerCase(); + if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") + || lowerName.endsWith(".mcr") || lowerName.endsWith(".bmp"))) + continue; + EaglerOutputStream baos = new EaglerOutputStream(); + int len; + while ((len = zis.read(bb)) != -1) { + baos.write(bb, 0, len); + } + baos.close(); + byte[] b = baos.toByteArray(); + String fileName = f.getName().substring(folderPrefixOffset); + if (fileName.equals("level.dat") || fileName.equals("level.dat_old")) { + NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b)); - NBTTagCompound gameRulesNBT = worldDatNBT.getCompoundTag("Data").getCompoundTag("GameRules"); - gameRulesNBT.setString("loadSpawnChunks", (gameRules & 2) != 0 ? "true" : "false"); - String s = (gameRules & 1) != 0 ? "true" : "false"; - gameRulesNBT.setString("bedSpawnPoint", s); - gameRulesNBT.setString("clickToRide", "false"); - gameRulesNBT.setString("clickToSit", s); - gameRulesNBT.setString("colorCodes", s); - gameRulesNBT.setString("doSignEditing", s); - worldDatNBT.getCompoundTag("Data").setTag("GameRules", gameRulesNBT); + NBTTagCompound gameRulesNBT = worldDatNBT.getCompoundTag("Data").getCompoundTag("GameRules"); + gameRulesNBT.setString("loadSpawnChunks", (gameRules & 2) != 0 ? "true" : "false"); + String s = (gameRules & 1) != 0 ? "true" : "false"; + gameRulesNBT.setString("bedSpawnPoint", s); + gameRulesNBT.setString("clickToRide", "false"); + gameRulesNBT.setString("clickToSit", s); + gameRulesNBT.setString("colorCodes", s); + gameRulesNBT.setString("doSignEditing", s); + worldDatNBT.getCompoundTag("Data").setTag("GameRules", gameRulesNBT); - worldDatNBT.getCompoundTag("Data").setString("LevelName", newName); - worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis()); - EaglerOutputStream bo = new EaglerOutputStream(); - CompressedStreamTools.writeCompressed(worldDatNBT, bo); - b = bo.toByteArray(); - VFile2 ff = new VFile2(worldDir, fileName); - ff.setAllBytes(b); - prog += b.length; - } else if ((fileName.endsWith(".mcr") || fileName.endsWith(".mca")) && (fileName.startsWith("region/") - || fileName.startsWith("DIM1/region/") || fileName.startsWith("DIM-1/region/"))) { - VFile2 chunkFolder = new VFile2(worldDir, - fileName.startsWith("DIM1") ? "level1" : (fileName.startsWith("DIM-1") ? "level-1" : "level0")); - RegionFile mca = new RegionFile(new RandomAccessMemoryFile(b, b.length)); - int loadChunksCount = 0; - for (int j = 0; j < 32; ++j) { - for (int k = 0; k < 32; ++k) { - if (mca.isChunkSaved(j, k)) { - NBTTagCompound chunkNBT; - NBTTagCompound chunkLevel; - try { - chunkNBT = CompressedStreamTools.read(mca.getChunkDataInputStream(j, k)); - if (!chunkNBT.hasKey("Level", 10)) { - throw new IOException("Chunk is missing level data!"); + worldDatNBT.getCompoundTag("Data").setString("LevelName", newName); + worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis()); + EaglerOutputStream bo = new EaglerOutputStream(); + CompressedStreamTools.writeCompressed(worldDatNBT, bo); + b = bo.toByteArray(); + VFile2 ff = new VFile2(worldDir, fileName); + ff.setAllBytes(b); + prog += b.length; + } else if ((fileName.endsWith(".mcr") || fileName.endsWith(".mca")) && (fileName.startsWith("region/") + || fileName.startsWith("DIM1/region/") || fileName.startsWith("DIM-1/region/"))) { + VFile2 chunkFolder = new VFile2(worldDir, fileName.startsWith("DIM1") ? "level1" + : (fileName.startsWith("DIM-1") ? "level-1" : "level0")); + RegionFile mca = new RegionFile(new RandomAccessMemoryFile(b, b.length)); + int loadChunksCount = 0; + for (int j = 0; j < 32; ++j) { + for (int k = 0; k < 32; ++k) { + if (mca.isChunkSaved(j, k)) { + NBTTagCompound chunkNBT; + NBTTagCompound chunkLevel; + try { + chunkNBT = CompressedStreamTools.read(mca.getChunkDataInputStream(j, k)); + if (!chunkNBT.hasKey("Level", 10)) { + throw new IOException("Chunk is missing level data!"); + } + chunkLevel = chunkNBT.getCompoundTag("Level"); + } catch (Throwable t) { + logger.error("{}: Could not read chunk: {}, {}", fileName, j, k); + logger.error(t); + continue; } - chunkLevel = chunkNBT.getCompoundTag("Level"); - } catch (Throwable t) { - logger.error("{}: Could not read chunk: {}, {}", fileName, j, k); - logger.error(t); - continue; + int chunkX = chunkLevel.getInteger("xPos"); + int chunkZ = chunkLevel.getInteger("zPos"); + VFile2 chunkOut = new VFile2(chunkFolder, + EaglerChunkLoader.getChunkPath(chunkX, chunkZ) + ".dat"); + if (chunkOut.exists()) { + logger.error("{}: Chunk already exists: {}", fileName, chunkOut.getPath()); + continue; + } + EaglerOutputStream bao = new EaglerOutputStream(); + CompressedStreamTools.writeCompressed(chunkNBT, bao); + b = bao.toByteArray(); + chunkOut.setAllBytes(b); + prog += b.length; + if (prog - lastProgUpdate > 25000) { + lastProgUpdate = prog; + EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.2", prog); + } + ++loadChunksCount; } - int chunkX = chunkLevel.getInteger("xPos"); - int chunkZ = chunkLevel.getInteger("zPos"); - VFile2 chunkOut = new VFile2(chunkFolder, - EaglerChunkLoader.getChunkPath(chunkX, chunkZ) + ".dat"); - if (chunkOut.exists()) { - logger.error("{}: Chunk already exists: {}", fileName, chunkOut.getPath()); - continue; - } - EaglerOutputStream bao = new EaglerOutputStream(); - CompressedStreamTools.writeCompressed(chunkNBT, bao); - b = bao.toByteArray(); - chunkOut.setAllBytes(b); - prog += b.length; - if (prog - lastProgUpdate > 25000) { - lastProgUpdate = prog; - EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.2", prog); - } - ++loadChunksCount; } } + logger.info("{}: Imported {} chunks successfully ({} bytes)", fileName, loadChunksCount, prog); + } else if (fileName.startsWith("playerdata/") || fileName.startsWith("stats/")) { + // TODO: LAN player inventories + } else if (fileName.startsWith("data/") || fileName.startsWith("players/") + || fileName.startsWith("eagler/skulls/")) { + VFile2 ff = new VFile2(worldDir, fileName); + ff.setAllBytes(b); + prog += b.length; + } else if (!fileName.equals("level.dat_mcr") && !fileName.equals("session.lock")) { + logger.info("Skipping file: {}", fileName); + } + if (prog - lastProgUpdate > 25000) { + lastProgUpdate = prog; + EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.2", prog); } - logger.info("{}: Imported {} chunks successfully ({} bytes)", fileName, loadChunksCount, prog); - } else if (fileName.startsWith("playerdata/") || fileName.startsWith("stats/")) { - // TODO: LAN player inventories - } else if (fileName.startsWith("data/") || fileName.startsWith("players/") - || fileName.startsWith("eagler/skulls/")) { - VFile2 ff = new VFile2(worldDir, fileName); - ff.setAllBytes(b); - prog += b.length; - } else if (!fileName.equals("level.dat_mcr") && !fileName.equals("session.lock")) { - logger.info("Skipping file: {}", fileName); - } - if (prog - lastProgUpdate > 25000) { - lastProgUpdate = prog; - EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.2", prog); } } logger.info("MCA was successfully extracted into directory \"{}\"", worldDir.getPath()); @@ -194,130 +195,130 @@ public class WorldConverterMCA { public static byte[] exportWorld(String folderName) throws IOException { EaglerOutputStream bao = new EaglerOutputStream(); - ZipOutputStream zos = new ZipOutputStream(bao); - zos.setComment("contains backup of world '" + folderName + "'"); - VFile2 worldFolder = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false) - .getWorldDirectory(); - logger.info("Exporting world directory \"{}\" as MCA", worldFolder.getPath()); - VFile2 vf = new VFile2(worldFolder, "level.dat"); - byte[] b; - int lastProgUpdate = 0; - int prog = 0; - boolean safe = false; - if (vf.exists()) { - zos.putNextEntry(new ZipEntry(folderName + "/level.dat")); - b = vf.getAllBytes(); - zos.write(b); - prog += b.length; - safe = true; - } - vf = new VFile2(worldFolder, "level.dat_old"); - if (vf.exists()) { - zos.putNextEntry(new ZipEntry(folderName + "/level.dat_old")); - b = vf.getAllBytes(); - zos.write(b); - prog += b.length; - safe = true; - } - if (prog - lastProgUpdate > 25000) { - lastProgUpdate = prog; - EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog); - } - String[] srcFolderNames = new String[] { "level0", "level-1", "level1" }; - String[] dstFolderNames = new String[] { "/region/", "/DIM-1/region/", "/DIM1/region/" }; - List fileList; - for (int i = 0; i < 3; ++i) { - vf = new VFile2(worldFolder, srcFolderNames[i]); - fileList = vf.listFiles(true); - String regionFolder = folderName + dstFolderNames[i]; - logger.info("Converting chunks in \"{}\" as MCA to \"{}\"...", vf.getPath(), regionFolder); - Map regionFiles = new HashMap(); - for (int k = 0, l = fileList.size(); k < l; ++k) { - VFile2 chunkFile = fileList.get(k); - NBTTagCompound chunkNBT; - NBTTagCompound chunkLevel; - try { - b = chunkFile.getAllBytes(); - chunkNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b)); - if (!chunkNBT.hasKey("Level", 10)) { - throw new IOException("Chunk is missing level data!"); + VFile2 worldFolder; + try (ZipOutputStream zos = new ZipOutputStream(bao)) { + zos.setComment("contains backup of world '" + folderName + "'"); + worldFolder = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory(); + logger.info("Exporting world directory \"{}\" as MCA", worldFolder.getPath()); + VFile2 vf = new VFile2(worldFolder, "level.dat"); + byte[] b; + int lastProgUpdate = 0; + int prog = 0; + boolean safe = false; + if (vf.exists()) { + zos.putNextEntry(new ZipEntry(folderName + "/level.dat")); + b = vf.getAllBytes(); + zos.write(b); + prog += b.length; + safe = true; + } + vf = new VFile2(worldFolder, "level.dat_old"); + if (vf.exists()) { + zos.putNextEntry(new ZipEntry(folderName + "/level.dat_old")); + b = vf.getAllBytes(); + zos.write(b); + prog += b.length; + safe = true; + } + if (prog - lastProgUpdate > 25000) { + lastProgUpdate = prog; + EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog); + } + String[] srcFolderNames = new String[] { "level0", "level-1", "level1" }; + String[] dstFolderNames = new String[] { "/region/", "/DIM-1/region/", "/DIM1/region/" }; + List fileList; + for (int i = 0; i < 3; ++i) { + vf = new VFile2(worldFolder, srcFolderNames[i]); + fileList = vf.listFiles(true); + String regionFolder = folderName + dstFolderNames[i]; + logger.info("Converting chunks in \"{}\" as MCA to \"{}\"...", vf.getPath(), regionFolder); + Map regionFiles = new HashMap(); + for (int k = 0, l = fileList.size(); k < l; ++k) { + VFile2 chunkFile = fileList.get(k); + NBTTagCompound chunkNBT; + NBTTagCompound chunkLevel; + try { + b = chunkFile.getAllBytes(); + chunkNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b)); + if (!chunkNBT.hasKey("Level", 10)) { + throw new IOException("Chunk is missing level data!"); + } + chunkLevel = chunkNBT.getCompoundTag("Level"); + } catch (IOException t) { + logger.error("Could not read chunk: {}", chunkFile.getPath()); + logger.error(t); + continue; } - chunkLevel = chunkNBT.getCompoundTag("Level"); - } catch (IOException t) { - logger.error("Could not read chunk: {}", chunkFile.getPath()); - logger.error(t); + int chunkX = chunkLevel.getInteger("xPos"); + int chunkZ = chunkLevel.getInteger("zPos"); + String regionFileName = "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mca"; + RegionFile rf = regionFiles.get(regionFileName); + if (rf == null) { + rf = new RegionFile(new RandomAccessMemoryFile(new byte[65536], 0)); + regionFiles.put(regionFileName, rf); + } + try (DataOutputStream dos = rf.getChunkDataOutputStream(chunkX & 31, chunkZ & 31)) { + CompressedStreamTools.write(chunkNBT, dos); + } catch (IOException t) { + logger.error("Could not write chunk to {}: {}", regionFileName, chunkFile.getPath()); + logger.error(t); + continue; + } + prog += b.length; + if (prog - lastProgUpdate > 25000) { + lastProgUpdate = prog; + EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog); + } + } + if (regionFiles.isEmpty()) { + logger.info("No region files were generated"); continue; } - int chunkX = chunkLevel.getInteger("xPos"); - int chunkZ = chunkLevel.getInteger("zPos"); - String regionFileName = "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mca"; - RegionFile rf = regionFiles.get(regionFileName); - if (rf == null) { - rf = new RegionFile(new RandomAccessMemoryFile(new byte[65536], 0)); - regionFiles.put(regionFileName, rf); - } - try (DataOutputStream dos = rf.getChunkDataOutputStream(chunkX & 31, chunkZ & 31)) { - CompressedStreamTools.write(chunkNBT, dos); - } catch (IOException t) { - logger.error("Could not write chunk to {}: {}", regionFileName, chunkFile.getPath()); - logger.error(t); - continue; + for (Entry etr : regionFiles.entrySet()) { + String regionPath = regionFolder + etr.getKey(); + logger.info("Writing region file: {}", regionPath); + zos.putNextEntry(new ZipEntry(regionPath)); + zos.write(etr.getValue().getFile().getByteArray()); } + } + logger.info("Copying extra world data..."); + fileList = (new VFile2(worldFolder, "data")).listFiles(false); + for (int k = 0, l = fileList.size(); k < l; ++k) { + VFile2 dataFile = fileList.get(k); + zos.putNextEntry(new ZipEntry(folderName + "/data/" + dataFile.getName())); + b = dataFile.getAllBytes(); + zos.write(b); prog += b.length; if (prog - lastProgUpdate > 25000) { lastProgUpdate = prog; EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog); } } - if (regionFiles.isEmpty()) { - logger.info("No region files were generated"); - continue; + fileList = (new VFile2(worldFolder, "players")).listFiles(false); + for (int k = 0, l = fileList.size(); k < l; ++k) { + VFile2 dataFile = fileList.get(k); + zos.putNextEntry(new ZipEntry(folderName + "/players/" + dataFile.getName())); + b = dataFile.getAllBytes(); + zos.write(b); + prog += b.length; + if (prog - lastProgUpdate > 25000) { + lastProgUpdate = prog; + EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog); + } } - for (Entry etr : regionFiles.entrySet()) { - String regionPath = regionFolder + etr.getKey(); - logger.info("Writing region file: {}", regionPath); - zos.putNextEntry(new ZipEntry(regionPath)); - zos.write(etr.getValue().getFile().getByteArray()); + fileList = (new VFile2(worldFolder, "eagler/skulls")).listFiles(false); + for (int k = 0, l = fileList.size(); k < l; ++k) { + VFile2 dataFile = fileList.get(k); + zos.putNextEntry(new ZipEntry(folderName + "/eagler/skulls/" + dataFile.getName())); + b = dataFile.getAllBytes(); + zos.write(b); + prog += b.length; + if (prog - lastProgUpdate > 25000) { + lastProgUpdate = prog; + EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog); + } } } - logger.info("Copying extra world data..."); - fileList = (new VFile2(worldFolder, "data")).listFiles(false); - for (int k = 0, l = fileList.size(); k < l; ++k) { - VFile2 dataFile = fileList.get(k); - zos.putNextEntry(new ZipEntry(folderName + "/data/" + dataFile.getName())); - b = dataFile.getAllBytes(); - zos.write(b); - prog += b.length; - if (prog - lastProgUpdate > 25000) { - lastProgUpdate = prog; - EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog); - } - } - fileList = (new VFile2(worldFolder, "players")).listFiles(false); - for (int k = 0, l = fileList.size(); k < l; ++k) { - VFile2 dataFile = fileList.get(k); - zos.putNextEntry(new ZipEntry(folderName + "/players/" + dataFile.getName())); - b = dataFile.getAllBytes(); - zos.write(b); - prog += b.length; - if (prog - lastProgUpdate > 25000) { - lastProgUpdate = prog; - EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog); - } - } - fileList = (new VFile2(worldFolder, "eagler/skulls")).listFiles(false); - for (int k = 0, l = fileList.size(); k < l; ++k) { - VFile2 dataFile = fileList.get(k); - zos.putNextEntry(new ZipEntry(folderName + "/eagler/skulls/" + dataFile.getName())); - b = dataFile.getAllBytes(); - zos.write(b); - prog += b.length; - if (prog - lastProgUpdate > 25000) { - lastProgUpdate = prog; - EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog); - } - } - zos.close(); logger.info("World directory \"{}\" was successfully exported as MCA", worldFolder.getPath()); return bao.toByteArray(); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/socket/IntegratedServerPlayerNetworkManager.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/socket/IntegratedServerPlayerNetworkManager.java index b08fbe1..032590b 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/socket/IntegratedServerPlayerNetworkManager.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/socket/IntegratedServerPlayerNetworkManager.java @@ -257,9 +257,9 @@ public class IntegratedServerPlayerNetworkManager { temporaryOutputStream.write((len >> 16) & 0xFF); temporaryOutputStream.write((len >> 8) & 0xFF); temporaryOutputStream.write(len & 0xFF); - OutputStream os = EaglerZLIB.newDeflaterOutputStream(temporaryOutputStream); - temporaryBuffer.readBytes(os, len); - os.close(); + try (OutputStream os = EaglerZLIB.newDeflaterOutputStream(temporaryOutputStream)) { + temporaryBuffer.readBytes(os, len); + } compressedData = temporaryOutputStream.toByteArray(); } catch (IOException ex) { logger.error("Failed to compress packet {}!", pkt.getClass().getSimpleName()); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/RelayUpdateChecker.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/RelayUpdateChecker.java index be5cd15..2670be0 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/RelayUpdateChecker.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/RelayUpdateChecker.java @@ -19,14 +19,21 @@ import net.minecraft.client.Minecraft; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -34,16 +41,16 @@ import net.minecraft.client.Minecraft; public class RelayUpdateChecker { private static class RelayEntry { - + private final String uri; private boolean queued; private boolean handshake; private RelayServerSocket currentSocket; - + private RelayEntry(String uri) { this.uri = uri; } - + } private static final List relaysList = new ArrayList(); @@ -56,16 +63,16 @@ public class RelayUpdateChecker { private static final String magic = "~!REQUEST_UPDATE_CERT"; public static void runTick() { - if(!EagRuntime.getConfiguration().isCheckRelaysForUpdates()) { + if (!EagRuntime.getConfiguration().isCheckRelaysForUpdates()) { return; } - if(!hasInit) { + if (!hasInit) { hasInit = true; - for(net.lax1dude.eaglercraft.v1_8.sp.relay.RelayEntry etr : EagRuntime.getConfiguration().getRelays()) { + for (net.lax1dude.eaglercraft.v1_8.sp.relay.RelayEntry etr : EagRuntime.getConfiguration().getRelays()) { relaysList.add(new RelayEntry(etr.address)); } - byte[] b = PlatformApplication.getLocalStorage("lastRelayUpdate"); - if(b != null) { + byte[] b = PlatformApplication.getLocalStorage("lastRelayUpdate", false); + if (b != null) { try { lastUpdateCheck = (new DataInputStream(new EaglerInputStream(b))).readLong(); } catch (IOException e) { @@ -74,33 +81,33 @@ public class RelayUpdateChecker { } long millis = System.currentTimeMillis(); Minecraft mc = Minecraft.getMinecraft(); - if((mc.theWorld == null || mc.isSingleplayer()) && millis - lastUpdateCheck > updateCheckRate) { + if ((mc.theWorld == null || mc.isSingleplayer()) && millis - lastUpdateCheck > updateCheckRate) { lastUpdateCheck = millis; try { EaglerOutputStream bao = new EaglerOutputStream(8); (new DataOutputStream(bao)).writeLong(lastUpdateCheck); - PlatformApplication.setLocalStorage("lastRelayUpdate", bao.toByteArray()); + PlatformApplication.setLocalStorage("lastRelayUpdate", bao.toByteArray(), false); } catch (IOException e) { } for (int i = 0, l = relaysList.size(); i < l; ++i) { relaysList.get(i).queued = true; } } - for(int i = 0, l = relaysList.size(); i < l; ++i) { + for (int i = 0, l = relaysList.size(); i < l; ++i) { RelayEntry etr = relaysList.get(i); - if(etr.currentSocket != null) { + if (etr.currentSocket != null) { updateRelay(etr); - if(etr.currentSocket != null) { + if (etr.currentSocket != null) { return; } } } - for(int i = 0, l = relaysList.size(); i < l; ++i) { + for (int i = 0, l = relaysList.size(); i < l; ++i) { RelayEntry etr = relaysList.get(i); - if(etr.queued) { + if (etr.queued) { etr.queued = false; connect(etr); - if(etr.currentSocket != null) { + if (etr.currentSocket != null) { return; } } @@ -111,30 +118,31 @@ public class RelayUpdateChecker { try { socket.handshake = false; socket.currentSocket = PlatformWebRTC.openRelayConnection(socket.uri, 10000); - if(socket.currentSocket.isClosed()) { + if (socket.currentSocket.isClosed()) { socket.currentSocket = null; } - }catch(Throwable t) { + } catch (Throwable t) { } } private static void updateRelay(RelayEntry socket) { try { - if(socket.currentSocket.isClosed()) { + if (socket.currentSocket.isClosed()) { socket.currentSocket = null; - }else if(socket.currentSocket.isOpen()) { - if(!socket.handshake) { + } else if (socket.currentSocket.isOpen()) { + if (!socket.handshake) { socket.handshake = true; - socket.currentSocket.writePacket(new IPacket00Handshake(0x02, RelayManager.preferredRelayVersion, magic)); - }else { + socket.currentSocket + .writePacket(new IPacket00Handshake(0x02, RelayManager.preferredRelayVersion, magic)); + } else { // close immediately - if(socket.currentSocket.nextPacket() != null) { + if (socket.currentSocket.nextPacket() != null) { socket.currentSocket.close(); socket.currentSocket = null; } } } - }catch(Throwable t) { + } catch (Throwable t) { } } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateCertificate.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateCertificate.java index 2bfdc43..bad944c 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateCertificate.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateCertificate.java @@ -19,14 +19,21 @@ import net.lax1dude.eaglercraft.v1_8.crypto.SHA256Digest; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -37,6 +44,7 @@ public class UpdateCertificate { public final String type; public final String addr; + private DLSource(String type, String addr) { this.type = type; this.addr = addr; @@ -78,44 +86,48 @@ public class UpdateCertificate { public final DLSource[] bundleDataSources; - public static UpdateCertificate parseAndVerifyCertificate(byte[] certData) throws IOException, CertificateInvalidException { + public static UpdateCertificate parseAndVerifyCertificate(byte[] certData) + throws IOException, CertificateInvalidException { InputStream is = new EaglerInputStream(certData); - if(is.read() != 'E' || is.read() != 'A' || is.read() != 'G' || is.read() != 'S' || is.read() != 'I' || is.read() != 'G') { + if (is.read() != 'E' || is.read() != 'A' || is.read() != 'G' || is.read() != 'S' || is.read() != 'I' + || is.read() != 'G') { throw new IOException("Data is not a certificate!"); } - + int vers = is.read() << 8; vers |= is.read(); - if(vers != 1) { + if (vers != 1) { throw new IOException("Invalid certificate version: " + vers); } - + byte[] rsa2048sum = new byte[256]; IOUtils.readFully(is, rsa2048sum); - - byte[] rsa2048sumDec = (new BigInteger(rsa2048sum)).modPow(new BigInteger("65537"), EaglercraftVersion.updateSignatureModulus).toByteArray(); - - if(rsa2048sumDec.length > 256) { + + byte[] rsa2048sumDec = (new BigInteger(rsa2048sum)) + .modPow(new BigInteger("65537"), EaglercraftVersion.updateSignatureModulus).toByteArray(); + + if (rsa2048sumDec.length > 256) { throw new IOException("Invalid decrypted hash length: " + rsa2048sum.length); } - - if(rsa2048sumDec.length < 256) { + + if (rsa2048sumDec.length < 256) { byte[] tmp = rsa2048sumDec; rsa2048sumDec = new byte[256]; System.arraycopy(tmp, 0, rsa2048sumDec, 256 - tmp.length, tmp.length); } - + int payloadLen = is.read() << 8; payloadLen |= is.read(); - + byte[] signaturePayload = new byte[payloadLen]; IOUtils.readFully(is, signaturePayload); - + SHA256Digest sha256 = new SHA256Digest(); sha256.update(new byte[] { (byte) 170, (byte) 191, (byte) 203, (byte) 188, (byte) 47, (byte) 37, (byte) 17, (byte) 187, (byte) 169, (byte) 225, (byte) 247, (byte) 193, (byte) 100, (byte) 101, (byte) 233, (byte) 106, (byte) 80, (byte) 204, (byte) 192, (byte) 140, (byte) 19, (byte) 18, (byte) 165, (byte) 252, - (byte) 138, (byte) 187, (byte) 229, (byte) 148, (byte) 118, (byte) 208, (byte) 179, (byte) 233 }, 0, 32); + (byte) 138, (byte) 187, (byte) 229, (byte) 148, (byte) 118, (byte) 208, (byte) 179, (byte) 233 }, 0, + 32); sha256.update(signaturePayload, 0, signaturePayload.length); byte[] hash2048 = new byte[256]; sha256.doFinal(hash2048, 0); @@ -140,15 +152,24 @@ public class UpdateCertificate { (byte) 88, (byte) 215, (byte) 216, (byte) 253, (byte) 235, (byte) 7, (byte) 60 }, 0, 32); sha256.update(signaturePayload, 0, signaturePayload.length); sha256.doFinal(hash2048, 96); - - hash2048[0] = (byte)((signaturePayload.length >> 8) & 0xFF); - hash2048[1] = (byte)(signaturePayload.length & 0xFF); - - if(!Arrays.equals(hash2048, rsa2048sumDec)) { + + hash2048[0] = (byte) ((signaturePayload.length >> 8) & 0xFF); + hash2048[1] = (byte) (signaturePayload.length & 0xFF); + + if (!Arrays.equals(hash2048, rsa2048sumDec)) { throw new CertificateInvalidException("SHA256 checksum of signature payload is invalid!"); } - - return new UpdateCertificate(certData, EaglerZLIB.newGZIPInputStream(new EaglerInputStream(signaturePayload)), vers); + + UpdateCertificate cert; + try (InputStream gis = EaglerZLIB.newGZIPInputStream(new EaglerInputStream(signaturePayload))) { + cert = new UpdateCertificate(certData, gis, vers); + } + + if (System.currentTimeMillis() < cert.sigTimestamp) { + throw new CertificateInvalidException("Update certificate timestamp is from the future!?"); + } + + return cert; } private UpdateCertificate(byte[] certData, InputStream is, int sigVers) throws IOException { @@ -168,14 +189,14 @@ public class UpdateCertificate { IOUtils.skipFully(dis, dis.read()); int sourceCount = dis.readInt(); this.bundleDataSources = new DLSource[sourceCount]; - for(int i = 0; i < sourceCount; ++i) { + for (int i = 0; i < sourceCount; ++i) { IOUtils.skipFully(dis, 4); bundleDataSources[i] = new DLSource(dis.readUTF(), dis.readUTF()); } } public boolean isBundleDataValid(byte[] bundleData) { - if(bundleData.length != bundleDataLength) { + if (bundleData.length != bundleDataLength) { return false; } SHA256Digest sha256 = new SHA256Digest(); @@ -217,9 +238,9 @@ public class UpdateCertificate { && sigVersion == other.sigVersion; } - public ListMultimap getSourceMultimap() { - ListMultimap ret = ListMultimapBuilder.hashKeys().arrayListValues().build(); - for(int i = 0; i < bundleDataSources.length; ++i) { + public ListMultimap getSourceMultimap() { + ListMultimap ret = ListMultimapBuilder.hashKeys().arrayListValues().build(); + for (int i = 0; i < bundleDataSources.length; ++i) { ret.put(bundleDataSources[i].type, bundleDataSources[i].addr); } return ret; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateService.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateService.java index 49aa9bb..61a806b 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateService.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateService.java @@ -17,14 +17,21 @@ import net.lax1dude.eaglercraft.v1_8.log4j.Logger; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -58,57 +65,63 @@ public class UpdateService { } public boolean equals(Object o) { - return o != null && (o == this || ((o instanceof RawKnownCertHolder) && Arrays.equals(((RawKnownCertHolder)o).data, data))); + return o != null && (o == this + || ((o instanceof RawKnownCertHolder) && Arrays.equals(((RawKnownCertHolder) o).data, data))); } } public static boolean supported() { - return EaglercraftVersion.enableUpdateService && EagRuntime.getConfiguration().allowUpdateSvc() && PlatformUpdateSvc.supported(); + return EaglercraftVersion.enableUpdateService && EagRuntime.getConfiguration().allowUpdateSvc() + && PlatformUpdateSvc.supported(); } public static void initialize() { - if(!supported()) { + if (!supported()) { logger.info("Update service is not supported on this client"); return; } PlatformUpdateSvc.initialize(); - if(PlatformUpdateSvc.getClientSignatureData() != null) { + if (PlatformUpdateSvc.getClientSignatureData() != null) { logger.info("Testing client update certificate..."); try { myUpdateCert = UpdateCertificate.parseAndVerifyCertificate(PlatformUpdateSvc.getClientSignatureData()); - if(!EaglercraftVersion.updateBundlePackageName.equalsIgnoreCase(myUpdateCert.bundlePackageName)) { - throw new CertificateInvalidException("Certificate package name does not match current client package name!"); + if (!EaglercraftVersion.updateBundlePackageName.equalsIgnoreCase(myUpdateCert.bundlePackageName)) { + throw new CertificateInvalidException( + "Certificate package name does not match current client package name!"); } - if(EaglercraftVersion.updateBundlePackageVersionInt != myUpdateCert.bundleVersionInteger) { - throw new CertificateInvalidException("Certificate client version does not match current client version!"); + if (EaglercraftVersion.updateBundlePackageVersionInt != myUpdateCert.bundleVersionInteger) { + throw new CertificateInvalidException( + "Certificate client version does not match current client version!"); } - }catch(Throwable t) { + } catch (Throwable t) { myUpdateCert = null; logger.error("Client update certificate is invalid!"); logger.error(t); } - if(myUpdateCert != null && PlatformUpdateSvc.getClientBundleData() != null) { + if (myUpdateCert != null && PlatformUpdateSvc.getClientBundleData() != null) { isBundleDataValid = myUpdateCert.isBundleDataValid(PlatformUpdateSvc.getClientBundleData()); - if(!isBundleDataValid) { - logger.error("Client checksum does not match certificate! \"Download Offline\" button will download a fresh client"); + if (!isBundleDataValid) { + logger.error( + "Client checksum does not match certificate! \"Download Offline\" button will download a fresh client"); } } } - byte[] latestUpdate = PlatformApplication.getLocalStorage(EaglercraftVersion.updateLatestLocalStorageKey); - if(latestUpdate != null) { + byte[] latestUpdate = PlatformApplication.getLocalStorage(EaglercraftVersion.updateLatestLocalStorageKey, + false); + if (latestUpdate != null) { addCertificateToSet(latestUpdate, false); } } public static byte[] getClientSignatureData() { - if(myUpdateCert != null) { + if (myUpdateCert != null) { return PlatformUpdateSvc.getClientSignatureData(); } return null; } public static byte[] getClientBundleData() { - if(isBundleDataValid) { + if (isBundleDataValid) { return PlatformUpdateSvc.getClientBundleData(); } return null; @@ -124,14 +137,16 @@ public class UpdateService { private static void addCertificateToSet(byte[] certificateData, boolean saveLatest) { if (EagRuntime.getConfiguration().allowUpdateDL()) { - synchronized(availableUpdates) { + synchronized (availableUpdates) { try { - if(certificateData.length > 32767) { - throw new CertificateInvalidException("Certificate is too large! (" + certificateData.length + " bytes)"); + if (certificateData.length > 32767) { + throw new CertificateInvalidException( + "Certificate is too large! (" + certificateData.length + " bytes)"); } - if(!fastUpdateKnownCheckSet.add(new RawKnownCertHolder(certificateData))) { + if (!fastUpdateKnownCheckSet.add(new RawKnownCertHolder(certificateData))) { if (EagRuntime.getConfiguration().isLogInvalidCerts()) { - logger.info("Ignoring {} byte certificate that has already been processed", certificateData.length); + logger.info("Ignoring {} byte certificate that has already been processed", + certificateData.length); } freeMemory(); return; @@ -139,8 +154,9 @@ public class UpdateService { UpdateCertificate cert = UpdateCertificate.parseAndVerifyCertificate(certificateData); if (EaglercraftVersion.updateBundlePackageName.equalsIgnoreCase(cert.bundlePackageName)) { if (myUpdateCert == null || !Arrays.equals(cert.bundleDataHash, myUpdateCert.bundleDataHash)) { - if(availableUpdates.add(cert)) { - logger.info("Found new update: {} - {}", cert.bundleDisplayName, cert.bundleDisplayVersion); + if (availableUpdates.add(cert)) { + logger.info("Found new update: {} - {}", cert.bundleDisplayName, + cert.bundleDisplayVersion); if (cert.bundleVersionInteger > EaglercraftVersion.updateBundlePackageVersionInt && (latestUpdateFound == null || cert.bundleVersionInteger > latestUpdateFound.bundleVersionInteger @@ -149,12 +165,14 @@ public class UpdateService { && !dismissedUpdates.contains(cert)) { latestUpdateFound = cert; if (saveLatest) { - PlatformApplication.setLocalStorage(EaglercraftVersion.updateLatestLocalStorageKey, - certificateData); + PlatformApplication.setLocalStorage( + EaglercraftVersion.updateLatestLocalStorageKey, + certificateData, false); } } - }else if(EagRuntime.getConfiguration().isLogInvalidCerts()) { - logger.info("Ignoring already indexed update: {} - {}", cert.bundleDisplayName, cert.bundleDisplayVersion); + } else if (EagRuntime.getConfiguration().isLogInvalidCerts()) { + logger.info("Ignoring already indexed update: {} - {}", cert.bundleDisplayName, + cert.bundleDisplayVersion); } } } else { @@ -166,7 +184,8 @@ public class UpdateService { } } catch (Throwable t) { if (EagRuntime.getConfiguration().isLogInvalidCerts()) { - logger.error("Invalid update certificate recieved! The certificate may be from a different client"); + logger.error( + "Invalid update certificate recieved! The certificate may be from a different client"); logger.error(t); } } @@ -175,11 +194,13 @@ public class UpdateService { } private static void freeMemory() { - if(fastUpdateKnownCheckSet.size() > 127) { + if (fastUpdateKnownCheckSet.size() > 127) { List lst = new ArrayList(fastUpdateKnownCheckSet); fastUpdateKnownCheckSet.clear(); - lst.sort((c1, c2) -> { return (int)(c2.age - c1.age); }); - for(int i = 0; i < 64; ++i) { + lst.sort((c1, c2) -> { + return (int) (c2.age - c1.age); + }); + for (int i = 0; i < 64; ++i) { fastUpdateKnownCheckSet.add(lst.get(i)); } } @@ -202,19 +223,19 @@ public class UpdateService { } public static void dismiss(UpdateCertificate cert) { - if(latestUpdateFound == cert) { + if (latestUpdateFound == cert) { latestUpdateFound = null; } dismissedUpdates.add(cert); } public static void quine() { - if(myUpdateCert != null) { + if (myUpdateCert != null) { byte[] data = getClientBundleData(); - if(data != null) { + if (data != null) { logger.info("Generating signed offline download..."); PlatformUpdateSvc.quine(myUpdateCert, data); - }else { + } else { logger.error("Client checksum does not match certificate! Downloading a fresh client..."); PlatformUpdateSvc.startClientUpdateFrom(myUpdateCert); } diff --git a/src/main/java/net/minecraft/client/Minecraft.java b/src/main/java/net/minecraft/client/Minecraft.java index 782c29e..70eb300 100644 --- a/src/main/java/net/minecraft/client/Minecraft.java +++ b/src/main/java/net/minecraft/client/Minecraft.java @@ -25,6 +25,7 @@ import net.hoosiertransfer.Config; import net.lax1dude.eaglercraft.v1_8.Display; import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.EagUtils; import net.lax1dude.eaglercraft.v1_8.EaglerXBungeeVersion; import net.lax1dude.eaglercraft.v1_8.HString; import net.lax1dude.eaglercraft.v1_8.IOUtils; @@ -819,7 +820,17 @@ public class Minecraft implements IThreadListener { long l = System.nanoTime(); this.mcProfiler.startSection("tick"); - for (int j = 0; j < this.timer.elapsedTicks; ++j) { + if (this.timer.elapsedTicks > 1) { + long watchdog = System.currentTimeMillis(); + for (int j = 0; j < this.timer.elapsedTicks; ++j) { + this.runTick(); + long millis = System.currentTimeMillis(); + if (millis - watchdog > 50l) { + watchdog = millis; + EagUtils.sleep(0l); + } + } + } else if (this.timer.elapsedTicks == 1) { this.runTick(); } @@ -907,7 +918,11 @@ public class Minecraft implements IThreadListener { public void updateDisplay() { this.mcProfiler.startSection("display_update"); - Display.setVSync(this.gameSettings.enableVsync); + if (Display.isVSyncSupported()) { + Display.setVSync(this.gameSettings.enableVsync); + } else { + this.gameSettings.enableVsync = false; + } Display.update(); this.mcProfiler.endSection(); this.checkWindowResize(); diff --git a/src/main/java/net/minecraft/client/audio/SoundHandler.java b/src/main/java/net/minecraft/client/audio/SoundHandler.java index e8c5d34..fae594d 100644 --- a/src/main/java/net/minecraft/client/audio/SoundHandler.java +++ b/src/main/java/net/minecraft/client/audio/SoundHandler.java @@ -59,6 +59,7 @@ import net.minecraft.util.ResourceLocation; */ public class SoundHandler implements IResourceManagerReloadListener, ITickable { private static final Logger logger = LogManager.getLogger(); + private static final Logger tipLogger = LogManager.getLogger("EaglercraftX"); public static final SoundPoolEntry missing_sound = new SoundPoolEntry(new ResourceLocation("meta:missing_sound"), 0.0D, 0.0D, false); private final SoundRegistry sndRegistry = new SoundRegistry(); @@ -84,6 +85,12 @@ public class SoundHandler implements IResourceManagerReloadListener, ITickable { this.loadSoundResource(new ResourceLocation(s, (String) entry.getKey()), (SoundList) entry.getValue()); } + + if (this.sndRegistry + .getObject(new ResourceLocation("minecraft:sounds/music/game/calm1.ogg")) == null) { + tipLogger.info( + "Download this resource pack if you want music: https://bafybeiayojww5jfyzvlmtuk7l5ufkt7nlfto7mhwmzf2vs4bvsjd5ouiuq.ipfs.nftstorage.link/?filename=Music_For_Eaglercraft.zip"); + } } catch (RuntimeException runtimeexception) { logger.warn("Invalid sounds.json", runtimeexception); } diff --git a/src/main/java/net/minecraft/client/gui/GuiClientSettings.java b/src/main/java/net/minecraft/client/gui/GuiClientSettings.java index 3dfe836..28277a2 100644 --- a/src/main/java/net/minecraft/client/gui/GuiClientSettings.java +++ b/src/main/java/net/minecraft/client/gui/GuiClientSettings.java @@ -1,4 +1,5 @@ package net.minecraft.client.gui; + import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.KeyBinding; @@ -14,32 +15,30 @@ public class GuiClientSettings extends GuiScreen { this.options = settings; } - /**+ - * Adds the buttons (and other controls) to the screen in - * question. Called when the GUI is displayed and when the - * window resizes, the buttonList is cleared beforehand. - */ + /** + * + + * Adds the buttons (and other controls) to the screen in + * question. Called when the GUI is displayed and when the + * window resizes, the buttonList is cleared beforehand. + */ public void initGui() { int i = 0; this.title = "Client Specific Settings"; this.buttonList.add(new GuiButton(GameSettings.Options.HIDE_PASSWORD.returnEnumOrdinal(), - this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, - this.options.getKeyBinding(GameSettings.Options.HIDE_PASSWORD))); + this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, + this.options.getKeyBinding(GameSettings.Options.HIDE_PASSWORD))); ++i; this.buttonList.add(new GuiButton(GameSettings.Options.ENABLE_SOUND.returnEnumOrdinal(), - this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, - this.options.getKeyBinding(GameSettings.Options.ENABLE_SOUND))); - ++i; - this.buttonList.add(new GuiButton(GameSettings.Options.SKIP_SOME_RENDERING.returnEnumOrdinal(), - this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, - this.options.getKeyBinding(GameSettings.Options.SKIP_SOME_RENDERING))); + this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, + this.options.getKeyBinding(GameSettings.Options.ENABLE_SOUND))); ++i; this.buttonList.add(new GuiButton(GameSettings.Options.DISABLE_ALPHA.returnEnumOrdinal(), - this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, - this.options.getKeyBinding(GameSettings.Options.DISABLE_ALPHA))); + this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, + this.options.getKeyBinding(GameSettings.Options.DISABLE_ALPHA))); + ++i; ++i; this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height / 6 + 24 * (i >> 1), - I18n.format("gui.done", new Object[0]))); + I18n.format("gui.done", new Object[0]))); } protected void actionPerformed(GuiButton parGuiButton) { @@ -58,11 +57,6 @@ public class GuiClientSettings extends GuiScreen { parGuiButton.displayString = this.options.getKeyBinding(GameSettings.Options.ENABLE_SOUND); } - if (parGuiButton.id == GameSettings.Options.SKIP_SOME_RENDERING.returnEnumOrdinal()) { - this.options.setOptionValue(GameSettings.Options.SKIP_SOME_RENDERING, 1); - parGuiButton.displayString = this.options.getKeyBinding(GameSettings.Options.SKIP_SOME_RENDERING); - } - if (parGuiButton.id == GameSettings.Options.DISABLE_ALPHA.returnEnumOrdinal()) { this.options.setOptionValue(GameSettings.Options.DISABLE_ALPHA, 1); parGuiButton.displayString = this.options.getKeyBinding(GameSettings.Options.DISABLE_ALPHA); @@ -75,5 +69,5 @@ public class GuiClientSettings extends GuiScreen { this.drawCenteredString(this.fontRendererObj, this.title, this.width / 2, 20, 16777215); super.drawScreen(i, j, f); } - + } diff --git a/src/main/java/net/minecraft/client/gui/GuiDisconnected.java b/src/main/java/net/minecraft/client/gui/GuiDisconnected.java index 84b56fd..877a025 100644 --- a/src/main/java/net/minecraft/client/gui/GuiDisconnected.java +++ b/src/main/java/net/minecraft/client/gui/GuiDisconnected.java @@ -55,10 +55,6 @@ public class GuiDisconnected extends GuiScreen { this.parentScreen = screen; this.reason = I18n.format(reasonLocalizationKey, new Object[0]); this.message = chatComp; - if (reason.toLowerCase().contains("banned from this server")) { - EaglerProfile.updateUsernameCookies(); - reloadPage(); - } if (reason.toLowerCase().contains("reload page")) { EaglerProfile.updateUsernameCookieFromLocalStorage(); diff --git a/src/main/java/net/minecraft/client/gui/GuiIngame.java b/src/main/java/net/minecraft/client/gui/GuiIngame.java index cc703d8..85c739f 100644 --- a/src/main/java/net/minecraft/client/gui/GuiIngame.java +++ b/src/main/java/net/minecraft/client/gui/GuiIngame.java @@ -1039,7 +1039,7 @@ public class GuiIngame extends Gui { ent.prevRenderYawOffset = f5; GlStateManager.popMatrix(); RenderHelper.disableStandardItemLighting(); - GlStateManager.disableDepth(); + // GlStateManager.disableDepth(); GlStateManager.disableRescaleNormal(); GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); GlStateManager.disableTexture2D(); diff --git a/src/main/java/net/minecraft/client/gui/GuiMainMenu.java b/src/main/java/net/minecraft/client/gui/GuiMainMenu.java index 9be0af8..316df4d 100644 --- a/src/main/java/net/minecraft/client/gui/GuiMainMenu.java +++ b/src/main/java/net/minecraft/client/gui/GuiMainMenu.java @@ -38,6 +38,7 @@ import net.lax1dude.eaglercraft.v1_8.update.UpdateCertificate; import net.lax1dude.eaglercraft.v1_8.update.UpdateService; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; @@ -286,7 +287,8 @@ public class GuiMainMenu extends GuiScreen implements GuiYesNoCallback { */ private void addSingleplayerMultiplayerButtons(int parInt1, int parInt2) { this.buttonList - .add(new GuiButton(1, this.width / 2 - 100, parInt1, I18n.format("menu.singleplayer", new Object[0]))); + .add(new GuiButton(1, this.width / 2 - 100, parInt1, + I18n.format("menu.singleplayer", new Object[0]))); this.buttonList.add(new GuiButton(2, this.width / 2 - 100, parInt1 + parInt2 * 1, I18n.format("menu.multiplayer", new Object[0]))); if (EaglercraftVersion.mainMenuEnableGithubButton) { @@ -567,10 +569,12 @@ public class GuiMainMenu extends GuiScreen implements GuiYesNoCallback { || (this.openGLWarning2 != null && this.openGLWarning2.length() > 0)); if (isForkLabel) { - drawRect(this.field_92022_t - 3, this.field_92021_u - 3, this.field_92020_v + 3, this.field_92019_w, + drawRect(this.field_92022_t - 3, this.field_92021_u - 3, this.field_92020_v + 3, + this.field_92019_w, 1428160512); if (this.openGLWarning1 != null) - this.drawString(this.fontRendererObj, this.openGLWarning1, this.field_92022_t, this.field_92021_u, -1); + this.drawString(this.fontRendererObj, this.openGLWarning1, this.field_92022_t, this.field_92021_u, + -1); if (this.openGLWarning2 != null) this.drawString(this.fontRendererObj, this.openGLWarning2, (this.width - this.field_92024_r) / 2, this.field_92021_u + 12, -1); diff --git a/src/main/java/net/minecraft/client/gui/GuiMultiplayer.java b/src/main/java/net/minecraft/client/gui/GuiMultiplayer.java index 63b34ed..50e1276 100644 --- a/src/main/java/net/minecraft/client/gui/GuiMultiplayer.java +++ b/src/main/java/net/minecraft/client/gui/GuiMultiplayer.java @@ -396,7 +396,7 @@ public class GuiMultiplayer extends GuiScreen implements GuiYesNoCallback { } } - private void connectToServer(ServerData server) { + public void connectToServer(ServerData server) { this.mc.displayGuiScreen(new GuiConnecting(this, this.mc, server)); } diff --git a/src/main/java/net/minecraft/client/multiplayer/GuiConnecting.java b/src/main/java/net/minecraft/client/multiplayer/GuiConnecting.java index 085c990..4f98526 100644 --- a/src/main/java/net/minecraft/client/multiplayer/GuiConnecting.java +++ b/src/main/java/net/minecraft/client/multiplayer/GuiConnecting.java @@ -14,6 +14,7 @@ import net.lax1dude.eaglercraft.v1_8.socket.RateLimitTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiDisconnected; +import net.minecraft.client.gui.GuiMainMenu; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.client.resources.I18n; @@ -239,7 +240,7 @@ public class GuiConnecting extends GuiScreen { this.networkManager.closeChannel(new ChatComponentText("Aborted")); } - this.mc.displayGuiScreen(this.previousGuiScreen); + this.mc.displayGuiScreen(new GuiMainMenu()); } } diff --git a/src/main/java/net/minecraft/client/renderer/EntityRenderer.java b/src/main/java/net/minecraft/client/renderer/EntityRenderer.java index 882336a..73082d2 100644 --- a/src/main/java/net/minecraft/client/renderer/EntityRenderer.java +++ b/src/main/java/net/minecraft/client/renderer/EntityRenderer.java @@ -276,29 +276,25 @@ public class EntityRenderer implements IResourceManagerReloadListener { if (this.mc.getRenderViewEntity() == null) { this.mc.setRenderViewEntity(this.mc.thePlayer); } - if (!Config.skipRenderUpdate()) { - float f3 = this.mc.theWorld.getLightBrightness( - DeferredStateManager.isDeferredRenderer() ? new BlockPos(this.mc.getRenderViewEntity()).up() - : new BlockPos(this.mc.getRenderViewEntity())); - float f4 = (float) this.mc.gameSettings.renderDistanceChunks / 32.0F; - float f2 = f3 * (1.0F - f4) + f4; - this.fogColor1 += (f2 - this.fogColor1) * 0.1F; - } + float f3 = this.mc.theWorld.getLightBrightness( + DeferredStateManager.isDeferredRenderer() ? new BlockPos(this.mc.getRenderViewEntity()).up() + : new BlockPos(this.mc.getRenderViewEntity())); + float f4 = (float) this.mc.gameSettings.renderDistanceChunks / 32.0F; + float f2 = f3 * (1.0F - f4) + f4; + this.fogColor1 += (f2 - this.fogColor1) * 0.1F; ++this.rendererUpdateCount; this.addRainParticles(); - if (!Config.skipRenderUpdate()) { - this.itemRenderer.updateEquippedItem(); - this.bossColorModifierPrev = this.bossColorModifier; - if (BossStatus.hasColorModifier) { - this.bossColorModifier += 0.05F; - if (this.bossColorModifier > 1.0F) { - this.bossColorModifier = 1.0F; - } - - BossStatus.hasColorModifier = false; - } else if (this.bossColorModifier > 0.0F) { - this.bossColorModifier -= 0.0125F; + this.itemRenderer.updateEquippedItem(); + this.bossColorModifierPrev = this.bossColorModifier; + if (BossStatus.hasColorModifier) { + this.bossColorModifier += 0.05F; + if (this.bossColorModifier > 1.0F) { + this.bossColorModifier = 1.0F; } + + BossStatus.hasColorModifier = false; + } else if (this.bossColorModifier > 0.0F) { + this.bossColorModifier -= 0.0125F; } } diff --git a/src/main/java/net/minecraft/client/renderer/entity/RenderManager.java b/src/main/java/net/minecraft/client/renderer/entity/RenderManager.java index a76a9d5..d713ccc 100644 --- a/src/main/java/net/minecraft/client/renderer/entity/RenderManager.java +++ b/src/main/java/net/minecraft/client/renderer/entity/RenderManager.java @@ -4,6 +4,7 @@ import java.util.Map; import com.google.common.collect.Maps; +import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.hoosiertransfer.Config; import net.hoosiertransfer.CullingMod; import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; @@ -28,7 +29,6 @@ import net.minecraft.client.model.ModelSlime; import net.minecraft.client.model.ModelSquid; import net.minecraft.client.model.ModelWolf; import net.minecraft.client.model.ModelZombie; -import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.culling.ICamera; @@ -231,6 +231,12 @@ public class RenderManager { this.skinMap.put("default", this.playerRenderer); this.skinMap.put("slim", new RenderPlayer(this, true, false)); this.skinMap.put("zombie", new RenderPlayer(this, false, true)); + if (EagRuntime.getConfiguration().isAllowFNAWSkins()) { + this.eaglerRenderer = new RenderHighPoly(this, this.playerRenderer.getMainModel(), + this.playerRenderer.shadowSize); + } else { + this.eaglerRenderer = this.playerRenderer; + } this.eaglerRenderer = new RenderHighPoly(this, this.playerRenderer.getMainModel(), this.playerRenderer.shadowSize); this.skinMap.put("eagler", diff --git a/src/main/java/net/minecraft/client/renderer/entity/layers/LayerElytra.java b/src/main/java/net/minecraft/client/renderer/entity/layers/LayerElytra.java index b6dda9a..3ba0d81 100644 --- a/src/main/java/net/minecraft/client/renderer/entity/layers/LayerElytra.java +++ b/src/main/java/net/minecraft/client/renderer/entity/layers/LayerElytra.java @@ -34,7 +34,6 @@ public class LayerElytra implements LayerRenderer { GlStateManager.enableBlend(); this.renderPlayer.bindTexture(TEXTURE_ELYTRA); - // GlStateManager.pushMatrix(); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); GlStateManager.translate(0.0F, 0.0F, 0.125F); this.modelElytra.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, @@ -43,15 +42,6 @@ public class LayerElytra implements LayerRenderer { this.modelElytra.render(entitylivingbaseIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale); - - if (itemstack.isItemEnchanted()) { - LayerArmorBase.renderEnchantedGlint(this.renderPlayer, entitylivingbaseIn, - this.modelElytra, limbSwing, - limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, - scale); - DeferredStateManager.setHDRTranslucentPassBlendFunc(); - } - // GlStateManager.popMatrix(); } } diff --git a/src/main/java/net/minecraft/client/settings/GameSettings.java b/src/main/java/net/minecraft/client/settings/GameSettings.java index 6b0a25b..655bc68 100644 --- a/src/main/java/net/minecraft/client/settings/GameSettings.java +++ b/src/main/java/net/minecraft/client/settings/GameSettings.java @@ -231,8 +231,6 @@ public class GameSettings { public boolean disableAlpha = false; - public boolean skipHandRender = false; - public GameSettings(Minecraft mcIn) { this.keyBindings = (KeyBinding[]) ArrayUtils.addAll(new KeyBinding[] { this.keyBindAttack, this.keyBindUseItem, this.keyBindForward, this.keyBindLeft, this.keyBindBack, this.keyBindRight, this.keyBindJump, @@ -368,10 +366,6 @@ public class GameSettings { * through the list i.e. render distances. */ public void setOptionValue(GameSettings.Options parOptions, int parInt1) { - if (parOptions == GameSettings.Options.SKIP_SOME_RENDERING) { - this.skipHandRender = !this.skipHandRender; - } - if (parOptions == GameSettings.Options.DISABLE_ALPHA) { this.disableAlpha = !this.disableAlpha; } @@ -547,8 +541,6 @@ public class GameSettings { public boolean getOptionOrdinalValue(GameSettings.Options parOptions) { switch (parOptions) { - case SKIP_SOME_RENDERING: - return this.skipHandRender; case DISABLE_ALPHA: return this.disableAlpha; case ENABLE_SOUND: @@ -705,10 +697,6 @@ public class GameSettings { return flag ? "Hide Password: " + I18n.format("options.on", new Object[0]) : "Hide Password: " + I18n.format("options.off", new Object[0]); } - if (parOptions == GameSettings.Options.SKIP_SOME_RENDERING) { - return flag ? "Skip Some Rendering: " + I18n.format("options.on", new Object[0]) - : "Skip Some Rendering: " + I18n.format("options.off", new Object[0]); - } if (parOptions == GameSettings.Options.DISABLE_ALPHA) { return !flag ? "Render Alpha: " + I18n.format("options.on", new Object[0]) : "Render Alpha: " + I18n.format("options.off", new Object[0]); @@ -776,10 +764,6 @@ public class GameSettings { this.mouseSensitivity = this.parseFloat(astring[1]); } - if (astring[0].equals("skipHandRender")) { - this.skipHandRender = astring[1].equals("true"); - } - if (astring[0].equals("disableAlpha")) { this.disableAlpha = astring[1].equals("true"); } @@ -1173,7 +1157,6 @@ public class GameSettings { } printwriter.println("hidePassword:" + this.hidePassword); printwriter.println("enableSound:" + this.getOptionOrdinalValue(GameSettings.Options.ENABLE_SOUND)); - printwriter.println("skipHandRender:" + this.skipHandRender); printwriter.println("disableAlpha:" + this.disableAlpha); printwriter.println("resourcePacks:" + toJSONArray(this.resourcePacks)); @@ -1325,8 +1308,8 @@ public class GameSettings { } public static enum Options { - DISABLE_ALPHA("options.alpha", false, true), SKIP_SOME_RENDERING("options.skipHandRender", false, true), - INVERT_MOUSE("options.invertMouse", false, true), SENSITIVITY("options.sensitivity", true, false), + DISABLE_ALPHA("options.alpha", false, true), INVERT_MOUSE("options.invertMouse", false, true), + SENSITIVITY("options.sensitivity", true, false), FOV("options.fov", true, false, 30.0F, 110.0F, 1.0F), GAMMA("options.gamma", true, false), SATURATION("options.saturation", true, false), RENDER_SCALE("options.renderScale", true, false, 40.0F, 100.0F, 1.0F), diff --git a/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java b/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java index cc42fed..1dafe6a 100644 --- a/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java +++ b/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java @@ -868,7 +868,7 @@ public abstract class ServerConfigurationManager { worldIn.theItemInWorldManager.initializeGameType(parWorld.getWorldInfo().getGameType()); } else { - parEntityPlayerMP2.theItemInWorldManager.setGameType(lanGamemode); + worldIn.theItemInWorldManager.setGameType(lanGamemode); } } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java index 2858d8d..1f43838 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java @@ -29,14 +29,21 @@ import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils; /** * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -44,7 +51,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils; public class PlatformApplication { public static void openLink(String url) { - if(url.indexOf(':') == -1) { + if (url.indexOf(':') == -1) { url = "http://" + url; } Window.current().open(url, "_blank", "noopener,noreferrer"); @@ -53,15 +60,15 @@ public class PlatformApplication { public static void setClipboard(String text) { try { setClipboard0(text); - }catch(Throwable t) { + } catch (Throwable t) { PlatformRuntime.logger.error("Exception setting clipboard data"); } } - + public static String getClipboard() { try { return getClipboard0(); - }catch(Throwable t) { + } catch (Throwable t) { PlatformRuntime.logger.error("Exception getting clipboard data"); return ""; } @@ -71,63 +78,97 @@ public class PlatformApplication { private static interface StupidFunctionResolveString extends JSObject { void resolveStr(String s); } - + @Async private static native String getClipboard0(); - + private static void getClipboard0(final AsyncCallback cb) { final long start = System.currentTimeMillis(); getClipboard1(new StupidFunctionResolveString() { @Override public void resolveStr(String s) { - if(System.currentTimeMillis() - start > 500l) { + if (System.currentTimeMillis() - start > 500l) { PlatformInput.unpressCTRL = true; } cb.complete(s); } }); } - - @JSBody(params = { "cb" }, script = "if(!window.navigator.clipboard || !window.navigator.clipboard.readText) cb(\"\"); else window.navigator.clipboard.readText().then(function(s) { cb(s); }, function(s) { cb(\"\"); });") + + @JSBody(params = { + "cb" }, script = "if(!window.navigator.clipboard || !window.navigator.clipboard.readText) cb(\"\"); else window.navigator.clipboard.readText().then(function(s) { cb(s); }, function(s) { cb(\"\"); });") private static native void getClipboard1(StupidFunctionResolveString cb); - + @JSBody(params = { "str" }, script = "if(window.navigator.clipboard) window.navigator.clipboard.writeText(str);") private static native void setClipboard0(String str); - + public static void setLocalStorage(String name, byte[] data) { + setLocalStorage(name, data, true); + } + + public static void setLocalStorage(String name, byte[] data, boolean hooks) { + IClientConfigAdapter adapter = PlatformRuntime.getClientConfigAdapter(); + String eagName = adapter.getLocalStorageNamespace() + "." + name; + String b64 = Base64.encodeBase64String(data); try { Storage s = Window.current().getLocalStorage(); - if(s != null) { - if(data != null) { - s.setItem("_eaglercraftX." + name, Base64.encodeBase64String(data)); - }else { - s.removeItem("_eaglercraftX." + name); + if (s != null) { + if (data != null) { + s.setItem(eagName, b64); + } else { + s.removeItem(eagName); } } - }catch(Throwable t) { + } catch (Throwable t) { + } + if (hooks) { + adapter.getHooks().callLocalStorageSavedHook(name, b64); } } - + public static byte[] getLocalStorage(String name) { - try { - Storage s = Window.current().getLocalStorage(); - if(s != null) { - String str = s.getItem("_eaglercraftX." + name); - if(str != null) { - return Base64.decodeBase64(str); - }else { + return getLocalStorage(name, true); + } + + public static byte[] getLocalStorage(String name, boolean hooks) { + IClientConfigAdapter adapter = PlatformRuntime.getClientConfigAdapter(); + String eagName = adapter.getLocalStorageNamespace() + "." + name; + byte[] hooked = null; + if (hooks) { + String hookedStr = adapter.getHooks().callLocalStorageLoadHook(eagName); + if (hookedStr != null) { + try { + hooked = Base64.decodeBase64(hookedStr); + } catch (Throwable t) { + PlatformRuntime.logger.error("Invalid Base64 recieved from local storage hook!"); + hooked = null; + } + } + } + if (hooked == null) { + try { + Storage s = Window.current().getLocalStorage(); + if (s != null) { + String str = s.getItem(eagName); + if (str != null) { + return Base64.decodeBase64(str); + } else { + return null; + } + } else { return null; } - }else { + } catch (Throwable t) { return null; } - }catch(Throwable t) { + } else { return null; } } - - private static final DateFormat dateFormatSS = EagRuntime.fixDateFormat(new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")); - + + private static final DateFormat dateFormatSS = EagRuntime + .fixDateFormat(new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")); + public static String saveScreenshot() { String name = "screenshot_" + dateFormatSS.format(new Date()).toString() + ".png"; int w = PlatformRuntime.canvas.getWidth(); @@ -140,10 +181,11 @@ public class PlatformApplication { saveScreenshot(name, copyCanvas); return name; } - - @JSBody(params = { "name", "cvs" }, script = "var a=document.createElement(\"a\");a.href=cvs.toDataURL(\"image/png\");a.download=name;a.click();") + + @JSBody(params = { "name", + "cvs" }, script = "var a=document.createElement(\"a\");a.href=cvs.toDataURL(\"image/png\");a.download=name;a.click();") private static native void saveScreenshot(String name, HTMLCanvasElement cvs); - + public static void showPopup(final String msg) { Window.setTimeout(new TimerHandler() { @Override @@ -165,10 +207,11 @@ public class PlatformApplication { @Override public void accept(String name, ArrayBuffer buffer) { fileChooserHasResult = true; - if(name == null) { + if (name == null) { fileChooserResultObject = null; - }else { - fileChooserResultObject = new FileChooserResult(name, TeaVMUtils.wrapUnsignedByteArray(Uint8Array.create(buffer))); + } else { + fileChooserResultObject = new FileChooserResult(name, + TeaVMUtils.wrapUnsignedByteArray(Uint8Array.create(buffer))); } } @@ -177,8 +220,7 @@ public class PlatformApplication { private static volatile boolean fileChooserHasResult = false; private static volatile FileChooserResult fileChooserResultObject = null; - @JSBody(params = { "inputElement", "callback" }, script = - "if(inputElement.files.length > 0) {" + @JSBody(params = { "inputElement", "callback" }, script = "if(inputElement.files.length > 0) {" + "const value = inputElement.files[0];" + "value.arrayBuffer().then(function(arr){ callback(value.name, arr); })" + ".catch(function(){ callback(null, null); });" @@ -194,9 +236,9 @@ public class PlatformApplication { public static void displayFileChooser(String mime, String ext) { final HTMLInputElement inputElement = (HTMLInputElement) Window.current().getDocument().createElement("input"); inputElement.setType("file"); - if(mime == null) { + if (mime == null) { setAcceptSelection(inputElement, "." + ext); - }else { + } else { setAcceptSelection(inputElement, mime); } setMultipleSelection(inputElement, false); @@ -231,15 +273,16 @@ public class PlatformApplication { public static void openCreditsPopup(String text) { Window currentWin = Window.current(); - - int w = (int)(850 * currentWin.getDevicePixelRatio()); - int h = (int)(700 * currentWin.getDevicePixelRatio()); - + + int w = (int) (850 * currentWin.getDevicePixelRatio()); + int h = (int) (700 * currentWin.getDevicePixelRatio()); + int x = (currentWin.getScreen().getWidth() - w) / 2; int y = (currentWin.getScreen().getHeight() - h) / 2; - - Window newWin = Window.current().open("", "_blank", "top=" + y + ",left=" + x + ",width=" + w + ",height=" + h + ",menubar=0,status=0,titlebar=0,toolbar=0"); - if(newWin == null) { + + Window newWin = Window.current().open("", "_blank", "top=" + y + ",left=" + x + ",width=" + w + ",height=" + h + + ",menubar=0,status=0,titlebar=0,toolbar=0"); + if (newWin == null) { Window.alert("ERROR: Popup blocked!\n\nPlease make sure you have popups enabled for this site!"); return; } @@ -247,8 +290,9 @@ public class PlatformApplication { newWin.focus(); documentWrite(newWin.getDocument(), "" + "EaglercraftX 1.8 Credits" - + "" - + "
" + text + "
"); + + "" + + "
" + text + "
"); } public static void clearFileChooserResult() { @@ -256,11 +300,11 @@ public class PlatformApplication { fileChooserResultObject = null; } - @JSBody(params = { "name", "buf" }, script = - "var hr = window.URL.createObjectURL(new Blob([buf], {type: \"octet/stream\"}));" + - "var a = document.createElement(\"a\");" + - "a.href = hr; a.download = name; a.click();" + - "window.URL.revokeObjectURL(hr);") + @JSBody(params = { "name", + "buf" }, script = "var hr = window.URL.createObjectURL(new Blob([buf], {type: \"octet/stream\"}));" + + "var a = document.createElement(\"a\");" + + "a.href = hr; a.download = name; a.click();" + + "window.URL.revokeObjectURL(hr);") private static final native void downloadBytesImpl(String str, ArrayBuffer buf); public static final void downloadFileWithName(String str, byte[] dat) { diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java index 07d0c9c..38669ab 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java @@ -30,41 +30,50 @@ import net.lax1dude.eaglercraft.v1_8.log4j.Logger; import net.minecraft.util.MathHelper; /** - * Copyright (c) 2022-2023 LAX1DUDE. All Rights Reserved. + * Copyright (c) 2022-2023 lax1dude, hoosiertransfer. All Rights Reserved. * - * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES - * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED - * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE - * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. - * - * NOT FOR COMMERCIAL OR MALICIOUS USE - * - * (please read the 'LICENSE' file this repo's root directory for more info) + * 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 PlatformAudio { - + static final Logger logger = LogManager.getLogger("BrowserAudio"); - + static AudioContext audioctx = null; static MediaStreamAudioDestinationNode recDest = null; private static final Map soundCache = new HashMap(); - + private static long cacheFreeTimer = 0l; - + protected static class BrowserAudioResource implements IAudioResource { - + protected AudioBuffer buffer; protected long cacheHit = 0l; - + protected BrowserAudioResource(AudioBuffer buffer) { this.buffer = buffer; } - + } - + protected static class BrowserAudioHandle implements IAudioHandle, EventListener { - + protected final BrowserAudioResource resource; protected AudioBufferSourceNode source; protected final PannerNode panner; @@ -72,7 +81,7 @@ public class PlatformAudio { protected float pitch; protected boolean isPaused = false; protected boolean isEnded = false; - + public BrowserAudioHandle(BrowserAudioResource resource, AudioBufferSourceNode source, PannerNode panner, GainNode gain, float pitch) { this.resource = resource; @@ -85,13 +94,13 @@ public class PlatformAudio { @Override public void pause(boolean setPaused) { - if(setPaused) { - if(!isPaused) { + if (setPaused) { + if (!isPaused) { isPaused = true; source.getPlaybackRate().setValue(0.0f); } - }else { - if(isPaused) { + } else { + if (isPaused) { isPaused = false; source.getPlaybackRate().setValue(pitch); } @@ -100,7 +109,7 @@ public class PlatformAudio { @Override public void restart() { - if(isEnded) { + if (isEnded) { isEnded = false; AudioBufferSourceNode src = audioctx.createBufferSource(); resource.cacheHit = System.currentTimeMillis(); @@ -110,7 +119,7 @@ public class PlatformAudio { src.connect(panner == null ? gain : panner); source = src; source.start(); - }else { + } else { source.getPlaybackRate().setValue(pitch); source.start(0.0); } @@ -118,7 +127,7 @@ public class PlatformAudio { @Override public void move(float x, float y, float z) { - if(panner != null) { + if (panner != null) { panner.setPosition(x, y, z); } } @@ -126,26 +135,28 @@ public class PlatformAudio { @Override public void pitch(float f) { pitch = f; - if(!isPaused) { + if (!isPaused) { source.getPlaybackRate().setValue(pitch); } } @Override public void gain(float f) { - if(panner != null) { + if (panner != null) { float v1 = f * 16.0f; - if(v1 < 16.0f) v1 = 16.0f; + if (v1 < 16.0f) + v1 = 16.0f; panner.setMaxDistance(v1); } float v2 = f; - if(v2 > 1.0f) v2 = 1.0f; + if (v2 > 1.0f) + v2 = 1.0f; gain.getGain().setValue(v2); } @Override public void end() { - if(!isEnded) { + if (!isEnded) { isEnded = true; source.stop(); } @@ -160,26 +171,27 @@ public class PlatformAudio { public void handleEvent(MediaEvent evt) { isEnded = true; } - + } - + static void initialize() { - + try { audioctx = AudioContext.create(); recDest = audioctx.createMediaStreamDestination(); - }catch(Throwable t) { + } catch (Throwable t) { throw new PlatformRuntime.RuntimeInitializationFailureException("Could not initialize audio context!", t); } - + PlatformInput.clearEvenBuffers(); - + } private static GainNode micGain; public static void setMicVol(float vol) { - if (micGain == null) return; + if (micGain == null) + return; micGain.getGain().setValue(vol); } @@ -206,23 +218,25 @@ public class PlatformAudio { public static IAudioResource loadAudioData(String filename, boolean holdInCache) { BrowserAudioResource buffer; - synchronized(soundCache) { + synchronized (soundCache) { buffer = soundCache.get(filename); } - if(buffer == null) { + if (buffer == null) { byte[] file = PlatformAssets.getResourceBytes(filename); - if(file == null) return null; - buffer = new BrowserAudioResource(decodeAudioAsync(TeaVMUtils.unwrapUnsignedByteArray(file).getBuffer(), filename)); - if(holdInCache) { - synchronized(soundCache) { + if (file == null) + return null; + buffer = new BrowserAudioResource( + decodeAudioAsync(TeaVMUtils.unwrapUnsignedByteArray(file).getBuffer(), filename)); + if (holdInCache) { + synchronized (soundCache) { soundCache.put(filename, buffer); } } } - if(buffer.buffer != null) { + if (buffer.buffer != null) { buffer.cacheHit = System.currentTimeMillis(); return buffer; - }else { + } else { return null; } } @@ -233,33 +247,35 @@ public class PlatformAudio { public static IAudioResource loadAudioDataNew(String filename, boolean holdInCache, IAudioCacheLoader loader) { BrowserAudioResource buffer; - synchronized(soundCache) { + synchronized (soundCache) { buffer = soundCache.get(filename); } - if(buffer == null) { + if (buffer == null) { byte[] file = loader.loadFile(filename); - if(file == null) return null; + if (file == null) + return null; Uint8Array buf = Uint8Array.create(file.length); buf.set(file); buffer = new BrowserAudioResource(decodeAudioAsync(buf.getBuffer(), filename)); - if(holdInCache) { - synchronized(soundCache) { + if (holdInCache) { + synchronized (soundCache) { soundCache.put(filename, buffer); } } } - if(buffer.buffer != null) { + if (buffer.buffer != null) { buffer.cacheHit = System.currentTimeMillis(); return buffer; - }else { + } else { return null; } } - + @Async public static native AudioBuffer decodeAudioAsync(ArrayBuffer buffer, String errorFileName); - - private static void decodeAudioAsync(ArrayBuffer buffer, final String errorFileName, final AsyncCallback cb) { + + private static void decodeAudioAsync(ArrayBuffer buffer, final String errorFileName, + final AsyncCallback cb) { audioctx.decodeAudioData(buffer, new DecodeSuccessCallback() { @Override public void onSuccess(AudioBuffer decodedData) { @@ -276,12 +292,12 @@ public class PlatformAudio { public static void clearAudioCache() { long millis = System.currentTimeMillis(); - if(millis - cacheFreeTimer > 30000l) { + if (millis - cacheFreeTimer > 30000l) { cacheFreeTimer = millis; - synchronized(soundCache) { + synchronized (soundCache) { Iterator itr = soundCache.values().iterator(); - while(itr.hasNext()) { - if(millis - itr.next().cacheHit > 600000l) { // 10 minutes + while (itr.hasNext()) { + if (millis - itr.next().cacheHit > 600000l) { // 10 minutes itr.remove(); } } @@ -290,28 +306,29 @@ public class PlatformAudio { } public static void flushAudioCache() { - synchronized(soundCache) { + synchronized (soundCache) { soundCache.clear(); } } - + public static boolean available() { return true; // this is not used } - + public static IAudioHandle beginPlayback(IAudioResource track, float x, float y, float z, float volume, float pitch) { BrowserAudioResource internalTrack = (BrowserAudioResource) track; internalTrack.cacheHit = System.currentTimeMillis(); - + AudioBufferSourceNode src = audioctx.createBufferSource(); src.setBuffer(internalTrack.buffer); src.getPlaybackRate().setValue(pitch); - + PannerNode panner = audioctx.createPanner(); panner.setPosition(x, y, z); float v1 = volume * 16.0f; - if(v1 < 16.0f) v1 = 16.0f; + if (v1 < 16.0f) + v1 = 16.0f; panner.setMaxDistance(v1); panner.setRolloffFactor(1.0f); panner.setDistanceModel("linear"); @@ -320,41 +337,43 @@ public class PlatformAudio { panner.setConeOuterAngle(0.0f); panner.setConeOuterGain(0.0f); panner.setOrientation(0.0f, 1.0f, 0.0f); - + GainNode gain = audioctx.createGain(); float v2 = volume; - if(v2 > 1.0f) v2 = 1.0f; + if (v2 > 1.0f) + v2 = 1.0f; gain.getGain().setValue(v2); - + src.connect(panner); panner.connect(gain); gain.connect(audioctx.getDestination()); gain.connect(recDest); src.start(); - + return new BrowserAudioHandle(internalTrack, src, panner, gain, pitch); } public static IAudioHandle beginPlaybackStatic(IAudioResource track, float volume, float pitch) { BrowserAudioResource internalTrack = (BrowserAudioResource) track; internalTrack.cacheHit = System.currentTimeMillis(); - + AudioBufferSourceNode src = audioctx.createBufferSource(); src.setBuffer(internalTrack.buffer); src.getPlaybackRate().setValue(pitch); - + GainNode gain = audioctx.createGain(); float v2 = volume; - if(v2 > 1.0f) v2 = 1.0f; + if (v2 > 1.0f) + v2 = 1.0f; gain.getGain().setValue(v2); - + src.connect(gain); gain.connect(audioctx.getDestination()); gain.connect(recDest); - + src.start(); - + return new BrowserAudioHandle(internalTrack, src, null, gain, pitch); } @@ -367,5 +386,5 @@ public class PlatformAudio { l.setPosition(x, y, z); l.setOrientation(-var3 * var4, -var5, -var2 * var4, 0.0f, 1.0f, 0.0f); } - + } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java index d874b06..67e2379 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java @@ -23,7 +23,6 @@ import org.teavm.jso.webgl.WebGLRenderbuffer; import net.lax1dude.eaglercraft.v1_8.EagUtils; import net.lax1dude.eaglercraft.v1_8.internal.teavm.EarlyLoadScreen; import net.lax1dude.eaglercraft.v1_8.internal.teavm.WebGL2RenderingContext; -import net.minecraft.client.Minecraft; import static net.lax1dude.eaglercraft.v1_8.internal.teavm.WebGL2RenderingContext.*; import static org.teavm.jso.webgl.WebGLRenderingContext.COLOR_ATTACHMENT0; @@ -33,8 +32,6 @@ import static org.teavm.jso.webgl.WebGLRenderingContext.FRAMEBUFFER; import static org.teavm.jso.webgl.WebGLRenderingContext.NEAREST; import static org.teavm.jso.webgl.WebGLRenderingContext.RENDERBUFFER; -import net.lax1dude.eaglercraft.v1_8.internal.RenderResolution; - /** * Copyright (c) 2022-2023 lax1dude, hoosiertransfer, ayunami2000. All Rights * Reserved. @@ -123,6 +120,7 @@ public class PlatformInput { public static boolean lockKeys = false; private static boolean vsync = true; + private static boolean vsyncSupport = false; @JSBody(params = {}, script = "window.onbeforeunload = () => {return false;};") private static native void onBeforeCloseRegister(); @@ -274,7 +272,17 @@ public class PlatformInput { mouseDY = 0.0D; } }); - onBeforeCloseRegister(); + try { + onBeforeCloseRegister(); + } catch (Throwable t) { + } + + try { + asyncRequestAnimationFrame(); + vsyncSupport = true; + } catch (Throwable t) { + PlatformRuntime.logger.error("VSync is not supported on this browser!"); + } fullscreenQuery = fullscreenMediaQuery(); if (keyboardLockSupported = checkKeyboardLockSupported()) { @@ -322,6 +330,9 @@ public class PlatformInput { vsync = enable; } + @JSBody(params = { "doc" }, script = "return (doc.visibilityState === \"visible\");") + private static native boolean getVisibilityState(JSObject doc); + public static void update() { double r = win.getDevicePixelRatio(); int w = (int) (PlatformRuntime.parent.getClientWidth()); @@ -342,10 +353,14 @@ public class PlatformInput { PlatformRuntime.lastFrame = t; } } - if (vsync) { - asyncRequestAnimationFrame(); + if (getVisibilityState(win.getDocument())) { + if (vsyncSupport && vsync) { + asyncRequestAnimationFrame(); + } else { + EagUtils.sleep(0l); + } } else { - EagUtils.sleep(0l); + EagUtils.sleep(50l); } } @@ -370,6 +385,10 @@ public class PlatformInput { }, 50); } + public static boolean isVSyncSupported() { + return vsyncSupport; + } + static void initFramebuffer(WebGL2RenderingContext ctx, WebGLFramebuffer fbo, int sw, int sh) { context = ctx; mainFramebuffer = fbo; @@ -628,7 +647,7 @@ public class PlatformInput { keyEvents.clear(); } - @JSBody(params = {}, script = "return window.matchMedia('(display-mode: fullscreen)');") + @JSBody(params = {}, script = "return window.matchMedia(\"(display-mode: fullscreen)\");") private static native JSObject fullscreenMediaQuery(); @JSBody(params = { "mediaQuery" }, script = "return mediaQuery.matches;") diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/ClientMain.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/ClientMain.java index 4efb197..0fc50e0 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/ClientMain.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/ClientMain.java @@ -9,6 +9,7 @@ import org.teavm.jso.JSBody; import org.teavm.jso.JSFunctor; import org.teavm.jso.JSObject; import org.teavm.jso.browser.Window; +import org.teavm.jso.core.JSArrayReader; import org.teavm.jso.core.JSError; import org.teavm.jso.dom.css.CSSStyleDeclaration; import org.teavm.jso.dom.html.HTMLCanvasElement; @@ -21,7 +22,6 @@ import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion; import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication; import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsAssetsURI; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsAssetsURIsArray; import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsRoot; import net.lax1dude.eaglercraft.v1_8.log4j.ILogRedirector; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; @@ -32,22 +32,28 @@ import net.minecraft.client.main.Main; /** * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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 ClientMain { - - private static final String crashImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATEAAABxCAAAAACYIctsAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH6AMMAyAVwaqINwAADutJREFUeNrtXCt75EiWPb1bn4cckRoSIrskRGZIiuySFLfQIv2ALG7zqiGD3HhtXoka6QfIZJYoSS9Rki0ikS2iWLBFdJHJDIgIpZSpfLir3eXqTwHstFKPiBP3ce6JkH/4O+b2rPZPMwQzYjNiM2IzYjNic5sRmxGbEZsRmxGb24zYjNiM2IzYjNiM2NxmxGbEZsRmxGbE5jYj9iu1N7+HQQgAzoidx8l0EAACESBVM2Lnmrk3IpBORAC1mBE729rcOiN/BYcUjj7LCSf/fhETkV/PrJ4B+necK5mFwdej3qcOSP9LABGIO/67sTEmsdTbvP0qTxRQhKAQQqGAguGvV4pY0wUgn88PSBVW7VdYmP1BQCik0FqVEkodgkL3zSjKvQrE8kJIpbL4RePP4bXW/+g+ghYYEUhplgFIIQjuPeUVIGbqFh1qSX9z3lsWRoU6gU0hQhe3TF6xZhIp7qfRV4JYa75FlUABTNEAK6rQWZfv0J0AK0Nla4m9gPYKcuVWvkXeAAAEAJrceAJmDxoQwDpv7Hl7YewVICam/SaAkZAOQLkGSYCgAD6aQVViDwn5yiK/1PhWXun90CZEuGQpMADSaNkfGkH27W2slm8BGATA4m5FpPdKDMShA5GO9wlu0mVgU+geYGdtTM4kcbkwy8vRs5rmUur0qyo6hDBCpbBI6aKVUABKwIXUTRo5doFnsAupTdOKgAy1S7WjCqM1YlpLaUKlDs/YRaq6aUWgQh1xwD9tOVJ3nmWY/ovJy8lQq+g8aiJjmjtJxWzgim4/CAewEIAC4jAD6QLbxZxfTFk2NjYCAamTZFD4NlVTG4HAD/fgjB3dKstG7H2CYfezFcwtAM8t+LB2X2TDQTZVYWTXDZUm5+rvaj2gK+omPlIiWdKgZBfYaPksBZ6fga4kuAAxU64HEbnrUG/KVT/BUt7tnd91qDfFKj6wxDLfdoOTBgPL2FbD013KlGTQQVPmTTd6yHbiIXtd33bDiT8Wxwa1pHVSiI1bhruzDCC8xCulznMLfAC09oquMDfJriMK/QmdY3hduX2fjkdjiofOzleATjiMSgZihBM+1e58ocnzbqobJyEz3eC2k4j1UoWN6fZ0a2OgGXhu0xIBh2cdQ6x6KAkJbaFgysoeLck9E08jRUBM5c7oPmAEmcnvCABhqggxZe2sKHYxI2vq3QQKhKEio4F/5QSQRlSAqUo7kmqtTlWgohJxdikI9bFEQm9jPhN67YJe0yBMVzRZ4pIlT9lY9VASiFaLkARkUeS2r0U8DrxhZmdb6sfcecJaD0YjxT0BIMgyEjCLtUVWX4cAiEQbYwpPYNOYJLkLdhaw4MZ1Y6keOwBgGZ+K/0zi2j5HkkSrcLoyEwa0diQWLaePiQBibFaSEgDaiDKMZFOINeuKgCzdYgMTmsJeUS5Hs6tcRGEctIVjV4+D0dQulnOpAEAllq7yMcg0ACgFMW3t5jhNxhHD5DkBaN+NODDOyvLrU0amxFI8ybLpiCeQbcVIxzBO4BGLHAVADT4uVIg2aMvcrOid+ISNSbEBANk9Lkq2bnaz0ezuztDpxhlZmfWOII/OfHTkp39rOgDdPTPlk39/D6X2cwb3HuK6gW5zyshMsW4B4DbTx2QealOasoFRog1oaBRAsAGlBfJEBeiCrjFODxpG/wnEqqKzA+hPolYOj2YYq4PF7o9YV1670btE5xHvb7QsLfRrnZwjVsYZ6OAhC/bTcvzqpshbAOHqxHqchKwM1gCSBaJ1CYAZ4/LB32Ngj+Ee6z+skmRTu5sOApZ/eDXkdIMYjV1O2D2t9mlH97fyN22Lc7WRFI7dDMYd+c/N8aurj+sWQHSTqeNytepUBgBMlyZ0+ajcWN8aN637svOojdXOWHQwJM4uA1ee6igAwyVCesvq2n4+mkOl1H/i5hxixgXG0epH/8BWH6WvBQAkJ0ibUBBBFAxASdYu6gmgUoWyccFQAKgsQxtxmFInENu6gQ5DRR9tfAWyuJUWyaR+LDtS1x3XlkdkdnLozkBHtVef+I6IkFI9VACC63f6lFpNmFAybKooo1x3jY3ETEVi3FvPzGQNIEoi7Gv9byY05AmxNuj5pRAAkwQyRuIQMXyNKCHemhUnasRuGjEpf2wBhFmmzoljCKMK0DAM7L1MowwIhHE1NI02wp7W/+aohsxRV4NuH4WX3RoijY/RmPJKmagWfIERrVKeF3tUiiZTuVlubb0tZUQ2OvLj4sCqR8ZxaGON41hiiENz+UV2M3FRcGZxdlcqDbqxUyWmfLrJPzreeg4wigDUizCvwIXTTKjRaEhrGdHa68Mh6AnGEcR8r1gMymRpunNzNoFKbxE7TuJPk3NmYPpu1IMzt6fcOM9dBLxW5yVrEIzyCiiKnjADAO4iw6gcZbxRkXSAmBdWdjnzpAuK6cQuuFeHHYuCA/rUC67xhYihrS/oBoBN7YbJMg7PCUIUCkOjazNh3BItyp2iHqqxBDtlY7w0UJm2MW1jRcUp5a4nnE3hIXNESuKElzryhfHyfsdc8kV6NkwIhdplFZ00qvJUKGyUQlp451/wctX6XMRqqqaqBODR7UhR+tE9OKf1QuMJx+qcFfSmLkf86sShbh3p03HM3jcM7M3fXW9F3n2M1YNlNTqJF7biCKLwgDa8OSr5flhMPc2TdimLbX1m6xYz7yn1ulmGlHZjA5Hcnq2ResBul6e6MT7oYa7yG56OYzY4LTKjaNY6ampTibX/HDpKWlojo+LB/By3MR2frHZzp2wFJFVE1PnELW6k8gVTqQBjrHj9LjtrYpd1Y5R9r7Pmg/tcnvFLV/QwFAZCgtKVaKvBCoQV+etckktV69MBxORrO52RjrWNs+UEYojf55vWcXwfwQOdPmfP6qW0L8wyFWauE3V+yi+tlAhhuADZKYFKKWH3o1+yQJAQTQEY407mZWtJxx9ZOsDim/h0nojD+GG05B2q+Dp6Dvm9kADKKiNUtnXzsi1WPAWYQ0F1HyEGEkgCbKFoBFopKIlhtBEUiwSgCHjBWpKcEmLc2k6aXDb/WqxQzFDHis+yrAsR44IAosyt2HTlIjlFx8RW15bFCBRaoEMaFSWSmBQyZZKXgLShwkjp3EeMHFeQ0ybmyC0XZwlIvu4kXsWdCAiGF+/yDTyXe9bGHyaplSFRFZE6OSN2F6K40lUpCNaRXpTgMgABSVgAaLbBngO9OTq75gRivvYKzwJ2R0Q3yfNrUD9c1vKci3XWuNl8jE+VFc7NGNqNA/DcpwCiQLmvF3UDZWMejiuK9CiwOuoPsr0wKkt+T2D1CwDbSRbP3CsVeZzavD7r9iTvYq9lkTfKACv7l0AQB5bnjHtwoMEq7RE7uoWkw4S8MdXK9SWF8fTIe2GnfBZkapm6PRrlozldWpJAeq37mQ8SrJs06cvOEEsFg3BvX+cBYpH2xXJhzqWvQXaQZkpM6PYlwVMGOco1qmcHxfO2MFoREADzSs5mYSs0C0GCDPyQ7AZYFUX3NzF5zsYi75bF2dkdjLEsJmTUrU30VdM3c5CCGUxmRab+eJU/N/j7mvrUhTbu09BvHBYICZS2tBYIBC0YqX3p9JBdJKWv3NfYW7IRIYfasVTa22NeHZFRWa/HMmqo9Ehb8K7NcuS+cS8gFNwrEQYvi0xpTNeuNmNZHK8t7B5+Q4P3OQSiYFTnjisIhQaIA62H+xYBAP/81/17vX36/MV72hcGV75vT/+zyT9HBPD0s/HH/vwWgHxe/1QHf3iyB//4p+DpCgCe8s9OEfq8a82nT9vNz1+CK3/fq8+f7LCv/u9P4RUA+WKF8bf/7cPDp/9/O+jG559/+pvlzfL55//yJyGQH9w9A/FLTZ+e+oMT7QrgE83mX5Po6erp6e3TH55+wn/8e/wvwBWu5O3/fvrybxGvrq6ucHW6SkqNOJrefix1okKgE9NUYrrMeYw3qPIui9Buy6YLU945JvQXFetYYbRuNl4Tqbd51ldKWrundT82ywD1tr5Rtp7w1UKXbxZ9N2ojbWxNeG12ah7ygirJaLvXX1hw8U5fxJVteE8GZWwUTbKBCcS4Yp+Z63ozSJASuFARe0ZWbu1XcZoZ/8JLXZfBfyqAyebYnuCue6j9SKLY715q79cAutAluxT9hqy2LYJBN9y2g1yNJ8K4mK+ypu4PsjsqXROGhovcrXtDkKwWHL5xw6E+dKJKYqaKjdt8tJNdwGjh1qfVDcrB1xJeJwmZ3vcPsNwgafL6WKLscty6/RRpm/se2a1PPrClqtj0e3+6QTdiTlMbHzDj1HSHmeUgkAHKKHls3CsjBlA6VOLZxa6YPK9dMI2Salvv1iSEkVaR9oUH45vYb5ESRss41gAX/dtitEmbmSq37Tg+7579GGfOLd+FReXtRsWLOOzTXhjvdSOMdd8NJntxn32hkNbbg4PT9M3gfWV3QIkS6lDthAoORe7dJT8c+7/WpjZGWmPTGxXVuCY0dWNaA6hQabdJq7kXMrBMxkeDKl9zsOdFYHYyZHKn9m5GFSo1rgdPdEMO0vPu0h0VY3x2TYfKqbLl+n2Mc1XZD38/ySk7AEdeTLPfBrvNOWKcrQ9We8sip9wuhwtojds5h+h9cvxmF3fjlze/mUIIISGQdpvow2D3DMS+upkiryjZrR4vP5V2t1J4k+Fbt/5NCMvsZW/Gpt6wfMl3Rkye15R4NZ43auIDzyhwv1WjzZLcD1YnpIYXfGdEirwlsIoOwu0ifgVgDVyPftH7EvnuBREr8xaQRB/2IlCXKB+/oWvahHjZ2S/nlcZumYsnVMfOcZDXAZgXcy6cwJezsbo5IH87NAFAh/ge28shZsthTuiS0tQEgkR9l4i9eUljB8AiSkeaokCsGpMlmBEbNa1sHX5XJYqE18yNqTctIavs+zSxF2SwsnarmiKiI5sYxVRCEhKuUo0ZsYNkua65p5W6LbZpGn+nFvayVZLUm6LaT9rCKFlGr4aLvS7EAJHaNK0x9s3VAEoz0qH6fuF6ccScnrJ7m5y/4b/v+14R+921+X91zojNiM2IzYjNiM1tRmxGbEZsRmxGbG4zYjNiM2IzYjNiM2JzmxGbEZsR+37bPwAIcCklAqwqLgAAAABJRU5ErkJggg=="; + private static final String crashImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATEAAABxCAAAAACYIctsAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH6AMMAyAVwaqINwAADutJREFUeNrtXCt75EiWPb1bn4cckRoSIrskRGZIiuySFLfQIv2ALG7zqiGD3HhtXoka6QfIZJYoSS9Rki0ikS2iWLBFdJHJDIgIpZSpfLir3eXqTwHstFKPiBP3ce6JkH/4O+b2rPZPMwQzYjNiM2IzYjNic5sRmxGbEZsRmxGb24zYjNiM2IzYjNiM2NxmxGbEZsRmxGbE5jYj9iu1N7+HQQgAzoidx8l0EAACESBVM2Lnmrk3IpBORAC1mBE729rcOiN/BYcUjj7LCSf/fhETkV/PrJ4B+necK5mFwdej3qcOSP9LABGIO/67sTEmsdTbvP0qTxRQhKAQQqGAguGvV4pY0wUgn88PSBVW7VdYmP1BQCik0FqVEkodgkL3zSjKvQrE8kJIpbL4RePP4bXW/+g+ghYYEUhplgFIIQjuPeUVIGbqFh1qSX9z3lsWRoU6gU0hQhe3TF6xZhIp7qfRV4JYa75FlUABTNEAK6rQWZfv0J0AK0Nla4m9gPYKcuVWvkXeAAAEAJrceAJmDxoQwDpv7Hl7YewVICam/SaAkZAOQLkGSYCgAD6aQVViDwn5yiK/1PhWXun90CZEuGQpMADSaNkfGkH27W2slm8BGATA4m5FpPdKDMShA5GO9wlu0mVgU+geYGdtTM4kcbkwy8vRs5rmUur0qyo6hDBCpbBI6aKVUABKwIXUTRo5doFnsAupTdOKgAy1S7WjCqM1YlpLaUKlDs/YRaq6aUWgQh1xwD9tOVJ3nmWY/ovJy8lQq+g8aiJjmjtJxWzgim4/CAewEIAC4jAD6QLbxZxfTFk2NjYCAamTZFD4NlVTG4HAD/fgjB3dKstG7H2CYfezFcwtAM8t+LB2X2TDQTZVYWTXDZUm5+rvaj2gK+omPlIiWdKgZBfYaPksBZ6fga4kuAAxU64HEbnrUG/KVT/BUt7tnd91qDfFKj6wxDLfdoOTBgPL2FbD013KlGTQQVPmTTd6yHbiIXtd33bDiT8Wxwa1pHVSiI1bhruzDCC8xCulznMLfAC09oquMDfJriMK/QmdY3hduX2fjkdjiofOzleATjiMSgZihBM+1e58ocnzbqobJyEz3eC2k4j1UoWN6fZ0a2OgGXhu0xIBh2cdQ6x6KAkJbaFgysoeLck9E08jRUBM5c7oPmAEmcnvCABhqggxZe2sKHYxI2vq3QQKhKEio4F/5QSQRlSAqUo7kmqtTlWgohJxdikI9bFEQm9jPhN67YJe0yBMVzRZ4pIlT9lY9VASiFaLkARkUeS2r0U8DrxhZmdb6sfcecJaD0YjxT0BIMgyEjCLtUVWX4cAiEQbYwpPYNOYJLkLdhaw4MZ1Y6keOwBgGZ+K/0zi2j5HkkSrcLoyEwa0diQWLaePiQBibFaSEgDaiDKMZFOINeuKgCzdYgMTmsJeUS5Hs6tcRGEctIVjV4+D0dQulnOpAEAllq7yMcg0ACgFMW3t5jhNxhHD5DkBaN+NODDOyvLrU0amxFI8ybLpiCeQbcVIxzBO4BGLHAVADT4uVIg2aMvcrOid+ISNSbEBANk9Lkq2bnaz0ezuztDpxhlZmfWOII/OfHTkp39rOgDdPTPlk39/D6X2cwb3HuK6gW5zyshMsW4B4DbTx2QealOasoFRog1oaBRAsAGlBfJEBeiCrjFODxpG/wnEqqKzA+hPolYOj2YYq4PF7o9YV1670btE5xHvb7QsLfRrnZwjVsYZ6OAhC/bTcvzqpshbAOHqxHqchKwM1gCSBaJ1CYAZ4/LB32Ngj+Ee6z+skmRTu5sOApZ/eDXkdIMYjV1O2D2t9mlH97fyN22Lc7WRFI7dDMYd+c/N8aurj+sWQHSTqeNytepUBgBMlyZ0+ajcWN8aN637svOojdXOWHQwJM4uA1ee6igAwyVCesvq2n4+mkOl1H/i5hxixgXG0epH/8BWH6WvBQAkJ0ibUBBBFAxASdYu6gmgUoWyccFQAKgsQxtxmFInENu6gQ5DRR9tfAWyuJUWyaR+LDtS1x3XlkdkdnLozkBHtVef+I6IkFI9VACC63f6lFpNmFAybKooo1x3jY3ETEVi3FvPzGQNIEoi7Gv9byY05AmxNuj5pRAAkwQyRuIQMXyNKCHemhUnasRuGjEpf2wBhFmmzoljCKMK0DAM7L1MowwIhHE1NI02wp7W/+aohsxRV4NuH4WX3RoijY/RmPJKmagWfIERrVKeF3tUiiZTuVlubb0tZUQ2OvLj4sCqR8ZxaGON41hiiENz+UV2M3FRcGZxdlcqDbqxUyWmfLrJPzreeg4wigDUizCvwIXTTKjRaEhrGdHa68Mh6AnGEcR8r1gMymRpunNzNoFKbxE7TuJPk3NmYPpu1IMzt6fcOM9dBLxW5yVrEIzyCiiKnjADAO4iw6gcZbxRkXSAmBdWdjnzpAuK6cQuuFeHHYuCA/rUC67xhYihrS/oBoBN7YbJMg7PCUIUCkOjazNh3BItyp2iHqqxBDtlY7w0UJm2MW1jRcUp5a4nnE3hIXNESuKElzryhfHyfsdc8kV6NkwIhdplFZ00qvJUKGyUQlp451/wctX6XMRqqqaqBODR7UhR+tE9OKf1QuMJx+qcFfSmLkf86sShbh3p03HM3jcM7M3fXW9F3n2M1YNlNTqJF7biCKLwgDa8OSr5flhMPc2TdimLbX1m6xYz7yn1ulmGlHZjA5Hcnq2ResBul6e6MT7oYa7yG56OYzY4LTKjaNY6ampTibX/HDpKWlojo+LB/By3MR2frHZzp2wFJFVE1PnELW6k8gVTqQBjrHj9LjtrYpd1Y5R9r7Pmg/tcnvFLV/QwFAZCgtKVaKvBCoQV+etckktV69MBxORrO52RjrWNs+UEYojf55vWcXwfwQOdPmfP6qW0L8wyFWauE3V+yi+tlAhhuADZKYFKKWH3o1+yQJAQTQEY407mZWtJxx9ZOsDim/h0nojD+GG05B2q+Dp6Dvm9kADKKiNUtnXzsi1WPAWYQ0F1HyEGEkgCbKFoBFopKIlhtBEUiwSgCHjBWpKcEmLc2k6aXDb/WqxQzFDHis+yrAsR44IAosyt2HTlIjlFx8RW15bFCBRaoEMaFSWSmBQyZZKXgLShwkjp3EeMHFeQ0ybmyC0XZwlIvu4kXsWdCAiGF+/yDTyXe9bGHyaplSFRFZE6OSN2F6K40lUpCNaRXpTgMgABSVgAaLbBngO9OTq75gRivvYKzwJ2R0Q3yfNrUD9c1vKci3XWuNl8jE+VFc7NGNqNA/DcpwCiQLmvF3UDZWMejiuK9CiwOuoPsr0wKkt+T2D1CwDbSRbP3CsVeZzavD7r9iTvYq9lkTfKACv7l0AQB5bnjHtwoMEq7RE7uoWkw4S8MdXK9SWF8fTIe2GnfBZkapm6PRrlozldWpJAeq37mQ8SrJs06cvOEEsFg3BvX+cBYpH2xXJhzqWvQXaQZkpM6PYlwVMGOco1qmcHxfO2MFoREADzSs5mYSs0C0GCDPyQ7AZYFUX3NzF5zsYi75bF2dkdjLEsJmTUrU30VdM3c5CCGUxmRab+eJU/N/j7mvrUhTbu09BvHBYICZS2tBYIBC0YqX3p9JBdJKWv3NfYW7IRIYfasVTa22NeHZFRWa/HMmqo9Ehb8K7NcuS+cS8gFNwrEQYvi0xpTNeuNmNZHK8t7B5+Q4P3OQSiYFTnjisIhQaIA62H+xYBAP/81/17vX36/MV72hcGV75vT/+zyT9HBPD0s/HH/vwWgHxe/1QHf3iyB//4p+DpCgCe8s9OEfq8a82nT9vNz1+CK3/fq8+f7LCv/u9P4RUA+WKF8bf/7cPDp/9/O+jG559/+pvlzfL55//yJyGQH9w9A/FLTZ+e+oMT7QrgE83mX5Po6erp6e3TH55+wn/8e/wvwBWu5O3/fvrybxGvrq6ucHW6SkqNOJrefix1okKgE9NUYrrMeYw3qPIui9Buy6YLU945JvQXFetYYbRuNl4Tqbd51ldKWrundT82ywD1tr5Rtp7w1UKXbxZ9N2ojbWxNeG12ah7ygirJaLvXX1hw8U5fxJVteE8GZWwUTbKBCcS4Yp+Z63ozSJASuFARe0ZWbu1XcZoZ/8JLXZfBfyqAyebYnuCue6j9SKLY715q79cAutAluxT9hqy2LYJBN9y2g1yNJ8K4mK+ypu4PsjsqXROGhovcrXtDkKwWHL5xw6E+dKJKYqaKjdt8tJNdwGjh1qfVDcrB1xJeJwmZ3vcPsNwgafL6WKLscty6/RRpm/se2a1PPrClqtj0e3+6QTdiTlMbHzDj1HSHmeUgkAHKKHls3CsjBlA6VOLZxa6YPK9dMI2Salvv1iSEkVaR9oUH45vYb5ESRss41gAX/dtitEmbmSq37Tg+7579GGfOLd+FReXtRsWLOOzTXhjvdSOMdd8NJntxn32hkNbbg4PT9M3gfWV3QIkS6lDthAoORe7dJT8c+7/WpjZGWmPTGxXVuCY0dWNaA6hQabdJq7kXMrBMxkeDKl9zsOdFYHYyZHKn9m5GFSo1rgdPdEMO0vPu0h0VY3x2TYfKqbLl+n2Mc1XZD38/ySk7AEdeTLPfBrvNOWKcrQ9We8sip9wuhwtojds5h+h9cvxmF3fjlze/mUIIISGQdpvow2D3DMS+upkiryjZrR4vP5V2t1J4k+Fbt/5NCMvsZW/Gpt6wfMl3Rkye15R4NZ43auIDzyhwv1WjzZLcD1YnpIYXfGdEirwlsIoOwu0ifgVgDVyPftH7EvnuBREr8xaQRB/2IlCXKB+/oWvahHjZ2S/nlcZumYsnVMfOcZDXAZgXcy6cwJezsbo5IH87NAFAh/ge28shZsthTuiS0tQEgkR9l4i9eUljB8AiSkeaokCsGpMlmBEbNa1sHX5XJYqE18yNqTctIavs+zSxF2SwsnarmiKiI5sYxVRCEhKuUo0ZsYNkua65p5W6LbZpGn+nFvayVZLUm6LaT9rCKFlGr4aLvS7EAJHaNK0x9s3VAEoz0qH6fuF6ccScnrJ7m5y/4b/v+14R+921+X91zojNiM2IzYjNiM1tRmxGbEZsRmxGbG4zYjNiM2IzYjNiM2JzmxGbEZsR+37bPwAIcCklAqwqLgAAAABJRU5ErkJggg=="; // avoid inlining of constant private static String crashImageWrapper() { @@ -60,117 +66,121 @@ public class ClientMain { public static void _main() { PrintStream systemOut = System.out; PrintStream systemErr = System.err; - if(getRunningFlag()) { + if (getRunningFlag()) { systemErr.println("ClientMain: [ERROR] eaglercraftx is already running!"); return; } try { systemOut.println("ClientMain: [INFO] eaglercraftx is starting..."); JSObject opts = getEaglerXOpts(); - - if(opts == null) { + + if (opts == null) { systemErr.println("ClientMain: [ERROR] the \"window.eaglercraftXOpts\" variable is undefined"); systemErr.println("ClientMain: [ERROR] eaglercraftx cannot start"); Window.alert("ERROR: game cannot start, the \"window.eaglercraftXOpts\" variable is undefined"); return; } - + try { - JSEaglercraftXOptsRoot eaglercraftOpts = (JSEaglercraftXOptsRoot)opts; - + JSEaglercraftXOptsRoot eaglercraftOpts = (JSEaglercraftXOptsRoot) opts; + configRootElementId = eaglercraftOpts.getContainer(); - if(configRootElementId == null) { + if (configRootElementId == null) { throw new JSONException("window.eaglercraftXOpts.container is undefined!"); } configRootElement = Window.current().getDocument().getElementById(configRootElementId); - + String epkSingleURL = eaglercraftOpts.getAssetsURI(); - if(epkSingleURL != null) { + if (epkSingleURL != null) { configEPKFiles = new EPKFileEntry[] { new EPKFileEntry(epkSingleURL, "") }; - }else { - JSEaglercraftXOptsAssetsURIsArray epkURLs = eaglercraftOpts.getAssetsURIArray(); + } else { + JSArrayReader epkURLs = eaglercraftOpts.getAssetsURIArray(); int len = epkURLs.getLength(); - if(len == 0) { + if (len == 0) { throw new JSONException("assetsURI array cannot be empty!"); } configEPKFiles = new EPKFileEntry[len]; - for(int i = 0; i < len; ++i) { + for (int i = 0; i < len; ++i) { JSEaglercraftXOptsAssetsURI etr = epkURLs.get(i); String url = etr.getURL(); - if(url == null) { + if (url == null) { throw new JSONException("assetsURI is missing a url!"); } configEPKFiles[i] = new EPKFileEntry(url, etr.getPath("")); } } - + configLocalesFolder = eaglercraftOpts.getLocalesURI("lang"); - if(configLocalesFolder.endsWith("/")) { + if (configLocalesFolder.endsWith("/")) { configLocalesFolder = configLocalesFolder.substring(0, configLocalesFolder.length() - 1); } - - ((TeaVMClientConfigAdapter)TeaVMClientConfigAdapter.instance).loadNative(eaglercraftOpts); - + + ((TeaVMClientConfigAdapter) TeaVMClientConfigAdapter.instance).loadNative(eaglercraftOpts); + systemOut.println("ClientMain: [INFO] configuration was successful"); - }catch(Throwable t) { + } catch (Throwable t) { systemErr.println("ClientMain: [ERROR] the \"window.eaglercraftXOpts\" variable is invalid"); EagRuntime.debugPrintStackTraceToSTDERR(t); systemErr.println("ClientMain: [ERROR] eaglercraftx cannot start"); - Window.alert("ERROR: game cannot start, the \"window.eaglercraftXOpts\" variable is invalid: " + t.toString()); + Window.alert("ERROR: game cannot start, the \"window.eaglercraftXOpts\" variable is invalid: " + + t.toString()); return; } - + systemOut.println("ClientMain: [INFO] registering crash handlers"); - + setWindowErrorHandler(new WindowErrorHandler() { @Override public void call(String message, String file, int line, int col, JSError error) { StringBuilder str = new StringBuilder(); - + str.append("Native Browser Exception\n"); str.append("----------------------------------\n"); - str.append(" Line: ").append((file == null ? "unknown" : file) + ":" + line + ":" + col).append('\n'); + str.append(" Line: ").append((file == null ? "unknown" : file) + ":" + line + ":" + col) + .append('\n'); str.append(" Type: ").append(error == null ? "generic" : error.getName()).append('\n'); - - if(error != null) { - str.append(" Desc: ").append(error.getMessage() == null ? "null" : error.getMessage()).append('\n'); + + if (error != null) { + str.append(" Desc: ").append(error.getMessage() == null ? "null" : error.getMessage()) + .append('\n'); } - - if(message != null) { - if(error == null || error.getMessage() == null || !message.endsWith(error.getMessage())) { + + if (message != null) { + if (error == null || error.getMessage() == null || !message.endsWith(error.getMessage())) { str.append(" Desc: ").append(message).append('\n'); } } - + str.append("----------------------------------\n\n"); - str.append(error.getStack() == null ? "No stack trace is available" : error.getStack()).append('\n'); - + str.append(error.getStack() == null ? "No stack trace is available" : error.getStack()) + .append('\n'); + showCrashScreen(str.toString()); } - + }); - + systemOut.println("ClientMain: [INFO] initializing eaglercraftx runtime"); - + LogManager.logRedirector = new ILogRedirector() { @Override public void log(String txt, boolean err) { PlatformApplication.addLogMessage(txt, err); } }; - + try { EagRuntime.create(); - }catch(PlatformRuntime.PlatformIncompatibleException ex) { + } catch (PlatformRuntime.PlatformIncompatibleException ex) { systemErr.println("ClientMain: [ERROR] this browser is incompatible with eaglercraftx!"); systemErr.println("ClientMain: [ERROR] Reason: " + ex.getMessage()); try { showIncompatibleScreen(ex.getMessage()); - }catch(Throwable t) { + } catch (Throwable t) { } return; - }catch(Throwable t) { + } catch (Throwable t) { systemErr.println("ClientMain: [ERROR] eaglercraftx's runtime could not be initialized!"); EagRuntime.debugPrintStackTraceToSTDERR(t); showCrashScreen("EaglercraftX's runtime could not be initialized!", t); @@ -182,27 +192,27 @@ public class ClientMain { try { Main.appMain(new String[0]); - }catch(Throwable t) { + } catch (Throwable t) { systemErr.println("ClientMain: [ERROR] unhandled exception caused main thread to exit"); EagRuntime.debugPrintStackTraceToSTDERR(t); showCrashScreen("Unhandled exception caused main thread to exit!", t); } - - }finally { + + } finally { systemErr.println("ClientMain: [ERROR] eaglercraftx main thread has exited"); } } - + @JSBody(params = {}, script = "if(typeof window.eaglercraftXOpts === \"undefined\") {return null;}" + "else if(typeof window.eaglercraftXOpts === \"string\") {return JSON.parse(window.eaglercraftXOpts);}" + "else {return window.eaglercraftXOpts;}") private static native JSObject getEaglerXOpts(); public static class EPKFileEntry { - + public final String url; public final String path; - + protected EPKFileEntry(String url, String path) { this.url = url; this.path = path; @@ -210,15 +220,15 @@ public class ClientMain { } public static String configRootElementId = null; - public static HTMLElement configRootElement = null; + public static HTMLElement configRootElement = null; public static EPKFileEntry[] configEPKFiles = null; public static String configLocalesFolder = null; - + @JSFunctor private static interface WindowErrorHandler extends JSObject { void call(String message, String file, int line, int col, JSError error); } - + @JSBody(params = { "handler" }, script = "window.addEventListener(\"error\", function(e) { handler(" + "(typeof e.message === \"string\") ? e.message : null," + "(typeof e.filename === \"string\") ? e.filename : null," @@ -226,22 +236,22 @@ public class ClientMain { + "(typeof e.colno === \"number\") ? e.colno : 0," + "(typeof e.error === \"undefined\") ? null : e.error); });") public static native void setWindowErrorHandler(WindowErrorHandler handler); - + public static void showCrashScreen(String message, Throwable t) { try { showCrashScreen(message + "\n\n" + EagRuntime.getStackTrace(t)); - }catch(Throwable tt) { + } catch (Throwable tt) { } } private static boolean isCrashed = false; public static void showCrashScreen(String t) { - if(!isCrashed) { + if (!isCrashed) { isCrashed = true; - + HTMLDocument doc = Window.current().getDocument(); - if(configRootElement == null) { + if (configRootElement == null) { configRootElement = doc.getElementById(configRootElementId); } @@ -262,7 +272,8 @@ public class ClientMain { str.append(TeaVMClientConfigAdapter.instance.toString()).append('\n'); str.append('\n'); str.append("currentTime = "); - str.append(EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")).format(new Date())).append('\n'); + str.append(EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")).format(new Date())) + .append('\n'); str.append('\n'); addDebugNav(str, "userAgent"); addDebugNav(str, "vendor"); @@ -272,8 +283,10 @@ public class ClientMain { addDebugNav(str, "platform"); addDebugNav(str, "product"); str.append('\n'); - str.append("rootElement.clientWidth = ").append(el == null ? "undefined" : el.getClientWidth()).append('\n'); - str.append("rootElement.clientHeight = ").append(el == null ? "undefined" : el.getClientHeight()).append('\n'); + str.append("rootElement.clientWidth = ").append(el == null ? "undefined" : el.getClientWidth()) + .append('\n'); + str.append("rootElement.clientHeight = ").append(el == null ? "undefined" : el.getClientHeight()) + .append('\n'); addDebug(str, "innerWidth"); addDebug(str, "innerHeight"); addDebug(str, "outerWidth"); @@ -288,8 +301,8 @@ public class ClientMain { str.append('\n'); addDebugLocation(str, "href"); str.append('\n'); - - if(el == null) { + + if (el == null) { Window.alert("Root element not found, crash report was printed to console"); System.err.println(str.toString()); return; @@ -301,18 +314,19 @@ public class ClientMain { HTMLElement div = doc.createElement("div"); img.setAttribute("style", "z-index:100;position:absolute;top:10px;left:calc(50% - 151px);"); img.setAttribute("src", crashImageWrapper()); - div.setAttribute("style", "z-index:100;position:absolute;top:135px;left:10%;right:10%;bottom:50px;background-color:white;border:1px solid #cccccc;overflow-x:hidden;overflow-y:scroll;overflow-wrap:break-word;white-space:pre-wrap;font: 14px monospace;padding:10px;"); + div.setAttribute("style", + "z-index:100;position:absolute;top:135px;left:10%;right:10%;bottom:50px;background-color:white;border:1px solid #cccccc;overflow-x:hidden;overflow-y:scroll;overflow-wrap:break-word;white-space:pre-wrap;font: 14px monospace;padding:10px;"); el.appendChild(img); el.appendChild(div); div.appendChild(doc.createTextNode(str.toString())); - + PlatformRuntime.removeEventHandlers(); - }else { + } else { System.err.println(); System.err.println("An additional crash report was supressed:"); String[] s = t.split("[\\r\\n]+"); - for(int i = 0; i < s.length; ++i) { + for (int i = 0; i < s.length; ++i) { System.err.println(" " + s[i]); } } @@ -320,145 +334,160 @@ public class ClientMain { private static String addWebGLToCrash() { StringBuilder ret = new StringBuilder(); - + WebGLRenderingContext ctx = PlatformRuntime.webgl; - - if(ctx == null) { + + if (ctx == null) { HTMLCanvasElement cvs = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas"); - + cvs.setWidth(64); cvs.setHeight(64); - - ctx = (WebGLRenderingContext)cvs.getContext("webgl"); + + ctx = (WebGLRenderingContext) cvs.getContext("webgl"); } - - if(ctx != null) { - if(PlatformRuntime.webgl != null) { - ret.append("webgl.version = ").append(ctx.getParameterString(WebGLRenderingContext.VERSION)).append('\n'); + + if (ctx != null) { + if (PlatformRuntime.webgl != null) { + ret.append("webgl.version = ").append(ctx.getParameterString(WebGLRenderingContext.VERSION)) + .append('\n'); } - if(ctx.getExtension("WEBGL_debug_renderer_info") != null) { - ret.append("webgl.renderer = ").append(ctx.getParameterString(/* UNMASKED_RENDERER_WEBGL */ 0x9246)).append('\n'); - ret.append("webgl.vendor = ").append(ctx.getParameterString(/* UNMASKED_VENDOR_WEBGL */ 0x9245)).append('\n'); - }else { - ret.append("webgl.renderer = ").append(ctx.getParameterString(WebGLRenderingContext.RENDERER) + " [masked]").append('\n'); - ret.append("webgl.vendor = ").append(ctx.getParameterString(WebGLRenderingContext.VENDOR) + " [masked]").append('\n'); + if (ctx.getExtension("WEBGL_debug_renderer_info") != null) { + ret.append("webgl.renderer = ").append(ctx.getParameterString(/* UNMASKED_RENDERER_WEBGL */ 0x9246)) + .append('\n'); + ret.append("webgl.vendor = ").append(ctx.getParameterString(/* UNMASKED_VENDOR_WEBGL */ 0x9245)) + .append('\n'); + } else { + ret.append("webgl.renderer = ") + .append(ctx.getParameterString(WebGLRenderingContext.RENDERER) + " [masked]").append('\n'); + ret.append("webgl.vendor = ").append(ctx.getParameterString(WebGLRenderingContext.VENDOR) + " [masked]") + .append('\n'); } - //ret.append('\n').append("\nwebgl.anisotropicGlitch = ").append(DetectAnisotropicGlitch.hasGlitch()).append('\n'); //TODO - ret.append('\n').append("webgl.ext.HDR16f = ").append(ctx.getExtension("EXT_color_buffer_half_float") != null).append('\n'); + // ret.append('\n').append("\nwebgl.anisotropicGlitch = + // ").append(DetectAnisotropicGlitch.hasGlitch()).append('\n'); //TODO + ret.append('\n').append("webgl.ext.HDR16f = ") + .append(ctx.getExtension("EXT_color_buffer_half_float") != null).append('\n'); ret.append("webgl.ext.HDR32f = ").append(ctx.getExtension("EXT_color_buffer_float") != null).append('\n'); - - }else { + + } else { ret.append("Failed to query GPU info!\n"); } - + return ret.toString(); } public static void showIncompatibleScreen(String t) { - if(!isCrashed) { + if (!isCrashed) { isCrashed = true; - + HTMLDocument doc = Window.current().getDocument(); - if(configRootElement == null) { + if (configRootElement == null) { configRootElement = doc.getElementById(configRootElementId); } - + HTMLElement el = configRootElement; - - if(el == null) { + + if (el == null) { System.err.println("Compatibility error: " + t); return; } - + String s = el.getAttribute("style"); el.setAttribute("style", (s == null ? "" : s) + "position:relative;"); HTMLElement img = doc.createElement("img"); HTMLElement div = doc.createElement("div"); img.setAttribute("style", "z-index:100;position:absolute;top:10px;left:calc(50% - 151px);"); img.setAttribute("src", crashImageWrapper()); - div.setAttribute("style", "z-index:100;position:absolute;top:135px;left:10%;right:10%;bottom:50px;background-color:white;border:1px solid #cccccc;overflow-x:hidden;overflow-y:scroll;font:18px sans-serif;padding:40px;"); + div.setAttribute("style", + "z-index:100;position:absolute;top:135px;left:10%;right:10%;bottom:50px;background-color:white;border:1px solid #cccccc;overflow-x:hidden;overflow-y:scroll;font:18px sans-serif;padding:40px;"); el.appendChild(img); el.appendChild(div); - div.setInnerHTML("

+ This device is incompatible with Eaglercraft :(

" - + "
" - + "

Issue:

" - + "

" - + "

" - + "

Current Date: " + EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")).format(new Date()) + "

" - + "


Things you can try:

" - + "
    " - + "
  1. Just try using Eaglercraft on a different device, it isn't a bug it's common sense
  2. " - + "
  3. If you are on a mobile device, please try a proper desktop or a laptop computer
  4. " - + "
  5. If you are using a device with no mouse cursor, please use a device with a mouse cursor
  6. " - + "
  7. If you are not using Chrome/Edge, try installing the latest Google Chrome
  8. " - + "
  9. If your browser is out of date, please update it to the latest version
  10. " - + "
  11. If you are using an old OS such as Windows 7, please try Windows 10 or 11
  12. " - + "
  13. If you have a GPU launched before 2009, WebGL 2.0 support may be impossible
  14. " - + "
" - + "
"); - + div.setInnerHTML( + "

+ This device is incompatible with Eaglercraft :(

" + + "
" + + "

Issue:

" + + "

" + + "

" + + "

Current Date: " + + EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")) + .format(new Date()) + + "

" + + "


Things you can try:

" + + "
    " + + "
  1. Just try using Eaglercraft on a different device, it isn't a bug it's common sense
  2. " + + "
  3. If you are on a mobile device, please try a proper desktop or a laptop computer
  4. " + + "
  5. If you are using a device with no mouse cursor, please use a device with a mouse cursor
  6. " + + "
  7. If you are not using Chrome/Edge, try installing the latest Google Chrome
  8. " + + "
  9. If your browser is out of date, please update it to the latest version
  10. " + + "
  11. If you are using an old OS such as Windows 7, please try Windows 10 or 11
  12. " + + "
  13. If you have a GPU launched before 2009, WebGL 2.0 support may be impossible
  14. " + + "
" + + "
"); + div.querySelector("#crashReason").appendChild(doc.createTextNode(t)); div.querySelector("#crashUserAgent").appendChild(doc.createTextNode(getStringNav("userAgent"))); - + PlatformRuntime.removeEventHandlers(); - + String webGLRenderer = "No GL_RENDERER string could be queried"; - + try { HTMLCanvasElement cvs = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas"); - + cvs.setWidth(64); cvs.setHeight(64); - - WebGLRenderingContext ctx = (WebGLRenderingContext)cvs.getContext("webgl"); - - if(ctx != null) { + + WebGLRenderingContext ctx = (WebGLRenderingContext) cvs.getContext("webgl"); + + if (ctx != null) { String r; - if(ctx.getExtension("WEBGL_debug_renderer_info") != null) { + if (ctx.getExtension("WEBGL_debug_renderer_info") != null) { r = ctx.getParameterString(/* UNMASKED_RENDERER_WEBGL */ 0x9246); - }else { + } else { r = ctx.getParameterString(WebGLRenderingContext.RENDERER); - if(r != null) { + if (r != null) { r += " [masked]"; } } - if(r != null) { + if (r != null) { webGLRenderer = r; } } - }catch(Throwable tt) { + } catch (Throwable tt) { } - + div.querySelector("#crashWebGL").appendChild(doc.createTextNode(webGLRenderer)); - + } } private static HTMLElement integratedServerCrashPanel = null; public static void showIntegratedServerCrashReportOverlay(String report, int x, int y, int w, int h) { - if(integratedServerCrashPanel == null) { + if (integratedServerCrashPanel == null) { HTMLDocument doc = Window.current().getDocument(); - if(configRootElement == null) { + if (configRootElement == null) { configRootElement = doc.getElementById(configRootElementId); } - + integratedServerCrashPanel = doc.createElement("div"); - integratedServerCrashPanel.setAttribute("style", "z-index:99;position:absolute;background-color:black;color:white;overflow-x:hidden;overflow-y:scroll;overflow-wrap:break-word;white-space:pre-wrap;font:18px sans-serif;padding:20px;display:none;"); + integratedServerCrashPanel.setAttribute("style", + "z-index:99;position:absolute;background-color:black;color:white;overflow-x:hidden;overflow-y:scroll;overflow-wrap:break-word;white-space:pre-wrap;font:18px sans-serif;padding:20px;display:none;"); configRootElement.appendChild(integratedServerCrashPanel); } String sourceURL = ClientPlatformSingleplayer.getLoadedWorkerSourceURLTeaVM(); String workerURL = ClientPlatformSingleplayer.getLoadedWorkerURLTeaVM(); - String currentDate = EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")).format(new Date()); - if(workerURL != null) { - report = "WORKER SRC: " + sourceURL +"\nWORKER URL: " + workerURL + "\n\nCURRENT DATE: " + currentDate + "\n\n" + report.replaceAll(workerURL, ""); - }else { + String currentDate = EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")) + .format(new Date()); + if (workerURL != null) { + report = "WORKER SRC: " + sourceURL + "\nWORKER URL: " + workerURL + "\n\nCURRENT DATE: " + currentDate + + "\n\n" + report.replaceAll(workerURL, ""); + } else { report = "CURRENT DATE: " + currentDate + "\n\n" + report; } setInnerText(integratedServerCrashPanel, ""); setInnerText(integratedServerCrashPanel, report); CSSStyleDeclaration style = integratedServerCrashPanel.getStyle(); - float s = (float)Window.current().getDevicePixelRatio(); + float s = (float) Window.current().getDevicePixelRatio(); style.setProperty("top", "" + (y / s) + "px"); style.setProperty("left", "" + (x / s) + "px"); style.setProperty("width", "" + ((w / s) - 20) + "px"); @@ -467,7 +496,7 @@ public class ClientMain { } public static void hideIntegratedServerCrashReportOverlay() { - if(integratedServerCrashPanel != null) { + if (integratedServerCrashPanel != null) { integratedServerCrashPanel.getStyle().setProperty("display", "none"); } } @@ -507,7 +536,8 @@ public class ClientMain { str.append("window.").append(var).append(" = ").append(getArray(var)).append('\n'); } - @JSBody(params = { "v" }, script = "try { return (typeof window[v] !== \"undefined\") ? JSON.stringify(window[v]) : \"[\\\"\\\"]\"; } catch(e) { return \"[\\\"\\\"]\"; }") + @JSBody(params = { + "v" }, script = "try { return (typeof window[v] !== \"undefined\") ? JSON.stringify(window[v]) : \"[\\\"\\\"]\"; } catch(e) { return \"[\\\"\\\"]\"; }") private static native String getArray(String var); } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/DebugConsoleWindow.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/DebugConsoleWindow.java index f00fa87..d6ecbb3 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/DebugConsoleWindow.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/DebugConsoleWindow.java @@ -13,19 +13,27 @@ import org.teavm.jso.dom.html.HTMLDocument; import org.teavm.jso.dom.html.HTMLElement; import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication; +import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -33,15 +41,15 @@ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; public class DebugConsoleWindow { private static class LogMessage { - + private final boolean err; private final String msg; - + public LogMessage(boolean err, String msg) { this.err = err; this.msg = msg; } - + } private static final int bufferSpoolSize = 256; @@ -63,13 +71,15 @@ public class DebugConsoleWindow { destroyWindow(); } }); - if("true".equals(parent.getLocalStorage().getItem("_eaglercraftX.showDebugConsole"))) { + if ("true".equals(parent.getLocalStorage() + .getItem(PlatformRuntime.getClientConfigAdapter().getLocalStorageNamespace() + ".showDebugConsole"))) { showDebugConsole0(); } } public static void showDebugConsole() { - parent.getLocalStorage().setItem("_eaglercraftX.showDebugConsole", "true"); + parent.getLocalStorage().setItem( + PlatformRuntime.getClientConfigAdapter().getLocalStorageNamespace() + ".showDebugConsole", "true"); showDebugConsole0(); } @@ -77,26 +87,29 @@ public class DebugConsoleWindow { private static native void documentWrite(HTMLDocument doc, String str); private static void showDebugConsole0() { - if(logger == null) { - int w = (int)(1000 * parent.getDevicePixelRatio()); - int h = (int)(400 * parent.getDevicePixelRatio()); + if (logger == null) { + int w = (int) (1000 * parent.getDevicePixelRatio()); + int h = (int) (400 * parent.getDevicePixelRatio()); int x = (parent.getScreen().getWidth() - w) / 2; int y = (parent.getScreen().getHeight() - h) / 2; - logger = parent.open("", "_blank", "top=" + y + ",left=" + x + ",width=" + w + ",height=" + h + ",menubar=0,status=0,titlebar=0,toolbar=0"); - if(logger == null) { + logger = parent.open("", "_blank", "top=" + y + ",left=" + x + ",width=" + w + ",height=" + h + + ",menubar=0,status=0,titlebar=0,toolbar=0"); + if (logger == null) { LogManager.getLogger("DebugConsoleWindow").error("Logger popup was blocked!"); Window.alert("ERROR: Popup blocked!\n\nPlease make sure you have popups enabled for this site!"); return; } logger.focus(); - documentWrite(logger.getDocument(), "" - + "Debug Console" - + "

"); + documentWrite(logger.getDocument(), + "" + + "Debug Console" + + "

"); loggerDoc = logger.getDocument(); loggerBody = loggerDoc.getBody(); loggerMessageContainer = loggerDoc.getElementById("loggerMessageContainer"); - synchronized(messageBuffer) { - for(LogMessage msg : messageBuffer) { + synchronized (messageBuffer) { + for (LogMessage msg : messageBuffer) { appendLogMessage(msg.msg + "\n", msg.err ? "#DD0000" : "#000000"); } messageBuffer.clear(); @@ -105,7 +118,7 @@ public class DebugConsoleWindow { EventListener unloadListener = new EventListener() { @Override public void handleEvent(Event evt) { - if(logger != null) { + if (logger != null) { logger = null; parent.getLocalStorage().setItem("_eaglercraftX.showDebugConsole", "false"); } @@ -113,17 +126,17 @@ public class DebugConsoleWindow { }; logger.addEventListener("beforeunload", unloadListener); logger.addEventListener("unload", unloadListener); - }else { + } else { logger.focus(); } } public static void addLogMessage(String text, boolean isErr) { - if(logger == null) { - synchronized(messageBuffer) { - if(logger == null) { + if (logger == null) { + synchronized (messageBuffer) { + if (logger == null) { messageBuffer.add(new LogMessage(isErr, text)); - while(messageBuffer.size() > bufferSpoolSize) { + while (messageBuffer.size() > bufferSpoolSize) { messageBuffer.remove(0); } return; @@ -136,7 +149,7 @@ public class DebugConsoleWindow { private static void appendLogMessageAndScroll(String text, String color) { boolean b = isScrollToEnd(logger, loggerDoc); appendLogMessage(text, color); - if(b) { + if (b) { scrollToEnd0(logger, loggerDoc); } } @@ -147,7 +160,7 @@ public class DebugConsoleWindow { el.getStyle().setProperty("color", color); loggerMessageContainer.appendChild(el); HTMLCollection children = loggerMessageContainer.getChildren(); - while(children.getLength() > windowMaxMessages) { + while (children.getLength() > windowMaxMessages) { children.get(0).delete(); } } @@ -155,11 +168,12 @@ public class DebugConsoleWindow { @JSBody(params = { "win", "doc" }, script = "return (win.innerHeight + win.pageYOffset) >= doc.body.offsetHeight;") private static native boolean isScrollToEnd(Window win, HTMLDocument doc); - @JSBody(params = { "win", "doc" }, script = "setTimeout(function(){win.scrollTo(0, doc.body.scrollHeight || doc.body.clientHeight);}, 1);") + @JSBody(params = { "win", + "doc" }, script = "setTimeout(function(){win.scrollTo(0, doc.body.scrollHeight || doc.body.clientHeight);}, 1);") private static native void scrollToEnd0(Window win, HTMLDocument doc); public static void destroyWindow() { - if(logger != null) { + if (logger != null) { Window w = logger; logger = null; w.close(); diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapter.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapter.java index 61d1791..a97c6e3 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapter.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapter.java @@ -10,26 +10,34 @@ import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager; import org.json.JSONArray; import org.json.JSONObject; import org.teavm.jso.JSObject; +import org.teavm.jso.core.JSArrayReader; import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapter; +import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapterHooks; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsHooks; import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsRelay; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsRelaysArray; import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsRoot; import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsServer; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsServersArray; import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayEntry; /** * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -41,7 +49,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { private String defaultLocale = "en_US"; private List defaultServers = new ArrayList(); private List relays = new ArrayList(); - private String serverToJoin = null; + private String serverToJoin = null; private String worldsDB = "worlds"; private String resourcePacksDB = "resourcePacks"; private JSONObject integratedServerOpts; @@ -56,25 +64,37 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { private boolean checkRelaysForUpdates = false; private boolean enableSignatureBadge = false; private boolean allowVoiceClient = true; + private boolean allowFNAWSkins = true; + private String localStorageNamespace = "_eaglercraftX"; + private final TeaVMClientConfigAdapterHooks hooks = new TeaVMClientConfigAdapterHooks(); public void loadNative(JSObject jsObject) { integratedServerOpts = new JSONObject(); - JSEaglercraftXOptsRoot eaglercraftXOpts = (JSEaglercraftXOptsRoot)jsObject; - + JSEaglercraftXOptsRoot eaglercraftXOpts = (JSEaglercraftXOptsRoot) jsObject; + defaultLocale = eaglercraftXOpts.getLang("en_US"); serverToJoin = eaglercraftXOpts.getJoinServer(null); worldsDB = eaglercraftXOpts.getWorldsDB("worlds"); resourcePacksDB = eaglercraftXOpts.getResourcePacksDB("resourcePacks"); checkShaderGLErrors = eaglercraftXOpts.getCheckShaderGLErrors(false); demoMode = EaglercraftVersion.forceDemoMode || eaglercraftXOpts.getDemoMode(false); - isAllowUpdateSvc = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftXOpts.getAllowUpdateSvc(true); - isAllowUpdateDL = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftXOpts.getAllowUpdateDL(true); + isAllowUpdateSvc = EaglercraftVersion.enableUpdateService && !demoMode + && eaglercraftXOpts.getAllowUpdateSvc(true); + isAllowUpdateDL = EaglercraftVersion.enableUpdateService && !demoMode + && eaglercraftXOpts.getAllowUpdateDL(true); isEnableDownloadOfflineButton = eaglercraftXOpts.getEnableDownloadOfflineButton(true); downloadOfflineButtonLink = eaglercraftXOpts.getDownloadOfflineButtonLink(null); useSpecialCursors = eaglercraftXOpts.getHtml5CursorSupport(false); - logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftXOpts.getLogInvalidCerts(false); + logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode + && eaglercraftXOpts.getLogInvalidCerts(false); enableSignatureBadge = eaglercraftXOpts.getEnableSignatureBadge(false); allowVoiceClient = eaglercraftXOpts.getAllowVoiceClient(true); + allowFNAWSkins = eaglercraftXOpts.getAllowFNAWSkins(true); + localStorageNamespace = eaglercraftXOpts.getLocalStorageNamespace(EaglercraftVersion.localStorageNamespace); + JSEaglercraftXOptsHooks hooksObj = eaglercraftXOpts.getHooks(); + if (hooksObj != null) { + hooks.loadHooks(hooksObj); + } integratedServerOpts.put("worldsDB", worldsDB); integratedServerOpts.put("demoMode", demoMode); @@ -82,31 +102,32 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { integratedServerOpts.put("allowUpdateSvc", isAllowUpdateSvc); integratedServerOpts.put("allowUpdateDL", isAllowUpdateDL); integratedServerOpts.put("allowVoiceClient", allowVoiceClient); - - JSEaglercraftXOptsServersArray serversArray = eaglercraftXOpts.getServers(); - if(serversArray != null) { - for(int i = 0, l = serversArray.getLength(); i < l; ++i) { + integratedServerOpts.put("allowFNAWSkins", allowFNAWSkins); + + JSArrayReader serversArray = eaglercraftXOpts.getServers(); + if (serversArray != null) { + for (int i = 0, l = serversArray.getLength(); i < l; ++i) { JSEaglercraftXOptsServer serverEntry = serversArray.get(i); String serverAddr = serverEntry.getAddr(); - if(serverAddr != null) { + if (serverAddr != null) { String serverName = serverEntry.getName("Default Server #" + i); defaultServers.add(new DefaultServer(serverName, serverAddr)); } } } - - JSEaglercraftXOptsRelaysArray relaysArray = eaglercraftXOpts.getRelays(); - if(relaysArray != null) { + + JSArrayReader relaysArray = eaglercraftXOpts.getRelays(); + if (relaysArray != null) { boolean gotAPrimary = false; - for(int i = 0, l = relaysArray.getLength(); i < l; ++i) { + for (int i = 0, l = relaysArray.getLength(); i < l; ++i) { JSEaglercraftXOptsRelay relay = relaysArray.get(i); String addr = relay.getAddr(); - if(addr != null) { + if (addr != null) { boolean p = relay.getPrimary(); - if(p) { - if(gotAPrimary) { + if (p) { + if (gotAPrimary) { p = false; - }else { + } else { gotAPrimary = true; } } @@ -114,19 +135,21 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { } } } - - boolean officialUpdates = !demoMode && EaglercraftVersion.updateBundlePackageName.equals("net.lax1dude.eaglercraft.v1_8.client"); + + boolean officialUpdates = !demoMode + && EaglercraftVersion.updateBundlePackageName.equals("net.lax1dude.eaglercraft.v1_8.client"); if (relays.size() <= 0) { int choice = ThreadLocalRandom.current().nextInt(3); relays.add(new RelayEntry("wss://relay.deev.is/", "lax1dude relay #1", choice == 0)); relays.add(new RelayEntry("wss://relay.lax1dude.net/", "lax1dude relay #2", choice == 1)); relays.add(new RelayEntry("wss://relay.shhnowisnottheti.me/", "ayunami relay #1", choice == 2)); checkRelaysForUpdates = !demoMode && eaglercraftXOpts.getCheckRelaysForUpdates(officialUpdates); - }else { - if(officialUpdates) { - for(int i = 0, l = relays.size(); i < l; ++i) { + } else { + if (officialUpdates) { + for (int i = 0, l = relays.size(); i < l; ++i) { String addr = relays.get(i).address; - if(!addr.contains("deev.is") && !addr.contains("lax1dude.net") && !addr.contains("shhnowisnottheti.me")) { + if (!addr.contains("deev.is") && !addr.contains("lax1dude.net") + && !addr.contains("shhnowisnottheti.me")) { officialUpdates = false; break; } @@ -134,9 +157,9 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { } checkRelaysForUpdates = !demoMode && eaglercraftXOpts.getCheckRelaysForUpdates(officialUpdates); } - + RelayManager.relayManager.load(EagRuntime.getStorage("r")); - + if (RelayManager.relayManager.count() <= 0) { RelayManager.relayManager.loadDefaults(); RelayManager.relayManager.save(); @@ -150,24 +173,30 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { worldsDB = eaglercraftOpts.optString("worldsDB", "worlds"); resourcePacksDB = eaglercraftOpts.optString("resourcePacksDB", "resourcePacks"); checkShaderGLErrors = eaglercraftOpts.optBoolean("checkShaderGLErrors", false); - if(EaglercraftVersion.forceDemoMode) { + if (EaglercraftVersion.forceDemoMode) { eaglercraftOpts.put("demoMode", true); } demoMode = EaglercraftVersion.forceDemoMode || eaglercraftOpts.optBoolean("demoMode", false); - isAllowUpdateSvc = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftOpts.optBoolean("allowUpdateSvc", true); - isAllowUpdateDL = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftOpts.optBoolean("allowUpdateDL", true); + isAllowUpdateSvc = EaglercraftVersion.enableUpdateService && !demoMode + && eaglercraftOpts.optBoolean("allowUpdateSvc", true); + isAllowUpdateDL = EaglercraftVersion.enableUpdateService && !demoMode + && eaglercraftOpts.optBoolean("allowUpdateDL", true); isEnableDownloadOfflineButton = eaglercraftOpts.optBoolean("enableDownloadOfflineButton", true); downloadOfflineButtonLink = eaglercraftOpts.optString("downloadOfflineButtonLink", null); useSpecialCursors = eaglercraftOpts.optBoolean("html5CursorSupport", false); - logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftOpts.optBoolean("logInvalidCerts", false); + logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode + && eaglercraftOpts.optBoolean("logInvalidCerts", false); enableSignatureBadge = eaglercraftOpts.optBoolean("enableSignatureBadge", false); allowVoiceClient = eaglercraftOpts.optBoolean("allowVoiceClient", true); + allowFNAWSkins = eaglercraftOpts.optBoolean("allowFNAWSkins", true); + localStorageNamespace = eaglercraftOpts.optString("localStorageNamespace", + EaglercraftVersion.localStorageNamespace); JSONArray serversArray = eaglercraftOpts.optJSONArray("servers"); - if(serversArray != null) { - for(int i = 0, l = serversArray.length(); i < l; ++i) { + if (serversArray != null) { + for (int i = 0, l = serversArray.length(); i < l; ++i) { JSONObject serverEntry = serversArray.getJSONObject(i); String serverAddr = serverEntry.optString("addr", null); - if(serverAddr != null) { + if (serverAddr != null) { String serverName = serverEntry.optString("name", "Default Server #" + i); defaultServers.add(new DefaultServer(serverName, serverAddr)); } @@ -175,15 +204,15 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { } JSONArray relaysArray = eaglercraftOpts.optJSONArray("relays"); - if(relaysArray != null) { + if (relaysArray != null) { boolean gotAPrimary = false; for (int i = 0, l = relaysArray.length(); i < l; ++i) { JSONObject relay = relaysArray.getJSONObject(i); boolean p = relay.optBoolean("primary"); - if(p) { - if(gotAPrimary) { + if (p) { + if (gotAPrimary) { p = false; - }else { + } else { gotAPrimary = true; } } @@ -191,18 +220,20 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { } } - boolean officialUpdates = !demoMode && EaglercraftVersion.updateBundlePackageName.equals("net.lax1dude.eaglercraft.v1_8.client"); + boolean officialUpdates = !demoMode + && EaglercraftVersion.updateBundlePackageName.equals("net.lax1dude.eaglercraft.v1_8.client"); if (relays.size() <= 0) { int choice = ThreadLocalRandom.current().nextInt(3); relays.add(new RelayEntry("wss://relay.deev.is/", "lax1dude relay #1", choice == 0)); relays.add(new RelayEntry("wss://relay.lax1dude.net/", "lax1dude relay #2", choice == 1)); relays.add(new RelayEntry("wss://relay.shhnowisnottheti.me/", "ayunami relay #1", choice == 2)); checkRelaysForUpdates = !demoMode && eaglercraftOpts.optBoolean("checkRelaysForUpdates", officialUpdates); - }else { - if(officialUpdates) { - for(int i = 0, l = relays.size(); i < l; ++i) { + } else { + if (officialUpdates) { + for (int i = 0, l = relays.size(); i < l; ++i) { String addr = relays.get(i).address; - if(!addr.contains("deev.is") && !addr.contains("lax1dude.net") && !addr.contains("shhnowisnottheti.me")) { + if (!addr.contains("deev.is") && !addr.contains("lax1dude.net") + && !addr.contains("shhnowisnottheti.me")) { officialUpdates = false; break; } @@ -210,9 +241,9 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { } checkRelaysForUpdates = !demoMode && eaglercraftOpts.optBoolean("checkRelaysForUpdates", officialUpdates); } - + RelayManager.relayManager.load(EagRuntime.getStorage("r")); - + if (RelayManager.relayManager.count() <= 0) { RelayManager.relayManager.loadDefaults(); RelayManager.relayManager.save(); @@ -309,6 +340,21 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { return allowVoiceClient; } + @Override + public boolean isAllowFNAWSkins() { + return allowFNAWSkins; + } + + @Override + public String getLocalStorageNamespace() { + return localStorageNamespace; + } + + @Override + public IClientConfigAdapterHooks getHooks() { + return hooks; + } + @Override public String toString() { JSONObject jsonObject = new JSONObject(); @@ -327,8 +373,10 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { jsonObject.put("checkRelaysForUpdates", checkRelaysForUpdates); jsonObject.put("enableSignatureBadge", enableSignatureBadge); jsonObject.put("allowVoiceClient", allowVoiceClient); + jsonObject.put("allowFNAWSkins", allowFNAWSkins); + jsonObject.put("localStorageNamespace", localStorageNamespace); JSONArray serversArr = new JSONArray(); - for(int i = 0, l = defaultServers.size(); i < l; ++i) { + for (int i = 0, l = defaultServers.size(); i < l; ++i) { DefaultServer srv = defaultServers.get(i); JSONObject obj = new JSONObject(); obj.put("addr", srv.addr); @@ -337,7 +385,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { } jsonObject.put("servers", serversArr); JSONArray relaysArr = new JSONArray(); - for(int i = 0, l = relays.size(); i < l; ++i) { + for (int i = 0, l = relays.size(); i < l; ++i) { RelayEntry rl = relays.get(i); JSONObject obj = new JSONObject(); obj.put("addr", rl.address); diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapterHooks.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapterHooks.java new file mode 100644 index 0000000..31c1906 --- /dev/null +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapterHooks.java @@ -0,0 +1,108 @@ +package net.lax1dude.eaglercraft.v1_8.internal.teavm; + +import java.util.function.Supplier; + +import org.teavm.interop.Async; +import org.teavm.interop.AsyncCallback; +import org.teavm.jso.JSFunctor; +import org.teavm.jso.JSObject; +import org.teavm.jso.browser.Window; + +import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapterHooks; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsHooks; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; + +/** + * 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 TeaVMClientConfigAdapterHooks implements IClientConfigAdapterHooks { + + private static final Logger logger = LogManager.getLogger("TeaVMClientConfigAdapterHooks"); + + private LocalStorageSaveHook saveHook = null; + private LocalStorageLoadHook loadHook = null; + + @JSFunctor + private static interface LocalStorageSaveHook extends JSObject { + void call(String key, String base64); + } + + @Override + public void callLocalStorageSavedHook(String key, String base64) { + if (saveHook != null) { + callHookSafe("localStorageSaved", () -> { + saveHook.call(key, base64); + }); + } + } + + @JSFunctor + private static interface LocalStorageLoadHook extends JSObject { + String call(String key); + } + + @Override + public String callLocalStorageLoadHook(String key) { + if (loadHook != null) { + return (String) callHookSafeWithReturn("localStorageLoaded", () -> { + return loadHook.call(key); + }); + } else { + return null; + } + } + + private static void callHookSafe(String identifer, Runnable hooker) { + Window.setTimeout(() -> { + try { + hooker.run(); + } catch (Throwable t) { + logger.error("Caught exception while invoking eaglercraftXOpts \"{}\" hook!", identifer); + logger.error(t); + } + }, 0); + } + + @Async + private static native Object callHookSafeWithReturn(String identifer, Supplier hooker); + + private static void callHookSafeWithReturn(String identifer, Supplier hooker, + final AsyncCallback cb) { + Window.setTimeout(() -> { + Object res = null; + try { + res = hooker.get(); + } catch (Throwable t) { + logger.error("Caught exception while invoking eaglercraftXOpts \"{}\" hook!", identifer); + logger.error(t); + } finally { + cb.complete(res); + } + }, 0); + } + + public void loadHooks(JSEaglercraftXOptsHooks hooks) { + saveHook = (LocalStorageSaveHook) hooks.getLocalStorageSavedHook(); + loadHook = (LocalStorageLoadHook) hooks.getLocalStorageLoadedHook(); + } +} diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsAssetsURIsArray.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsAssetsURIsArray.java index de08a40..b16ac1e 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsAssetsURIsArray.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsAssetsURIsArray.java @@ -7,14 +7,21 @@ import org.teavm.jso.JSProperty; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -22,7 +29,7 @@ import org.teavm.jso.JSProperty; public interface JSEaglercraftXOptsAssetsURIsArray extends JSObject { @JSIndexer - JSEaglercraftXOptsAssetsURI get(int idx); + JSEaglercraftXOptsHooks get(int idx); @JSProperty int getLength(); diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsServersArray.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsHooks.java similarity index 57% rename from src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsServersArray.java rename to src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsHooks.java index 3299302..25d81a0 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsServersArray.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsHooks.java @@ -1,30 +1,36 @@ package net.lax1dude.eaglercraft.v1_8.internal.teavm.opts; -import org.teavm.jso.JSIndexer; +import org.teavm.jso.JSBody; import org.teavm.jso.JSObject; -import org.teavm.jso.JSProperty; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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 JSEaglercraftXOptsServersArray extends JSObject { +public abstract class JSEaglercraftXOptsHooks implements JSObject { - @JSIndexer - JSEaglercraftXOptsServer get(int idx); + @JSBody(script = "return (typeof this.localStorageSaved === \"function\") ? this.localStorageSaved : null;") + public native JSObject getLocalStorageSavedHook(); - @JSProperty - int getLength(); + @JSBody(script = "return (typeof this.localStorageLoaded === \"function\") ? this.localStorageLoaded : null;") + public native JSObject getLocalStorageLoadedHook(); } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRoot.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRoot.java index 9e1e4a0..56ee89e 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRoot.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRoot.java @@ -2,18 +2,26 @@ package net.lax1dude.eaglercraft.v1_8.internal.teavm.opts; import org.teavm.jso.JSBody; import org.teavm.jso.JSObject; +import org.teavm.jso.core.JSArrayReader; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -27,7 +35,7 @@ public abstract class JSEaglercraftXOptsRoot implements JSObject { public native String getAssetsURI(); @JSBody(script = "return (typeof this.assetsURI === \"object\") ? this.assetsURI : null;") - public native JSEaglercraftXOptsAssetsURIsArray getAssetsURIArray(); + public native JSArrayReader getAssetsURIArray(); @JSBody(params = { "def" }, script = "return (typeof this.lang === \"string\") ? this.lang : def;") public native String getLang(String defaultValue); @@ -41,45 +49,68 @@ public abstract class JSEaglercraftXOptsRoot implements JSObject { @JSBody(params = { "def" }, script = "return (typeof this.worldsDB === \"string\") ? this.worldsDB : def;") public native String getWorldsDB(String defaultValue); - @JSBody(params = { "def" }, script = "return (typeof this.resourcePacksDB === \"string\") ? this.resourcePacksDB : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.resourcePacksDB === \"string\") ? this.resourcePacksDB : def;") public native String getResourcePacksDB(String defaultValue); @JSBody(params = { "def" }, script = "return (typeof this.demoMode === \"boolean\") ? this.demoMode : def;") public native boolean getDemoMode(boolean defaultValue); @JSBody(script = "return (typeof this.servers === \"object\") ? this.servers : null;") - public native JSEaglercraftXOptsServersArray getServers(); + public native JSArrayReader getServers(); @JSBody(script = "return (typeof this.relays === \"object\") ? this.relays : null;") - public native JSEaglercraftXOptsRelaysArray getRelays(); + public native JSArrayReader getRelays(); - @JSBody(params = { "def" }, script = "return (typeof this.checkShaderGLErrors === \"boolean\") ? this.checkShaderGLErrors : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.checkShaderGLErrors === \"boolean\") ? this.checkShaderGLErrors : def;") public native boolean getCheckShaderGLErrors(boolean defaultValue); - @JSBody(params = { "def" }, script = "return (typeof this.enableDownloadOfflineButton === \"boolean\") ? this.enableDownloadOfflineButton : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.enableDownloadOfflineButton === \"boolean\") ? this.enableDownloadOfflineButton : def;") public native boolean getEnableDownloadOfflineButton(boolean defaultValue); - @JSBody(params = { "def" }, script = "return (typeof this.downloadOfflineButtonLink === \"string\") ? this.downloadOfflineButtonLink : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.downloadOfflineButtonLink === \"string\") ? this.downloadOfflineButtonLink : def;") public native String getDownloadOfflineButtonLink(String defaultValue); - @JSBody(params = { "def" }, script = "return (typeof this.html5CursorSupport === \"boolean\") ? this.html5CursorSupport : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.html5CursorSupport === \"boolean\") ? this.html5CursorSupport : def;") public native boolean getHtml5CursorSupport(boolean defaultValue); - @JSBody(params = { "def" }, script = "return (typeof this.allowUpdateSvc === \"boolean\") ? this.allowUpdateSvc : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.allowUpdateSvc === \"boolean\") ? this.allowUpdateSvc : def;") public native boolean getAllowUpdateSvc(boolean defaultValue); - @JSBody(params = { "def" }, script = "return (typeof this.allowUpdateDL === \"boolean\") ? this.allowUpdateDL : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.allowUpdateDL === \"boolean\") ? this.allowUpdateDL : def;") public native boolean getAllowUpdateDL(boolean defaultValue); - @JSBody(params = { "def" }, script = "return (typeof this.logInvalidCerts === \"boolean\") ? this.logInvalidCerts : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.logInvalidCerts === \"boolean\") ? this.logInvalidCerts : def;") public native boolean getLogInvalidCerts(boolean defaultValue); - @JSBody(params = { "def" }, script = "return (typeof this.enableSignatureBadge === \"boolean\") ? this.enableSignatureBadge : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.enableSignatureBadge === \"boolean\") ? this.enableSignatureBadge : def;") public native boolean getEnableSignatureBadge(boolean defaultValue); - @JSBody(params = { "def" }, script = "return (typeof this.checkRelaysForUpdates === \"boolean\") ? this.checkRelaysForUpdates : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.checkRelaysForUpdates === \"boolean\") ? this.checkRelaysForUpdates : def;") public native boolean getCheckRelaysForUpdates(boolean defaultValue); - @JSBody(params = { "def" }, script = "return (typeof this.allowVoiceClient === \"boolean\") ? this.allowVoiceClient : def;") + @JSBody(params = { + "def" }, script = "return (typeof this.allowVoiceClient === \"boolean\") ? this.allowVoiceClient : def;") public native boolean getAllowVoiceClient(boolean defaultValue); + + @JSBody(params = { + "def" }, script = "return (typeof this.allowFNAWSkins === \"boolean\") ? this.allowFNAWSkins : def;") + public native boolean getAllowFNAWSkins(boolean defaultValue); + + @JSBody(script = "return (typeof this.hooks === \"object\") ? this.hooks : null;") + public native JSEaglercraftXOptsHooks getHooks(); + + @JSBody(params = { + "def" }, script = "return (typeof this.localStorageNamespace === \"string\") ? this.localStorageNamespace : def;") + public native String getLocalStorageNamespace(String defaultValue); + } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/sp/server/internal/teavm/WorkerMain.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/sp/server/internal/teavm/WorkerMain.java index 7ea61c1..2c33f95 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/sp/server/internal/teavm/WorkerMain.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/sp/server/internal/teavm/WorkerMain.java @@ -18,16 +18,24 @@ import net.lax1dude.eaglercraft.v1_8.sp.server.EaglerIntegratedServerWorker; import net.lax1dude.eaglercraft.v1_8.sp.server.internal.ServerPlatformSingleplayer; /** - * Copyright (c) 2023-2024 lax1dude, hoosiertransfer, ayunami2000. All Rights Reserved. + * Copyright (c) 2023-2024 lax1dude, hoosiertransfer, ayunami2000. All Rights + * Reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * 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) + * 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. * @@ -41,25 +49,28 @@ public class WorkerMain { __println(systemOut, false, "WorkerMain: [INFO] eaglercraftx worker thread is starting..."); String startArgs = getStartArgs(); __println(systemOut, false, "WorkerMain: [INFO] reading configuration"); - if(startArgs == null) { + if (startArgs == null) { throw new NullPointerException("startup arguments is null!"); } - ((TeaVMClientConfigAdapter)TeaVMClientConfigAdapter.instance).loadJSON(new JSONObject(startArgs)); + ((TeaVMClientConfigAdapter) TeaVMClientConfigAdapter.instance).loadJSON(new JSONObject(startArgs)); __println(systemOut, false, "WorkerMain: [INFO] initializing server runtime"); EaglerIntegratedServerWorker.enableLoggingRedirector(true); ServerPlatformSingleplayer.initializeContext(); __println(systemOut, false, "WorkerMain: [INFO] starting worker thread"); PlatformRuntime.setThreadName("IntegratedServer"); EaglerIntegratedServerWorker.serverMain(); - }catch(Throwable t) { + } catch (Throwable t) { System.setOut(systemOut); System.setErr(systemErr); __println(systemErr, true, "WorkerMain: [ERROR] uncaught exception thrown!"); EaglerIntegratedServerWorker.sendLogMessagePacket(EagRuntime.getStackTrace(t), true); EagRuntime.debugPrintStackTraceToSTDERR(t); - EaglerIntegratedServerWorker.sendIPCPacket(new IPCPacket15Crashed("UNCAUGHT EXCEPTION CAUGHT IN WORKER PROCESS!\n\n" + EagRuntime.getStackTrace(t))); - EaglerIntegratedServerWorker.sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacketFFProcessKeepAlive.EXITED)); - }finally { + EaglerIntegratedServerWorker.sendIPCPacket(new IPCPacket15Crashed( + "UNCAUGHT EXCEPTION CAUGHT IN WORKER PROCESS!\n\n" + EagRuntime.getStackTrace(t))); + EaglerIntegratedServerWorker + .sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacketFFProcessKeepAlive.EXITED)); + + } finally { __println(systemErr, true, "WorkerMain: [ERROR] eaglercraftx worker thread has exited"); } } @@ -68,7 +79,7 @@ public class WorkerMain { stream.println(msg); try { EaglerIntegratedServerWorker.sendLogMessagePacket(msg, err); - }catch(Throwable t) { + } catch (Throwable t) { } }