Update #45 - Fixed various issues with the client

This commit is contained in:
lax1dude 2024-12-14 20:54:34 -08:00
parent 12535d429f
commit 346047cf24
39 changed files with 571 additions and 208 deletions

View File

@ -1 +1 @@
u44 u45

View File

@ -74,13 +74,12 @@
> DELETE 1 @ 1 : 10 > DELETE 1 @ 1 : 10
> INSERT 3 : 8 @ 3 > INSERT 3 : 7 @ 3
+ if (lanServerList == null) { + if (lanServerList == null) {
+ lanServerList = new LANServerList(); + lanServerList = new LANServerList();
+ } else {
+ lanServerList.forceRefresh();
+ } + }
+ lanServerList.forceRefresh();
> INSERT 12 : 17 @ 12 > INSERT 12 : 17 @ 12

View File

@ -426,7 +426,7 @@
+ eaglercraft.singleplayer.demo.create.join=Join Shared World + eaglercraft.singleplayer.demo.create.join=Join Shared World
+ eaglercraft.singleplayer.demo.create.join.tooltip=Join someone else's world and play multiplayer + eaglercraft.singleplayer.demo.create.join.tooltip=Join someone else's world and play multiplayer
+ +
+ eaglercraft.createWorld.seedNote=Note: Vanilla seeds now work! + eaglercraft.createWorld.seedNote=Note: Vanilla seeds work
+ +
+ eaglercraft.singleplayer.oldseedwarning.title=Old World Detected! + eaglercraft.singleplayer.oldseedwarning.title=Old World Detected!
+ eaglercraft.singleplayer.oldseedwarning.msg1=Please use EaglercraftX u32 or older to "Re-Create" this world + eaglercraft.singleplayer.oldseedwarning.msg1=Please use EaglercraftX u32 or older to "Re-Create" this world

View File

@ -14,8 +14,6 @@ import org.lwjgl.glfw.GLFWGamepadState;
import org.lwjgl.glfw.GLFWVidMode; import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
import net.lax1dude.eaglercraft.v1_8.Display;
/** /**
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
* *
@ -302,7 +300,7 @@ public class PlatformInput {
update(0); update(0);
} }
private static final long[] syncTimer = new long[1]; private static long syncTimer = 0l;
public static void update(int limitFps) { public static void update(int limitFps) {
glfwPollEvents(); glfwPollEvents();
@ -311,10 +309,23 @@ public class PlatformInput {
glfwVSyncState = vsync; glfwVSyncState = vsync;
} }
glfwSwapBuffers(win); glfwSwapBuffers(win);
if(limitFps > 0 && !vsync) { if(!vsync && limitFps > 0 && limitFps <= 1000) {
Display.sync(limitFps, syncTimer); long frameNanos = (1000000000l / limitFps);
if(syncTimer == 0l) {
syncTimer = System.nanoTime() + frameNanos;
}else {
long nanos = System.nanoTime();
int remaining = (int)((syncTimer - nanos) / 1000000l);
if(remaining > 0) {
PlatformRuntime.sleep(remaining);
nanos = System.nanoTime();
}
if((syncTimer += frameNanos) < nanos) {
syncTimer = nanos;
}
}
}else { }else {
syncTimer[0] = 0l; syncTimer = 0l;
} }
} }

View File

@ -647,4 +647,8 @@ public class PlatformRuntime {
// nope // nope
} }
public static boolean immediateContinueSupported() {
return false;
}
} }

View File

@ -33,48 +33,74 @@ public class EaglerLWJGLAllocator {
return allocCount; return allocCount;
} }
private static final ByteBuffer ZERO_LENGTH_BYTE_BUFFER = new EaglerLWJGLByteBuffer(0l, 0, true);
public static ByteBuffer allocByteBuffer(int len) { public static ByteBuffer allocByteBuffer(int len) {
long ret = JEmalloc.nje_malloc(len); if(len != 0) {
if(ret == 0l) { long ret = JEmalloc.nje_malloc(len);
throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
if(enableAllocCount) ++allocCount;
return new EaglerLWJGLByteBuffer(ret, len, true);
}else {
return ZERO_LENGTH_BYTE_BUFFER;
} }
if(enableAllocCount) ++allocCount;
return new EaglerLWJGLByteBuffer(ret, len, true);
} }
private static final ShortBuffer ZERO_LENGTH_SHORT_BUFFER = new EaglerLWJGLShortBuffer(0l, 0, true);
public static ShortBuffer allocShortBuffer(int len) { public static ShortBuffer allocShortBuffer(int len) {
long ret = JEmalloc.nje_malloc(len << 1); if(len != 0) {
if(ret == 0l) { long ret = JEmalloc.nje_malloc(len << 1);
throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
if(enableAllocCount) ++allocCount;
return new EaglerLWJGLShortBuffer(ret, len, true);
}else {
return ZERO_LENGTH_SHORT_BUFFER;
} }
if(enableAllocCount) ++allocCount;
return new EaglerLWJGLShortBuffer(ret, len, true);
} }
private static final IntBuffer ZERO_LENGTH_INT_BUFFER = new EaglerLWJGLIntBuffer(0l, 0, true);
public static IntBuffer allocIntBuffer(int len) { public static IntBuffer allocIntBuffer(int len) {
long ret = JEmalloc.nje_malloc(len << 2); if(len != 0) {
if(ret == 0l) { long ret = JEmalloc.nje_malloc(len << 2);
throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
if(enableAllocCount) ++allocCount;
return new EaglerLWJGLIntBuffer(ret, len, true);
}else {
return ZERO_LENGTH_INT_BUFFER;
} }
if(enableAllocCount) ++allocCount;
return new EaglerLWJGLIntBuffer(ret, len, true);
} }
private static final FloatBuffer ZERO_LENGTH_FLOAT_BUFFER = new EaglerLWJGLFloatBuffer(0l, 0, true);
public static FloatBuffer allocFloatBuffer(int len) { public static FloatBuffer allocFloatBuffer(int len) {
long ret = JEmalloc.nje_malloc(len << 2); if(len != 0) {
if(ret == 0l) { long ret = JEmalloc.nje_malloc(len << 2);
throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); if(ret == 0l) {
throw new OutOfMemoryError("Native je_malloc call returned null pointer!");
}
if(enableAllocCount) ++allocCount;
return new EaglerLWJGLFloatBuffer(ret, len, true);
}else {
return ZERO_LENGTH_FLOAT_BUFFER;
} }
if(enableAllocCount) ++allocCount;
return new EaglerLWJGLFloatBuffer(ret, len, true);
} }
public static void freeByteBuffer(ByteBuffer buffer) { public static void freeByteBuffer(ByteBuffer buffer) {
if(buffer instanceof EaglerLWJGLByteBuffer) { if(buffer instanceof EaglerLWJGLByteBuffer) {
EaglerLWJGLByteBuffer buf = (EaglerLWJGLByteBuffer)buffer; EaglerLWJGLByteBuffer buf = (EaglerLWJGLByteBuffer)buffer;
if(buf.original) { if(buf.original) {
JEmalloc.nje_free(buf.address); if(buf.address != 0l) {
if(enableAllocCount) --allocCount; JEmalloc.nje_free(buf.address);
if(enableAllocCount) --allocCount;
}
}else { }else {
throwNotOriginal(buffer); throwNotOriginal(buffer);
} }
@ -96,8 +122,10 @@ public class EaglerLWJGLAllocator {
if(buffer instanceof EaglerLWJGLShortBuffer) { if(buffer instanceof EaglerLWJGLShortBuffer) {
EaglerLWJGLShortBuffer buf = (EaglerLWJGLShortBuffer)buffer; EaglerLWJGLShortBuffer buf = (EaglerLWJGLShortBuffer)buffer;
if(buf.original) { if(buf.original) {
JEmalloc.nje_free(buf.address); if(buf.address != 0l) {
if(enableAllocCount) --allocCount; JEmalloc.nje_free(buf.address);
if(enableAllocCount) --allocCount;
}
}else { }else {
throwNotOriginal(buffer); throwNotOriginal(buffer);
} }
@ -119,8 +147,10 @@ public class EaglerLWJGLAllocator {
if(buffer instanceof EaglerLWJGLIntBuffer) { if(buffer instanceof EaglerLWJGLIntBuffer) {
EaglerLWJGLIntBuffer buf = (EaglerLWJGLIntBuffer)buffer; EaglerLWJGLIntBuffer buf = (EaglerLWJGLIntBuffer)buffer;
if(buf.original) { if(buf.original) {
JEmalloc.nje_free(buf.address); if(buf.address != 0l) {
if(enableAllocCount) --allocCount; JEmalloc.nje_free(buf.address);
if(enableAllocCount) --allocCount;
}
}else { }else {
throwNotOriginal(buffer); throwNotOriginal(buffer);
} }
@ -142,8 +172,10 @@ public class EaglerLWJGLAllocator {
if(buffer instanceof EaglerLWJGLFloatBuffer) { if(buffer instanceof EaglerLWJGLFloatBuffer) {
EaglerLWJGLFloatBuffer buf = (EaglerLWJGLFloatBuffer)buffer; EaglerLWJGLFloatBuffer buf = (EaglerLWJGLFloatBuffer)buffer;
if(buf.original) { if(buf.original) {
JEmalloc.nje_free(buf.address); if(buf.address != 0l) {
if(enableAllocCount) --allocCount; JEmalloc.nje_free(buf.address);
if(enableAllocCount) --allocCount;
}
}else { }else {
throwNotOriginal(buffer); throwNotOriginal(buffer);
} }

View File

@ -19,7 +19,6 @@ import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput;
*/ */
public class Display { public class Display {
private static long lastSwap = 0l;
private static long lastDPIUpdate = -250l; private static long lastDPIUpdate = -250l;
private static float cacheDPI = 1.0f; private static float cacheDPI = 1.0f;
@ -79,41 +78,6 @@ public class Display {
PlatformInput.update(limitFramerate); PlatformInput.update(limitFramerate);
} }
private static final long[] defaultSyncPtr = new long[1];
public static void sync(int limitFramerate) {
sync(limitFramerate, defaultSyncPtr);
}
public static boolean sync(int limitFramerate, long[] timerPtr) {
boolean limitFPS = limitFramerate > 0 && limitFramerate < 1000;
boolean blocked = false;
if(limitFPS) {
if(timerPtr[0] == 0l) {
timerPtr[0] = EagRuntime.steadyTimeMillis();
}else {
long millis = EagRuntime.steadyTimeMillis();
long frameMillis = (1000l / limitFramerate);
long frameTime = millis - timerPtr[0];
if(frameTime > 2000l || frameTime < 0l) {
frameTime = frameMillis;
timerPtr[0] = millis;
}else {
timerPtr[0] += frameMillis;
}
if(frameTime >= 0l && frameTime < frameMillis) {
EagUtils.sleep(frameMillis - frameTime);
blocked = true;
}
}
}else {
timerPtr[0] = 0l;
}
return blocked;
}
public static boolean contextLost() { public static boolean contextLost() {
return PlatformInput.contextLost(); return PlatformInput.contextLost();
} }

View File

@ -375,4 +375,8 @@ public class EagRuntime {
PlatformRuntime.immediateContinue(); PlatformRuntime.immediateContinue();
} }
public static boolean immediateContinueSupported() {
return PlatformRuntime.immediateContinueSupported();
}
} }

