u31 and v1.3.2

This commit is contained in:
radmanplays 2024-05-29 19:26:04 +03:30
parent ef3e8657fc
commit cdca8c4d9f
70 changed files with 3517 additions and 460 deletions

View File

@ -22,7 +22,7 @@
> DELETE 1 @ 1 : 4 > DELETE 1 @ 1 : 4
> CHANGE 1 : 60 @ 1 : 4 > CHANGE 1 : 61 @ 1 : 4
~ ~
~ import net.eaglerforge.EaglerForge; ~ import net.eaglerforge.EaglerForge;
@ -38,6 +38,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;
@ -450,7 +451,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
@ -523,9 +538,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
@ -788,7 +807,11 @@
~ GameSettings g = theMinecraft.gameSettings; ~ GameSettings g = theMinecraft.gameSettings;
~ return g.ambientOcclusion != 0 && !g.shadersAODisable; ~ return g.ambientOcclusion != 0 && !g.shadersAODisable;
> CHANGE 130 : 131 @ 130 : 131 > CHANGE 2 : 3 @ 2 : 3
~ public void middleClickMouse() {
> CHANGE 127 : 128 @ 127 : 128
~ return EagRuntime.getVersion(); ~ return EagRuntime.getVersion();

View File

@ -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 {
+ +

View File

@ -329,7 +329,7 @@
> CHANGE 1 : 3 @ 1 : 2 > CHANGE 1 : 3 @ 1 : 2
~ this.drawString(this.fontRendererObj, s, 2, this.height - 20, -1); ~ this.drawString(this.fontRendererObj, s, 2, this.height - 20, -1);
~ s = EaglercraftVersion.mainMenuStringB; ~ s = EaglercraftVersion.getMainMenuStringB();
> CHANGE 1 : 3 @ 1 : 2 > CHANGE 1 : 3 @ 1 : 2

View File

@ -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);

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -53,9 +53,11 @@
> DELETE 1 @ 1 : 5 > DELETE 1 @ 1 : 5
> DELETE 2 @ 2 : 4 > CHANGE 2 : 3 @ 2 : 5
> CHANGE 3 : 5 @ 3 : 9 ~ this.maxPlayers = 100;
> CHANGE 2 : 4 @ 2 : 8
~ public void initializeConnectionToPlayer(IntegratedServerPlayerNetworkManager netManager, EntityPlayerMP playerIn) { ~ public void initializeConnectionToPlayer(IntegratedServerPlayerNetworkManager netManager, EntityPlayerMP playerIn) {
~ GameProfile gameprofile1 = playerIn.getGameProfile(); ~ GameProfile gameprofile1 = playerIn.getGameProfile();
@ -131,14 +133,12 @@
+ } + }
+ +
> CHANGE 4 : 11 @ 4 : 11 > CHANGE 4 : 9 @ 4 : 11
~ public String allowUserToConnect(GameProfile gameprofile) { ~ public String allowUserToConnect(GameProfile gameprofile) {
~ return this.playerEntityList.size() >= this.maxPlayers && !this.func_183023_f(gameprofile) ~ return doesPlayerAlreadyExist(gameprofile)
~ ? "The server is full!" ~ ? "\"" + gameprofile.getName() + "\" is already playing on this world!"
~ : (doesPlayerAlreadyExist(gameprofile) ~ : null;
~ ? "\"" + gameprofile.getName() + "\" is already playing on this world!"
~ : null);
~ } ~ }
> CHANGE 1 : 7 @ 1 : 9 > CHANGE 1 : 7 @ 1 : 9
@ -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

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -0,0 +1,8 @@
# Eagler Context Redacted Diff
# Copyright (c) 2024 lax1dude. All rights reserved.
# Version: 1.0
# Author: lax1dude
> EOF

View File

@ -64,8 +64,12 @@ public class PlatformApplication {
String str = glfwGetClipboardString(win); String str = glfwGetClipboardString(win);
return str == null ? "" : str; return str == null ? "" : 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) {
if(data == null) { if(data == null) {
(new File("_eagstorage."+name+".dat")).delete(); (new File("_eagstorage."+name+".dat")).delete();
}else { }else {
@ -76,8 +80,12 @@ 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;

View File

@ -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;

View File

@ -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;
}
}
} }

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,17 @@ import org.teavm.jso.JSObject;
import org.teavm.jso.JSFunctor; import org.teavm.jso.JSFunctor;
public abstract class BaseData implements JSObject { public abstract class BaseData implements JSObject {
@JSFunctor
public interface ClassFinderCallback extends JSObject {
BaseData onCallback(String classIdentifier);
}
@JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void setCallbackClassFinder(String key, ClassFinderCallback value);
@JSFunctor @JSFunctor
public interface VoidCallback extends JSObject { public interface VoidCallback extends JSObject {
void onCallback(); void onCallback();
@ -20,6 +31,16 @@ public abstract class BaseData implements JSObject {
JSObject onCallback(); JSObject onCallback();
} }
@JSFunctor
public interface ReflectiveObjectCallback extends JSObject {
Object onCallback();
}
@JSFunctor
public interface DataReflectiveObjectCallback extends JSObject {
Object onCallback(BaseData data);
}
@JSFunctor @JSFunctor
public interface FloatCallback extends JSObject { public interface FloatCallback extends JSObject {
float onCallback(); float onCallback();
@ -138,6 +159,9 @@ public abstract class BaseData implements JSObject {
@JSBody(params = { "key", "value" }, script = "this[key]=value;") @JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void set(String key, String value); public native void set(String key, String value);
@JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void set(String key, Object value);
@JSBody(params = { "key", "value" }, script = "this[key]=value;") @JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void set(String key, int value); public native void set(String key, int value);
@ -162,6 +186,9 @@ public abstract class BaseData implements JSObject {
@JSBody(params = { "key", "value" }, script = "this[key]=value;") @JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void set(String key, BaseData value); public native void set(String key, BaseData value);
@JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void setReflective(String key, Object value);
@JSBody(params = { "key", "value" }, script = "this[key]=value;") @JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void set(String key, String[] value); public native void set(String key, String[] value);
@ -216,6 +243,12 @@ public abstract class BaseData implements JSObject {
@JSBody(params = { "key", "value" }, script = "this[key]=value;") @JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void setCallbackFloat(String key, FloatCallback value); public native void setCallbackFloat(String key, FloatCallback value);
@JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void setCallbackReflective(String key, ReflectiveObjectCallback value);
@JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void setCallbackReflectiveWithDataArg(String key, DataReflectiveObjectCallback value);
@JSBody(params = { "key", "value" }, script = "this[key]=value;") @JSBody(params = { "key", "value" }, script = "this[key]=value;")
public native void setCallbackObject(String key, ObjectCallback value); public native void setCallbackObject(String key, ObjectCallback value);
@ -300,6 +333,9 @@ public abstract class BaseData implements JSObject {
@JSBody(params = { "key" }, script = "return this[key];") @JSBody(params = { "key" }, script = "return this[key];")
public native JSObject getObject(String key); public native JSObject getObject(String key);
@JSBody(params = { "key" }, script = "return this[key];")
public native Object getReflective(String key);
@JSBody(params = { "key" }, script = "return this[key];") @JSBody(params = { "key" }, script = "return this[key];")
public native BaseData getBaseData(String key); public native BaseData getBaseData(String key);
@ -357,4 +393,4 @@ public abstract class BaseData implements JSObject {
@JSBody(params = { }, script = "if(this.getRef){ return this.getRef(); } else { return null; }") @JSBody(params = { }, script = "if(this.getRef){ return this.getRef(); } else { return null; }")
public native BaseData getRef(); public native BaseData getRef();
} }

View File

@ -1,6 +1,7 @@
package net.eaglerforge.api; package net.eaglerforge.api;
import net.eaglerforge.gui.ModGUI; import net.eaglerforge.gui.ModGUI;
import net.eaglerforge.reflect.PLReflect;
import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger; import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
@ -310,6 +311,7 @@ public class ModAPI {
setGlobal("mcinstance", mc); setGlobal("mcinstance", mc);
setMinecraftContext(mc); setMinecraftContext(mc);
setGlobal("platform", PlatformAPI.makeModData()); setGlobal("platform", PlatformAPI.makeModData());
setGlobal("reflect", PLReflect.makeModData());
setGlobal("logger", LoggerAPI.makeModData()); setGlobal("logger", LoggerAPI.makeModData());
//setGlobal("emptygui", EmptyGui.makeModData()); //setGlobal("emptygui", EmptyGui.makeModData());
setGlobal("ScaledResolution", ScaledResolution.makeModData()); setGlobal("ScaledResolution", ScaledResolution.makeModData());

View File

@ -1,4 +1,4 @@
package net.eaglerforge.api; package net.eaglerforge.api;
public class ModData extends BaseData{ public class ModData extends BaseData {
} }

File diff suppressed because it is too large Load Diff

View File

@ -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();
} }

View File

@ -1,5 +1,6 @@
package net.lax1dude.eaglercraft.v1_8; package net.lax1dude.eaglercraft.v1_8;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import java.math.BigInteger; import java.math.BigInteger;
import static net.eaglerforge.api.ModLoader.returntotalloadedmods; import static net.eaglerforge.api.ModLoader.returntotalloadedmods;
@ -12,7 +13,7 @@ public class EaglercraftVersion {
/// Customize these to fit your fork: /// Customize these to fit your fork:
public static final String projectForkName = "EaglerForge"; public static final String projectForkName = "EaglerForge";
public static final String projectForkVersion = "v1.3.1"; public static final String projectForkVersion = "v1.3.2";
public static final String projectForkVendor = "radmanplays"; public static final String projectForkVendor = "radmanplays";
public static final String projectForkURL = "https://github.com/eaglerforge/EaglerForge"; public static final String projectForkURL = "https://github.com/eaglerforge/EaglerForge";
@ -22,7 +23,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 = "u31";
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
@ -43,9 +44,20 @@ public class EaglercraftVersion {
// Miscellaneous variables: // Miscellaneous variables:
public static int loadedmods = returntotalloadedmods();
public static final String mainMenuStringA = "Minecraft* 1.8.8"; public static final String mainMenuStringA = "Minecraft* 1.8.8";
public static String mainMenuStringB = projectForkName + " " + projectForkVersion + " (" + loadedmods + " Mods loaded)"; public static String getMainMenuStringB() {
int loadedmods = returntotalloadedmods();
String mainMenuStringB = projectForkName + " " + projectForkVersion;
if(!PlatformRuntime.isDebugRuntime()) {
if(loadedmods == 1) {
mainMenuStringB = mainMenuStringB + " (" + loadedmods + " Mod loaded)";
} else {
mainMenuStringB = mainMenuStringB + " (" + loadedmods + " Mods loaded)";
}
}
return mainMenuStringB;
}
public static final String mainMenuStringC = ""; public static final String mainMenuStringC = "";
public static final String mainMenuStringD = "Resources Copyright Mojang AB"; public static final String mainMenuStringD = "Resources Copyright Mojang AB";
@ -61,4 +73,6 @@ public class EaglercraftVersion {
public static final boolean forceDemoMode = false; public static final boolean forceDemoMode = false;
public static final String localStorageNamespace = "_eaglercraftX";
} }

View File

@ -69,4 +69,11 @@ public interface IClientConfigAdapter {
boolean isEnableSignatureBadge(); boolean isEnableSignatureBadge();
boolean isAllowVoiceClient(); boolean isAllowVoiceClient();
boolean isAllowFNAWSkins();
String getLocalStorageNamespace();
IClientConfigAdapterHooks getHooks();
} }

View File

@ -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 JSEaglercraftXOptsServersArray extends JSObject { public interface IClientConfigAdapterHooks {
@JSIndexer void callLocalStorageSavedHook(String key, String base64);
JSEaglercraftXOptsServer get(int idx);
@JSProperty String callLocalStorageLoadHook(String key);
int getLength();
} }

View File

@ -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");

View File

@ -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);
} }
} }

View File

@ -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;

View File

@ -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));
} }

