diff --git a/desktopRuntime/d3dcompiler_47.dll b/desktopRuntime/d3dcompiler_47.dll index 7f2da62..8e07cf7 100755 Binary files a/desktopRuntime/d3dcompiler_47.dll and b/desktopRuntime/d3dcompiler_47.dll differ diff --git a/desktopRuntime/libEGL.dll b/desktopRuntime/libEGL.dll index 6332cc1..3c5b773 100755 Binary files a/desktopRuntime/libEGL.dll and b/desktopRuntime/libEGL.dll differ diff --git a/desktopRuntime/libEGL.so b/desktopRuntime/libEGL.so index 7d0cf97..12e971c 100755 Binary files a/desktopRuntime/libEGL.so and b/desktopRuntime/libEGL.so differ diff --git a/desktopRuntime/libGLESv2.dll b/desktopRuntime/libGLESv2.dll index c179d16..0450fe4 100755 Binary files a/desktopRuntime/libGLESv2.dll and b/desktopRuntime/libGLESv2.dll differ diff --git a/desktopRuntime/libGLESv2.so b/desktopRuntime/libGLESv2.so index 354cb86..da548ec 100755 Binary files a/desktopRuntime/libGLESv2.so and b/desktopRuntime/libGLESv2.so differ diff --git a/desktopRuntime/libvulkan.so.1 b/desktopRuntime/libvulkan.so.1 index bdfd842..735842f 100755 Binary files a/desktopRuntime/libvulkan.so.1 and b/desktopRuntime/libvulkan.so.1 differ diff --git a/desktopRuntime/resources/plugin_download.zip b/desktopRuntime/resources/plugin_download.zip index 7b99d4b..7ce5830 100755 Binary files a/desktopRuntime/resources/plugin_download.zip and b/desktopRuntime/resources/plugin_download.zip differ diff --git a/desktopRuntime/resources/plugin_version.json b/desktopRuntime/resources/plugin_version.json index 56a0adb..d002100 100755 --- a/desktopRuntime/resources/plugin_version.json +++ b/desktopRuntime/resources/plugin_version.json @@ -1 +1 @@ -{"pluginName":"EaglercraftXBungee","pluginVersion":"1.1.0","pluginButton":"Download \"EaglerXBungee-1.1.0.jar\"","pluginFilename":"EaglerXBungee.zip"} \ No newline at end of file +{"pluginName":"EaglercraftXBungee","pluginVersion":"1.2.0","pluginButton":"Download \"EaglerXBungee-1.2.0.jar\"","pluginFilename":"EaglerXBungee.zip"} \ No newline at end of file diff --git a/desktopRuntime/resources/relay_download.zip b/desktopRuntime/resources/relay_download.zip index 7b644bc..dc97f94 100755 Binary files a/desktopRuntime/resources/relay_download.zip and b/desktopRuntime/resources/relay_download.zip differ diff --git a/desktopRuntime/vulkan-1.dll b/desktopRuntime/vulkan-1.dll index 2b703e3..20093ef 100755 Binary files a/desktopRuntime/vulkan-1.dll and b/desktopRuntime/vulkan-1.dll 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 7289c53..936d536 100755 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java @@ -64,8 +64,12 @@ public class PlatformApplication { String str = glfwGetClipboardString(win); return str == null ? "" : str; } - + 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 { @@ -76,8 +80,12 @@ 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 da4dd22..5aec52d 100755 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java @@ -230,6 +230,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 e0c69c5..476ebc6 100755 --- 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,6 +8,7 @@ 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; /** @@ -31,6 +32,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"; @@ -129,4 +132,32 @@ public class DesktopClientConfigAdapter implements IClientConfigAdapter { 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/lax1dude/eaglercraft/v1_8/Display.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java index defa278..360723e 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java @@ -49,6 +49,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 b6a04af..319a4a3 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java @@ -10,7 +10,7 @@ public class EaglercraftVersion { /// Customize these to fit your fork: public static final String projectForkName = "EaglercraftX"; - public static final String projectForkVersion = "u29"; + public static final String projectForkVersion = "u30"; public static final String projectForkVendor = "lax1dude"; public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; @@ -20,7 +20,7 @@ public class EaglercraftVersion { public static final String projectOriginName = "EaglercraftX"; public static final String projectOriginAuthor = "lax1dude"; public static final String projectOriginRevision = "1.8"; - public static final String projectOriginVersion = "u29"; + public static final String projectOriginVersion = "u30"; public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace @@ -31,7 +31,7 @@ public class EaglercraftVersion { public static final boolean enableUpdateService = true; 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; @@ -60,4 +60,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 72ba8cf..32a4ff2 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapter.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapter.java @@ -69,4 +69,11 @@ 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 72% 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 a3b0710..3236026 100755 --- 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,8 +1,4 @@ -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. @@ -19,12 +15,10 @@ import org.teavm.jso.JSProperty; * 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 cdb2b45..044d59a 100755 --- 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,6 +13,21 @@ 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"); 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 83382e0..54c796d 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/EaglerSkinTexture.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/EaglerSkinTexture.java @@ -61,7 +61,7 @@ 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 4149e63..e56cfaa 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditProfile.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditProfile.java @@ -73,14 +73,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; } @@ -106,6 +112,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 : DefaultSkins.getSkinFromId(skid).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 01c9ae8..116bbb7 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportExportProfile.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportExportProfile.java @@ -56,11 +56,15 @@ public class GuiScreenImportExportProfile extends GuiScreen { FileChooserResult result = EagRuntime.getFileChooserResult(); 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) { + try { + importer.close(); + } catch (IOException e) { + } EagRuntime.debugPrintStackTrace(ex); mc.displayGuiScreen(new GuiScreenGenericErrorMessage("settingsBackup.importing.failed.1", "settingsBackup.importing.failed.2", back)); } 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 b214798..e46fd60 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportProfile.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenImportProfile.java @@ -62,6 +62,14 @@ public class GuiScreenImportProfile extends GuiScreen { 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) { 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 6726f52..0d0e8f5 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileExporter.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileExporter.java @@ -69,98 +69,97 @@ public class ProfileExporter { 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:> byte[] ret = osb.toByteArray(); 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 def291f..026338d 100755 --- 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; @@ -29,7 +30,7 @@ import net.minecraft.client.multiplayer.ServerList; * POSSIBILITY OF SUCH DAMAGE. * */ -public class ProfileImporter { +public class ProfileImporter implements Closeable { private static final Logger logger = LogManager.getLogger("ProfileImporter"); @@ -148,4 +149,9 @@ public class ProfileImporter { } 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 020db6d..1422c4c 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/RenderHighPoly.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/RenderHighPoly.java @@ -468,4 +468,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); + } + } } 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 f289da0..d0d1d5f 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinModel.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinModel.java @@ -46,7 +46,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/sp/gui/GuiShareToLan.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiShareToLan.java index b0b24b7..63a458b 100755 --- 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 @@ -156,7 +156,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 49c4aa1..b959b23 100755 --- 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 @@ -340,9 +340,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 99af1d1..b54c7e3 100755 --- 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 @@ -479,7 +479,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 ad08945..0761458 100755 --- 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; @@ -24,7 +25,7 @@ import net.lax1dude.eaglercraft.v1_8.IOUtils; * POSSIBILITY OF SUCH DAMAGE. * */ -public class EPKDecompiler { +public class EPKDecompiler implements Closeable { public static class FileEntry { public final String type; @@ -178,4 +179,9 @@ public class EPKDecompiler { 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 2ad3c5d..c20629c 100755 --- 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 @@ -40,44 +40,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 75b0641..4ddf2e2 100755 --- 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 @@ -50,111 +50,113 @@ 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)); - - 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!"); + 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); + + 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()); @@ -172,129 +174,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 80ae085..65ec712 100755 --- 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 @@ -243,9 +243,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 caacd61..c9e1e88 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/RelayUpdateChecker.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/RelayUpdateChecker.java @@ -64,7 +64,7 @@ public class RelayUpdateChecker { for(net.lax1dude.eaglercraft.v1_8.sp.relay.RelayEntry etr : EagRuntime.getConfiguration().getRelays()) { relaysList.add(new RelayEntry(etr.address)); } - byte[] b = PlatformApplication.getLocalStorage("lastRelayUpdate"); + byte[] b = PlatformApplication.getLocalStorage("lastRelayUpdate", false); if(b != null) { try { lastUpdateCheck = (new DataInputStream(new EaglerInputStream(b))).readLong(); @@ -79,7 +79,7 @@ public class RelayUpdateChecker { 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) { 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 63df0b0..86a47e0 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateCertificate.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateCertificate.java @@ -148,7 +148,16 @@ public class UpdateCertificate { 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 { 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 1548eed..8b74e15 100755 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateService.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateService.java @@ -94,7 +94,7 @@ public class UpdateService { } } } - byte[] latestUpdate = PlatformApplication.getLocalStorage(EaglercraftVersion.updateLatestLocalStorageKey); + byte[] latestUpdate = PlatformApplication.getLocalStorage(EaglercraftVersion.updateLatestLocalStorageKey, false); if(latestUpdate != null) { addCertificateToSet(latestUpdate, false); } @@ -150,7 +150,7 @@ public class UpdateService { latestUpdateFound = cert; if (saveLatest) { PlatformApplication.setLocalStorage(EaglercraftVersion.updateLatestLocalStorageKey, - certificateData); + certificateData, false); } } }else if(EagRuntime.getConfiguration().isLogInvalidCerts()) { diff --git a/src/main/java/net/minecraft/client/Minecraft.java b/src/main/java/net/minecraft/client/Minecraft.java index eb4c7ce..138c897 100755 --- a/src/main/java/net/minecraft/client/Minecraft.java +++ b/src/main/java/net/minecraft/client/Minecraft.java @@ -21,6 +21,7 @@ import com.google.common.collect.Lists; 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; @@ -788,7 +789,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(); } @@ -876,7 +887,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 e6ae622..0da27e5 100755 --- a/src/main/java/net/minecraft/client/audio/SoundHandler.java +++ b/src/main/java/net/minecraft/client/audio/SoundHandler.java @@ -49,6 +49,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(); @@ -83,6 +84,10 @@ public class SoundHandler implements IResourceManagerReloadListener, ITickable { } } + 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"); + } } public static class SoundMap { 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 7475903..7726ece 100755 --- 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.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper; import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; @@ -218,8 +219,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)); - this.eaglerRenderer = new RenderHighPoly(this, this.playerRenderer.getMainModel(), - this.playerRenderer.shadowSize); + if (EagRuntime.getConfiguration().isAllowFNAWSkins()) { + this.eaglerRenderer = new RenderHighPoly(this, this.playerRenderer.getMainModel(), + this.playerRenderer.shadowSize); + } else { + this.eaglerRenderer = this.playerRenderer; + } this.skinMap.put("eagler", Minecraft.getMinecraft().gameSettings.enableFNAWSkins ? this.eaglerRenderer : this.playerRenderer); } diff --git a/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java b/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java index 3a8d9d4..12bb42c 100755 --- a/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java +++ b/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java @@ -835,7 +835,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 052ad22..77f0be3 100755 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java @@ -95,34 +95,66 @@ public class PlatformApplication { 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)); + s.setItem(eagName, b64); }else { - s.removeItem("_eaglercraftX." + name); + s.removeItem(eagName); } } }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); + 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) { - return null; + }else { + return hooked; } } 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 6d1e3b0..b12a3af 100755 --- 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,16 +30,18 @@ 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. 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 { 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 be7efd1..b9606c2 100755 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java @@ -102,8 +102,9 @@ public class PlatformInput { public static boolean keyboardLockSupported = false; 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(); @@ -252,7 +253,18 @@ 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()) { @@ -300,6 +312,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 = PlatformRuntime.parent.getClientWidth(); @@ -320,10 +335,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); } } @@ -348,6 +367,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; @@ -599,7 +622,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 3732f49..4f970c3 100755 --- 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; @@ -87,7 +87,7 @@ public class ClientMain { if(epkSingleURL != null) { configEPKFiles = new EPKFileEntry[] { new EPKFileEntry(epkSingleURL, "") }; }else { - JSEaglercraftXOptsAssetsURIsArray epkURLs = eaglercraftOpts.getAssetsURIArray(); + JSArrayReader epkURLs = eaglercraftOpts.getAssetsURIArray(); int len = epkURLs.getLength(); if(len == 0) { throw new JSONException("assetsURI array cannot be empty!"); 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 b916cd7..cef537b 100755 --- 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,6 +13,7 @@ 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; /** @@ -63,13 +64,13 @@ 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(); } 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 3bb147a..c0587a5 100755 --- 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,13 +10,14 @@ 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; /** @@ -56,6 +57,9 @@ 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(); @@ -75,6 +79,12 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { 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,8 +92,9 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { integratedServerOpts.put("allowUpdateSvc", isAllowUpdateSvc); integratedServerOpts.put("allowUpdateDL", isAllowUpdateDL); integratedServerOpts.put("allowVoiceClient", allowVoiceClient); + integratedServerOpts.put("allowFNAWSkins", allowFNAWSkins); - JSEaglercraftXOptsServersArray serversArray = eaglercraftXOpts.getServers(); + JSArrayReader serversArray = eaglercraftXOpts.getServers(); if(serversArray != null) { for(int i = 0, l = serversArray.getLength(); i < l; ++i) { JSEaglercraftXOptsServer serverEntry = serversArray.get(i); @@ -95,7 +106,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { } } - JSEaglercraftXOptsRelaysArray relaysArray = eaglercraftXOpts.getRelays(); + JSArrayReader relaysArray = eaglercraftXOpts.getRelays(); if(relaysArray != null) { boolean gotAPrimary = false; for(int i = 0, l = relaysArray.getLength(); i < l; ++i) { @@ -162,6 +173,8 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { 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) { @@ -309,6 +322,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,6 +355,8 @@ 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) { DefaultServer srv = defaultServers.get(i); 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 100755 index 0000000..2c462db --- /dev/null +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapterHooks.java @@ -0,0 +1,100 @@ +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/JSEaglercraftXOptsHooks.java similarity index 67% rename from src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsAssetsURIsArray.java rename to src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsHooks.java index 038df76..e1beb7a 100755 --- 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/JSEaglercraftXOptsHooks.java @@ -1,8 +1,7 @@ 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. @@ -19,12 +18,12 @@ import org.teavm.jso.JSProperty; * POSSIBILITY OF SUCH DAMAGE. * */ -public interface JSEaglercraftXOptsAssetsURIsArray extends JSObject { +public abstract class JSEaglercraftXOptsHooks implements JSObject { - @JSIndexer - JSEaglercraftXOptsAssetsURI 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 bfee147..1127d84 100755 --- 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,6 +2,7 @@ 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. @@ -27,7 +28,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); @@ -48,10 +49,10 @@ public abstract class JSEaglercraftXOptsRoot implements JSObject { 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;") public native boolean getCheckShaderGLErrors(boolean defaultValue); @@ -83,4 +84,13 @@ public abstract class JSEaglercraftXOptsRoot implements JSObject { @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/internal/teavm/opts/JSEaglercraftXOptsServersArray.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsServersArray.java deleted file mode 100755 index ce4f070..0000000 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsServersArray.java +++ /dev/null @@ -1,30 +0,0 @@ -package net.lax1dude.eaglercraft.v1_8.internal.teavm.opts; - -import org.teavm.jso.JSIndexer; -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 - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ -public interface JSEaglercraftXOptsServersArray extends JSObject { - - @JSIndexer - JSEaglercraftXOptsServer get(int idx); - - @JSProperty - int getLength(); - -}