View File

@ -142,6 +142,16 @@ public class EaglerInputStream extends InputStream {
} }
} }
public static byte[] inputStreamToBytesNoClose(InputStream is) throws IOException {
EaglerOutputStream os = new EaglerOutputStream(1024);
byte[] buf = new byte[1024];
int i;
while ((i = is.read(buf)) != -1) {
os.write(buf, 0, i);
}
return os.toByteArray();
}
public byte[] getAsArray() { public byte[] getAsArray() {
if (pos == 0 && count == buf.length) { if (pos == 0 && count == buf.length) {
return buf; return buf;

View File

@ -10,7 +10,7 @@ public class EaglercraftVersion {
/// Customize these to fit your fork: /// Customize these to fit your fork:
public static final String projectForkName = "EaglercraftX"; public static final String projectForkName = "EaglercraftX";
public static final String projectForkVersion = "u44"; public static final String projectForkVersion = "u45";
public static final String projectForkVendor = "lax1dude"; public static final String projectForkVendor = "lax1dude";
public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8";
@ -20,20 +20,20 @@ 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 = "u44"; public static final String projectOriginVersion = "u45";
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
// EPK Version Identifier // EPK Version Identifier
public static final String EPKVersionIdentifier = "u44"; // Set to null to disable EPK version check public static final String EPKVersionIdentifier = "u45"; // Set to null to disable EPK version check
// Updating configuration // Updating configuration
public static final boolean enableUpdateService = true; public static final boolean enableUpdateService = true;
public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client"; public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client";
public static final int updateBundlePackageVersionInt = 44; public static final int updateBundlePackageVersionInt = 45;
public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName; public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName;

View File

@ -211,7 +211,7 @@ public class EaglerFolderResourcePack extends AbstractResourcePack {
i += j; i += j;
} }
}else { }else {
buffer = EaglerInputStream.inputStreamToBytes(ziss); buffer = EaglerInputStream.inputStreamToBytesNoClose(ziss);
} }
(new VFile2(prefix, folderName, fn.substring(prefixLen))).setAllBytes(buffer); (new VFile2(prefix, folderName, fn.substring(prefixLen))).setAllBytes(buffer);
totalSize += buffer.length; totalSize += buffer.length;

View File

@ -930,6 +930,8 @@ public class EaglercraftGPU {
InstancedParticleRenderer.destroy(); InstancedParticleRenderer.destroy();
EffectPipelineFXAA.destroy(); EffectPipelineFXAA.destroy();
TextureCopyUtil.destroy(); TextureCopyUtil.destroy();
FixedFunctionPipeline.flushCache();
StreamBuffer.destroyPool();
emulatedVAOs = false; emulatedVAOs = false;
emulatedVAOState = null; emulatedVAOState = null;
glesVers = -1; glesVers = -1;

View File

@ -76,8 +76,8 @@ public class FixedFunctionPipeline {
StreamBufferInstance sb = self.streamBuffer.getBuffer(buffer.remaining()); StreamBufferInstance sb = self.streamBuffer.getBuffer(buffer.remaining());
self.currentVertexArray = sb; self.currentVertexArray = sb;
EaglercraftGPU.bindGLBufferArray(sb.vertexArray); EaglercraftGPU.bindGLBufferArray(sb.getVertexArray());
EaglercraftGPU.bindGLArrayBuffer(sb.vertexBuffer); EaglercraftGPU.bindGLArrayBuffer(sb.getVertexBuffer());
_wglBufferSubData(GL_ARRAY_BUFFER, 0, buffer); _wglBufferSubData(GL_ARRAY_BUFFER, 0, buffer);

View File

@ -7,7 +7,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
/** /**
* Copyright (c) 2023 lax1dude. All Rights Reserved. * Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -23,10 +23,48 @@ import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
*/ */
public class StreamBuffer { public class StreamBuffer {
public static final int poolSize = 16;
public final int initialSize; public final int initialSize;
public final int initialCount; public final int initialCount;
public final int maxCount; public final int maxCount;
protected static final PoolInstance[] pool = new PoolInstance[poolSize];
protected static int poolBufferID = 0;
static {
for(int i = 0; i < poolSize; ++i) {
pool[i] = new PoolInstance();
}
}
protected static class PoolInstance {
protected IBufferGL vertexBuffer = null;
protected int vertexBufferSize = 0;
}
private static PoolInstance fillPoolInstance() {
PoolInstance ret = pool[poolBufferID++];
if(poolBufferID > poolSize - 1) {
poolBufferID = 0;
}
return ret;
}
private static void resizeInstance(PoolInstance instance, int requiredMemory) {
if(instance.vertexBuffer == null) {
instance.vertexBuffer = _wglGenBuffers();
}
if(instance.vertexBufferSize < requiredMemory) {
int newSize = (requiredMemory & 0xFFFFF000) + 0x2000;
EaglercraftGPU.bindGLArrayBuffer(instance.vertexBuffer);
_wglBufferData(GL_ARRAY_BUFFER, newSize, GL_STREAM_DRAW);
instance.vertexBufferSize = newSize;
}
}
protected StreamBufferInstance[] buffers; protected StreamBufferInstance[] buffers;
protected int currentBufferId = 0; protected int currentBufferId = 0;
@ -36,9 +74,8 @@ public class StreamBuffer {
public static class StreamBufferInstance { public static class StreamBufferInstance {
protected PoolInstance poolInstance = null;
protected IBufferArrayGL vertexArray = null; protected IBufferArrayGL vertexArray = null;
protected IBufferGL vertexBuffer = null;
protected int vertexBufferSize = 0;
public boolean bindQuad16 = false; public boolean bindQuad16 = false;
public boolean bindQuad32 = false; public boolean bindQuad32 = false;
@ -48,7 +85,7 @@ public class StreamBuffer {
} }
public IBufferGL getVertexBuffer() { public IBufferGL getVertexBuffer() {
return vertexBuffer; return poolInstance.vertexBuffer;
} }
} }
@ -58,9 +95,14 @@ public class StreamBuffer {
} }
public StreamBuffer(int initialSize, int initialCount, int maxCount, IStreamBufferInitializer initializer) { public StreamBuffer(int initialSize, int initialCount, int maxCount, IStreamBufferInitializer initializer) {
if(maxCount > poolSize) {
maxCount = poolSize;
}
this.buffers = new StreamBufferInstance[initialCount]; this.buffers = new StreamBufferInstance[initialCount];
for(int i = 0; i < this.buffers.length; ++i) { for(int i = 0; i < this.buffers.length; ++i) {
this.buffers[i] = new StreamBufferInstance(); StreamBufferInstance j = new StreamBufferInstance();
j.poolInstance = fillPoolInstance();
this.buffers[i] = j;
} }
this.initialSize = initialSize; this.initialSize = initialSize;
this.initialCount = initialCount; this.initialCount = initialCount;
@ -70,18 +112,10 @@ public class StreamBuffer {
public StreamBufferInstance getBuffer(int requiredMemory) { public StreamBufferInstance getBuffer(int requiredMemory) {
StreamBufferInstance next = buffers[(currentBufferId++) % buffers.length]; StreamBufferInstance next = buffers[(currentBufferId++) % buffers.length];
if(next.vertexBuffer == null) { resizeInstance(next.poolInstance, requiredMemory);
next.vertexBuffer = _wglGenBuffers();
}
if(next.vertexArray == null) { if(next.vertexArray == null) {
next.vertexArray = EaglercraftGPU.createGLBufferArray(); next.vertexArray = EaglercraftGPU.createGLBufferArray();
initializer.initialize(next.vertexArray, next.vertexBuffer); initializer.initialize(next.vertexArray, next.poolInstance.vertexBuffer);
}
if(next.vertexBufferSize < requiredMemory) {
int newSize = (requiredMemory & 0xFFFFF000) + 0x2000;
EaglercraftGPU.bindGLArrayBuffer(next.vertexBuffer);
_wglBufferData(GL_ARRAY_BUFFER, newSize, GL_STREAM_DRAW);
next.vertexBufferSize = newSize;
} }
return next; return next;
} }
@ -102,12 +136,10 @@ public class StreamBuffer {
if(buffers[i].vertexArray != null) { if(buffers[i].vertexArray != null) {
EaglercraftGPU.destroyGLBufferArray(buffers[i].vertexArray); EaglercraftGPU.destroyGLBufferArray(buffers[i].vertexArray);
} }
if(buffers[i].vertexBuffer != null) {
_wglDeleteBuffers(buffers[i].vertexBuffer);
}
} }
} }
buffers = newArray; buffers = newArray;
refill();
} }
overflowCounter = 0; overflowCounter = 0;
}else if(overflowCounter > 15) { }else if(overflowCounter > 15) {
@ -125,25 +157,51 @@ public class StreamBuffer {
} }
} }
buffers = newArray; buffers = newArray;
refill();
} }
overflowCounter = 0; overflowCounter = 0;
} }
currentBufferId = 0; currentBufferId = 0;
} }
private void refill() {
for(int i = 0; i < buffers.length; ++i) {
PoolInstance j = fillPoolInstance();
StreamBufferInstance k = buffers[i];
if(j != k.poolInstance) {
PoolInstance l = k.poolInstance;
k.poolInstance = j;
if(k.vertexArray != null) {
if(j.vertexBuffer == null) {
resizeInstance(j, l.vertexBufferSize);
}
initializer.initialize(k.vertexArray, j.vertexBuffer);
}
}
}
}
public void destroy() { public void destroy() {
for(int i = 0; i < buffers.length; ++i) { for(int i = 0; i < buffers.length; ++i) {
StreamBufferInstance next = buffers[i]; StreamBufferInstance next = buffers[i];
if(next.vertexArray != null) { if(next.vertexArray != null) {
EaglercraftGPU.destroyGLBufferArray(next.vertexArray); EaglercraftGPU.destroyGLBufferArray(next.vertexArray);
} }
if(next.vertexBuffer != null) {
_wglDeleteBuffers(next.vertexBuffer);
}
} }
buffers = new StreamBufferInstance[initialCount]; buffers = new StreamBufferInstance[initialCount];
for(int i = 0; i < buffers.length; ++i) { for(int i = 0; i < initialCount; ++i) {
buffers[i] = new StreamBufferInstance(); StreamBufferInstance j = new StreamBufferInstance();
j.poolInstance = fillPoolInstance();
buffers[i] = j;
}
}
public static void destroyPool() {
for(int i = 0; i < pool.length; ++i) {
if(pool[i].vertexBuffer != null) {
_wglDeleteBuffers(pool[i].vertexBuffer);
pool[i].vertexBuffer = null;
}
} }
} }