View File

@ -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) {

View File

@ -69,98 +69,97 @@ public class ProfileExporter {
osb.write(new byte[]{(byte)255,(byte)255,(byte)255,(byte)255}); // this will be replaced with the file count osb.write(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)) {
if(doExportProfile) { os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
byte[] profileData = EaglerProfile.write(); os.write(new byte[]{(byte)9,(byte)102,(byte)105,(byte)108,(byte)101,(byte)45,(byte)116,(byte)121,
if(profileData == null) { (byte)112,(byte)101}); // 9 + file-type
throw new IOException("Could not write profile data!"); 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
exportFileToEPK("_eaglercraftX.p", profileData, os); os.write('>');
++fileCount;
} 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,
if(doExportSettings) { (byte)112,(byte)111,(byte)114,(byte)116,(byte)115,(byte)0,(byte)0,(byte)0,(byte)1}); // 12 + file-exports + 1
logger.info("Exporting game settings..."); os.write((doExportProfile ? 1 : 0) | (doExportSettings ? 2 : 0) | (doExportServers ? 4 : 0) | (doExportResourcePacks ? 8 : 0));
byte[] gameSettings = Minecraft.getMinecraft().gameSettings.writeOptions(); os.write('>');
if(gameSettings == null) {
throw new IOException("Could not write game settings!");
} if(doExportProfile) {
exportFileToEPK("_eaglercraftX.g", gameSettings, os); byte[] profileData = EaglerProfile.write();
++fileCount; if(profileData == null) {
logger.info("Exporting relay settings..."); throw new IOException("Could not write profile data!");
byte[] relays = RelayManager.relayManager.write(); }
if(relays == null) { exportFileToEPK("_eaglercraftX.p", profileData, os);
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;
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:>
byte[] ret = osb.toByteArray(); byte[] ret = osb.toByteArray();

View File

@ -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();
}
} }

View File

@ -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);
}
}
} }

