Update #30 - Fixed various client bugs
This commit is contained in:
parent
32fda35ace
commit
c6ac781036
31
README.md
31
README.md
|
@ -153,6 +153,37 @@ The default eaglercraftXOpts values is this:
|
||||||
- `enableSignatureBadge:` show a badge on the title screen indicating if digital signature is valid
|
- `enableSignatureBadge:` show a badge on the title screen indicating if digital signature is valid
|
||||||
- `checkRelaysForUpdates:` proprietary feature used in offline downloads
|
- `checkRelaysForUpdates:` proprietary feature used in offline downloads
|
||||||
- `allowVoiceClient:` can be used to disable the voice chat feature
|
- `allowVoiceClient:` can be used to disable the voice chat feature
|
||||||
|
- `allowFNAWSkins:` can be used to disable the high poly FNAW skins
|
||||||
|
- `localStorageNamespace:` can be used to change the prefix of the local storage keys (Default: `"_eaglercraftX"`)
|
||||||
|
- `hooks:` can be used to define JavaScript callbacks for certain events
|
||||||
|
* `localStorageSaved:` JavaScript callback to save local storage keys
|
||||||
|
* `localStorageLoaded:` JavaScript callback to load local storage keys
|
||||||
|
|
||||||
|
### Using Hooks
|
||||||
|
|
||||||
|
You may want to implement some custom logic for loading/saving certain local storage keys. The eaglercraftXOpts hooks section can be used to override the client's local storage load and save functions. Currently, local storage keys are used to save game settings, the user's profile, custom servers, and shared world relays. Worlds and resource packs do not use local storage keys because modern browsers limit local storage keys to only 5 megabytes per domain which is too small for saving entire worlds and resource packs. Worlds and resource packs are saved using [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).
|
||||||
|
|
||||||
|
window.eaglercraftXOpts = {
|
||||||
|
...
|
||||||
|
...
|
||||||
|
...
|
||||||
|
hooks: {
|
||||||
|
localStorageSaved: function(key, data) {
|
||||||
|
// 'key' is local storage key name as a string
|
||||||
|
// 'data' is base64-encoded byte array as a string
|
||||||
|
// function returns nothing
|
||||||
|
},
|
||||||
|
localStorageLoaded: function(key) {
|
||||||
|
// 'key' is local storage key name as a string
|
||||||
|
// function returns a base64-encoded byte array as a string
|
||||||
|
// function returns null if the key does not exist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Be aware that the client will still save the key to the browser's local storage anyway even if you define a custom save handler, and will just attempt to load the key from the browser's local storage normally if you return null, these are meant to be used like event handlers for creating backups of keys instead of completely replacing the local storage save and load functions.
|
||||||
|
|
||||||
|
On a normal client you will only ever need to handle local storage keys called `_eaglercraftX.p` (profile), `_eaglercraftX.g` (game settings), `_eaglercraftX.s` (server list), `_eaglercraftX.r` (shared world relays), feel free to just ignore any other keys. It is guaranteed that the data the client stores will always be valid base64, so it is best practice to decode it to raw binary first if possible to reduce it's size before saving it to something like a MySQL database in your backend if you are trying to implement some kind of profile syncing system for your website. The keys already have GZIP compression applied to them by default so don't bother trying to compress them yourself a second time because it won't reduce their size.
|
||||||
|
|
||||||
## Developing a Client
|
## Developing a Client
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
u29
|
u30
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
> DELETE 1 @ 1 : 4
|
> DELETE 1 @ 1 : 4
|
||||||
|
|
||||||
> CHANGE 1 : 55 @ 1 : 4
|
> CHANGE 1 : 56 @ 1 : 4
|
||||||
|
|
||||||
~
|
~
|
||||||
~ import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput;
|
~ import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput;
|
||||||
|
@ -31,6 +31,7 @@
|
||||||
~
|
~
|
||||||
~ import net.lax1dude.eaglercraft.v1_8.Display;
|
~ import net.lax1dude.eaglercraft.v1_8.Display;
|
||||||
~ import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
~ 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.EaglerXBungeeVersion;
|
||||||
~ import net.lax1dude.eaglercraft.v1_8.HString;
|
~ import net.lax1dude.eaglercraft.v1_8.HString;
|
||||||
~ import net.lax1dude.eaglercraft.v1_8.IOUtils;
|
~ import net.lax1dude.eaglercraft.v1_8.IOUtils;
|
||||||
|
@ -430,7 +431,21 @@
|
||||||
|
|
||||||
~ Util.func_181617_a((FutureTask) this.scheduledTasks.remove(0), logger);
|
~ Util.func_181617_a((FutureTask) this.scheduledTasks.remove(0), logger);
|
||||||
|
|
||||||
> DELETE 18 @ 18 : 26
|
> CHANGE 7 : 18 @ 7 : 8
|
||||||
|
|
||||||
|
~ 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) {
|
||||||
|
|
||||||
|
> DELETE 10 @ 10 : 18
|
||||||
|
|
||||||
> CHANGE 1 : 4 @ 1 : 5
|
> CHANGE 1 : 4 @ 1 : 5
|
||||||
|
|
||||||
|
@ -503,9 +518,13 @@
|
||||||
|
|
||||||
+ Mouse.tickCursorShape();
|
+ Mouse.tickCursorShape();
|
||||||
|
|
||||||
> INSERT 5 : 6 @ 5
|
> INSERT 5 : 10 @ 5
|
||||||
|
|
||||||
+ Display.setVSync(this.gameSettings.enableVsync);
|
+ if (Display.isVSyncSupported()) {
|
||||||
|
+ Display.setVSync(this.gameSettings.enableVsync);
|
||||||
|
+ } else {
|
||||||
|
+ this.gameSettings.enableVsync = false;
|
||||||
|
+ }
|
||||||
|
|
||||||
> DELETE 34 @ 34 : 52
|
> DELETE 34 @ 34 : 52
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,9 @@
|
||||||
|
|
||||||
> DELETE 7 @ 7 : 11
|
> DELETE 7 @ 7 : 11
|
||||||
|
|
||||||
> DELETE 3 @ 3 : 18
|
> CHANGE 3 : 4 @ 3 : 18
|
||||||
|
|
||||||
|
~ private static final Logger tipLogger = LogManager.getLogger("EaglercraftX");
|
||||||
|
|
||||||
> CHANGE 3 : 4 @ 3 : 4
|
> CHANGE 3 : 4 @ 3 : 4
|
||||||
|
|
||||||
|
@ -44,7 +46,14 @@
|
||||||
|
|
||||||
~ for (Entry entry : (Set<Entry>) map.entrySet()) {
|
~ for (Entry entry : (Set<Entry>) map.entrySet()) {
|
||||||
|
|
||||||
> INSERT 14 : 24 @ 14
|
> INSERT 12 : 16 @ 12
|
||||||
|
|
||||||
|
+ 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");
|
||||||
|
+ }
|
||||||
|
|
||||||
|
> INSERT 2 : 12 @ 2
|
||||||
|
|
||||||
+ public static class SoundMap {
|
+ public static class SoundMap {
|
||||||
+
|
+
|
||||||
|
|
|
@ -7,11 +7,12 @@
|
||||||
|
|
||||||
> DELETE 2 @ 2 : 3
|
> DELETE 2 @ 2 : 3
|
||||||
|
|
||||||
> INSERT 1 : 9 @ 1
|
> INSERT 1 : 10 @ 1
|
||||||
|
|
||||||
+
|
+
|
||||||
+ import com.google.common.collect.Maps;
|
+ import com.google.common.collect.Maps;
|
||||||
+
|
+
|
||||||
|
+ import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
+ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper;
|
+ import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper;
|
||||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
|
+ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
|
||||||
|
@ -32,12 +33,16 @@
|
||||||
|
|
||||||
+ private RenderPlayer eaglerRenderer;
|
+ private RenderPlayer eaglerRenderer;
|
||||||
|
|
||||||
> CHANGE 82 : 88 @ 82 : 83
|
> CHANGE 82 : 92 @ 82 : 83
|
||||||
|
|
||||||
~ this.skinMap.put("slim", new RenderPlayer(this, true, false));
|
~ this.skinMap.put("slim", new RenderPlayer(this, true, false));
|
||||||
~ this.skinMap.put("zombie", new RenderPlayer(this, false, true));
|
~ this.skinMap.put("zombie", new RenderPlayer(this, false, true));
|
||||||
~ this.eaglerRenderer = new RenderHighPoly(this, this.playerRenderer.getMainModel(),
|
~ if (EagRuntime.getConfiguration().isAllowFNAWSkins()) {
|
||||||
~ this.playerRenderer.shadowSize);
|
~ this.eaglerRenderer = new RenderHighPoly(this, this.playerRenderer.getMainModel(),
|
||||||
|
~ this.playerRenderer.shadowSize);
|
||||||
|
~ } else {
|
||||||
|
~ this.eaglerRenderer = this.playerRenderer;
|
||||||
|
~ }
|
||||||
~ this.skinMap.put("eagler",
|
~ this.skinMap.put("eagler",
|
||||||
~ Minecraft.getMinecraft().gameSettings.enableFNAWSkins ? this.eaglerRenderer : this.playerRenderer);
|
~ Minecraft.getMinecraft().gameSettings.enableFNAWSkins ? this.eaglerRenderer : this.playerRenderer);
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@
|
||||||
|
|
||||||
~ worldIn.theItemInWorldManager.initializeGameType(parWorld.getWorldInfo().getGameType());
|
~ worldIn.theItemInWorldManager.initializeGameType(parWorld.getWorldInfo().getGameType());
|
||||||
~ } else {
|
~ } else {
|
||||||
~ parEntityPlayerMP2.theItemInWorldManager.setGameType(lanGamemode);
|
~ worldIn.theItemInWorldManager.setGameType(lanGamemode);
|
||||||
~ }
|
~ }
|
||||||
|
|
||||||
> CHANGE 7 : 8 @ 7 : 8
|
> CHANGE 7 : 8 @ 7 : 8
|
||||||
|
|
|
@ -66,6 +66,10 @@ public class PlatformApplication {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setLocalStorage(String name, byte[] data) {
|
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) {
|
if(data == null) {
|
||||||
(new File("_eagstorage."+name+".dat")).delete();
|
(new File("_eagstorage."+name+".dat")).delete();
|
||||||
}else {
|
}else {
|
||||||
|
@ -78,6 +82,10 @@ public class PlatformApplication {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] getLocalStorage(String data) {
|
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");
|
File f = new File("_eagstorage."+data+".dat");
|
||||||
if(!f.isFile()) {
|
if(!f.isFile()) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -230,6 +230,10 @@ public class PlatformInput {
|
||||||
glfwSwapBuffers(win);
|
glfwSwapBuffers(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isVSyncSupported() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean wasResized() {
|
public static boolean wasResized() {
|
||||||
boolean b = windowResized;
|
boolean b = windowResized;
|
||||||
windowResized = false;
|
windowResized = false;
|
||||||
|
|
|
@ -8,6 +8,7 @@ import org.json.JSONObject;
|
||||||
import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom;
|
import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom;
|
||||||
import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion;
|
import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion;
|
||||||
import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapter;
|
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;
|
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayEntry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +32,8 @@ public class DesktopClientConfigAdapter implements IClientConfigAdapter {
|
||||||
|
|
||||||
public final List<DefaultServer> defaultServers = new ArrayList();
|
public final List<DefaultServer> defaultServers = new ArrayList();
|
||||||
|
|
||||||
|
private final DesktopClientConfigAdapterHooks hooks = new DesktopClientConfigAdapterHooks();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDefaultLocale() {
|
public String getDefaultLocale() {
|
||||||
return "en_US";
|
return "en_US";
|
||||||
|
@ -129,4 +132,32 @@ public class DesktopClientConfigAdapter implements IClientConfigAdapter {
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,10 @@ public class Display {
|
||||||
PlatformInput.setVSync(enable);
|
PlatformInput.setVSync(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isVSyncSupported() {
|
||||||
|
return PlatformInput.isVSyncSupported();
|
||||||
|
}
|
||||||
|
|
||||||
public static void update() {
|
public static void update() {
|
||||||
PlatformInput.update();
|
PlatformInput.update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ public class EaglercraftVersion {
|
||||||
/// Customize these to fit your fork:
|
/// Customize these to fit your fork:
|
||||||
|
|
||||||
public static final String projectForkName = "EaglercraftX";
|
public static final String projectForkName = "EaglercraftX";
|
||||||
public static final String projectForkVersion = "u29";
|
public static final String projectForkVersion = "u30";
|
||||||
public static final String projectForkVendor = "lax1dude";
|
public static final String projectForkVendor = "lax1dude";
|
||||||
|
|
||||||
public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8";
|
public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8";
|
||||||
|
@ -20,7 +20,7 @@ public class EaglercraftVersion {
|
||||||
public static final String projectOriginName = "EaglercraftX";
|
public static final String projectOriginName = "EaglercraftX";
|
||||||
public static final String projectOriginAuthor = "lax1dude";
|
public static final String projectOriginAuthor = "lax1dude";
|
||||||
public static final String projectOriginRevision = "1.8";
|
public static final String projectOriginRevision = "1.8";
|
||||||
public static final String projectOriginVersion = "u29";
|
public static final String projectOriginVersion = "u30";
|
||||||
|
|
||||||
public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace
|
public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ public class EaglercraftVersion {
|
||||||
public static final boolean enableUpdateService = true;
|
public static final boolean enableUpdateService = true;
|
||||||
|
|
||||||
public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client";
|
public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client";
|
||||||
public static final int updateBundlePackageVersionInt = 29;
|
public static final int updateBundlePackageVersionInt = 30;
|
||||||
|
|
||||||
public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName;
|
public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName;
|
||||||
|
|
||||||
|
@ -60,4 +60,6 @@ public class EaglercraftVersion {
|
||||||
|
|
||||||
public static final boolean forceDemoMode = false;
|
public static final boolean forceDemoMode = false;
|
||||||
|
|
||||||
|
public static final String localStorageNamespace = "_eaglercraftX";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,4 +69,11 @@ public interface IClientConfigAdapter {
|
||||||
boolean isEnableSignatureBadge();
|
boolean isEnableSignatureBadge();
|
||||||
|
|
||||||
boolean isAllowVoiceClient();
|
boolean isAllowVoiceClient();
|
||||||
|
|
||||||
|
boolean isAllowFNAWSkins();
|
||||||
|
|
||||||
|
String getLocalStorageNamespace();
|
||||||
|
|
||||||
|
IClientConfigAdapterHooks getHooks();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
package net.lax1dude.eaglercraft.v1_8.internal.teavm.opts;
|
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||||
|
|
||||||
import org.teavm.jso.JSIndexer;
|
|
||||||
import org.teavm.jso.JSObject;
|
|
||||||
import org.teavm.jso.JSProperty;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||||||
|
@ -19,12 +15,10 @@ import org.teavm.jso.JSProperty;
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface JSEaglercraftXOptsRelaysArray extends JSObject {
|
public interface IClientConfigAdapterHooks {
|
||||||
|
|
||||||
@JSIndexer
|
void callLocalStorageSavedHook(String key, String base64);
|
||||||
JSEaglercraftXOptsRelay get(int idx);
|
|
||||||
|
|
||||||
@JSProperty
|
String callLocalStorageLoadHook(String key);
|
||||||
int getLength();
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -13,6 +13,21 @@ import net.minecraft.client.resources.IResourceManager;
|
||||||
import net.minecraft.client.resources.IResourceManagerReloadListener;
|
import net.minecraft.client.resources.IResourceManagerReloadListener;
|
||||||
import net.minecraft.util.ResourceLocation;
|
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 {
|
public class BlockVertexIDs implements IResourceManagerReloadListener {
|
||||||
|
|
||||||
private static final Logger logger = LogManager.getLogger("BlockVertexIDsCSV");
|
private static final Logger logger = LogManager.getLogger("BlockVertexIDsCSV");
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class EaglerSkinTexture implements ITextureObject {
|
||||||
}
|
}
|
||||||
System.arraycopy(pixels, 0, this.pixels, 0, pixels.length);
|
System.arraycopy(pixels, 0, this.pixels, 0, pixels.length);
|
||||||
if(textureId != -1) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,14 +73,20 @@ public class GuiScreenEditProfile extends GuiScreen {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOptions() {
|
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();
|
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) {
|
for(int i = 0; i < numCustom; ++i) {
|
||||||
n[i] = EaglerProfile.customSkins.get(i).name;
|
n[i] = EaglerProfile.customSkins.get(i).name;
|
||||||
}
|
}
|
||||||
int numDefault = DefaultSkins.defaultSkinsMap.length;
|
int numDefault = arr.length;
|
||||||
for(int j = 0; j < numDefault; ++j) {
|
for(int j = 0; j < numDefault; ++j) {
|
||||||
n[numCustom + j] = DefaultSkins.defaultSkinsMap[j].name;
|
n[numCustom + j] = arr[j].name;
|
||||||
}
|
}
|
||||||
dropDownOptions = n;
|
dropDownOptions = n;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +112,10 @@ public class GuiScreenEditProfile extends GuiScreen {
|
||||||
GlStateManager.translate(skinX + 2, skinY - 9, 0.0f);
|
GlStateManager.translate(skinX + 2, skinY - 9, 0.0f);
|
||||||
GlStateManager.scale(0.75f, 0.75f, 0.75f);
|
GlStateManager.scale(0.75f, 0.75f, 0.75f);
|
||||||
|
|
||||||
|
if(selectedSlot > dropDownOptions.length - 1) {
|
||||||
|
selectedSlot = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int numberOfCustomSkins = EaglerProfile.customSkins.size();
|
int numberOfCustomSkins = EaglerProfile.customSkins.size();
|
||||||
int skid = selectedSlot - numberOfCustomSkins;
|
int skid = selectedSlot - numberOfCustomSkins;
|
||||||
SkinModel selectedSkinModel = skid < 0 ? EaglerProfile.customSkins.get(selectedSlot).model : DefaultSkins.getSkinFromId(skid).model;
|
SkinModel selectedSkinModel = skid < 0 ? EaglerProfile.customSkins.get(selectedSlot).model : DefaultSkins.getSkinFromId(skid).model;
|
||||||
|
|
|
@ -56,11 +56,15 @@ public class GuiScreenImportExportProfile extends GuiScreen {
|
||||||
FileChooserResult result = EagRuntime.getFileChooserResult();
|
FileChooserResult result = EagRuntime.getFileChooserResult();
|
||||||
if(result != null) {
|
if(result != null) {
|
||||||
mc.loadingScreen.eaglerShow(I18n.format("settingsBackup.importing.1"), "settingsBackup.importing.2");
|
mc.loadingScreen.eaglerShow(I18n.format("settingsBackup.importing.1"), "settingsBackup.importing.2");
|
||||||
|
ProfileImporter importer = new ProfileImporter(result.fileData);
|
||||||
try {
|
try {
|
||||||
ProfileImporter importer = new ProfileImporter(result.fileData);
|
|
||||||
importer.readHeader();
|
importer.readHeader();
|
||||||
mc.displayGuiScreen(new GuiScreenImportProfile(importer, back));
|
mc.displayGuiScreen(new GuiScreenImportProfile(importer, back));
|
||||||
}catch(IOException ex) {
|
}catch(IOException ex) {
|
||||||
|
try {
|
||||||
|
importer.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
EagRuntime.debugPrintStackTrace(ex);
|
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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")));
|
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) {
|
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||||
if(par1GuiButton.id == 0) {
|
if(par1GuiButton.id == 0) {
|
||||||
if(!doImportProfile && !doImportSettings && !doImportServers && !doImportResourcePacks) {
|
if(!doImportProfile && !doImportSettings && !doImportServers && !doImportResourcePacks) {
|
||||||
|
|
|
@ -69,97 +69,96 @@ 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(new byte[]{(byte)255,(byte)255,(byte)255,(byte)255}); // this will be replaced with the file count
|
||||||
|
|
||||||
osb.write('G');
|
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;
|
int fileCount = 2;
|
||||||
|
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('>');
|
||||||
|
|
||||||
if(doExportProfile) {
|
os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
|
||||||
byte[] profileData = EaglerProfile.write();
|
os.write(new byte[]{(byte)12,(byte)102,(byte)105,(byte)108,(byte)101,(byte)45,(byte)101,(byte)120,
|
||||||
if(profileData == null) {
|
(byte)112,(byte)111,(byte)114,(byte)116,(byte)115,(byte)0,(byte)0,(byte)0,(byte)1}); // 12 + file-exports + 1
|
||||||
throw new IOException("Could not write profile data!");
|
os.write((doExportProfile ? 1 : 0) | (doExportSettings ? 2 : 0) | (doExportServers ? 4 : 0) | (doExportResourcePacks ? 8 : 0));
|
||||||
}
|
os.write('>');
|
||||||
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) {
|
if(doExportProfile) {
|
||||||
logger.info("Exporting server list...");
|
byte[] profileData = EaglerProfile.write();
|
||||||
byte[] servers = ServerList.getServerList().writeServerList();
|
if(profileData == null) {
|
||||||
if(servers == null) {
|
throw new IOException("Could not write profile data!");
|
||||||
throw new IOException("Could not write server list!");
|
}
|
||||||
}
|
exportFileToEPK("_eaglercraftX.p", profileData, os);
|
||||||
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<UpdateCertificate> 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;
|
++fileCount;
|
||||||
VFile2 baseDir = new VFile2(EaglerFolderResourcePack.RESOURCE_PACKS);
|
}
|
||||||
List<VFile2> files = baseDir.listFiles(true);
|
|
||||||
logger.info("({} files to export)", files.size());
|
if(doExportSettings) {
|
||||||
for(int i = 0, l = files.size(); i < l; ++i) {
|
logger.info("Exporting game settings...");
|
||||||
VFile2 f = files.get(i);
|
byte[] gameSettings = Minecraft.getMinecraft().gameSettings.writeOptions();
|
||||||
if(f.getPath().equals(EaglerFolderResourcePack.RESOURCE_PACKS + "/manifest.json")) {
|
if(gameSettings == null) {
|
||||||
continue;
|
throw new IOException("Could not write game settings!");
|
||||||
}
|
}
|
||||||
exportFileToEPK(f.getPath(), f.getAllBytes(), os);
|
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<UpdateCertificate> 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;
|
++fileCount;
|
||||||
if(i > 0 && i % 100 == 0) {
|
VFile2 baseDir = new VFile2(EaglerFolderResourcePack.RESOURCE_PACKS);
|
||||||
logger.info("Exported {} files", i);
|
List<VFile2> 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:>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.lax1dude.eaglercraft.v1_8.profile;
|
package net.lax1dude.eaglercraft.v1_8.profile;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||||
|
@ -29,7 +30,7 @@ import net.minecraft.client.multiplayer.ServerList;
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ProfileImporter {
|
public class ProfileImporter implements Closeable {
|
||||||
|
|
||||||
private static final Logger logger = LogManager.getLogger("ProfileImporter");
|
private static final Logger logger = LogManager.getLogger("ProfileImporter");
|
||||||
|
|
||||||
|
@ -148,4 +149,9 @@ public class ProfileImporter {
|
||||||
}
|
}
|
||||||
logger.info("Import complete!");
|
logger.info("Import complete!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
epkDecompiler.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,4 +468,13 @@ public class RenderHighPoly extends RenderPlayer {
|
||||||
GlStateManager.popMatrix();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ public enum SkinModel {
|
||||||
private SkinModel(int id, HighPolySkin highPoly) {
|
private SkinModel(int id, HighPolySkin highPoly) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.width = 256;
|
this.width = 256;
|
||||||
this.height = 128;
|
this.height = 256;
|
||||||
this.profileSkinType = "eagler";
|
this.profileSkinType = "eagler";
|
||||||
this.sanitize = true;
|
this.sanitize = true;
|
||||||
this.highPoly = highPoly;
|
this.highPoly = highPoly;
|
||||||
|
|
|
@ -156,7 +156,6 @@ public class GuiShareToLan extends GuiScreen {
|
||||||
this.mc.ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(I18n.format("lanServer.opened")
|
this.mc.ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(I18n.format("lanServer.opened")
|
||||||
.replace("$relay$", LANServerController.getCurrentURI()).replace("$code$", code)));
|
.replace("$relay$", LANServerController.getCurrentURI()).replace("$code$", code)));
|
||||||
} else {
|
} else {
|
||||||
SingleplayerServerController.configureLAN(mc.theWorld.getWorldInfo().getGameType(), false);
|
|
||||||
this.mc.displayGuiScreen(new GuiScreenNoRelays(this, "noRelay.titleFail"));
|
this.mc.displayGuiScreen(new GuiScreenNoRelays(this, "noRelay.titleFail"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -340,9 +340,11 @@ public class LANClientNetworkManager extends EaglercraftNetworkManager {
|
||||||
}
|
}
|
||||||
EaglerInputStream bi = new EaglerInputStream(fullData);
|
EaglerInputStream bi = new EaglerInputStream(fullData);
|
||||||
int i = (bi.read() << 24) | (bi.read() << 16) | (bi.read() << 8) | bi.read();
|
int i = (bi.read() << 24) | (bi.read() << 16) | (bi.read() << 8) | bi.read();
|
||||||
InputStream inflaterInputStream = EaglerZLIB.newInflaterInputStream(bi);
|
|
||||||
fullData = new byte[i];
|
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) {
|
if (i != r) {
|
||||||
logger.warn("Decompressed packet expected size {} differs from actual size {}!", i, r);
|
logger.warn("Decompressed packet expected size {} differs from actual size {}!", i, r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -479,7 +479,7 @@ public class EaglerIntegratedServerWorker {
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
mainLoop();
|
mainLoop();
|
||||||
EagUtils.sleep(1l);
|
EagUtils.sleep(0l);
|
||||||
}
|
}
|
||||||
}catch(Throwable tt) {
|
}catch(Throwable tt) {
|
||||||
if(tt instanceof ReportedException) {
|
if(tt instanceof ReportedException) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.lax1dude.eaglercraft.v1_8.sp.server.export;
|
package net.lax1dude.eaglercraft.v1_8.sp.server.export;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -24,7 +25,7 @@ import net.lax1dude.eaglercraft.v1_8.IOUtils;
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class EPKDecompiler {
|
public class EPKDecompiler implements Closeable {
|
||||||
|
|
||||||
public static class FileEntry {
|
public static class FileEntry {
|
||||||
public final String type;
|
public final String type;
|
||||||
|
@ -178,4 +179,9 @@ public class EPKDecompiler {
|
||||||
return new String(charIn);
|
return new String(charIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
zis.close();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,44 +40,45 @@ public class WorldConverterEPK {
|
||||||
folderName += "_";
|
folderName += "_";
|
||||||
worldDir = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory();
|
worldDir = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory();
|
||||||
}
|
}
|
||||||
EPKDecompiler dc = new EPKDecompiler(archiveContents);
|
try(EPKDecompiler dc = new EPKDecompiler(archiveContents)) {
|
||||||
EPKDecompiler.FileEntry f = null;
|
EPKDecompiler.FileEntry f = null;
|
||||||
int lastProgUpdate = 0;
|
int lastProgUpdate = 0;
|
||||||
int prog = 0;
|
int prog = 0;
|
||||||
String hasReadType = null;
|
String hasReadType = null;
|
||||||
boolean has152Format = false;
|
boolean has152Format = false;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
while((f = dc.readFile()) != null) {
|
while((f = dc.readFile()) != null) {
|
||||||
byte[] b = f.data;
|
byte[] b = f.data;
|
||||||
if(hasReadType == null) {
|
if(hasReadType == null) {
|
||||||
if (f.type.equals("HEAD") && f.name.equals("file-type")
|
if (f.type.equals("HEAD") && f.name.equals("file-type")
|
||||||
&& ((hasReadType = EPKDecompiler.readASCII(f.data)).equals("epk/world188")
|
&& ((hasReadType = EPKDecompiler.readASCII(f.data)).equals("epk/world188")
|
||||||
|| (has152Format = hasReadType.equals("epk/world152")))) {
|
|| (has152Format = hasReadType.equals("epk/world152")))) {
|
||||||
if(has152Format) {
|
if(has152Format) {
|
||||||
logger.warn("World type detected as 1.5.2, it will be converted to 1.8.8 format");
|
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.type.equals("FILE")) {
|
if(f.name.equals("level.dat") || f.name.equals("level.dat_old")) {
|
||||||
if(f.name.equals("level.dat") || f.name.equals("level.dat_old")) {
|
NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b));
|
||||||
NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b));
|
worldDatNBT.getCompoundTag("Data").setString("LevelName", newName);
|
||||||
worldDatNBT.getCompoundTag("Data").setString("LevelName", newName);
|
worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis());
|
||||||
worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis());
|
EaglerOutputStream tmp = new EaglerOutputStream();
|
||||||
EaglerOutputStream tmp = new EaglerOutputStream();
|
CompressedStreamTools.writeCompressed(worldDatNBT, tmp);
|
||||||
CompressedStreamTools.writeCompressed(worldDatNBT, tmp);
|
b = tmp.toByteArray();
|
||||||
b = tmp.toByteArray();
|
}
|
||||||
}
|
VFile2 ff = new VFile2(worldDir, f.name);
|
||||||
VFile2 ff = new VFile2(worldDir, f.name);
|
ff.setAllBytes(b);
|
||||||
ff.setAllBytes(b);
|
prog += b.length;
|
||||||
prog += b.length;
|
++cnt;
|
||||||
++cnt;
|
if(prog - lastProgUpdate > 25000) {
|
||||||
if(prog - lastProgUpdate > 25000) {
|
lastProgUpdate = prog;
|
||||||
lastProgUpdate = prog;
|
logger.info("Extracted {} files, {} bytes from EPK...", cnt, prog);
|
||||||
logger.info("Extracted {} files, {} bytes from EPK...", cnt, prog);
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.1", prog);
|
||||||
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.importing.1", prog);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,111 +50,113 @@ public class WorldConverterMCA {
|
||||||
folderName += "_";
|
folderName += "_";
|
||||||
worldDir = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory();
|
worldDir = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory();
|
||||||
}
|
}
|
||||||
ZipInputStream zis = new ZipInputStream(new EaglerInputStream(archiveContents));
|
|
||||||
ZipEntry folderNameFile = null;
|
|
||||||
List<char[]> fileNames = new ArrayList<>();
|
List<char[]> fileNames = new ArrayList<>();
|
||||||
while((folderNameFile = zis.getNextEntry()) != null) {
|
try(ZipInputStream zis = new ZipInputStream(new EaglerInputStream(archiveContents))) {
|
||||||
if (folderNameFile.getName().contains("__MACOSX/")) continue;
|
ZipEntry folderNameFile = null;
|
||||||
if (folderNameFile.isDirectory()) continue;
|
while((folderNameFile = zis.getNextEntry()) != null) {
|
||||||
String lowerName = folderNameFile.getName().toLowerCase();
|
if (folderNameFile.getName().contains("__MACOSX/")) continue;
|
||||||
if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr"))) continue;
|
if (folderNameFile.isDirectory()) continue;
|
||||||
fileNames.add(folderNameFile.getName().toCharArray());
|
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 };
|
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]++;
|
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];
|
int folderPrefixOffset = i[0];
|
||||||
zis = new ZipInputStream(new EaglerInputStream(archiveContents));
|
try(ZipInputStream zis = new ZipInputStream(new EaglerInputStream(archiveContents))) {
|
||||||
ZipEntry f = null;
|
ZipEntry f = null;
|
||||||
int lastProgUpdate = 0;
|
int lastProgUpdate = 0;
|
||||||
int prog = 0;
|
int prog = 0;
|
||||||
byte[] bb = new byte[16384];
|
byte[] bb = new byte[16384];
|
||||||
while ((f = zis.getNextEntry()) != null) {
|
while ((f = zis.getNextEntry()) != null) {
|
||||||
if (f.getName().contains("__MACOSX/")) continue;
|
if (f.getName().contains("__MACOSX/")) continue;
|
||||||
if (f.isDirectory()) continue;
|
if (f.isDirectory()) continue;
|
||||||
String lowerName = f.getName().toLowerCase();
|
String lowerName = f.getName().toLowerCase();
|
||||||
if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr") || lowerName.endsWith(".bmp"))) continue;
|
if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr") || lowerName.endsWith(".bmp"))) continue;
|
||||||
EaglerOutputStream baos = new EaglerOutputStream();
|
EaglerOutputStream baos = new EaglerOutputStream();
|
||||||
int len;
|
int len;
|
||||||
while ((len = zis.read(bb)) != -1) {
|
while ((len = zis.read(bb)) != -1) {
|
||||||
baos.write(bb, 0, len);
|
baos.write(bb, 0, len);
|
||||||
}
|
}
|
||||||
baos.close();
|
baos.close();
|
||||||
byte[] b = baos.toByteArray();
|
byte[] b = baos.toByteArray();
|
||||||
String fileName = f.getName().substring(folderPrefixOffset);
|
String fileName = f.getName().substring(folderPrefixOffset);
|
||||||
if (fileName.equals("level.dat") || fileName.equals("level.dat_old")) {
|
if (fileName.equals("level.dat") || fileName.equals("level.dat_old")) {
|
||||||
NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b));
|
NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b));
|
||||||
|
|
||||||
NBTTagCompound gameRulesNBT = worldDatNBT.getCompoundTag("Data").getCompoundTag("GameRules");
|
NBTTagCompound gameRulesNBT = worldDatNBT.getCompoundTag("Data").getCompoundTag("GameRules");
|
||||||
gameRulesNBT.setString("loadSpawnChunks", (gameRules & 2) != 0 ? "true" : "false");
|
gameRulesNBT.setString("loadSpawnChunks", (gameRules & 2) != 0 ? "true" : "false");
|
||||||
String s = (gameRules & 1) != 0 ? "true" : "false";
|
String s = (gameRules & 1) != 0 ? "true" : "false";
|
||||||
gameRulesNBT.setString("bedSpawnPoint", s);
|
gameRulesNBT.setString("bedSpawnPoint", s);
|
||||||
gameRulesNBT.setString("clickToRide", "false");
|
gameRulesNBT.setString("clickToRide", "false");
|
||||||
gameRulesNBT.setString("clickToSit", s);
|
gameRulesNBT.setString("clickToSit", s);
|
||||||
gameRulesNBT.setString("colorCodes", s);
|
gameRulesNBT.setString("colorCodes", s);
|
||||||
gameRulesNBT.setString("doSignEditing", s);
|
gameRulesNBT.setString("doSignEditing", s);
|
||||||
worldDatNBT.getCompoundTag("Data").setTag("GameRules", gameRulesNBT);
|
worldDatNBT.getCompoundTag("Data").setTag("GameRules", gameRulesNBT);
|
||||||
|
|
||||||
worldDatNBT.getCompoundTag("Data").setString("LevelName", newName);
|
worldDatNBT.getCompoundTag("Data").setString("LevelName", newName);
|
||||||
worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis());
|
worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis());
|
||||||
EaglerOutputStream bo = new EaglerOutputStream();
|
EaglerOutputStream bo = new EaglerOutputStream();
|
||||||
CompressedStreamTools.writeCompressed(worldDatNBT, bo);
|
CompressedStreamTools.writeCompressed(worldDatNBT, bo);
|
||||||
b = bo.toByteArray();
|
b = bo.toByteArray();
|
||||||
VFile2 ff = new VFile2(worldDir, fileName);
|
VFile2 ff = new VFile2(worldDir, fileName);
|
||||||
ff.setAllBytes(b);
|
ff.setAllBytes(b);
|
||||||
prog += b.length;
|
prog += b.length;
|
||||||
} else if ((fileName.endsWith(".mcr") || fileName.endsWith(".mca")) && (fileName.startsWith("region/") || fileName.startsWith("DIM1/region/") || fileName.startsWith("DIM-1/region/"))) {
|
} 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"));
|
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));
|
RegionFile mca = new RegionFile(new RandomAccessMemoryFile(b, b.length));
|
||||||
int loadChunksCount = 0;
|
int loadChunksCount = 0;
|
||||||
for(int j = 0; j < 32; ++j) {
|
for(int j = 0; j < 32; ++j) {
|
||||||
for(int k = 0; k < 32; ++k) {
|
for(int k = 0; k < 32; ++k) {
|
||||||
if(mca.isChunkSaved(j, k)) {
|
if(mca.isChunkSaved(j, k)) {
|
||||||
NBTTagCompound chunkNBT;
|
NBTTagCompound chunkNBT;
|
||||||
NBTTagCompound chunkLevel;
|
NBTTagCompound chunkLevel;
|
||||||
try {
|
try {
|
||||||
chunkNBT = CompressedStreamTools.read(mca.getChunkDataInputStream(j, k));
|
chunkNBT = CompressedStreamTools.read(mca.getChunkDataInputStream(j, k));
|
||||||
if(!chunkNBT.hasKey("Level", 10)) {
|
if(!chunkNBT.hasKey("Level", 10)) {
|
||||||
throw new IOException("Chunk is missing level data!");
|
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");
|
int chunkX = chunkLevel.getInteger("xPos");
|
||||||
}catch(Throwable t) {
|
int chunkZ = chunkLevel.getInteger("zPos");
|
||||||
logger.error("{}: Could not read chunk: {}, {}", fileName, j, k);
|
VFile2 chunkOut = new VFile2(chunkFolder, EaglerChunkLoader.getChunkPath(chunkX, chunkZ) + ".dat");
|
||||||
logger.error(t);
|
if(chunkOut.exists()) {
|
||||||
continue;
|
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());
|
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 {
|
public static byte[] exportWorld(String folderName) throws IOException {
|
||||||
EaglerOutputStream bao = new EaglerOutputStream();
|
EaglerOutputStream bao = new EaglerOutputStream();
|
||||||
ZipOutputStream zos = new ZipOutputStream(bao);
|
VFile2 worldFolder;
|
||||||
zos.setComment("contains backup of world '" + folderName + "'");
|
try(ZipOutputStream zos = new ZipOutputStream(bao)) {
|
||||||
VFile2 worldFolder = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory();
|
zos.setComment("contains backup of world '" + folderName + "'");
|
||||||
logger.info("Exporting world directory \"{}\" as MCA", worldFolder.getPath());
|
worldFolder = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(folderName, false).getWorldDirectory();
|
||||||
VFile2 vf = new VFile2(worldFolder, "level.dat");
|
logger.info("Exporting world directory \"{}\" as MCA", worldFolder.getPath());
|
||||||
byte[] b;
|
VFile2 vf = new VFile2(worldFolder, "level.dat");
|
||||||
int lastProgUpdate = 0;
|
byte[] b;
|
||||||
int prog = 0;
|
int lastProgUpdate = 0;
|
||||||
boolean safe = false;
|
int prog = 0;
|
||||||
if(vf.exists()) {
|
boolean safe = false;
|
||||||
zos.putNextEntry(new ZipEntry(folderName + "/level.dat"));
|
if(vf.exists()) {
|
||||||
b = vf.getAllBytes();
|
zos.putNextEntry(new ZipEntry(folderName + "/level.dat"));
|
||||||
zos.write(b);
|
b = vf.getAllBytes();
|
||||||
prog += b.length;
|
zos.write(b);
|
||||||
safe = true;
|
prog += b.length;
|
||||||
}
|
safe = true;
|
||||||
vf = new VFile2(worldFolder, "level.dat_old");
|
}
|
||||||
if(vf.exists()) {
|
vf = new VFile2(worldFolder, "level.dat_old");
|
||||||
zos.putNextEntry(new ZipEntry(folderName + "/level.dat_old"));
|
if(vf.exists()) {
|
||||||
b = vf.getAllBytes();
|
zos.putNextEntry(new ZipEntry(folderName + "/level.dat_old"));
|
||||||
zos.write(b);
|
b = vf.getAllBytes();
|
||||||
prog += b.length;
|
zos.write(b);
|
||||||
safe = true;
|
prog += b.length;
|
||||||
}
|
safe = true;
|
||||||
if (prog - lastProgUpdate > 25000) {
|
}
|
||||||
lastProgUpdate = prog;
|
if (prog - lastProgUpdate > 25000) {
|
||||||
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
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/" };
|
String[] srcFolderNames = new String[] { "level0", "level-1", "level1" };
|
||||||
List<VFile2> fileList;
|
String[] dstFolderNames = new String[] { "/region/", "/DIM-1/region/", "/DIM1/region/" };
|
||||||
for(int i = 0; i < 3; ++i) {
|
List<VFile2> fileList;
|
||||||
vf = new VFile2(worldFolder, srcFolderNames[i]);
|
for(int i = 0; i < 3; ++i) {
|
||||||
fileList = vf.listFiles(true);
|
vf = new VFile2(worldFolder, srcFolderNames[i]);
|
||||||
String regionFolder = folderName + dstFolderNames[i];
|
fileList = vf.listFiles(true);
|
||||||
logger.info("Converting chunks in \"{}\" as MCA to \"{}\"...", vf.getPath(), regionFolder);
|
String regionFolder = folderName + dstFolderNames[i];
|
||||||
Map<String,RegionFile> regionFiles = new HashMap();
|
logger.info("Converting chunks in \"{}\" as MCA to \"{}\"...", vf.getPath(), regionFolder);
|
||||||
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
Map<String,RegionFile> regionFiles = new HashMap();
|
||||||
VFile2 chunkFile = fileList.get(k);
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
||||||
NBTTagCompound chunkNBT;
|
VFile2 chunkFile = fileList.get(k);
|
||||||
NBTTagCompound chunkLevel;
|
NBTTagCompound chunkNBT;
|
||||||
try {
|
NBTTagCompound chunkLevel;
|
||||||
b = chunkFile.getAllBytes();
|
try {
|
||||||
chunkNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b));
|
b = chunkFile.getAllBytes();
|
||||||
if(!chunkNBT.hasKey("Level", 10)) {
|
chunkNBT = CompressedStreamTools.readCompressed(new EaglerInputStream(b));
|
||||||
throw new IOException("Chunk is missing level data!");
|
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");
|
int chunkX = chunkLevel.getInteger("xPos");
|
||||||
}catch(IOException t) {
|
int chunkZ = chunkLevel.getInteger("zPos");
|
||||||
logger.error("Could not read chunk: {}", chunkFile.getPath());
|
String regionFileName = "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mca";
|
||||||
logger.error(t);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
int chunkX = chunkLevel.getInteger("xPos");
|
for(Entry<String,RegionFile> etr : regionFiles.entrySet()) {
|
||||||
int chunkZ = chunkLevel.getInteger("zPos");
|
String regionPath = regionFolder + etr.getKey();
|
||||||
String regionFileName = "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mca";
|
logger.info("Writing region file: {}", regionPath);
|
||||||
RegionFile rf = regionFiles.get(regionFileName);
|
zos.putNextEntry(new ZipEntry(regionPath));
|
||||||
if(rf == null) {
|
zos.write(etr.getValue().getFile().getByteArray());
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
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;
|
prog += b.length;
|
||||||
if (prog - lastProgUpdate > 25000) {
|
if (prog - lastProgUpdate > 25000) {
|
||||||
lastProgUpdate = prog;
|
lastProgUpdate = prog;
|
||||||
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.exporting.2", prog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(regionFiles.isEmpty()) {
|
fileList = (new VFile2(worldFolder, "players")).listFiles(false);
|
||||||
logger.info("No region files were generated");
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
||||||
continue;
|
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<String,RegionFile> etr : regionFiles.entrySet()) {
|
fileList = (new VFile2(worldFolder, "eagler/skulls")).listFiles(false);
|
||||||
String regionPath = regionFolder + etr.getKey();
|
for(int k = 0, l = fileList.size(); k < l; ++k) {
|
||||||
logger.info("Writing region file: {}", regionPath);
|
VFile2 dataFile = fileList.get(k);
|
||||||
zos.putNextEntry(new ZipEntry(regionPath));
|
zos.putNextEntry(new ZipEntry(folderName + "/eagler/skulls/" + dataFile.getName()));
|
||||||
zos.write(etr.getValue().getFile().getByteArray());
|
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());
|
logger.info("World directory \"{}\" was successfully exported as MCA", worldFolder.getPath());
|
||||||
return bao.toByteArray();
|
return bao.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,9 +243,9 @@ public class IntegratedServerPlayerNetworkManager {
|
||||||
temporaryOutputStream.write((len >> 16) & 0xFF);
|
temporaryOutputStream.write((len >> 16) & 0xFF);
|
||||||
temporaryOutputStream.write((len >> 8) & 0xFF);
|
temporaryOutputStream.write((len >> 8) & 0xFF);
|
||||||
temporaryOutputStream.write(len & 0xFF);
|
temporaryOutputStream.write(len & 0xFF);
|
||||||
OutputStream os = EaglerZLIB.newDeflaterOutputStream(temporaryOutputStream);
|
try(OutputStream os = EaglerZLIB.newDeflaterOutputStream(temporaryOutputStream)) {
|
||||||
temporaryBuffer.readBytes(os, len);
|
temporaryBuffer.readBytes(os, len);
|
||||||
os.close();
|
}
|
||||||
compressedData = temporaryOutputStream.toByteArray();
|
compressedData = temporaryOutputStream.toByteArray();
|
||||||
}catch(IOException ex) {
|
}catch(IOException ex) {
|
||||||
logger.error("Failed to compress packet {}!", pkt.getClass().getSimpleName());
|
logger.error("Failed to compress packet {}!", pkt.getClass().getSimpleName());
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class RelayUpdateChecker {
|
||||||
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));
|
relaysList.add(new RelayEntry(etr.address));
|
||||||
}
|
}
|
||||||
byte[] b = PlatformApplication.getLocalStorage("lastRelayUpdate");
|
byte[] b = PlatformApplication.getLocalStorage("lastRelayUpdate", false);
|
||||||
if(b != null) {
|
if(b != null) {
|
||||||
try {
|
try {
|
||||||
lastUpdateCheck = (new DataInputStream(new EaglerInputStream(b))).readLong();
|
lastUpdateCheck = (new DataInputStream(new EaglerInputStream(b))).readLong();
|
||||||
|
@ -79,7 +79,7 @@ public class RelayUpdateChecker {
|
||||||
try {
|
try {
|
||||||
EaglerOutputStream bao = new EaglerOutputStream(8);
|
EaglerOutputStream bao = new EaglerOutputStream(8);
|
||||||
(new DataOutputStream(bao)).writeLong(lastUpdateCheck);
|
(new DataOutputStream(bao)).writeLong(lastUpdateCheck);
|
||||||
PlatformApplication.setLocalStorage("lastRelayUpdate", bao.toByteArray());
|
PlatformApplication.setLocalStorage("lastRelayUpdate", bao.toByteArray(), false);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
}
|
}
|
||||||
for (int i = 0, l = relaysList.size(); i < l; ++i) {
|
for (int i = 0, l = relaysList.size(); i < l; ++i) {
|
||||||
|
|
|
@ -148,7 +148,16 @@ public class UpdateCertificate {
|
||||||
throw new CertificateInvalidException("SHA256 checksum of signature payload is invalid!");
|
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 {
|
private UpdateCertificate(byte[] certData, InputStream is, int sigVers) throws IOException {
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class UpdateService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
byte[] latestUpdate = PlatformApplication.getLocalStorage(EaglercraftVersion.updateLatestLocalStorageKey);
|
byte[] latestUpdate = PlatformApplication.getLocalStorage(EaglercraftVersion.updateLatestLocalStorageKey, false);
|
||||||
if(latestUpdate != null) {
|
if(latestUpdate != null) {
|
||||||
addCertificateToSet(latestUpdate, false);
|
addCertificateToSet(latestUpdate, false);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ public class UpdateService {
|
||||||
latestUpdateFound = cert;
|
latestUpdateFound = cert;
|
||||||
if (saveLatest) {
|
if (saveLatest) {
|
||||||
PlatformApplication.setLocalStorage(EaglercraftVersion.updateLatestLocalStorageKey,
|
PlatformApplication.setLocalStorage(EaglercraftVersion.updateLatestLocalStorageKey,
|
||||||
certificateData);
|
certificateData, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else if(EagRuntime.getConfiguration().isLogInvalidCerts()) {
|
}else if(EagRuntime.getConfiguration().isLogInvalidCerts()) {
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -95,34 +95,66 @@ public class PlatformApplication {
|
||||||
private static native void setClipboard0(String str);
|
private static native void setClipboard0(String str);
|
||||||
|
|
||||||
public static void setLocalStorage(String name, byte[] data) {
|
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 {
|
try {
|
||||||
Storage s = Window.current().getLocalStorage();
|
Storage s = Window.current().getLocalStorage();
|
||||||
if(s != null) {
|
if(s != null) {
|
||||||
if(data != null) {
|
if(data != null) {
|
||||||
s.setItem("_eaglercraftX." + name, Base64.encodeBase64String(data));
|
s.setItem(eagName, b64);
|
||||||
}else {
|
}else {
|
||||||
s.removeItem("_eaglercraftX." + name);
|
s.removeItem(eagName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}catch(Throwable t) {
|
}catch(Throwable t) {
|
||||||
}
|
}
|
||||||
|
if(hooks) {
|
||||||
|
adapter.getHooks().callLocalStorageSavedHook(name, b64);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] getLocalStorage(String name) {
|
public static byte[] getLocalStorage(String name) {
|
||||||
try {
|
return getLocalStorage(name, true);
|
||||||
Storage s = Window.current().getLocalStorage();
|
}
|
||||||
if(s != null) {
|
|
||||||
String str = s.getItem("_eaglercraftX." + name);
|
public static byte[] getLocalStorage(String name, boolean hooks) {
|
||||||
if(str != null) {
|
IClientConfigAdapter adapter = PlatformRuntime.getClientConfigAdapter();
|
||||||
return Base64.decodeBase64(str);
|
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 {
|
}else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}else {
|
}catch(Throwable t) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}catch(Throwable t) {
|
}else {
|
||||||
return null;
|
return hooked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,16 +30,18 @@ import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||||
import net.minecraft.util.MathHelper;
|
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
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
*
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
* NOT FOR COMMERCIAL OR MALICIOUS USE
|
* 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,
|
||||||
* (please read the 'LICENSE' file this repo's root directory for more info)
|
* 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 {
|
public class PlatformAudio {
|
||||||
|
|
|
@ -104,6 +104,7 @@ public class PlatformInput {
|
||||||
public static boolean lockKeys = false;
|
public static boolean lockKeys = false;
|
||||||
|
|
||||||
private static boolean vsync = true;
|
private static boolean vsync = true;
|
||||||
|
private static boolean vsyncSupport = false;
|
||||||
|
|
||||||
@JSBody(params = { }, script = "window.onbeforeunload = () => {return false;};")
|
@JSBody(params = { }, script = "window.onbeforeunload = () => {return false;};")
|
||||||
private static native void onBeforeCloseRegister();
|
private static native void onBeforeCloseRegister();
|
||||||
|
@ -252,7 +253,18 @@ public class PlatformInput {
|
||||||
mouseDY = 0.0D;
|
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();
|
fullscreenQuery = fullscreenMediaQuery();
|
||||||
if (keyboardLockSupported = checkKeyboardLockSupported()) {
|
if (keyboardLockSupported = checkKeyboardLockSupported()) {
|
||||||
|
@ -300,6 +312,9 @@ public class PlatformInput {
|
||||||
vsync = enable;
|
vsync = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JSBody(params = { "doc" }, script = "return (doc.visibilityState === \"visible\");")
|
||||||
|
private static native boolean getVisibilityState(JSObject doc);
|
||||||
|
|
||||||
public static void update() {
|
public static void update() {
|
||||||
double r = win.getDevicePixelRatio();
|
double r = win.getDevicePixelRatio();
|
||||||
int w = PlatformRuntime.parent.getClientWidth();
|
int w = PlatformRuntime.parent.getClientWidth();
|
||||||
|
@ -320,10 +335,14 @@ public class PlatformInput {
|
||||||
PlatformRuntime.lastFrame = t;
|
PlatformRuntime.lastFrame = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(vsync) {
|
if(getVisibilityState(win.getDocument())) {
|
||||||
asyncRequestAnimationFrame();
|
if(vsyncSupport && vsync) {
|
||||||
|
asyncRequestAnimationFrame();
|
||||||
|
}else {
|
||||||
|
EagUtils.sleep(0l);
|
||||||
|
}
|
||||||
}else {
|
}else {
|
||||||
EagUtils.sleep(0l);
|
EagUtils.sleep(50l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,6 +367,10 @@ public class PlatformInput {
|
||||||
}, 50);
|
}, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isVSyncSupported() {
|
||||||
|
return vsyncSupport;
|
||||||
|
}
|
||||||
|
|
||||||
static void initFramebuffer(WebGL2RenderingContext ctx, WebGLFramebuffer fbo, int sw, int sh) {
|
static void initFramebuffer(WebGL2RenderingContext ctx, WebGLFramebuffer fbo, int sw, int sh) {
|
||||||
context = ctx;
|
context = ctx;
|
||||||
mainFramebuffer = fbo;
|
mainFramebuffer = fbo;
|
||||||
|
@ -599,7 +622,7 @@ public class PlatformInput {
|
||||||
keyEvents.clear();
|
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();
|
private static native JSObject fullscreenMediaQuery();
|
||||||
|
|
||||||
@JSBody(params = { "mediaQuery" }, script = "return mediaQuery.matches;")
|
@JSBody(params = { "mediaQuery" }, script = "return mediaQuery.matches;")
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.teavm.jso.JSBody;
|
||||||
import org.teavm.jso.JSFunctor;
|
import org.teavm.jso.JSFunctor;
|
||||||
import org.teavm.jso.JSObject;
|
import org.teavm.jso.JSObject;
|
||||||
import org.teavm.jso.browser.Window;
|
import org.teavm.jso.browser.Window;
|
||||||
|
import org.teavm.jso.core.JSArrayReader;
|
||||||
import org.teavm.jso.core.JSError;
|
import org.teavm.jso.core.JSError;
|
||||||
import org.teavm.jso.dom.css.CSSStyleDeclaration;
|
import org.teavm.jso.dom.css.CSSStyleDeclaration;
|
||||||
import org.teavm.jso.dom.html.HTMLCanvasElement;
|
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.PlatformApplication;
|
||||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
|
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.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.internal.teavm.opts.JSEaglercraftXOptsRoot;
|
||||||
import net.lax1dude.eaglercraft.v1_8.log4j.ILogRedirector;
|
import net.lax1dude.eaglercraft.v1_8.log4j.ILogRedirector;
|
||||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||||
|
@ -87,7 +87,7 @@ public class ClientMain {
|
||||||
if(epkSingleURL != null) {
|
if(epkSingleURL != null) {
|
||||||
configEPKFiles = new EPKFileEntry[] { new EPKFileEntry(epkSingleURL, "") };
|
configEPKFiles = new EPKFileEntry[] { new EPKFileEntry(epkSingleURL, "") };
|
||||||
}else {
|
}else {
|
||||||
JSEaglercraftXOptsAssetsURIsArray epkURLs = eaglercraftOpts.getAssetsURIArray();
|
JSArrayReader<JSEaglercraftXOptsAssetsURI> epkURLs = eaglercraftOpts.getAssetsURIArray();
|
||||||
int len = epkURLs.getLength();
|
int len = epkURLs.getLength();
|
||||||
if(len == 0) {
|
if(len == 0) {
|
||||||
throw new JSONException("assetsURI array cannot be empty!");
|
throw new JSONException("assetsURI array cannot be empty!");
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.teavm.jso.dom.html.HTMLDocument;
|
||||||
import org.teavm.jso.dom.html.HTMLElement;
|
import org.teavm.jso.dom.html.HTMLElement;
|
||||||
|
|
||||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication;
|
import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication;
|
||||||
|
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
|
||||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,13 +64,13 @@ public class DebugConsoleWindow {
|
||||||
destroyWindow();
|
destroyWindow();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if("true".equals(parent.getLocalStorage().getItem("_eaglercraftX.showDebugConsole"))) {
|
if("true".equals(parent.getLocalStorage().getItem(PlatformRuntime.getClientConfigAdapter().getLocalStorageNamespace() + ".showDebugConsole"))) {
|
||||||
showDebugConsole0();
|
showDebugConsole0();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showDebugConsole() {
|
public static void showDebugConsole() {
|
||||||
parent.getLocalStorage().setItem("_eaglercraftX.showDebugConsole", "true");
|
parent.getLocalStorage().setItem(PlatformRuntime.getClientConfigAdapter().getLocalStorageNamespace() + ".showDebugConsole", "true");
|
||||||
showDebugConsole0();
|
showDebugConsole0();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,14 @@ import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.teavm.jso.JSObject;
|
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.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.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.JSEaglercraftXOptsRoot;
|
||||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsServer;
|
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;
|
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayEntry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,6 +57,9 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||||
private boolean checkRelaysForUpdates = false;
|
private boolean checkRelaysForUpdates = false;
|
||||||
private boolean enableSignatureBadge = false;
|
private boolean enableSignatureBadge = false;
|
||||||
private boolean allowVoiceClient = true;
|
private boolean allowVoiceClient = true;
|
||||||
|
private boolean allowFNAWSkins = true;
|
||||||
|
private String localStorageNamespace = "_eaglercraftX";
|
||||||
|
private final TeaVMClientConfigAdapterHooks hooks = new TeaVMClientConfigAdapterHooks();
|
||||||
|
|
||||||
public void loadNative(JSObject jsObject) {
|
public void loadNative(JSObject jsObject) {
|
||||||
integratedServerOpts = new JSONObject();
|
integratedServerOpts = new JSONObject();
|
||||||
|
@ -75,6 +79,12 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||||
logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftXOpts.getLogInvalidCerts(false);
|
logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftXOpts.getLogInvalidCerts(false);
|
||||||
enableSignatureBadge = eaglercraftXOpts.getEnableSignatureBadge(false);
|
enableSignatureBadge = eaglercraftXOpts.getEnableSignatureBadge(false);
|
||||||
allowVoiceClient = eaglercraftXOpts.getAllowVoiceClient(true);
|
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("worldsDB", worldsDB);
|
||||||
integratedServerOpts.put("demoMode", demoMode);
|
integratedServerOpts.put("demoMode", demoMode);
|
||||||
|
@ -82,8 +92,9 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||||
integratedServerOpts.put("allowUpdateSvc", isAllowUpdateSvc);
|
integratedServerOpts.put("allowUpdateSvc", isAllowUpdateSvc);
|
||||||
integratedServerOpts.put("allowUpdateDL", isAllowUpdateDL);
|
integratedServerOpts.put("allowUpdateDL", isAllowUpdateDL);
|
||||||
integratedServerOpts.put("allowVoiceClient", allowVoiceClient);
|
integratedServerOpts.put("allowVoiceClient", allowVoiceClient);
|
||||||
|
integratedServerOpts.put("allowFNAWSkins", allowFNAWSkins);
|
||||||
|
|
||||||
JSEaglercraftXOptsServersArray serversArray = eaglercraftXOpts.getServers();
|
JSArrayReader<JSEaglercraftXOptsServer> serversArray = eaglercraftXOpts.getServers();
|
||||||
if(serversArray != null) {
|
if(serversArray != null) {
|
||||||
for(int i = 0, l = serversArray.getLength(); i < l; ++i) {
|
for(int i = 0, l = serversArray.getLength(); i < l; ++i) {
|
||||||
JSEaglercraftXOptsServer serverEntry = serversArray.get(i);
|
JSEaglercraftXOptsServer serverEntry = serversArray.get(i);
|
||||||
|
@ -95,7 +106,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSEaglercraftXOptsRelaysArray relaysArray = eaglercraftXOpts.getRelays();
|
JSArrayReader<JSEaglercraftXOptsRelay> relaysArray = eaglercraftXOpts.getRelays();
|
||||||
if(relaysArray != null) {
|
if(relaysArray != null) {
|
||||||
boolean gotAPrimary = false;
|
boolean gotAPrimary = false;
|
||||||
for(int i = 0, l = relaysArray.getLength(); i < l; ++i) {
|
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);
|
logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftOpts.optBoolean("logInvalidCerts", false);
|
||||||
enableSignatureBadge = eaglercraftOpts.optBoolean("enableSignatureBadge", false);
|
enableSignatureBadge = eaglercraftOpts.optBoolean("enableSignatureBadge", false);
|
||||||
allowVoiceClient = eaglercraftOpts.optBoolean("allowVoiceClient", true);
|
allowVoiceClient = eaglercraftOpts.optBoolean("allowVoiceClient", true);
|
||||||
|
allowFNAWSkins = eaglercraftOpts.optBoolean("allowFNAWSkins", true);
|
||||||
|
localStorageNamespace = eaglercraftOpts.optString("localStorageNamespace", EaglercraftVersion.localStorageNamespace);
|
||||||
JSONArray serversArray = eaglercraftOpts.optJSONArray("servers");
|
JSONArray serversArray = eaglercraftOpts.optJSONArray("servers");
|
||||||
if(serversArray != null) {
|
if(serversArray != null) {
|
||||||
for(int i = 0, l = serversArray.length(); i < l; ++i) {
|
for(int i = 0, l = serversArray.length(); i < l; ++i) {
|
||||||
|
@ -309,6 +322,21 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||||
return allowVoiceClient;
|
return allowVoiceClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowFNAWSkins() {
|
||||||
|
return allowFNAWSkins;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLocalStorageNamespace() {
|
||||||
|
return localStorageNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IClientConfigAdapterHooks getHooks() {
|
||||||
|
return hooks;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
JSONObject jsonObject = new JSONObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
@ -327,6 +355,8 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
|
||||||
jsonObject.put("checkRelaysForUpdates", checkRelaysForUpdates);
|
jsonObject.put("checkRelaysForUpdates", checkRelaysForUpdates);
|
||||||
jsonObject.put("enableSignatureBadge", enableSignatureBadge);
|
jsonObject.put("enableSignatureBadge", enableSignatureBadge);
|
||||||
jsonObject.put("allowVoiceClient", allowVoiceClient);
|
jsonObject.put("allowVoiceClient", allowVoiceClient);
|
||||||
|
jsonObject.put("allowFNAWSkins", allowFNAWSkins);
|
||||||
|
jsonObject.put("localStorageNamespace", localStorageNamespace);
|
||||||
JSONArray serversArr = new JSONArray();
|
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);
|
DefaultServer srv = defaultServers.get(i);
|
||||||
|
|
|
@ -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<Object> hooker);
|
||||||
|
|
||||||
|
private static void callHookSafeWithReturn(String identifer, Supplier<Object> hooker, final AsyncCallback<Object> 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
package net.lax1dude.eaglercraft.v1_8.internal.teavm.opts;
|
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.JSObject;
|
||||||
import org.teavm.jso.JSProperty;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||||||
|
@ -19,12 +18,12 @@ import org.teavm.jso.JSProperty;
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface JSEaglercraftXOptsAssetsURIsArray extends JSObject {
|
public abstract class JSEaglercraftXOptsHooks implements JSObject {
|
||||||
|
|
||||||
@JSIndexer
|
@JSBody(script = "return (typeof this.localStorageSaved === \"function\") ? this.localStorageSaved : null;")
|
||||||
JSEaglercraftXOptsAssetsURI get(int idx);
|
public native JSObject getLocalStorageSavedHook();
|
||||||
|
|
||||||
@JSProperty
|
@JSBody(script = "return (typeof this.localStorageLoaded === \"function\") ? this.localStorageLoaded : null;")
|
||||||
int getLength();
|
public native JSObject getLocalStorageLoadedHook();
|
||||||
|
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@ package net.lax1dude.eaglercraft.v1_8.internal.teavm.opts;
|
||||||
|
|
||||||
import org.teavm.jso.JSBody;
|
import org.teavm.jso.JSBody;
|
||||||
import org.teavm.jso.JSObject;
|
import org.teavm.jso.JSObject;
|
||||||
|
import org.teavm.jso.core.JSArrayReader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||||||
|
@ -27,7 +28,7 @@ public abstract class JSEaglercraftXOptsRoot implements JSObject {
|
||||||
public native String getAssetsURI();
|
public native String getAssetsURI();
|
||||||
|
|
||||||
@JSBody(script = "return (typeof this.assetsURI === \"object\") ? this.assetsURI : null;")
|
@JSBody(script = "return (typeof this.assetsURI === \"object\") ? this.assetsURI : null;")
|
||||||
public native JSEaglercraftXOptsAssetsURIsArray getAssetsURIArray();
|
public native JSArrayReader<JSEaglercraftXOptsAssetsURI> getAssetsURIArray();
|
||||||
|
|
||||||
@JSBody(params = { "def" }, script = "return (typeof this.lang === \"string\") ? this.lang : def;")
|
@JSBody(params = { "def" }, script = "return (typeof this.lang === \"string\") ? this.lang : def;")
|
||||||
public native String getLang(String defaultValue);
|
public native String getLang(String defaultValue);
|
||||||
|
@ -48,10 +49,10 @@ public abstract class JSEaglercraftXOptsRoot implements JSObject {
|
||||||
public native boolean getDemoMode(boolean defaultValue);
|
public native boolean getDemoMode(boolean defaultValue);
|
||||||
|
|
||||||
@JSBody(script = "return (typeof this.servers === \"object\") ? this.servers : null;")
|
@JSBody(script = "return (typeof this.servers === \"object\") ? this.servers : null;")
|
||||||
public native JSEaglercraftXOptsServersArray getServers();
|
public native JSArrayReader<JSEaglercraftXOptsServer> getServers();
|
||||||
|
|
||||||
@JSBody(script = "return (typeof this.relays === \"object\") ? this.relays : null;")
|
@JSBody(script = "return (typeof this.relays === \"object\") ? this.relays : null;")
|
||||||
public native JSEaglercraftXOptsRelaysArray getRelays();
|
public native JSArrayReader<JSEaglercraftXOptsRelay> 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);
|
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;")
|
@JSBody(params = { "def" }, script = "return (typeof this.allowVoiceClient === \"boolean\") ? this.allowVoiceClient : def;")
|
||||||
public native boolean getAllowVoiceClient(boolean defaultValue);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user