View File

@ -153,7 +153,7 @@ public class SingleplayerServerController implements ISaveFormat {
} }
public static boolean isChannelNameAllowed(String ch) { public static boolean isChannelNameAllowed(String ch) {
return !IPC_CHANNEL.equals(ch) && !PLAYER_CHANNEL.equals(ch); return !ch.startsWith("~!");
} }
public static void openPlayerChannel(String ch) { public static void openPlayerChannel(String ch) {

View File

@ -1,5 +1,6 @@
package net.lax1dude.eaglercraft.v1_8.sp.lan; package net.lax1dude.eaglercraft.v1_8.sp.lan;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.EagRuntime;
@ -42,6 +43,8 @@ class LANClientPeer {
protected long startTime; protected long startTime;
protected String localICECandidate = null; protected String localICECandidate = null;
protected boolean localChannel = false;
protected List<byte[]> packetPreBuffer = null;
protected LANClientPeer(String clientId) { protected LANClientPeer(String clientId) {
this.clientId = clientId; this.clientId = clientId;
@ -75,7 +78,19 @@ class LANClientPeer {
protected void handleSuccess() { protected void handleSuccess() {
if(state == SENT_ICE_CANDIDATE) { if(state == SENT_ICE_CANDIDATE) {
state = RECEIVED_SUCCESS; if(localChannel) {
SingleplayerServerController.openPlayerChannel(clientId);
PlatformWebRTC.serverLANPeerMapIPC(clientId, clientId);
if(packetPreBuffer != null) {
for(byte[] b : packetPreBuffer) {
ClientPlatformSingleplayer.sendPacket(new IPCPacketData(clientId, b));
}
packetPreBuffer = null;
}
state = CONNECTED;
}else {
state = RECEIVED_SUCCESS;
}
}else if(state != CONNECTED) { }else if(state != CONNECTED) {
logger.error("Relay [{}] unexpected IPacket05ClientSuccess for '{}'", LANServerController.lanRelaySocket.getURI(), clientId); logger.error("Relay [{}] unexpected IPacket05ClientSuccess for '{}'", LANServerController.lanRelaySocket.getURI(), clientId);
} }
@ -113,13 +128,7 @@ class LANClientPeer {
localICECandidate = ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates; localICECandidate = ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates;
continue read_loop; continue read_loop;
} }
} break;
case RECEIVED_ICE_CANDIDATE: {
if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
LANServerController.lanRelaySocket.writePacket(new RelayPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates));
state = SENT_ICE_CANDIDATE;
continue read_loop;
}
} }
case RECEIVED_DESCRIPTION: { case RECEIVED_DESCRIPTION: {
if(evt instanceof LANPeerEvent.LANPeerDescriptionEvent) { if(evt instanceof LANPeerEvent.LANPeerDescriptionEvent) {
@ -127,15 +136,50 @@ class LANClientPeer {
state = SENT_DESCRIPTION; state = SENT_DESCRIPTION;
continue read_loop; continue read_loop;
} }
break;
}
case RECEIVED_ICE_CANDIDATE: {
if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
LANServerController.lanRelaySocket.writePacket(new RelayPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates));
state = SENT_ICE_CANDIDATE;
continue read_loop;
}else if(evt instanceof LANPeerEvent.LANPeerDataChannelEvent) {
localChannel = true;
continue read_loop;
}else if(evt instanceof LANPeerEvent.LANPeerPacketEvent) {
if(packetPreBuffer == null) packetPreBuffer = new LinkedList<>();
packetPreBuffer.add(((LANPeerEvent.LANPeerPacketEvent)evt).payload);
continue read_loop;
}
break;
}
case SENT_ICE_CANDIDATE: {
if(evt instanceof LANPeerEvent.LANPeerDataChannelEvent) {
localChannel = true;
continue read_loop;
}else if(evt instanceof LANPeerEvent.LANPeerPacketEvent) {
if(packetPreBuffer == null) packetPreBuffer = new LinkedList<>();
packetPreBuffer.add(((LANPeerEvent.LANPeerPacketEvent)evt).payload);
continue read_loop;
}
break;
} }
case SENT_ICE_CANDIDATE:
case RECEIVED_SUCCESS: { case RECEIVED_SUCCESS: {
if(evt instanceof LANPeerEvent.LANPeerDataChannelEvent) { if(evt instanceof LANPeerEvent.LANPeerDataChannelEvent) {
SingleplayerServerController.openPlayerChannel(clientId); SingleplayerServerController.openPlayerChannel(clientId);
PlatformWebRTC.serverLANPeerMapIPC(clientId, clientId); PlatformWebRTC.serverLANPeerMapIPC(clientId, clientId);
if(packetPreBuffer != null) {
for(byte[] b : packetPreBuffer) {
ClientPlatformSingleplayer.sendPacket(new IPCPacketData(clientId, b));
}
packetPreBuffer = null;
}
state = CONNECTED; state = CONNECTED;
continue read_loop; continue read_loop;
}else if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
continue read_loop;
} }
break;
} }
case CONNECTED: { case CONNECTED: {
if(evt instanceof LANPeerEvent.LANPeerPacketEvent) { if(evt instanceof LANPeerEvent.LANPeerPacketEvent) {
@ -144,6 +188,7 @@ class LANClientPeer {
ClientPlatformSingleplayer.sendPacket(new IPCPacketData(clientId, ((LANPeerEvent.LANPeerPacketEvent)evt).payload)); ClientPlatformSingleplayer.sendPacket(new IPCPacketData(clientId, ((LANPeerEvent.LANPeerPacketEvent)evt).payload));
continue read_loop; continue read_loop;
} }
break;
} }
default: { default: {
break; break;

View File

@ -12,6 +12,7 @@ import net.lax1dude.eaglercraft.v1_8.EagUtils;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC; import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
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;
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager; import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocket; import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocket;
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.*; import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.*;
@ -142,7 +143,9 @@ public class LANServerController {
while((pkt = lanRelaySocket.readPacket()) != null) { while((pkt = lanRelaySocket.readPacket()) != null) {
if(pkt instanceof RelayPacket02NewClient) { if(pkt instanceof RelayPacket02NewClient) {
RelayPacket02NewClient ipkt = (RelayPacket02NewClient) pkt; RelayPacket02NewClient ipkt = (RelayPacket02NewClient) pkt;
if(clients.containsKey(ipkt.clientId)) { if(!SingleplayerServerController.isChannelNameAllowed(ipkt.clientId)) {
logger.error("Relay [{}] relay tried to open disallowed channel name: '{}'", lanRelaySocket.getURI(), ipkt.clientId);
}else if(clients.containsKey(ipkt.clientId)) {
logger.error("Relay [{}] relay provided duplicate client '{}'", lanRelaySocket.getURI(), ipkt.clientId); logger.error("Relay [{}] relay provided duplicate client '{}'", lanRelaySocket.getURI(), ipkt.clientId);
}else { }else {
clients.put(ipkt.clientId, new LANClientPeer(ipkt.clientId)); clients.put(ipkt.clientId, new LANClientPeer(ipkt.clientId));

View File

@ -103,11 +103,10 @@ public class WorldConverterEPK {
public static byte[] exportWorld(String worldName) { public static byte[] exportWorld(String worldName) {
String realWorldName = worldName; String realWorldName = worldName;
String worldOwner = "UNKNOWN"; String worldOwner = "UNKNOWN";
String splitter = new String(new char[] { (char)253, (char)233, (char)233 }); int j = worldName.lastIndexOf(new String(new char[] { (char)253, (char)233, (char)233 }));
if(worldName.contains(splitter)) { if(j != -1) {
int i = worldName.lastIndexOf(splitter); worldOwner = worldName.substring(j + 3);
worldOwner = worldName.substring(i + 3); realWorldName = worldName.substring(0, j);
realWorldName = worldName.substring(0, i);
} }
VFile2 worldDir = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(realWorldName, false).getWorldDirectory(); VFile2 worldDir = EaglerIntegratedServerWorker.saveFormat.getSaveLoader(realWorldName, false).getWorldDirectory();
logger.info("Exporting world directory \"{}\" as EPK", worldDir.getPath()); logger.info("Exporting world directory \"{}\" as EPK", worldDir.getPath());

View File

@ -70,7 +70,6 @@ public class WorldConverterMCA {
ZipEntry f = null; ZipEntry f = null;
int lastProgUpdate = 0; int lastProgUpdate = 0;
int prog = 0; int prog = 0;
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;
@ -85,7 +84,7 @@ public class WorldConverterMCA {
j += k; j += k;
} }
}else { }else {
b = EaglerInputStream.inputStreamToBytes(zis); b = EaglerInputStream.inputStreamToBytesNoClose(zis);
} }
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")) {

View File

@ -1 +1 @@
u44 u45

View File

@ -5,5 +5,5 @@ call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/main.c -o bin/emscripten/main.o
call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_crc32.c -o bin/emscripten/xz_crc32.o call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_crc32.c -o bin/emscripten/xz_crc32.o
call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_lzma2.c -o bin/emscripten/xz_dec_lzma2.o call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_lzma2.c -o bin/emscripten/xz_dec_lzma2.o
call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_stream.c -o bin/emscripten/xz_dec_stream.o call emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_stream.c -o bin/emscripten/xz_dec_stream.o
call emcc -O3 -sMALLOC=dlmalloc -sALLOW_MEMORY_GROWTH -sINITIAL_HEAP=16777216 -sMAXIMUM_MEMORY=67108864 --pre-js ../src/wasm-gc-teavm-loader/js/pre.js --js-library ../src/wasm-gc-teavm-loader/js/library.js bin/emscripten/main.o bin/emscripten/xz_crc32.o bin/emscripten/xz_dec_lzma2.o bin/emscripten/xz_dec_stream.o -o javascript/loader.js call emcc -O3 -sMALLOC=dlmalloc -sALLOW_MEMORY_GROWTH -sINITIAL_HEAP=16777216 -sMAXIMUM_MEMORY=67108864 --closure 1 --closure-args=--isolation_mode=IIFE --closure-args=--emit_use_strict --pre-js ../src/wasm-gc-teavm-loader/js/pre.js --js-library ../src/wasm-gc-teavm-loader/js/library.js bin/emscripten/main.o bin/emscripten/xz_crc32.o bin/emscripten/xz_dec_lzma2.o bin/emscripten/xz_dec_stream.o -o javascript/loader.js
pause pause

View File

@ -4,4 +4,4 @@ emcc -c -O3 ../src/wasm-gc-teavm-loader/c/main.c -o bin/emscripten/main.o
emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_crc32.c -o bin/emscripten/xz_crc32.o emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_crc32.c -o bin/emscripten/xz_crc32.o
emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_lzma2.c -o bin/emscripten/xz_dec_lzma2.o emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_lzma2.c -o bin/emscripten/xz_dec_lzma2.o
emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_stream.c -o bin/emscripten/xz_dec_stream.o emcc -c -O3 ../src/wasm-gc-teavm-loader/c/xz/xz_dec_stream.c -o bin/emscripten/xz_dec_stream.o
emcc -O3 -sMALLOC=dlmalloc -sALLOW_MEMORY_GROWTH -sINITIAL_HEAP=16777216 -sMAXIMUM_MEMORY=67108864 --pre-js ../src/wasm-gc-teavm-loader/js/pre.js --js-library ../src/wasm-gc-teavm-loader/js/library.js bin/emscripten/main.o bin/emscripten/xz_crc32.o bin/emscripten/xz_dec_lzma2.o bin/emscripten/xz_dec_stream.o -o javascript/loader.js emcc -O3 -sMALLOC=dlmalloc -sALLOW_MEMORY_GROWTH -sINITIAL_HEAP=16777216 -sMAXIMUM_MEMORY=67108864 --closure 1 --closure-args=--isolation_mode=IIFE --closure-args=--emit_use_strict --pre-js ../src/wasm-gc-teavm-loader/js/pre.js --js-library ../src/wasm-gc-teavm-loader/js/library.js bin/emscripten/main.o bin/emscripten/xz_crc32.o bin/emscripten/xz_dec_lzma2.o bin/emscripten/xz_dec_stream.o -o javascript/loader.js

View File

@ -1,8 +1,8 @@
client-version-integer=44 client-version-integer=45
client-package-name=net.lax1dude.eaglercraft.v1_8.client client-package-name=net.lax1dude.eaglercraft.v1_8.client
client-origin-name=EaglercraftX client-origin-name=EaglercraftX
client-origin-version=u44 client-origin-version=u45
client-origin-vendor=lax1dude client-origin-vendor=lax1dude
client-fork-name=EaglercraftX client-fork-name=EaglercraftX
client-fork-version=u44 client-fork-version=u45
client-fork-vendor=lax1dude client-fork-vendor=lax1dude

File diff suppressed because one or more lines are too long

View File

@ -382,7 +382,7 @@ public class ClientBootFactory {
System.arraycopy(classesServerJS, 0, concatClassesServerJS, appendToClassesServerJS.length, classesServerJS.length); System.arraycopy(classesServerJS, 0, concatClassesServerJS, appendToClassesServerJS.length, classesServerJS.length);
TeaVMBlobURLHandle classesServerJSURL = TeaVMBlobURLManager.registerNewURLByte(concatClassesServerJS, "text/javascript"); TeaVMBlobURLHandle classesServerJSURL = TeaVMBlobURLManager.registerNewURLByte(concatClassesServerJS, "text/javascript");
toCleanOnException.add(classesServerJSURL); toCleanOnException.add(classesServerJSURL);
launchOpts.put("serverWorkerURI", classesServerJSURL); launchOpts.put("serverWorkerURI", classesServerJSURL.toExternalForm());
doUpdateMessage(cb, "Resolving assets.epk (" + clientData.epkFiles.get(0).dataUUID + ")"); doUpdateMessage(cb, "Resolving assets.epk (" + clientData.epkFiles.get(0).dataUUID + ")");
TeaVMBlobURLHandle assetsEPKURL = loadingCache.get(new UUIDStringPair(clientData.epkFiles.get(0).dataUUID, "application/octet-stream")); TeaVMBlobURLHandle assetsEPKURL = loadingCache.get(new UUIDStringPair(clientData.epkFiles.get(0).dataUUID, "application/octet-stream"));
if(assetsEPKURL == null) { if(assetsEPKURL == null) {

View File

@ -36,8 +36,6 @@ import org.teavm.jso.gamepad.Gamepad;
import org.teavm.jso.gamepad.GamepadButton; import org.teavm.jso.gamepad.GamepadButton;
import org.teavm.jso.gamepad.GamepadEvent; import org.teavm.jso.gamepad.GamepadEvent;
import net.lax1dude.eaglercraft.v1_8.Display;
import net.lax1dude.eaglercraft.v1_8.EagUtils;
import net.lax1dude.eaglercraft.v1_8.internal.teavm.ClientMain; import net.lax1dude.eaglercraft.v1_8.internal.teavm.ClientMain;
import net.lax1dude.eaglercraft.v1_8.internal.teavm.EarlyLoadScreen; import net.lax1dude.eaglercraft.v1_8.internal.teavm.EarlyLoadScreen;
import net.lax1dude.eaglercraft.v1_8.internal.teavm.InputEvent; import net.lax1dude.eaglercraft.v1_8.internal.teavm.InputEvent;
@ -889,7 +887,7 @@ public class PlatformInput {
update(0); update(0);
} }
private static final long[] syncTimer = new long[1]; private static double syncTimer = 0.0;
public static void update(int fpsLimit) { public static void update(int fpsLimit) {
double r = getDevicePixelRatio(win); double r = getDevicePixelRatio(win);
@ -943,21 +941,44 @@ public class PlatformInput {
PlatformScreenRecord.captureFrameHook(); PlatformScreenRecord.captureFrameHook();
if(getVisibilityState(win.getDocument())) { if(getVisibilityState(win.getDocument())) {
if(vsyncSupport && vsync) { if(vsyncSupport && vsync) {
syncTimer[0] = 0l; syncTimer = 0.0;
asyncRequestAnimationFrame(); asyncRequestAnimationFrame();
}else { }else {
if(fpsLimit <= 0) { if(fpsLimit <= 0 || fpsLimit > 1000) {
syncTimer[0] = 0l; syncTimer = 0.0;
PlatformRuntime.swapDelayTeaVM(); PlatformRuntime.swapDelayTeaVM();
}else { }else {
if(!Display.sync(fpsLimit, syncTimer)) { double frameMillis = (1000.0 / fpsLimit);
if(syncTimer == 0.0) {
syncTimer = PlatformRuntime.steadyTimeMillisTeaVM() + frameMillis;
PlatformRuntime.swapDelayTeaVM(); PlatformRuntime.swapDelayTeaVM();
}else {
double millis = PlatformRuntime.steadyTimeMillisTeaVM();
int remaining = (int)(syncTimer - millis);
if(remaining > 0) {
if(!PlatformRuntime.useDelayOnSwap && PlatformRuntime.immediateContinueSupport) {
PlatformRuntime.immediateContinue(); // cannot stack setTimeouts, or it will throttle
millis = PlatformRuntime.steadyTimeMillisTeaVM();
remaining = (int)(syncTimer - millis);
if(remaining > 0) {
PlatformRuntime.sleep((int)remaining);
}
}else {
PlatformRuntime.sleep((int)remaining);
}
}else {
PlatformRuntime.swapDelayTeaVM();
}
millis = PlatformRuntime.steadyTimeMillisTeaVM();
if((syncTimer += frameMillis) < millis) {
syncTimer = millis;
}
} }
} }
} }
}else { }else {
syncTimer[0] = 0l; syncTimer = 0.0;
EagUtils.sleep(50); PlatformRuntime.sleep(50);
} }
} }
@ -1579,7 +1600,7 @@ public class PlatformInput {
EarlyLoadScreen.paintEnable(PlatformOpenGL.checkVAOCapable(), allowBootMenu); EarlyLoadScreen.paintEnable(PlatformOpenGL.checkVAOCapable(), allowBootMenu);
while(mouseEvents.isEmpty() && keyEvents.isEmpty() && touchEvents.isEmpty()) { while(mouseEvents.isEmpty() && keyEvents.isEmpty() && touchEvents.isEmpty()) {
EagUtils.sleep(100); PlatformRuntime.sleep(100);
} }
} }
} }
@ -1864,7 +1885,7 @@ public class PlatformInput {
if(touchKeyboardField != null) { if(touchKeyboardField != null) {
touchKeyboardField.blur(); touchKeyboardField.blur();
touchKeyboardField.setValue(""); touchKeyboardField.setValue("");
EagUtils.sleep(10); PlatformRuntime.sleep(10);
if(touchKeyboardForm != null) { if(touchKeyboardForm != null) {
touchKeyboardForm.removeChild(touchKeyboardField); touchKeyboardForm.removeChild(touchKeyboardField);
}else { }else {
@ -2135,7 +2156,7 @@ public class PlatformInput {
touchKeyboardField.blur(); touchKeyboardField.blur();
touchKeyboardField.setValue(""); touchKeyboardField.setValue("");
if(sync) { if(sync) {
EagUtils.sleep(10); PlatformRuntime.sleep(10);
if(touchKeyboardForm != null) { if(touchKeyboardForm != null) {
touchKeyboardForm.removeChild(touchKeyboardField); touchKeyboardForm.removeChild(touchKeyboardField);
}else { }else {

View File

@ -766,6 +766,10 @@ public class PlatformRuntime {
} }
} }
public static boolean immediateContinueSupported() {
return immediateContinueSupport;
}
@Async @Async
private static native void immediateContinueTeaVM0(); private static native void immediateContinueTeaVM0();
@ -1101,6 +1105,10 @@ public class PlatformRuntime {
@JSBody(params = { "steadyTimeFunc" }, script = "return steadyTimeFunc();") @JSBody(params = { "steadyTimeFunc" }, script = "return steadyTimeFunc();")
private static native double steadyTimeMillis0(JSObject steadyTimeFunc); private static native double steadyTimeMillis0(JSObject steadyTimeFunc);
public static double steadyTimeMillisTeaVM() {
return steadyTimeMillis0(steadyTimeFunc);
}
public static long steadyTimeMillis() { public static long steadyTimeMillis() {
return (long)steadyTimeMillis0(steadyTimeFunc); return (long)steadyTimeMillis0(steadyTimeFunc);
} }

View File

@ -111,6 +111,7 @@ public class PlatformVoiceClient {
if(!PlatformWebRTC.hasCheckedSupport) PlatformWebRTC.supported(); if(!PlatformWebRTC.hasCheckedSupport) PlatformWebRTC.supported();
switch(PlatformWebRTC.supportedImpl) { switch(PlatformWebRTC.supportedImpl) {
case PlatformWebRTC.WEBRTC_SUPPORT_CORE: case PlatformWebRTC.WEBRTC_SUPPORT_CORE:
case PlatformWebRTC.WEBRTC_SUPPORT_CORE_NON_PROMISING:
case PlatformWebRTC.WEBRTC_SUPPORT_WEBKIT: case PlatformWebRTC.WEBRTC_SUPPORT_WEBKIT:
addCoreIceCandidate(peerConnection, str); addCoreIceCandidate(peerConnection, str);
break; break;

View File

@ -49,8 +49,18 @@ public class PlatformWebRTC {
static final int WEBRTC_SUPPORT_CORE = 1; static final int WEBRTC_SUPPORT_CORE = 1;
static final int WEBRTC_SUPPORT_WEBKIT = 2; static final int WEBRTC_SUPPORT_WEBKIT = 2;
static final int WEBRTC_SUPPORT_MOZ = 3; static final int WEBRTC_SUPPORT_MOZ = 3;
static final int WEBRTC_SUPPORT_CORE_NON_PROMISING = 4;
@JSBody(script = "return (typeof RTCPeerConnection !== \"undefined\") ? 1 : ((typeof webkitRTCPeerConnection !== \"undefined\") ? 2 : ((typeof mozRTCPeerConnection !== \"undefined\") ? 3 : 0));") @JSBody(script = "var checkPromising = function() { try {"
+ "return (typeof (new RTCPeerConnection({iceServers:[{urls:\"stun:127.69.0.1:6969\"}]})).createOffer() === \"object\") ? 1 : 4;"
+ "} catch(ex) {"
+ "return (ex.name === \"TypeError\") ? 4 : 1;"
+ "}};"
+ "return (typeof RTCPeerConnection !== \"undefined\")"
+ " ? checkPromising()"
+ " : ((typeof webkitRTCPeerConnection !== \"undefined\") ? 2"
+ " : ((typeof mozRTCPeerConnection !== \"undefined\") ? 3"
+ " : 0));")
private static native int checkSupportedImpl(); private static native int checkSupportedImpl();
static boolean hasCheckedSupport = false; static boolean hasCheckedSupport = false;
@ -69,6 +79,8 @@ public class PlatformWebRTC {
logger.info("Using webkit- prefix for RTCPeerConnection"); logger.info("Using webkit- prefix for RTCPeerConnection");
}else if(supportedImpl == WEBRTC_SUPPORT_MOZ) { }else if(supportedImpl == WEBRTC_SUPPORT_MOZ) {
logger.info("Using moz- prefix for RTCPeerConnection"); logger.info("Using moz- prefix for RTCPeerConnection");
}else if(supportedImpl == WEBRTC_SUPPORT_CORE_NON_PROMISING) {
logger.info("Using non-promising RTCPeerConnection");
} }
if(supportedImpl != WEBRTC_SUPPORT_NONE) { if(supportedImpl != WEBRTC_SUPPORT_NONE) {
belowChrome71Fix = isChromeBelow71(); belowChrome71Fix = isChromeBelow71();
@ -160,6 +172,7 @@ public class PlatformWebRTC {
if(!hasCheckedSupport) supported(); if(!hasCheckedSupport) supported();
switch(supportedImpl) { switch(supportedImpl) {
case WEBRTC_SUPPORT_CORE: case WEBRTC_SUPPORT_CORE:
case WEBRTC_SUPPORT_CORE_NON_PROMISING:
return createCoreRTCPeerConnection(iceServers); return createCoreRTCPeerConnection(iceServers);
case WEBRTC_SUPPORT_WEBKIT: case WEBRTC_SUPPORT_WEBKIT:
return createWebkitRTCPeerConnection(iceServers); return createWebkitRTCPeerConnection(iceServers);
@ -191,11 +204,49 @@ public class PlatformWebRTC {
@JSBody(params = { "item" }, script = "return item.channel;") @JSBody(params = { "item" }, script = "return item.channel;")
static native JSObject getChannel(JSObject item); static native JSObject getChannel(JSObject item);
@JSBody(params = { "peerConnection", "h1", "h2" }, script = "peerConnection.createOffer().then(h1).catch(h2);")
private static native void createOfferPromising(JSObject peerConnection, DescHandler h1, ErrorHandler h2);
@JSBody(params = { "peerConnection", "h1", "h2" }, script = "peerConnection.createOffer(h1, h2);") @JSBody(params = { "peerConnection", "h1", "h2" }, script = "peerConnection.createOffer(h1, h2);")
static native void createOffer(JSObject peerConnection, DescHandler h1, ErrorHandler h2); private static native void createOfferLegacy(JSObject peerConnection, DescHandler h1, ErrorHandler h2);
static void createOffer(JSObject peerConnection, DescHandler h1, ErrorHandler h2) {
if(!hasCheckedSupport) supported();
switch(supportedImpl) {
case WEBRTC_SUPPORT_CORE:
createOfferPromising(peerConnection, h1, h2);
break;
case WEBRTC_SUPPORT_WEBKIT:
case WEBRTC_SUPPORT_MOZ:
case WEBRTC_SUPPORT_CORE_NON_PROMISING:
createOfferLegacy(peerConnection, h1, h2);
break;
default:
throw new UnsupportedOperationException();
}
}
@JSBody(params = { "peerConnection", "desc", "h1", "h2" }, script = "peerConnection.setLocalDescription(desc).then(h1).catch(h2);")
private static native void setLocalDescriptionPromising(JSObject peerConnection, JSObject desc, EmptyHandler h1, ErrorHandler h2);
@JSBody(params = { "peerConnection", "desc", "h1", "h2" }, script = "peerConnection.setLocalDescription(desc, h1, h2);") @JSBody(params = { "peerConnection", "desc", "h1", "h2" }, script = "peerConnection.setLocalDescription(desc, h1, h2);")
static native void setLocalDescription(JSObject peerConnection, JSObject desc, EmptyHandler h1, ErrorHandler h2); private static native void setLocalDescriptionLegacy(JSObject peerConnection, JSObject desc, EmptyHandler h1, ErrorHandler h2);
static void setLocalDescription(JSObject peerConnection, JSObject desc, EmptyHandler h1, ErrorHandler h2) {
if(!hasCheckedSupport) supported();
switch(supportedImpl) {
case WEBRTC_SUPPORT_CORE:
setLocalDescriptionPromising(peerConnection, desc, h1, h2);
break;
case WEBRTC_SUPPORT_WEBKIT:
case WEBRTC_SUPPORT_MOZ:
case WEBRTC_SUPPORT_CORE_NON_PROMISING:
setLocalDescriptionLegacy(peerConnection, desc, h1, h2);
break;
default:
throw new UnsupportedOperationException();
}
}
@JSBody(params = { "peerConnection", "str" }, script = "var candidateList = JSON.parse(str); for (var i = 0; i < candidateList.length; ++i) { peerConnection.addIceCandidate(new RTCIceCandidate(candidateList[i])); }; return null;") @JSBody(params = { "peerConnection", "str" }, script = "var candidateList = JSON.parse(str); for (var i = 0; i < candidateList.length; ++i) { peerConnection.addIceCandidate(new RTCIceCandidate(candidateList[i])); }; return null;")
private static native void addCoreIceCandidates(JSObject peerConnection, String str); private static native void addCoreIceCandidates(JSObject peerConnection, String str);
@ -219,6 +270,7 @@ public class PlatformWebRTC {
if(!hasCheckedSupport) supported(); if(!hasCheckedSupport) supported();
switch(supportedImpl) { switch(supportedImpl) {
case WEBRTC_SUPPORT_CORE: case WEBRTC_SUPPORT_CORE:
case WEBRTC_SUPPORT_CORE_NON_PROMISING:
case WEBRTC_SUPPORT_WEBKIT: case WEBRTC_SUPPORT_WEBKIT:
addCoreIceCandidates(peerConnection, str); addCoreIceCandidates(peerConnection, str);
break; break;
@ -246,6 +298,7 @@ public class PlatformWebRTC {
} }
switch(supportedImpl) { switch(supportedImpl) {
case WEBRTC_SUPPORT_CORE: case WEBRTC_SUPPORT_CORE:
case WEBRTC_SUPPORT_CORE_NON_PROMISING:
if(useSessionDescConstructor) { if(useSessionDescConstructor) {
setCoreRemoteDescriptionLegacy(peerConnection, str); setCoreRemoteDescriptionLegacy(peerConnection, str);
}else { }else {
@ -267,14 +320,20 @@ public class PlatformWebRTC {
} }
} }
@JSBody(params = { "peerConnection", "str", "h1", "h2" }, script = "try { peerConnection.setRemoteDescription(str).then(h1).catch(h2); return true; } catch(ex) { if(ex.name === \"TypeError\") return false; else throw ex; }")
private static native boolean setCoreRemoteDescription2Promising(JSObject peerConnection, JSObject str, EmptyHandler h1, ErrorHandler h2);
@JSBody(params = { "peerConnection", "str", "h1", "h2" }, script = "try { peerConnection.setRemoteDescription(str, h1, h2); return true; } catch(ex) { if(ex.name === \"TypeError\") return false; else throw ex; }") @JSBody(params = { "peerConnection", "str", "h1", "h2" }, script = "try { peerConnection.setRemoteDescription(str, h1, h2); return true; } catch(ex) { if(ex.name === \"TypeError\") return false; else throw ex; }")
private static native boolean setCoreRemoteDescription2(JSObject peerConnection, JSObject str, EmptyHandler h1, ErrorHandler h2); private static native boolean setCoreRemoteDescription2Legacy(JSObject peerConnection, JSObject str, EmptyHandler h1, ErrorHandler h2);
@JSBody(params = { "peerConnection", "str", "h1", "h2" }, script = "peerConnection.setRemoteDescription(new RTCSessionDescription(str)).then(h1).catch(h2);")
private static native void setCoreRemoteDescription2PromisingLegacy(JSObject peerConnection, JSObject str, EmptyHandler h1, ErrorHandler h2);
@JSBody(params = { "peerConnection", "str", "h1", "h2" }, script = "peerConnection.setRemoteDescription(new RTCSessionDescription(str), h1, h2);") @JSBody(params = { "peerConnection", "str", "h1", "h2" }, script = "peerConnection.setRemoteDescription(new RTCSessionDescription(str), h1, h2);")
private static native void setCoreRemoteDescription2Legacy(JSObject peerConnection, JSObject str, EmptyHandler h1, ErrorHandler h2); private static native void setCoreRemoteDescription2LegacyLegacy(JSObject peerConnection, JSObject str, EmptyHandler h1, ErrorHandler h2);
@JSBody(params = { "peerConnection", "str", "h1", "h2" }, script = "peerConnection.setRemoteDescription(new mozRTCSessionDescription(str), h1, h2);") @JSBody(params = { "peerConnection", "str", "h1", "h2" }, script = "peerConnection.setRemoteDescription(new mozRTCSessionDescription(str), h1, h2);")
private static native void setMozRemoteDescription2Legacy(JSObject peerConnection, JSObject str, EmptyHandler h1, ErrorHandler h2); private static native void setMozRemoteDescription2LegacyLegacy(JSObject peerConnection, JSObject str, EmptyHandler h1, ErrorHandler h2);
static void setRemoteDescription2(JSObject peerConnection, JSObject str, EmptyHandler h1, ErrorHandler h2) { static void setRemoteDescription2(JSObject peerConnection, JSObject str, EmptyHandler h1, ErrorHandler h2) {
if(!hasCheckedSupport) supported(); if(!hasCheckedSupport) supported();
@ -284,20 +343,31 @@ public class PlatformWebRTC {
switch(supportedImpl) { switch(supportedImpl) {
case WEBRTC_SUPPORT_CORE: case WEBRTC_SUPPORT_CORE:
if(useSessionDescConstructor) { if(useSessionDescConstructor) {
setCoreRemoteDescription2Legacy(peerConnection, str, h1, h2); setCoreRemoteDescription2PromisingLegacy(peerConnection, str, h1, h2);
}else { }else {
if(!setCoreRemoteDescription2(peerConnection, str, h1, h2)) { if(!setCoreRemoteDescription2Promising(peerConnection, str, h1, h2)) {
useSessionDescConstructor = true; useSessionDescConstructor = true;
logger.info("Note: Caught suspicious exception, using legacy RTCSessionDescription method"); logger.info("Note: Caught suspicious exception, using legacy RTCSessionDescription method");
setCoreRemoteDescription2Legacy(peerConnection, str, h1, h2); setCoreRemoteDescription2PromisingLegacy(peerConnection, str, h1, h2);
} }
} }
break; break;
case WEBRTC_SUPPORT_WEBKIT: case WEBRTC_SUPPORT_WEBKIT:
setCoreRemoteDescription2Legacy(peerConnection, str, h1, h2); setCoreRemoteDescription2LegacyLegacy(peerConnection, str, h1, h2);
break; break;
case WEBRTC_SUPPORT_MOZ: case WEBRTC_SUPPORT_MOZ:
setMozRemoteDescription2Legacy(peerConnection, str, h1, h2); setMozRemoteDescription2LegacyLegacy(peerConnection, str, h1, h2);
break;
case WEBRTC_SUPPORT_CORE_NON_PROMISING:
if(useSessionDescConstructor) {
setCoreRemoteDescription2LegacyLegacy(peerConnection, str, h1, h2);
}else {
if(!setCoreRemoteDescription2Legacy(peerConnection, str, h1, h2)) {
useSessionDescConstructor = true;
logger.info("Note: Caught suspicious exception, using legacy RTCSessionDescription method");
setCoreRemoteDescription2LegacyLegacy(peerConnection, str, h1, h2);
}
}
break; break;
default: default:
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@ -312,8 +382,27 @@ public class PlatformWebRTC {
+ "}") + "}")
private static native void removeExtmapAllowMixed(JSObject objIn); private static native void removeExtmapAllowMixed(JSObject objIn);
@JSBody(params = { "peerConnection", "h1", "h2" }, script = "peerConnection.createAnswer().then(h1).catch(h2);")
private static native void createAnswerPromising(JSObject peerConnection, DescHandler h1, ErrorHandler h2);
@JSBody(params = { "peerConnection", "h1", "h2" }, script = "peerConnection.createAnswer(h1, h2);") @JSBody(params = { "peerConnection", "h1", "h2" }, script = "peerConnection.createAnswer(h1, h2);")
static native void createAnswer(JSObject peerConnection, DescHandler h1, ErrorHandler h2); private static native void createAnswerLegacy(JSObject peerConnection, DescHandler h1, ErrorHandler h2);
static void createAnswer(JSObject peerConnection, DescHandler h1, ErrorHandler h2) {
if(!hasCheckedSupport) supported();
switch(supportedImpl) {
case WEBRTC_SUPPORT_CORE:
createAnswerPromising(peerConnection, h1, h2);
break;
case WEBRTC_SUPPORT_WEBKIT:
case WEBRTC_SUPPORT_MOZ:
case WEBRTC_SUPPORT_CORE_NON_PROMISING:
createAnswerLegacy(peerConnection, h1, h2);
break;
default:
throw new UnsupportedOperationException();
}
}
@JSBody(params = { "sock", "buffer" }, script = "sock.send(buffer);") @JSBody(params = { "sock", "buffer" }, script = "sock.send(buffer);")
static native void nativeBinarySend(WebSocket sock, ArrayBuffer buffer); static native void nativeBinarySend(WebSocket sock, ArrayBuffer buffer);

View File

@ -8,7 +8,7 @@ import org.teavm.jso.typedarrays.Uint16Array;
import org.teavm.jso.typedarrays.Uint8Array; import org.teavm.jso.typedarrays.Uint8Array;
/** /**
* Copyright (c) 2022-2023 lax1dude. All Rights Reserved. * Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -30,8 +30,14 @@ public class EaglerArrayBufferAllocator {
} }
} }
private static final ByteBuffer ZERO_LENGTH_BYTE_BUFFER = new EaglerArrayByteBuffer(Int8Array.create(0));
public static ByteBuffer allocateByteBuffer(int size) { public static ByteBuffer allocateByteBuffer(int size) {
return new EaglerArrayByteBuffer(Int8Array.create(size)); if(size != 0) {
return new EaglerArrayByteBuffer(Int8Array.create(size));
}else {
return ZERO_LENGTH_BYTE_BUFFER;
}
} }
public static ByteBuffer wrapByteBufferTeaVM(DataView dv) { public static ByteBuffer wrapByteBufferTeaVM(DataView dv) {
@ -42,16 +48,28 @@ public class EaglerArrayBufferAllocator {
return new EaglerArrayByteBuffer(typedArray); return new EaglerArrayByteBuffer(typedArray);
} }
private static final IntBuffer ZERO_LENGTH_INT_BUFFER = new EaglerArrayIntBuffer(Int32Array.create(0));
public static IntBuffer allocateIntBuffer(int size) { public static IntBuffer allocateIntBuffer(int size) {
return new EaglerArrayIntBuffer(Int32Array.create(size)); if(size != 0) {
return new EaglerArrayIntBuffer(Int32Array.create(size));
}else {
return ZERO_LENGTH_INT_BUFFER;
}
} }
public static IntBuffer wrapIntBufferTeaVM(Int32Array typedArray) { public static IntBuffer wrapIntBufferTeaVM(Int32Array typedArray) {
return new EaglerArrayIntBuffer(typedArray); return new EaglerArrayIntBuffer(typedArray);
} }
private static final FloatBuffer ZERO_LENGTH_FLOAT_BUFFER = new EaglerArrayFloatBuffer(Float32Array.create(0));
public static FloatBuffer allocateFloatBuffer(int size) { public static FloatBuffer allocateFloatBuffer(int size) {
return new EaglerArrayFloatBuffer(Float32Array.create(size)); if(size != 0) {
return new EaglerArrayFloatBuffer(Float32Array.create(size));
}else {
return ZERO_LENGTH_FLOAT_BUFFER;
}
} }
public static FloatBuffer wrapFloatBufferTeaVM(Float32Array typedArray) { public static FloatBuffer wrapFloatBufferTeaVM(Float32Array typedArray) {

View File

@ -41,6 +41,11 @@ addToLibrary({
return id; return id;
}, },
resultFailed: function(msg) { resultFailed: function(msg) {
results = null;
epwFile = null;
setTimeout(unsetHeapViews, 20);
const parentElement = createCrashParentElement(); const parentElement = createCrashParentElement();
const messageContainer = document.createElement("div"); const messageContainer = document.createElement("div");
@ -85,40 +90,43 @@ addToLibrary({
for(var i = 0, j; i < numEPKs; ++i) { for(var i = 0, j; i < numEPKs; ++i) {
j = idx + 11 + i * 3; j = idx + 11 + i * 3;
epkFiles[i] = { epkFiles[i] = {
data: results[HEAP32[j]], "data": results[HEAP32[j]],
name: results[HEAP32[j + 1]], "name": results[HEAP32[j + 1]],
path: results[HEAP32[j + 2]] "path": results[HEAP32[j + 2]]
}; };
} }
results.length = 0; results = null;
epwFile = null;
window.__eaglercraftXLoaderContext = { setTimeout(unsetHeapViews, 20);
getEaglercraftXOpts: function() {
window["__eaglercraftXLoaderContext"] = {
"getEaglercraftXOpts": function() {
return optsObj; return optsObj;
}, },
getEagRuntimeJSURL: function() { "getEagRuntimeJSURL": function() {
return eagRuntimeJSURL; return eagRuntimeJSURL;
}, },
getClassesWASMURL: function() { "getClassesWASMURL": function() {
return classesWASMURL; return classesWASMURL;
}, },
getClassesDeobfWASMURL: function() { "getClassesDeobfWASMURL": function() {
return classesDeobfWASMURL; return classesDeobfWASMURL;
}, },
getClassesTEADBGURL: function() { "getClassesTEADBGURL": function() {
return classesDeobfTEADBGURL; return classesDeobfTEADBGURL;
}, },
getEPKFiles: function() { "getEPKFiles": function() {
return epkFiles; return epkFiles;
}, },
getRootElement: function() { "getRootElement": function() {
return rootElement; return rootElement;
}, },
getMainArgs: function() { "getMainArgs": function() {
return []; return [];
}, },
getImageURL: function(idx) { "getImageURL": function(idx) {
switch(idx) { switch(idx) {
case 0: case 0:
return splashURL; return splashURL;
@ -132,7 +140,7 @@ addToLibrary({
return null; return null;
} }
}, },
runMain: function(fn) { "runMain": function(fn) {
setTimeout(fn, 10); setTimeout(fn, 10);
} }
}; };
@ -152,6 +160,11 @@ addToLibrary({
const markupData = results[HEAP32[idx + 2]]; const markupData = results[HEAP32[idx + 2]];
const markup = markupData ? UTF8Decoder.decode(markupData) : "<h1>Failed to load error screen</h1>"; const markup = markupData ? UTF8Decoder.decode(markupData) : "<h1>Failed to load error screen</h1>";
results = null;
epwFile = null;
setTimeout(unsetHeapViews, 20);
const parentElement = createCrashParentElement(); const parentElement = createCrashParentElement();
const img = document.createElement("img"); const img = document.createElement("img");

View File

@ -14,20 +14,24 @@
* *
*/ */
var loaderWASMPath = window["__eaglercraftXLoaderContextPre"]["loaderWASMURL"];
Module["locateFile"] = function(path) { Module["locateFile"] = function(path) {
if(path === "loader.wasm") { if(path === "loader.wasm") {
return window.__eaglercraftXLoaderContextPre.loaderWASMURL; return loaderWASMPath;
}else { }else {
return path; return path;
} }
}; };
const rootElement = window.__eaglercraftXLoaderContextPre.rootElement; var rootElement = window["__eaglercraftXLoaderContextPre"]["rootElement"];
const optsObj = window.__eaglercraftXLoaderContextPre.eaglercraftXOpts; var optsObj = window["__eaglercraftXLoaderContextPre"]["eaglercraftXOpts"];
const epwFile = window.__eaglercraftXLoaderContextPre.theEPWFileBuffer; var epwFile = window["__eaglercraftXLoaderContextPre"]["theEPWFileBuffer"];
const splashURL = window.__eaglercraftXLoaderContextPre.splashURL; var splashURL = window["__eaglercraftXLoaderContextPre"]["splashURL"];
const results = [ null ]; delete window["__eaglercraftXLoaderContextPre"];
var results = [ null ];
function createCrashParentElement() { function createCrashParentElement() {
var oldSplash = null; var oldSplash = null;
@ -59,3 +63,9 @@ function createCrashParentElement() {
return parentElement; return parentElement;
} }
function unsetHeapViews() {
HEAP = HEAP8 = HEAPU8 = HEAP16 = HEAPU16 = HEAP32 = HEAPU32 = HEAPF32 = HEAPF64 = null;
wasmMemory = null;
Module = null;
}

View File

@ -464,6 +464,9 @@ public class PlatformRuntime {
@Import(module = "platformRuntime", name = "immediateContinue") @Import(module = "platformRuntime", name = "immediateContinue")
private static native void immediateContinue0(); private static native void immediateContinue0();
@Import(module = "platformRuntime", name = "immediateContinueSupported")
public static native boolean immediateContinueSupported();
public static void postCreate() { public static void postCreate() {
} }

View File

@ -32,7 +32,7 @@ public class WASMGCBufferAllocator {
public static Address malloc(int size) { public static Address malloc(int size) {
if(size == 0) { if(size == 0) {
throw new IllegalArgumentException("Tried to allocate 0 bytes!"); return Address.fromInt(0);
} }
Address addr; Address addr;
if(enableBufferOverflowCheck) { if(enableBufferOverflowCheck) {
@ -55,11 +55,11 @@ public class WASMGCBufferAllocator {
} }
public static Address calloc(int size) { public static Address calloc(int size) {
if(size == 0) {
return Address.fromInt(0);
}
Address addr; Address addr;
if(enableBufferOverflowCheck) { if(enableBufferOverflowCheck) {
if(size == 0) {
throw new OutOfMemoryError("Tried to allocate 0 bytes!");
}
addr = DirectMalloc.calloc(size + 12); addr = DirectMalloc.calloc(size + 12);
if(addr.toInt() == 0) { if(addr.toInt() == 0) {
throw new OutOfMemoryError("DirectMalloc returned null pointer!"); throw new OutOfMemoryError("DirectMalloc returned null pointer!");
@ -87,33 +87,55 @@ public class WASMGCBufferAllocator {
if(tag != ptr.add(size + 8).getInt()) { if(tag != ptr.add(size + 8).getInt()) {
throw new RuntimeException("Detected a buffer write overflow"); throw new RuntimeException("Detected a buffer write overflow");
} }
DirectMalloc.free(ptr);
}else {
DirectMalloc.free(ptr);
} }
DirectMalloc.free(ptr);
} }
} }
private static final ByteBuffer ZERO_LENGTH_BYTE_BUFFER = new DirectMallocByteBuffer(Address.fromInt(0), 0, true);
public static ByteBuffer allocateByteBuffer(int size) { public static ByteBuffer allocateByteBuffer(int size) {
return new DirectMallocByteBuffer(malloc(size), size, true); if(size != 0) {
return new DirectMallocByteBuffer(malloc(size), size, true);
}else {
return ZERO_LENGTH_BYTE_BUFFER;
}
} }
private static final ShortBuffer ZERO_LENGTH_SHORT_BUFFER = new DirectMallocShortBuffer(Address.fromInt(0), 0, true);
public static ShortBuffer allocateShortBuffer(int size) { public static ShortBuffer allocateShortBuffer(int size) {
return new DirectMallocShortBuffer(malloc(size << 1), size, true); if(size != 0) {
return new DirectMallocShortBuffer(malloc(size << 1), size, true);
}else {
return ZERO_LENGTH_SHORT_BUFFER;
}
} }
private static final IntBuffer ZERO_LENGTH_INT_BUFFER = new DirectMallocIntBuffer(Address.fromInt(0), 0, true);
public static IntBuffer allocateIntBuffer(int size) { public static IntBuffer allocateIntBuffer(int size) {
return new DirectMallocIntBuffer(malloc(size << 2), size, true); if(size != 0) {
return new DirectMallocIntBuffer(malloc(size << 2), size, true);
}else {
return ZERO_LENGTH_INT_BUFFER;
}
} }
private static final FloatBuffer ZERO_LENGTH_FLOAT_BUFFER = new DirectMallocFloatBuffer(Address.fromInt(0), 0, true);
public static FloatBuffer allocateFloatBuffer(int size) { public static FloatBuffer allocateFloatBuffer(int size) {
return new DirectMallocFloatBuffer(malloc(size << 2), size, true); if(size != 0) {
return new DirectMallocFloatBuffer(malloc(size << 2), size, true);
}else {
return ZERO_LENGTH_FLOAT_BUFFER;
}
} }
public static void freeByteBuffer(ByteBuffer buffer) { public static void freeByteBuffer(ByteBuffer buffer) {
DirectMallocByteBuffer buf = (DirectMallocByteBuffer)buffer; DirectMallocByteBuffer buf = (DirectMallocByteBuffer)buffer;
if(buf.original) { if(buf.original) {
WASMGCBufferAllocator.free(buf.address); free(buf.address);
}else { }else {
throwNotOriginal(buf); throwNotOriginal(buf);
} }
@ -122,7 +144,7 @@ public class WASMGCBufferAllocator {
public static void freeShortBuffer(ShortBuffer buffer) { public static void freeShortBuffer(ShortBuffer buffer) {
DirectMallocShortBuffer buf = (DirectMallocShortBuffer)buffer; DirectMallocShortBuffer buf = (DirectMallocShortBuffer)buffer;
if(buf.original) { if(buf.original) {
WASMGCBufferAllocator.free(buf.address); free(buf.address);
}else { }else {
throwNotOriginal(buf); throwNotOriginal(buf);
} }
@ -131,7 +153,7 @@ public class WASMGCBufferAllocator {
public static void freeIntBuffer(IntBuffer buffer) { public static void freeIntBuffer(IntBuffer buffer) {
DirectMallocIntBuffer buf = (DirectMallocIntBuffer)buffer; DirectMallocIntBuffer buf = (DirectMallocIntBuffer)buffer;
if(buf.original) { if(buf.original) {
WASMGCBufferAllocator.free(buf.address); free(buf.address);
}else { }else {
throwNotOriginal(buf); throwNotOriginal(buf);
} }
@ -140,7 +162,7 @@ public class WASMGCBufferAllocator {
public static void freeFloatBuffer(FloatBuffer buffer) { public static void freeFloatBuffer(FloatBuffer buffer) {
DirectMallocFloatBuffer buf = (DirectMallocFloatBuffer)buffer; DirectMallocFloatBuffer buf = (DirectMallocFloatBuffer)buffer;
if(buf.original) { if(buf.original) {
WASMGCBufferAllocator.free(buf.address); free(buf.address);
}else { }else {
throwNotOriginal(buf); throwNotOriginal(buf);
} }

View File

@ -1,7 +1,6 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer; package net.lax1dude.eaglercraft.v1_8.internal.buffer;
import org.teavm.interop.Address; import org.teavm.interop.Address;
import org.teavm.interop.DirectMalloc;
import org.teavm.jso.typedarrays.Float32Array; import org.teavm.jso.typedarrays.Float32Array;
import org.teavm.jso.typedarrays.Int16Array; import org.teavm.jso.typedarrays.Int16Array;
import org.teavm.jso.typedarrays.Int32Array; import org.teavm.jso.typedarrays.Int32Array;

View File

@ -28,6 +28,7 @@ async function entryPoint() {
crashURL = self.__eaglercraftXLoaderContext.getImageURL(2); crashURL = self.__eaglercraftXLoaderContext.getImageURL(2);
faviconURL = self.__eaglercraftXLoaderContext.getImageURL(3); faviconURL = self.__eaglercraftXLoaderContext.getImageURL(3);
const args = self.__eaglercraftXLoaderContext.getMainArgs(); const args = self.__eaglercraftXLoaderContext.getMainArgs();
delete self.__eaglercraftXLoaderContext;
const isWorker = args[0] === "_worker_process_"; const isWorker = args[0] === "_worker_process_";
if(!isWorker) { if(!isWorker) {

View File

@ -561,21 +561,39 @@ async function initPlatformInput(inputImports) {
* @return {Promise} * @return {Promise}
*/ */
function syncDelay(fpsLimit) { function syncDelay(fpsLimit) {
if(fpsLimit > 0 && fpsLimit < 1000) { if(fpsLimit > 0 && fpsLimit <= 1000) {
const frameMillis = (1000 / fpsLimit);
if(manualSyncTimer === 0) { if(manualSyncTimer === 0) {
manualSyncTimer = performance.now(); manualSyncTimer = performance.now() + frameMillis;
}else { }else {
const millis = performance.now(); var millis = performance.now();
const frameMillis = (1000 / fpsLimit); var remaining = (manualSyncTimer - millis) | 0;
var frameTime = millis - manualSyncTimer; if(remaining > 0) {
if(frameTime > 2000 || frameTime < 0) { if(!runtimeOpts.useDelayOnSwap && allowImmediateContinue) {
frameTime = frameMillis; return immediateContinueImpl().then(function() {
var millis0 = performance.now();
var remaining0 = (manualSyncTimer - millis0) | 0;
if(remaining0 > 0) {
return sleepPromise(remaining0).then(function() {
var millis1 = performance.now();
if((manualSyncTimer += frameMillis) < millis1) {
manualSyncTimer = millis1;
}
});
}else if((manualSyncTimer += frameMillis) < millis0) {
manualSyncTimer = millis0;
}
});
}else {
return sleepPromise(remaining).then(function() {
var millis0 = performance.now();
if((manualSyncTimer += frameMillis) < millis0) {
manualSyncTimer = millis0;
}
});
}
}else if((manualSyncTimer += frameMillis) < millis) {
manualSyncTimer = millis; manualSyncTimer = millis;
}else {
manualSyncTimer += frameMillis;
}
if(frameTime >= 0 && frameTime < frameMillis) {
return sleepPromise(frameMillis - frameTime);
} }
} }
}else { }else {

View File

@ -199,6 +199,13 @@ function swapDelayImpl() {
eagruntimeImpl.platformRuntime["immediateContinue"] = new WebAssembly.Suspending(immediateContinueImpl); eagruntimeImpl.platformRuntime["immediateContinue"] = new WebAssembly.Suspending(immediateContinueImpl);
/**
* @return {boolean}
*/
eagruntimeImpl.platformRuntime["immediateContinueSupported"] = function() {
return allowImmediateContinue;
};
/** /**
* @param {number} id * @param {number} id
* @param {string} str * @param {string} str