View File

@ -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;

View File

@ -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"));
} }
} }

View File

@ -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);
} }

View File

@ -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) {

View File

@ -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();
}
} }

View File

@ -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); }
} }
} }
} }

View File

@ -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();
} }

View File

@ -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());

View File

@ -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) {

View File

@ -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 {

View File

@ -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()) {

View File

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

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,6 @@
<script type="text/javascript" src="ModAPI.js"></script> <script type="text/javascript" src="ModAPI.js"></script>
<script type="text/javascript" src="ModLoader.js"></script> <script type="text/javascript" src="ModLoader.js"></script>
<script type="text/javascript" src="ModGUI.js"></script> <script type="text/javascript" src="ModGUI.js"></script>
<script type="text/javascript" src="anvil.js"></script>
<script type="text/javascript" src="classes.js"></script> <script type="text/javascript" src="classes.js"></script>
<script type="text/javascript"> <script type="text/javascript">
"use strict"; "use strict";

View File

@ -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;
} }
} }

View File

@ -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 {

View File

@ -102,8 +102,9 @@ public class PlatformInput {
public static boolean keyboardLockSupported = false; public static boolean keyboardLockSupported = false;
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;")

View File

@ -608,7 +608,7 @@ public class PlatformRuntime {
FixWebMDurationJS.getRecUrl(evt, (int) (System.currentTimeMillis() - startTime), url -> { FixWebMDurationJS.getRecUrl(evt, (int) (System.currentTimeMillis() - startTime), url -> {
HTMLAnchorElement a = (HTMLAnchorElement) doc.createElement("a"); HTMLAnchorElement a = (HTMLAnchorElement) doc.createElement("a");
dateInstance.setTime(startTime); dateInstance.setTime(startTime);
a.setDownload(EaglercraftVersion.mainMenuStringB + " - " + EaglerProfile.getName() + " - " + fmt.format(dateInstance) + ".webm"); a.setDownload(EaglercraftVersion.getMainMenuStringB() + " - " + EaglerProfile.getName() + " - " + fmt.format(dateInstance) + ".webm");
a.setHref(url); a.setHref(url);
a.click(); a.click();
TeaVMUtils.freeDataURL(url); TeaVMUtils.freeDataURL(url);

View File

@ -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!");

View File

@ -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();
} }

View File

@ -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 = !demoMode && 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);

View File

@ -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();
}
}

View File

@ -0,0 +1,29 @@
package net.lax1dude.eaglercraft.v1_8.internal.teavm.opts;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
/**
* 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 abstract class JSEaglercraftXOptsHooks implements JSObject {
@JSBody(script = "return (typeof this.localStorageSaved === \"function\") ? this.localStorageSaved : null;")
public native JSObject getLocalStorageSavedHook();
@JSBody(script = "return (typeof this.localStorageLoaded === \"function\") ? this.localStorageLoaded : null;")
public native JSObject getLocalStorageLoadedHook();
}

View File

@ -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);
} }