Forgot to fix TeaVM classes (compile)

This commit is contained in:
PeytonPlayz595 2025-03-11 19:08:04 -07:00
parent d103637281
commit b12fd7654f
23 changed files with 20105 additions and 931 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
javascript/assets.epk Normal file

Binary file not shown.

6437
javascript/classes.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -50,13 +50,13 @@ class OpenGLObjects {
}
static class BufferArrayGL implements IBufferArrayGL {
static class VertexArrayGL implements IVertexArrayGL {
private static int hashGen = 0;
final WebGLVertexArray ptr;
final int hash;
BufferArrayGL(WebGLVertexArray ptr) {
VertexArrayGL(WebGLVertexArray ptr) {
this.ptr = ptr;
this.hash = ++hashGen;
}

View File

@ -31,11 +31,7 @@ import org.teavm.jso.dom.html.HTMLElement;
import org.teavm.jso.dom.html.HTMLFormElement;
import org.teavm.jso.dom.html.HTMLInputElement;
import org.teavm.jso.dom.html.TextRectangle;
import org.teavm.jso.gamepad.Gamepad;
import org.teavm.jso.gamepad.GamepadButton;
import org.teavm.jso.gamepad.GamepadEvent;
import net.lax1dude.eaglercraft.GamepadConstants;
import net.lax1dude.eaglercraft.KeyboardConstants;
import net.lax1dude.eaglercraft.internal.teavm.ClientMain;
import net.lax1dude.eaglercraft.internal.teavm.EarlyLoadScreen;
@ -74,8 +70,6 @@ public class PlatformInput {
private static EventListener<?> touchend = null;
private static EventListener<?> touchmove = null;
private static EventListener<?> touchcancel = null;
private static EventListener<?> gamepadconnected = null;
private static EventListener<?> gamepaddisconnected = null;
private static EventListener<?> keydown = null;
private static EventListener<?> keyup = null;
private static EventListener<?> wheel = null;
@ -165,14 +159,6 @@ public class PlatformInput {
public static int touchOffsetXTeaVM = 0;
public static int touchOffsetYTeaVM = 0;
private static boolean gamepadSupported = false;
private static final List<Gamepad> gamepadList = new ArrayList<>();
private static Gamepad selectedGamepad = null;
private static String selectedGamepadName = null;
private static double gamepadTimestamp = -1.0;
private static final boolean[] gamepadButtonStates = new boolean[24];
private static final float[] gamepadAxisStates = new float[4];
private static int windowWidth = -1;
private static int windowHeight = -1;
private static float windowDPI = 1.0f;
@ -617,32 +603,6 @@ public class PlatformInput {
}
}, 1000);
}
try {
gamepadSupported = gamepadSupported();
if(gamepadSupported) {
win.addEventListener("gamepadconnected", gamepadconnected = new EventListener<GamepadEvent>() {
@Override
public void handleEvent(GamepadEvent evt) {
enumerateGamepads();
}
});
win.addEventListener("gamepaddisconnected", gamepaddisconnected = new EventListener<GamepadEvent>() {
@Override
public void handleEvent(GamepadEvent evt) {
if(selectedGamepad != null && evt.getGamepad().getIndex() == selectedGamepad.getIndex()) {
selectedGamepad = null;
}
enumerateGamepads();
}
});
}
}catch(Throwable t) {
gamepadSupported = false;
PlatformRuntime.logger.error("Gamepad detected as unsupported!");
}
enumerateGamepads();
}
@JSFunctor
@ -1292,14 +1252,6 @@ public class PlatformInput {
canvas.removeEventListener("mouseleave", mouseleave);
mouseleave = null;
}
if(gamepadconnected != null) {
win.removeEventListener("gamepadconnected", gamepadconnected);
gamepadconnected = null;
}
if(gamepaddisconnected != null) {
win.removeEventListener("gamepaddisconnected", gamepaddisconnected);
gamepaddisconnected = null;
}
if(keydown != null) {
win.removeEventListener("keydown", keydown);
keydown = null;
@ -1415,7 +1367,6 @@ public class PlatformInput {
public static void clearEvenBuffers() {
mouseEvents.clear();
keyEvents.clear();
net.lax1dude.eaglercraft.v1_8.Gamepad.clearEventBuffer();
}
@JSBody(params = {}, script = "return window.matchMedia(\"(display-mode: fullscreen)\");")
@ -1546,190 +1497,6 @@ public class PlatformInput {
@JSBody(params = { "doc", "el" }, script = "return doc.activeElement === el;")
private static native boolean isActiveElement(HTMLDocument doc, HTMLElement el);
private static void enumerateGamepads() {
if(!gamepadSupported) return;
if(selectedGamepad != null) {
selectedGamepad = updateGamepad(selectedGamepad);
if(selectedGamepad == null || !TeaVMUtils.isTruthy(selectedGamepad) || !selectedGamepad.isConnected()) {
selectedGamepad = null;
}
}
List<Gamepad> oldList = null;
if(!gamepadList.isEmpty()) {
oldList = new ArrayList<>(gamepadList);
gamepadList.clear();
}
Gamepad[] gamepads = Navigator.getGamepads();
if(gamepads != null && gamepads.length > 0) {
for(int i = 0; i < gamepads.length; ++i) {
Gamepad g = gamepads[i];
if(TeaVMUtils.isTruthy(g) && g.isConnected() && "standard".equals(g.getMapping())) {
gamepadList.add(g);
}
}
}
if(selectedGamepad != null) {
selectedGamepadName = selectedGamepad.getId();
}
if(oldList == null) {
if(!gamepadList.isEmpty()) {
for(int i = 0, l = gamepadList.size(); i < l; ++i) {
PlatformRuntime.logger.info("Found controller: {}", gamepadList.get(i).getId());
}
}
}else {
if(gamepadList.isEmpty()) {
for(int i = 0, l = oldList.size(); i < l; ++i) {
PlatformRuntime.logger.info("Lost controller: {}", oldList.get(i).getId());
}
}else {
Map<String,Integer> oldDevCounts = new HashMap<>();
for(Gamepad gg : oldList) {
String s = gg.getId();
Integer i = oldDevCounts.get(s);
if(i != null) {
oldDevCounts.put(s, Integer.valueOf(i.intValue() + 1));
}else {
oldDevCounts.put(s, Integer.valueOf(1));
}
}
Map<String,Integer> newDevCounts = new HashMap<>();
for(Gamepad gg : gamepadList) {
String s = gg.getId();
Integer i = newDevCounts.get(s);
if(i != null) {
newDevCounts.put(s, Integer.valueOf(i.intValue() + 1));
}else {
newDevCounts.put(s, Integer.valueOf(1));
}
}
for(Entry<String,Integer> etr : oldDevCounts.entrySet()) {
Integer i = newDevCounts.get(etr.getKey());
if(i == null) {
for(int j = 0, l = etr.getValue().intValue(); j < l; ++j) {
PlatformRuntime.logger.info("Lost controller: {}", etr.getKey());
}
}else {
int j = i.intValue();
int k = etr.getValue().intValue();
if(k != j) {
if(k < j) {
for(int m = 0, l = j - k; m < l; ++m) {
PlatformRuntime.logger.info("Found controller: {}", etr.getKey());
}
}else {
for(int m = 0, l = k - j; m < l; ++m) {
PlatformRuntime.logger.info("Lost controller: {}", etr.getKey());
}
}
}
}
}
for(Entry<String,Integer> etr : newDevCounts.entrySet()) {
Integer i = oldDevCounts.get(etr.getKey());
if(i == null) {
for(int j = 0, l = etr.getValue().intValue(); j < l; ++j) {
PlatformRuntime.logger.info("Found controller: {}", etr.getKey());
}
}
}
}
}
}
public static int gamepadGetValidDeviceCount() {
if(!gamepadSupported) return 0;
return gamepadList.size();
}
public static String gamepadGetDeviceName(int deviceId) {
if(gamepadSupported && deviceId >= 0 && deviceId < gamepadList.size()) {
return gamepadList.get(deviceId).getId();
}else {
return "Unknown";
}
}
public static void gamepadSetSelectedDevice(int deviceId) {
if(!gamepadSupported) return;
gamepadReset();
if(deviceId >= 0 && deviceId < gamepadList.size()) {
selectedGamepad = gamepadList.get(deviceId);
gamepadTimestamp = -1.0;
if(!TeaVMUtils.isTruthy(selectedGamepad) || !selectedGamepad.isConnected()) {
selectedGamepad = null;
}
}else {
selectedGamepad = null;
}
}
private static void gamepadReset() {
for(int i = 0; i < gamepadButtonStates.length; ++i) {
gamepadButtonStates[i] = false;
}
for(int i = 0; i < gamepadAxisStates.length; ++i) {
gamepadAxisStates[i] = 0.0f;
}
}
@JSBody(params = { }, script = "return (typeof navigator.getGamepads === \"function\");")
private static native boolean gamepadSupported();
@JSBody(params = { "gp" }, script = "return navigator.getGamepads()[gp.index];")
private static native Gamepad updateGamepad(Gamepad gp);
public static void gamepadUpdate() {
if(!gamepadSupported) return;
if(selectedGamepad != null) {
selectedGamepad = updateGamepad(selectedGamepad);
if(selectedGamepad == null || !TeaVMUtils.isTruthy(selectedGamepad) || !selectedGamepad.isConnected()) {
gamepadReset();
selectedGamepad = null;
return;
}
double ts = selectedGamepad.getTimestamp();
if(ts != gamepadTimestamp) {
gamepadTimestamp = ts;
gamepadReset();
GamepadButton[] btns = selectedGamepad.getButtons();
for(int i = 0; i < btns.length; ++i) {
int j = GamepadConstants.getEaglerButtonFromBrowser(i);
if(j >= 0 && j < gamepadButtonStates.length) {
gamepadButtonStates[j] = btns[i].isPressed();
}
}
double[] axes = selectedGamepad.getAxes();
for(int i = 0; i < axes.length; ++i) {
if(i >= 4) {
break;
}
gamepadAxisStates[i] = (float)axes[i];
}
}
}else {
gamepadReset();
}
}
public static boolean gamepadIsValid() {
if(!gamepadSupported) return false;
return selectedGamepad != null;
}
public static String gamepadGetName() {
return gamepadSupported && selectedGamepad != null ? selectedGamepadName : "Unknown";
}
public static boolean gamepadGetButtonState(int button) {
return gamepadSupported && selectedGamepad != null && button >= 0 && button < gamepadButtonStates.length ? gamepadButtonStates[button] : false;
}
public static float gamepadGetAxis(int axis) {
return gamepadSupported && selectedGamepad != null && axis >= 0 && axis < gamepadAxisStates.length ? gamepadAxisStates[axis] : 0.0f;
}
public static float getDPI() {
return windowDPI;
}

View File

@ -1,26 +1,12 @@
package net.lax1dude.eaglercraft.internal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.teavm.interop.Async;
import org.teavm.interop.AsyncCallback;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
import org.teavm.jso.dom.events.Event;
import org.teavm.jso.dom.events.EventListener;
import org.teavm.jso.dom.events.MessageEvent;
import org.teavm.jso.typedarrays.ArrayBuffer;
import org.teavm.jso.websocket.WebSocket;
import net.lax1dude.eaglercraft.internal.teavm.TeaVMServerQuery;
import net.lax1dude.eaglercraft.internal.teavm.TeaVMUtils;
import net.lax1dude.eaglercraft.internal.teavm.TeaVMWebSocketClient;
/**
* Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved.
* Copyright (c) 2022-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
@ -36,169 +22,20 @@ import net.lax1dude.eaglercraft.internal.teavm.TeaVMUtils;
*/
public class PlatformNetworking {
private static WebSocket sock = null;
private static boolean sockIsConnecting = false;
private static boolean sockIsConnected = false;
private static boolean sockIsAlive = false;
private static boolean sockIsFailed = false;
private static LinkedList<byte[]> readPackets = new LinkedList();
private static String currentSockURI = null;
private static EnumServerRateLimit serverRateLimit = null;
private static final Logger logger = LogManager.getLogger("PlatformNetworking");
public static EnumEaglerConnectionState playConnectionState() {
return !sockIsConnected ? (sockIsFailed ? EnumEaglerConnectionState.FAILED : EnumEaglerConnectionState.CLOSED)
: (sockIsConnecting ? EnumEaglerConnectionState.CONNECTING : EnumEaglerConnectionState.CONNECTED);
}
public static void startPlayConnection(String destination) {
sockIsFailed = !connectWebSocket(destination).booleanValue();
}
@JSBody(params = { "obj" }, script = "return typeof obj === \"string\";")
private static native boolean isString(JSObject obj);
@Async
public static native Boolean connectWebSocket(String sockURI);
private static void connectWebSocket(String sockURI, final AsyncCallback<Boolean> cb) {
sockIsConnecting = true;
sockIsConnected = false;
sockIsAlive = false;
currentSockURI = sockURI;
public static IWebSocketClient openWebSocket(String socketURI) {
try {
sock = WebSocket.create(sockURI);
} catch(Throwable t) {
sockIsFailed = true;
sockIsConnecting = false;
sockIsAlive = false;
cb.complete(Boolean.FALSE);
return;
}
final WebSocket oldSock = sock;
sock.setBinaryType("arraybuffer");
TeaVMUtils.addEventListener(sock, "open", new EventListener<Event>() {
@Override
public void handleEvent(Event evt) {
if (oldSock != sock) return;
sockIsConnecting = false;
sockIsAlive = false;
sockIsConnected = true;
synchronized(readPackets) {
readPackets.clear();
}
cb.complete(Boolean.TRUE);
}
});
TeaVMUtils.addEventListener(sock, "close", new EventListener<Event>() {
@Override
public void handleEvent(Event evt) {
if (oldSock != sock) return;
sock = null;
boolean b = sockIsConnecting;
sockIsConnecting = false;
sockIsConnected = false;
sockIsAlive = false;
if(b) cb.complete(Boolean.FALSE);
}
});
TeaVMUtils.addEventListener(sock, "message", new EventListener<MessageEvent>() {
@Override
public void handleEvent(MessageEvent evt) {
if (oldSock != sock) return;
sockIsAlive = true;
if(isString(evt.getData())) {
String str = evt.getDataAsString();
if(str.equalsIgnoreCase("BLOCKED")) {
logger.error("Reached full IP ratelimit!");
serverRateLimit = EnumServerRateLimit.BLOCKED;
}else if(str.equalsIgnoreCase("LOCKED")) {
logger.error("Reached full IP ratelimit lockout!");
serverRateLimit = EnumServerRateLimit.LOCKED_OUT;
}
}else {
synchronized(readPackets) {
readPackets.add(TeaVMUtils.wrapByteArrayBuffer(evt.getDataAsArray()));
}
}
}
});
TeaVMUtils.addEventListener(sock, "error", new EventListener<Event>() {
@Override
public void handleEvent(Event evt) {
if (oldSock != sock) return;
if(sockIsConnecting) {
sockIsFailed = true;
sockIsConnecting = false;
sockIsAlive = false;
cb.complete(Boolean.FALSE);
}
}
});
}
public static void playDisconnect() {
if(sock != null) sock.close();
sockIsConnecting = false;
}
public static byte[] readPlayPacket() {
synchronized(readPackets) {
if(!readPackets.isEmpty()) {
return readPackets.remove(0);
}else {
return null;
}
}
}
public static List<byte[]> readAllPacket() {
synchronized(readPackets) {
if(!readPackets.isEmpty()) {
List<byte[]> ret = new ArrayList<>(readPackets);
readPackets.clear();
return ret;
}else {
return null;
}
}
}
public static int countAvailableReadData() {
int total = 0;
synchronized(readPackets) {
for(int i = 0, l = readPackets.size(); i < l; ++i) {
total += readPackets.get(i).length;
}
}
return total;
}
@JSBody(params = { "sock", "buffer" }, script = "sock.send(buffer);")
protected static native void nativeBinarySend(WebSocket sock, ArrayBuffer buffer);
public static void writePlayPacket(byte[] pkt) {
if(sock != null && !sockIsConnecting) {
nativeBinarySend(sock, TeaVMUtils.unwrapArrayBuffer(pkt));
}
}
public static IServerQuery sendServerQuery(String uri, String accept) {
try {
return new TeaVMServerQuery(uri, accept);
return new TeaVMWebSocketClient(socketURI);
}catch(Throwable t) {
logger.error("Could not send query to \"{}\"!", uri);
logger.error("Could not open WebSocket to \"{}\"!", socketURI);
logger.error(t);
return null;
}
}
public static EnumServerRateLimit getRateLimit() {
return serverRateLimit == null ? EnumServerRateLimit.OK : serverRateLimit;
}
public static String getCurrentURI() {
return currentSockURI;
public static IWebSocketClient openWebSocketUnsafe(String socketURI) {
return new TeaVMWebSocketClient(socketURI);
}
}

View File

@ -278,12 +278,12 @@ public class PlatformOpenGL {
return new OpenGLObjects.TextureGL(ctx.createTexture());
}
public static final IBufferArrayGL _wglGenVertexArrays() {
public static final IVertexArrayGL _wglGenVertexArrays() {
switch(vertexArrayImpl) {
case VAO_IMPL_CORE:
return new OpenGLObjects.BufferArrayGL(ctx.createVertexArray());
return new OpenGLObjects.VertexArrayGL(ctx.createVertexArray());
case VAO_IMPL_OES:
return new OpenGLObjects.BufferArrayGL(OESVertexArrayObject.createVertexArrayOES());
return new OpenGLObjects.VertexArrayGL(OESVertexArrayObject.createVertexArrayOES());
default:
throw new UnsupportedOperationException();
}
@ -317,8 +317,8 @@ public class PlatformOpenGL {
ctx.deleteTexture(((OpenGLObjects.TextureGL)obj).ptr);
}
public static final void _wglDeleteVertexArrays(IBufferArrayGL obj) {
WebGLVertexArray ptr = ((OpenGLObjects.BufferArrayGL)obj).ptr;
public static final void _wglDeleteVertexArrays(IVertexArrayGL obj) {
WebGLVertexArray ptr = ((OpenGLObjects.VertexArrayGL)obj).ptr;
switch(vertexArrayImpl) {
case VAO_IMPL_CORE:
ctx.deleteVertexArray(ptr);
@ -383,8 +383,8 @@ public class PlatformOpenGL {
ctx.bufferSubData(target, offset, EaglerArrayBufferAllocator.getDataView32F(data));
}
public static final void _wglBindVertexArray(IBufferArrayGL obj) {
WebGLVertexArray ptr = obj != null ? ((OpenGLObjects.BufferArrayGL)obj).ptr : null;
public static final void _wglBindVertexArray(IVertexArrayGL obj) {
WebGLVertexArray ptr = obj != null ? ((OpenGLObjects.VertexArrayGL)obj).ptr : null;
switch(vertexArrayImpl) {
case VAO_IMPL_CORE:
ctx.bindVertexArray(ptr);

View File

@ -3,6 +3,7 @@ package net.lax1dude.eaglercraft.internal;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@ -42,9 +43,6 @@ import org.teavm.jso.webgl.WebGLFramebuffer;
import org.teavm.platform.Platform;
import org.teavm.platform.PlatformRunnable;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import com.jcraft.jzlib.Deflater;
import com.jcraft.jzlib.DeflaterOutputStream;
import com.jcraft.jzlib.GZIPInputStream;
@ -212,7 +210,11 @@ public class PlatformRuntime {
if(viewportTag != null) {
String cont = viewportTag.getAttribute("content");
if(cont != null) {
Set<String> oldTokens = Sets.newHashSet(Iterators.transform(Iterators.forArray(cont.split(",")), String::trim));
String[] oldTokenArray = cont.split(",");
Set<String> oldTokens = new HashSet<>();
for (String token : oldTokenArray) {
oldTokens.add(token.trim());
}
Set<String> tokens = new HashSet<>();
for(String str : oldTokens) {
if (!(str.startsWith("width=") || str.startsWith("initial-scale=")
@ -475,7 +477,11 @@ public class PlatformRuntime {
private static void dumpShims(Set<EnumES6Shims> shims) {
if(!shims.isEmpty()) {
logger.info("(Enabled {} shims: {})", shims.size(), String.join(", ", Collections2.transform(shims, (shim) -> shim.shimDesc)));
List<String> descriptions = new ArrayList<>();
for (EnumES6Shims shim : shims) {
descriptions.add(shim.shimDesc);
}
logger.info("(Enabled {} shims: {})", shims.size(), String.join(", ", descriptions));
}
}

View File

@ -275,14 +275,6 @@ public class EaglerArrayByteBuffer extends ByteBuffer {
return this;
}
@Override
public ByteBuffer putDouble(double value) {
if(position + 8 > limit) throw Buffer.makeIOOBE(position);
dataView.setFloat64(position, value, true);
position += 8;
return this;
}
@Override
public int getInt(int index) {
if(index < 0 || index + 4 > limit) throw Buffer.makeIOOBE(index);
@ -340,14 +332,6 @@ public class EaglerArrayByteBuffer extends ByteBuffer {
return f;
}
@Override
public double getDouble() {
if(position + 8 > limit) throw Buffer.makeIOOBE(position);
double f = dataView.getFloat64(position, true);
position += 8;
return f;
}
@Override
public ByteBuffer putFloat(float value) {
if(position + 4 > limit) throw Buffer.makeIOOBE(position);
@ -424,9 +408,4 @@ public class EaglerArrayByteBuffer extends ByteBuffer {
position = newPosition;
return this;
}
@Override
public ByteBuffer compact() {
return this;
}
}

View File

@ -1,120 +0,0 @@
package net.lax1dude.eaglercraft.internal.teavm;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSProperty;
import org.teavm.jso.dom.html.HTMLIFrameElement;
import org.teavm.jso.dom.types.DOMTokenList;
import com.google.common.collect.Iterators;
/**
* 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 AdvancedHTMLIFrameElement implements HTMLIFrameElement {
@JSProperty
public abstract void setAllow(String str);
@JSProperty
public abstract String getAllow();
public void setAllowSafe(String requiredValue) {
setAllow(requiredValue);
if(!requiredValue.equals(getAllow())) {
throw new IFrameSafetyException("Could not set allow attribute to: " + requiredValue);
}
}
@JSProperty
public abstract void setAllowFullscreen(boolean en);
@JSProperty
public abstract void setCredentialless(boolean en);
@JSProperty
public abstract void setLoading(String str);
@JSProperty
public abstract void setReferrerPolicy(String str);
@JSProperty("csp")
public abstract void setCSP(String str);
@JSProperty
public abstract void setSandbox(String str);
@JSProperty
public abstract DOMTokenList getSandbox();
public void assertSafetyFeaturesSupported() {
if(!checkSafetyFeaturesSupported()) {
throw new IFrameSafetyException("Some required security features are not supported on this browser!");
}
}
public void setSandboxSafe(Collection<String> requiredTokens) {
setSandboxSafe(new HashSet<>(requiredTokens));
}
public void setSandboxSafe(Set<String> requiredTokens) {
setSandbox(String.join(" ", requiredTokens));
DOMTokenList theSandbox = getSandbox();
for(String s : requiredTokens) {
if(!theSandbox.contains(s)) {
throw new IFrameSafetyException("Failed to set sandbox attribute: " + s);
}
}
int l = theSandbox.getLength();
for(int i = 0; i < l; ++i) {
String s = theSandbox.item(i);
if(!requiredTokens.contains(s)) {
throw new IFrameSafetyException("Unknown sandbox attribute detected: " + s);
}
}
}
public void setSandboxSafe(Collection<String> requiredTokens, Collection<String> optionalTokens) {
setSandboxSafe(new HashSet<>(requiredTokens), new HashSet<>(optionalTokens));
}
public void setSandboxSafe(Set<String> requiredTokens, Set<String> optionalTokens) {
setSandbox(StringUtils.join(Iterators.concat(requiredTokens.iterator(), optionalTokens.iterator()), " "));
DOMTokenList theSandbox = getSandbox();
for(String s : requiredTokens) {
if(!theSandbox.contains(s)) {
throw new IFrameSafetyException("Failed to set sandbox attribute: " + s);
}
}
int l = theSandbox.getLength();
for(int i = 0; i < l; ++i) {
String s = theSandbox.item(i);
if(!requiredTokens.contains(s) && !optionalTokens.contains(s)) {
throw new IFrameSafetyException("Unknown sandbox attribute detected: " + s);
}
}
}
@JSBody(params = {}, script = "return (typeof this.allow === \"string\") && (typeof this.sandbox === \"object\");")
public native boolean checkSafetyFeaturesSupported();
@JSBody(params = {}, script = "return (typeof this.csp === \"string\");")
public native boolean checkCSPSupported();
}

View File

@ -6,7 +6,7 @@ import net.lax1dude.eaglercraft.opengl.ImageData;
import static net.lax1dude.eaglercraft.internal.PlatformOpenGL.*;
import static net.lax1dude.eaglercraft.opengl.RealOpenGLEnums.*;
import net.lax1dude.eaglercraft.internal.IBufferArrayGL;
import net.lax1dude.eaglercraft.internal.IVertexArrayGL;
import net.lax1dude.eaglercraft.internal.IBufferGL;
import net.lax1dude.eaglercraft.internal.IProgramGL;
import net.lax1dude.eaglercraft.internal.IShaderGL;
@ -151,7 +151,7 @@ public class EarlyLoadScreen {
_wglUseProgram(program);
_wglUniform2f(_wglGetUniformLocation(program, "aspect"), x, y);
IBufferArrayGL vao = null;
IVertexArrayGL vao = null;
if(vaos) {
vao = _wglGenVertexArrays();
_wglBindVertexArray(vao);
@ -213,7 +213,7 @@ public class EarlyLoadScreen {
_wglUniform2f(_wglGetUniformLocation(program, "aspect"), x, y);
IBufferArrayGL vao = null;
IVertexArrayGL vao = null;
if(vaos) {
vao = _wglGenVertexArrays();
_wglBindVertexArray(vao);
@ -283,11 +283,11 @@ public class EarlyLoadScreen {
_wglUniform2f(_wglGetUniformLocation(program, "aspect"), x, y);
IBufferArrayGL vao = null;
IVertexArrayGL vao = null;
if(vaos) {
if(softVAOs) {
vao = EaglercraftGPU.createGLBufferArray();
EaglercraftGPU.bindGLBufferArray(vao);
vao = EaglercraftGPU.createGLVertexArray();
EaglercraftGPU.bindGLVertexArray(vao);
}else {
vao = _wglGenVertexArrays();
_wglBindVertexArray(vao);
@ -297,7 +297,7 @@ public class EarlyLoadScreen {
EaglercraftGPU.bindVAOGLArrayBuffer(vbo);
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0);
EaglercraftGPU.doDrawArrays(GL_TRIANGLES, 0, 6);
EaglercraftGPU.drawArrays(GL_TRIANGLES, 0, 6);
}else {
_wglBindBuffer(GL_ARRAY_BUFFER, vbo);
_wglEnableVertexAttribArray(0);
@ -322,7 +322,7 @@ public class EarlyLoadScreen {
}
if(vaos) {
if(softVAOs) {
EaglercraftGPU.destroyGLBufferArray(vao);
EaglercraftGPU.destroyGLVertexArray(vao);
}else {
_wglDeleteVertexArrays(vao);
}

View File

@ -1,11 +1,11 @@
package net.lax1dude.eaglercraft.internal.teavm;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Sets;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
@ -51,9 +51,15 @@ public class LegacyKeycodeTranslator {
}
private static final Set<String> numpadVolatile = Sets.newHashSet(
private static final Set<String> numpadVolatile = newHashSet(
"Comma", "Minus", "Period", "Slash", "Equal", "Enter", "Digit0", "Digit1", "Digit2", "Digit3",
"Digit4", "Digit5", "Digit6", "Digit7", "Digit8", "Digit9", "IntlYen");
public static <E extends Object> HashSet<E> newHashSet(E... elements) {
HashSet<E> set = new HashSet<E>(elements.length);
Collections.addAll(set, elements);
return set;
}
private final Map<String,LegacyKeycode> codeLookupBase = new HashMap<>();
private final Map<String,LegacyKeycode> codeLookupLayout = new HashMap<>();

View File

@ -1,7 +1,9 @@
package net.lax1dude.eaglercraft.internal.teavm;
import net.lax1dude.eaglercraft.EaglercraftVersion;
import org.json.JSONObject;
import java.util.List;
import org.teavm.jso.JSObject;
import net.lax1dude.eaglercraft.internal.IClientConfigAdapter;
@ -32,30 +34,12 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
private String serverToJoin = null;
private String worldsDB = "worlds";
private String resourcePacksDB = "resourcePacks";
private JSONObject integratedServerOpts;
private boolean checkGLErrors = false;
private boolean checkShaderGLErrors = false;
private boolean demoMode = EaglercraftVersion.forceDemoMode;
private boolean isEnableDownloadOfflineButton = true;
private String downloadOfflineButtonLink = null;
private boolean useSpecialCursors = false;
private boolean allowVoiceClient = true;
private boolean allowFNAWSkins = true;
private String localStorageNamespace = "_eaglercraftX";
private final TeaVMClientConfigAdapterHooks hooks = new TeaVMClientConfigAdapterHooks();
private boolean enableMinceraft = true;
private boolean enableServerCookies = true;
private boolean allowServerRedirects = true;
private boolean crashOnUncaughtExceptions = false;
private boolean openDebugConsoleOnLaunch = false;
private boolean fixDebugConsoleUnloadListener = false;
private boolean forceWebViewSupport = false;
private boolean enableWebViewCSP = true;
private boolean autoFixLegacyStyleAttr = false;
private boolean showBootMenuOnLaunch = false;
private boolean bootMenuBlocksUnsignedClients = false;
private boolean allowBootMenu = true;
private boolean forceProfanityFilter = false;
private boolean forceWebGL1 = false;
private boolean forceWebGL2 = false;
private boolean allowExperimentalWebGL1 = true;
@ -72,7 +56,6 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
private boolean enableEPKVersionCheck = true;
public void loadNative(JSObject jsObject) {
integratedServerOpts = new JSONObject();
JSEaglercraftXOptsRoot eaglercraftXOpts = (JSEaglercraftXOptsRoot)jsObject;
defaultLocale = eaglercraftXOpts.getLang("en_US");
@ -80,27 +63,10 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
worldsDB = eaglercraftXOpts.getWorldsDB("worlds");
resourcePacksDB = eaglercraftXOpts.getResourcePacksDB("resourcePacks");
checkGLErrors = eaglercraftXOpts.getCheckGLErrors(false);
checkShaderGLErrors = eaglercraftXOpts.getCheckShaderGLErrors(false);
demoMode = EaglercraftVersion.forceDemoMode || eaglercraftXOpts.getDemoMode(false);
isEnableDownloadOfflineButton = eaglercraftXOpts.getEnableDownloadOfflineButton(true);
downloadOfflineButtonLink = eaglercraftXOpts.getDownloadOfflineButtonLink(null);
useSpecialCursors = eaglercraftXOpts.getHtml5CursorSupport(false);
allowVoiceClient = eaglercraftXOpts.getAllowVoiceClient(true);
allowFNAWSkins = !demoMode && eaglercraftXOpts.getAllowFNAWSkins(true);
localStorageNamespace = eaglercraftXOpts.getLocalStorageNamespace(EaglercraftVersion.localStorageNamespace);
enableMinceraft = eaglercraftXOpts.getEnableMinceraft(true);
enableServerCookies = !demoMode && eaglercraftXOpts.getEnableServerCookies(true);
allowServerRedirects = eaglercraftXOpts.getAllowServerRedirects(true);
crashOnUncaughtExceptions = eaglercraftXOpts.getCrashOnUncaughtExceptions(false);
openDebugConsoleOnLaunch = eaglercraftXOpts.getOpenDebugConsoleOnLaunch(false);
fixDebugConsoleUnloadListener = eaglercraftXOpts.getFixDebugConsoleUnloadListener(false);
forceWebViewSupport = eaglercraftXOpts.getForceWebViewSupport(false);
enableWebViewCSP = eaglercraftXOpts.getEnableWebViewCSP(true);
autoFixLegacyStyleAttr = eaglercraftXOpts.getAutoFixLegacyStyleAttr(true);
showBootMenuOnLaunch = eaglercraftXOpts.getShowBootMenuOnLaunch(false);
bootMenuBlocksUnsignedClients = eaglercraftXOpts.getBootMenuBlocksUnsignedClients(false);
allowBootMenu = eaglercraftXOpts.getAllowBootMenu(!demoMode);
forceProfanityFilter = eaglercraftXOpts.getForceProfanityFilter(false);
forceWebGL1 = eaglercraftXOpts.getForceWebGL1(false);
forceWebGL2 = eaglercraftXOpts.getForceWebGL2(false);
allowExperimentalWebGL1 = eaglercraftXOpts.getAllowExperimentalWebGL1(true);
@ -119,65 +85,6 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
if(hooksObj != null) {
hooks.loadHooks(hooksObj);
}
integratedServerOpts.put("worldsDB", worldsDB);
integratedServerOpts.put("demoMode", demoMode);
integratedServerOpts.put("lang", defaultLocale);
integratedServerOpts.put("allowVoiceClient", allowVoiceClient);
integratedServerOpts.put("allowFNAWSkins", allowFNAWSkins);
integratedServerOpts.put("crashOnUncaughtExceptions", crashOnUncaughtExceptions);
integratedServerOpts.put("deobfStackTraces", deobfStackTraces);
integratedServerOpts.put("disableBlobURLs", disableBlobURLs);
integratedServerOpts.put("eaglerNoDelay", eaglerNoDelay);
integratedServerOpts.put("ramdiskMode", ramdiskMode);
integratedServerOpts.put("singleThreadMode", singleThreadMode);
}
public void loadJSON(JSONObject eaglercraftOpts) {
integratedServerOpts = eaglercraftOpts;
defaultLocale = eaglercraftOpts.optString("lang", "en_US");
serverToJoin = eaglercraftOpts.optString("joinServer", null);
worldsDB = eaglercraftOpts.optString("worldsDB", "worlds");
resourcePacksDB = eaglercraftOpts.optString("resourcePacksDB", "resourcePacks");
checkGLErrors = eaglercraftOpts.optBoolean("checkGLErrors", false);
checkShaderGLErrors = eaglercraftOpts.optBoolean("checkShaderGLErrors", false);
if(EaglercraftVersion.forceDemoMode) {
eaglercraftOpts.put("demoMode", true);
}
demoMode = EaglercraftVersion.forceDemoMode || eaglercraftOpts.optBoolean("demoMode", false);
isEnableDownloadOfflineButton = eaglercraftOpts.optBoolean("enableDownloadOfflineButton", true);
downloadOfflineButtonLink = eaglercraftOpts.optString("downloadOfflineButtonLink", null);
useSpecialCursors = eaglercraftOpts.optBoolean("html5CursorSupport", false);
allowVoiceClient = eaglercraftOpts.optBoolean("allowVoiceClient", true);
allowFNAWSkins = eaglercraftOpts.optBoolean("allowFNAWSkins", true);
localStorageNamespace = eaglercraftOpts.optString("localStorageNamespace", EaglercraftVersion.localStorageNamespace);
enableMinceraft = eaglercraftOpts.optBoolean("enableMinceraft", true);
enableServerCookies = !demoMode && eaglercraftOpts.optBoolean("enableServerCookies", true);
allowServerRedirects = eaglercraftOpts.optBoolean("allowServerRedirects", true);
crashOnUncaughtExceptions = eaglercraftOpts.optBoolean("crashOnUncaughtExceptions", false);
openDebugConsoleOnLaunch = eaglercraftOpts.optBoolean("openDebugConsoleOnLaunch", false);
fixDebugConsoleUnloadListener = eaglercraftOpts.optBoolean("fixDebugConsoleUnloadListener", false);
forceWebViewSupport = eaglercraftOpts.optBoolean("forceWebViewSupport", false);
enableWebViewCSP = eaglercraftOpts.optBoolean("enableWebViewCSP", true);
autoFixLegacyStyleAttr = eaglercraftOpts.optBoolean("autoFixLegacyStyleAttr", true);
showBootMenuOnLaunch = eaglercraftOpts.optBoolean("showBootMenuOnLaunch", false);
bootMenuBlocksUnsignedClients = eaglercraftOpts.optBoolean("bootMenuBlocksUnsignedClients", false);
allowBootMenu = eaglercraftOpts.optBoolean("allowBootMenu", !demoMode);
forceProfanityFilter = eaglercraftOpts.optBoolean("forceProfanityFilter", false);
forceWebGL1 = eaglercraftOpts.optBoolean("forceWebGL1", false);
forceWebGL2 = eaglercraftOpts.optBoolean("forceWebGL2", false);
allowExperimentalWebGL1 = eaglercraftOpts.optBoolean("allowExperimentalWebGL1", true);
useWebGLExt = eaglercraftOpts.optBoolean("useWebGLExt", true);
useDelayOnSwap = eaglercraftOpts.optBoolean("useDelayOnSwap", false);
useJOrbisAudioDecoder = eaglercraftOpts.optBoolean("useJOrbisAudioDecoder", false);
useXHRFetch = eaglercraftOpts.optBoolean("useXHRFetch", false);
useVisualViewport = eaglercraftOpts.optBoolean("useVisualViewport", true);
deobfStackTraces = eaglercraftOpts.optBoolean("deobfStackTraces", true);
disableBlobURLs = eaglercraftOpts.optBoolean("disableBlobURLs", false);
eaglerNoDelay = eaglercraftOpts.optBoolean("eaglerNoDelay", false);
ramdiskMode = eaglercraftOpts.optBoolean("ramdiskMode", false);
singleThreadMode = eaglercraftOpts.optBoolean("singleThreadMode", false);
enableEPKVersionCheck = eaglercraftOpts.optBoolean("enableEPKVersionCheck", true);
}
public String getDefaultLocale() {
@ -280,58 +187,133 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter {
return hooks;
}
public JSONObject toJSONObject() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("lang", defaultLocale);
jsonObject.put("joinServer", serverToJoin);
jsonObject.put("worldsDB", worldsDB);
jsonObject.put("resourcePacksDB", resourcePacksDB);
jsonObject.put("checkGLErrors", checkGLErrors);
jsonObject.put("checkShaderGLErrors", checkShaderGLErrors);
jsonObject.put("demoMode", demoMode);
jsonObject.put("enableDownloadOfflineButton", isEnableDownloadOfflineButton);
jsonObject.put("downloadOfflineButtonLink", downloadOfflineButtonLink);
jsonObject.put("html5CursorSupport", useSpecialCursors);
jsonObject.put("allowVoiceClient", allowVoiceClient);
jsonObject.put("allowFNAWSkins", allowFNAWSkins);
jsonObject.put("localStorageNamespace", localStorageNamespace);
jsonObject.put("enableMinceraft", enableMinceraft);
jsonObject.put("enableServerCookies", enableServerCookies);
jsonObject.put("allowServerRedirects", allowServerRedirects);
jsonObject.put("crashOnUncaughtExceptions", crashOnUncaughtExceptions);
jsonObject.put("openDebugConsoleOnLaunch", openDebugConsoleOnLaunch);
jsonObject.put("fixDebugConsoleUnloadListener", fixDebugConsoleUnloadListener);
jsonObject.put("forceWebViewSupport", forceWebViewSupport);
jsonObject.put("enableWebViewCSP", enableWebViewCSP);
jsonObject.put("autoFixLegacyStyleAttr", autoFixLegacyStyleAttr);
jsonObject.put("showBootMenuOnLaunch", showBootMenuOnLaunch);
jsonObject.put("bootMenuBlocksUnsignedClients", bootMenuBlocksUnsignedClients);
jsonObject.put("allowBootMenu", allowBootMenu);
jsonObject.put("forceProfanityFilter", forceProfanityFilter);
jsonObject.put("forceWebGL1", forceWebGL1);
jsonObject.put("forceWebGL2", forceWebGL2);
jsonObject.put("allowExperimentalWebGL1", allowExperimentalWebGL1);
jsonObject.put("useWebGLExt", useWebGLExt);
jsonObject.put("useDelayOnSwap", useDelayOnSwap);
jsonObject.put("useJOrbisAudioDecoder", useJOrbisAudioDecoder);
jsonObject.put("useXHRFetch", useXHRFetch);
jsonObject.put("useVisualViewport", useVisualViewport);
jsonObject.put("deobfStackTraces", deobfStackTraces);
jsonObject.put("disableBlobURLs", disableBlobURLs);
jsonObject.put("eaglerNoDelay", eaglerNoDelay);
jsonObject.put("ramdiskMode", ramdiskMode);
jsonObject.put("singleThreadMode", singleThreadMode);
jsonObject.put("enableEPKVersionCheck", enableEPKVersionCheck);
return jsonObject;
@Override
public List<DefaultServer> getDefaultServerList() {
return null;
}
@Override
public String toString() {
return toJSONObject().toString();
public String getResourcePacksDB() {
return this.resourcePacksDB;
}
public String toStringFormatted() {
return toJSONObject().toString(4);
@Override
public boolean isCheckShaderGLErrors() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isDemo() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean allowUpdateSvc() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean allowUpdateDL() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isEnableDownloadOfflineButton() {
// TODO Auto-generated method stub
return false;
}
@Override
public String getDownloadOfflineButtonLink() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean useSpecialCursors() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isLogInvalidCerts() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isCheckRelaysForUpdates() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isEnableSignatureBadge() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAllowVoiceClient() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAllowFNAWSkins() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isEnableMinceraft() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isEnableServerCookies() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAllowServerRedirects() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isOpenDebugConsoleOnLaunch() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isForceWebViewSupport() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isEnableWebViewCSP() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAllowBootMenu() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isForceProfanityFilter() {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -1,5 +1,7 @@
package net.lax1dude.eaglercraft.internal.teavm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -11,8 +13,6 @@ import org.teavm.jso.JSObject;
import org.teavm.jso.core.JSArrayReader;
import org.teavm.jso.core.JSString;
import com.google.common.collect.Lists;
import net.lax1dude.eaglercraft.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.internal.teavm.generators.TeaVMRuntimeDeobfuscatorGenerator;
import net.lax1dude.eaglercraft.EagUtils;
@ -171,7 +171,7 @@ public class TeaVMRuntimeDeobfuscator {
public static String deobfExceptionStack(String stackLines) {
if(!isInitialized) return stackLines;
try {
List<String> lines = Lists.newArrayList(EagUtils.splitPattern.split(stackLines));
List<String> lines = Arrays.asList(EagUtils.splitPattern.split(stackLines));
deobfExceptionStack(lines);
return String.join("\n", lines);
}catch(Throwable t) {

View File

@ -1,203 +0,0 @@
package net.lax1dude.eaglercraft.internal.teavm;
import java.util.LinkedList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
import org.teavm.jso.dom.events.Event;
import org.teavm.jso.dom.events.EventListener;
import org.teavm.jso.dom.events.MessageEvent;
import org.teavm.jso.typedarrays.ArrayBuffer;
import org.teavm.jso.websocket.WebSocket;
import net.lax1dude.eaglercraft.internal.EnumServerRateLimit;
import net.lax1dude.eaglercraft.internal.IServerQuery;
import net.lax1dude.eaglercraft.internal.QueryResponse;
/**
* Copyright (c) 2022 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 TeaVMServerQuery implements IServerQuery {
public static final Logger logger = LogManager.getLogger("WebSocketQuery");
private final List<QueryResponse> queryResponses = new LinkedList();
private final List<byte[]> queryResponsesBytes = new LinkedList();
protected final String uri;
protected final String accept;
protected final WebSocket sock;
protected boolean open = true;
protected boolean alive = false;
protected long pingStart = -1l;
protected long pingTimer = -1l;
private EnumServerRateLimit rateLimit = EnumServerRateLimit.OK;
public TeaVMServerQuery(String uri, String accept) {
this.uri = uri;
this.accept = accept;
this.sock = WebSocket.create(uri);
initHandlers();
}
@JSBody(params = { "obj" }, script = "return typeof obj === \"string\";")
private static native boolean isString(JSObject obj);
protected void initHandlers() {
sock.setBinaryType("arraybuffer");
TeaVMUtils.addEventListener(sock, "open", new EventListener<Event>() {
@Override
public void handleEvent(Event evt) {
sock.send("Accept: " + accept);
}
});
TeaVMUtils.addEventListener(sock, "close", new EventListener<Event>() {
@Override
public void handleEvent(Event evt) {
open = false;
}
});
TeaVMUtils.addEventListener(sock, "message", new EventListener<MessageEvent>() {
@Override
public void handleEvent(MessageEvent evt) {
alive = true;
if(pingTimer == -1) {
pingTimer = System.currentTimeMillis() - pingStart;
if(pingTimer < 1) {
pingTimer = 1;
}
}
if(isString(evt.getData())) {
String str = evt.getDataAsString();
if(str.equalsIgnoreCase("BLOCKED")) {
logger.error("Reached full IP ratelimit for {}!", uri);
rateLimit = EnumServerRateLimit.BLOCKED;
return;
}
if(str.equalsIgnoreCase("LOCKED")) {
logger.error("Reached full IP ratelimit lockout for {}!", uri);
rateLimit = EnumServerRateLimit.LOCKED_OUT;
return;
}
try {
JSONObject obj = new JSONObject(str);
if("blocked".equalsIgnoreCase(obj.optString("type", null))) {
logger.error("Reached query ratelimit for {}!", uri);
rateLimit = EnumServerRateLimit.BLOCKED;
}else if("locked".equalsIgnoreCase(obj.optString("type", null))) {
logger.error("Reached query ratelimit lockout for {}!", uri);
rateLimit = EnumServerRateLimit.LOCKED_OUT;
}else {
QueryResponse response = new QueryResponse(obj, pingTimer);
synchronized(queryResponses) {
queryResponses.add(response);
}
}
}catch(Throwable t) {
logger.error("Exception thrown parsing websocket query response from \"" + uri + "\"!");
logger.error(t);
}
}else {
synchronized(queryResponsesBytes) {
queryResponsesBytes.add(TeaVMUtils.wrapByteArrayBuffer(evt.getDataAsArray()));
}
}
}
});
TeaVMUtils.addEventListener(sock, "error", new EventListener<Event>() {
@Override
public void handleEvent(Event evt) {
sock.close();
open = false;
}
});
}
@Override
public void send(String str) {
if(open) {
sock.send(str);
}
}
@JSBody(params = { "sock", "buffer" }, script = "sock.send(buffer);")
private static native void nativeBinarySend(WebSocket sock, ArrayBuffer buffer);
@Override
public void send(byte[] bytes) {
if(open) {
nativeBinarySend(sock, TeaVMUtils.unwrapArrayBuffer(bytes));
}
}
@Override
public int responsesAvailable() {
synchronized(queryResponses) {
return queryResponses.size();
}
}
@Override
public QueryResponse getResponse() {
synchronized(queryResponses) {
if(queryResponses.size() > 0) {
return queryResponses.remove(0);
}else {
return null;
}
}
}
@Override
public int binaryResponsesAvailable() {
synchronized(queryResponsesBytes) {
return queryResponsesBytes.size();
}
}
@Override
public byte[] getBinaryResponse() {
synchronized(queryResponsesBytes) {
if(queryResponsesBytes.size() > 0) {
return queryResponsesBytes.remove(0);
}else {
return null;
}
}
}
@Override
public QueryReadyState readyState() {
return open ? (alive ? QueryReadyState.OPEN : QueryReadyState.CONNECTING)
: (alive ? QueryReadyState.CLOSED : QueryReadyState.FAILED);
}
@Override
public void close() {
if(open) {
open = false;
sock.close();
}
}
@Override
public EnumServerRateLimit getRateLimit() {
return rateLimit;
}
}

View File

@ -0,0 +1,120 @@
package net.lax1dude.eaglercraft.internal.teavm;
import org.teavm.jso.dom.events.Event;
import org.teavm.jso.dom.events.EventListener;
import org.teavm.jso.dom.events.MessageEvent;
import org.teavm.jso.websocket.WebSocket;
import net.lax1dude.eaglercraft.EagUtils;
import net.lax1dude.eaglercraft.internal.AbstractWebSocketClient;
import net.lax1dude.eaglercraft.internal.EnumEaglerConnectionState;
import net.lax1dude.eaglercraft.internal.PlatformRuntime;
/**
* Copyright (c) 2022-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 TeaVMWebSocketClient extends AbstractWebSocketClient {
private final WebSocket sock;
private boolean sockIsConnecting = true;
private boolean sockIsConnected = false;
private boolean sockIsFailed = false;
public TeaVMWebSocketClient(String socketURI) {
super(socketURI);
sock = WebSocket.create(socketURI);
sock.setBinaryType("arraybuffer");
TeaVMUtils.addEventListener(sock, "open", new EventListener<Event>() {
@Override
public void handleEvent(Event evt) {
sockIsConnecting = false;
sockIsConnected = true;
}
});
TeaVMUtils.addEventListener(sock, "close", new EventListener<Event>() {
@Override
public void handleEvent(Event evt) {
sockIsConnecting = false;
sockIsConnected = false;
}
});
TeaVMUtils.addEventListener(sock, "message", new EventListener<MessageEvent>() {
@Override
public void handleEvent(MessageEvent evt) {
addRecievedFrame(new TeaVMWebSocketFrame(evt.getData()));
}
});
TeaVMUtils.addEventListener(sock, "error", new EventListener<Event>() {
@Override
public void handleEvent(Event evt) {
if(sockIsConnecting) {
sockIsFailed = true;
sockIsConnecting = false;
}
}
});
}
@Override
public boolean connectBlocking(int timeoutMS) {
long startTime = PlatformRuntime.steadyTimeMillis();
while(!sockIsConnected && !sockIsFailed) {
EagUtils.sleep(50);
if(PlatformRuntime.steadyTimeMillis() - startTime > timeoutMS * 1000) {
break;
}
}
return sockIsConnected;
}
@Override
public EnumEaglerConnectionState getState() {
return sockIsConnected ? EnumEaglerConnectionState.CONNECTED
: (sockIsFailed ? EnumEaglerConnectionState.FAILED
: (sockIsConnecting ? EnumEaglerConnectionState.CONNECTING : EnumEaglerConnectionState.CLOSED));
}
@Override
public boolean isOpen() {
return sockIsConnected;
}
@Override
public boolean isClosed() {
return !sockIsConnecting && !sockIsConnected;
}
@Override
public void close() {
sockIsConnecting = false;
sockIsConnected = false;
sock.close();
}
@Override
public void send(String str) {
if(sockIsConnected) {
sock.send(str);
}
}
@Override
public void send(byte[] bytes) {
if(sockIsConnected) {
sock.send(TeaVMUtils.unwrapArrayBuffer(bytes));
}
}
}

View File

@ -0,0 +1,114 @@
package net.lax1dude.eaglercraft.internal.teavm;
import java.io.InputStream;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
import org.teavm.jso.typedarrays.ArrayBuffer;
import net.lax1dude.eaglercraft.internal.IWebSocketFrame;
import net.lax1dude.eaglercraft.internal.PlatformRuntime;
/**
* 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 TeaVMWebSocketFrame implements IWebSocketFrame {
private JSObject data;
private boolean str;
private String cachedStrContent = null;
private byte[] cachedByteContent = null;
private int cachedLen = -1;
private final long timestamp;
@JSBody(params = { "obj" }, script = "return (typeof obj === \"string\");")
private static native boolean isStr(JSObject obj);
public TeaVMWebSocketFrame(JSObject data) {
this.data = data;
this.str = isStr(data);
this.timestamp = PlatformRuntime.steadyTimeMillis();
}
@Override
public boolean isString() {
return str;
}
@JSBody(params = { "obj" }, script = "return obj;")
private static native String toStr(JSObject obj);
@Override
public String getString() {
if(str) {
if(cachedStrContent == null) {
return (cachedStrContent = toStr(data));
}else {
return cachedStrContent;
}
}else {
return null;
}
}
@Override
public byte[] getByteArray() {
if(!str) {
if(cachedByteContent == null) {
return (cachedByteContent = TeaVMUtils.wrapByteArrayBuffer((ArrayBuffer)data));
}else {
return cachedByteContent;
}
}else {
return null;
}
}
@Override
public InputStream getInputStream() {
if(!str) {
return new ArrayBufferInputStream((ArrayBuffer)data);
}else {
return null;
}
}
@JSBody(params = { "obj" }, script = "return obj.length;")
private static native int strLen(JSObject obj);
@JSBody(params = { "obj" }, script = "return obj.byteLength;")
private static native int arrLen(JSObject obj);
@Override
public int getLength() {
if(cachedLen == -1) {
if(str) {
cachedLen = strLen(data);
}else {
cachedLen = arrLen(data);
}
}
return cachedLen;
}
@Override
public long getTimestamp() {
return timestamp;
}
}

View File

@ -5,7 +5,7 @@ import static net.lax1dude.eaglercraft.opengl.RealOpenGLEnums.*;
import org.teavm.jso.webgl.WebGLFramebuffer;
import net.lax1dude.eaglercraft.internal.IBufferArrayGL;
import net.lax1dude.eaglercraft.internal.IVertexArrayGL;
import net.lax1dude.eaglercraft.internal.IBufferGL;
import net.lax1dude.eaglercraft.internal.IFramebufferGL;
import net.lax1dude.eaglercraft.internal.IProgramGL;
@ -50,7 +50,7 @@ public class WebGLBackBuffer {
private static ITextureGL gles2ColorTexture;
private static IRenderbufferGL gles2DepthRenderbuffer;
private static IProgramGL gles2BlitProgram;
private static IBufferArrayGL gles2BlitVAO;
private static IVertexArrayGL gles2BlitVAO;
private static IBufferGL gles2BlitVBO;
private static boolean isVAOCapable = false;
@ -60,8 +60,9 @@ public class WebGLBackBuffer {
private static final int _GL_RENDERBUFFER = 0x8D41;
private static final int _GL_COLOR_ATTACHMENT0 = 0x8CE0;
private static final int _GL_DEPTH_ATTACHMENT = 0x8D00;
private static final int _GL_DEPTH_COMPONENT16 = 0x81A5;
private static final int _GL_DEPTH_STENCIL_ATTACHMENT = 0x821A;
private static final int _GL_DEPTH_COMPONENT32F = 0x8CAC;
private static final int _GL_DEPTH_STENCIL = 0x84F9;
private static final int _GL_READ_FRAMEBUFFER = 0x8CA8;
private static final int _GL_DRAW_FRAMEBUFFER = 0x8CA9;
@ -97,8 +98,8 @@ public class WebGLBackBuffer {
_wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sw, sh, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
_wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gles2ColorTexture, 0);
_wglBindRenderbuffer(_GL_RENDERBUFFER, gles2DepthRenderbuffer);
_wglRenderbufferStorage(_GL_RENDERBUFFER, _GL_DEPTH_COMPONENT16, sw, sh);
_wglFramebufferRenderbuffer(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, _GL_RENDERBUFFER, gles2DepthRenderbuffer);
_wglRenderbufferStorage(_GL_RENDERBUFFER, _GL_DEPTH_STENCIL, sw, sh);
_wglFramebufferRenderbuffer(_GL_FRAMEBUFFER, _GL_DEPTH_STENCIL_ATTACHMENT, _GL_RENDERBUFFER, gles2DepthRenderbuffer);
ByteBuffer upload = PlatformRuntime.allocateByteBuffer(48);
upload.putFloat(0.0f); upload.putFloat(0.0f);
@ -159,8 +160,8 @@ public class WebGLBackBuffer {
if(isVAOCapable) {
_wglDeleteVertexArrays(gles2BlitVAO);
}
gles2BlitVAO = EaglercraftGPU.createGLBufferArray();
EaglercraftGPU.bindGLBufferArray(gles2BlitVAO);
gles2BlitVAO = EaglercraftGPU.createGLVertexArray();
EaglercraftGPU.bindGLVertexArray(gles2BlitVAO);
EaglercraftGPU.bindVAOGLArrayBuffer(gles2BlitVBO);
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0);
@ -171,8 +172,8 @@ public class WebGLBackBuffer {
private static void drawBlitQuad() {
if(isEmulatedVAOPhase) {
EaglercraftGPU.bindGLBufferArray(gles2BlitVAO);
EaglercraftGPU.doDrawArrays(GL_TRIANGLES, 0, 6);
EaglercraftGPU.bindGLVertexArray(gles2BlitVAO);
EaglercraftGPU.drawArrays(GL_TRIANGLES, 0, 6);
}else {
if(isVAOCapable) {
_wglBindVertexArray(gles2BlitVAO);
@ -236,7 +237,7 @@ public class WebGLBackBuffer {
_wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, windowWidth, windowHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
_wglBindRenderbuffer(_GL_RENDERBUFFER, gles2DepthRenderbuffer);
_wglRenderbufferStorage(_GL_RENDERBUFFER, _GL_DEPTH_COMPONENT16, windowWidth, windowHeight);
_wglRenderbufferStorage(_GL_RENDERBUFFER, _GL_DEPTH_STENCIL, windowWidth, windowHeight);
}
if(isEmulatedVAOPhase) {
@ -280,7 +281,7 @@ public class WebGLBackBuffer {
}
if(gles2BlitVAO != null) {
if(isEmulatedVAOPhase) {
EaglercraftGPU.destroyGLBufferArray(gles2BlitVAO);
EaglercraftGPU.destroyGLVertexArray(gles2BlitVAO);
}else if(isVAOCapable) {
_wglDeleteVertexArrays(gles2BlitVAO);
}

View File

@ -0,0 +1,114 @@
package org.apache.commons.lang3;
import java.lang.reflect.Array;
public class ArrayUtils {
/**
* Checks if an array of primitive booleans is empty or {@code null}.
*
* @param array the array to test
* @return {@code true} if the array is empty or {@code null}
* @since 2.1
*/
public static boolean isEmpty(final boolean[] array) {
return isArrayEmpty(array);
}
/**
* Checks if an array of primitive bytes is empty or {@code null}.
*
* @param array the array to test
* @return {@code true} if the array is empty or {@code null}
* @since 2.1
*/
public static boolean isEmpty(final byte[] array) {
return isArrayEmpty(array);
}
/**
* Checks if an array of primitive chars is empty or {@code null}.
*
* @param array the array to test
* @return {@code true} if the array is empty or {@code null}
* @since 2.1
*/
public static boolean isEmpty(final char[] array) {
return isArrayEmpty(array);
}
/**
* Checks if an array of primitive doubles is empty or {@code null}.
*
* @param array the array to test
* @return {@code true} if the array is empty or {@code null}
* @since 2.1
*/
public static boolean isEmpty(final double[] array) {
return isArrayEmpty(array);
}
/**
* Checks if an array of primitive floats is empty or {@code null}.
*
* @param array the array to test
* @return {@code true} if the array is empty or {@code null}
* @since 2.1
*/
public static boolean isEmpty(final float[] array) {
return isArrayEmpty(array);
}
/**
* Checks if an array of primitive ints is empty or {@code null}.
*
* @param array the array to test
* @return {@code true} if the array is empty or {@code null}
* @since 2.1
*/
public static boolean isEmpty(final int[] array) {
return isArrayEmpty(array);
}
/**
* Checks if an array of primitive longs is empty or {@code null}.
*
* @param array the array to test
* @return {@code true} if the array is empty or {@code null}
* @since 2.1
*/
public static boolean isEmpty(final long[] array) {
return isArrayEmpty(array);
}
/**
* Checks if an array of Objects is empty or {@code null}.
*
* @param array the array to test
* @return {@code true} if the array is empty or {@code null}
* @since 2.1
*/
public static boolean isEmpty(final Object[] array) {
return isArrayEmpty(array);
}
/**
* Checks if an array of primitive shorts is empty or {@code null}.
*
* @param array the array to test
* @return {@code true} if the array is empty or {@code null}
* @since 2.1
*/
public static boolean isEmpty(final short[] array) {
return isArrayEmpty(array);
}
private static boolean isArrayEmpty(final Object array) {
return getLength(array) == 0;
}
public static int getLength(final Object array) {
return array != null ? Array.getLength(array) : 0;
}
}

View File

@ -0,0 +1,44 @@
package org.apache.commons.lang3;
public class StringUtils {
/**
* Tests if a CharSequence is empty ("") or null.
*
* <pre>
* StringUtils.isEmpty(null) = true
* StringUtils.isEmpty("") = true
* StringUtils.isEmpty(" ") = false
* StringUtils.isEmpty("bob") = false
* StringUtils.isEmpty(" bob ") = false
* </pre>
*
* <p>NOTE: This method changed in Lang version 2.0.
* It no longer trims the CharSequence.
* That functionality is available in isBlank().</p>
*
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is empty or null
* @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
*/
public static boolean isEmpty(final CharSequence cs) {
return cs == null || cs.length() == 0;
}
public static boolean isAllEmpty(final CharSequence... css) {
if (ArrayUtils.isEmpty(css)) {
return true;
}
for (final CharSequence cs : css) {
if (isNotEmpty(cs)) {
return false;
}
}
return true;
}
public static boolean isNotEmpty(final CharSequence cs) {
return !isEmpty(cs);
}
}

View File

@ -0,0 +1,45 @@
package org.json;
/*
Public Domain.
*/
/**
* The JSONException is thrown by the JSON.org classes when things are amiss.
*
* @author JSON.org
* @version 2015-12-09
*/
public class JSONException extends RuntimeException {
/** Serialization ID */
private static final long serialVersionUID = 0;
/**
* Constructs a JSONException with an explanatory message.
*
* @param message Detail about the reason for the exception.
*/
public JSONException(final String message) {
super(message);
}
/**
* Constructs a JSONException with an explanatory message and cause.
*
* @param message Detail about the reason for the exception.
* @param cause The cause.
*/
public JSONException(final String message, final Throwable cause) {
super(message, cause);
}
/**
* Constructs a new JSONException with the specified cause.
*
* @param cause The cause.
*/
public JSONException(final Throwable cause) {
super(cause.getMessage(), cause);
}
}