Update #44 - WebAssembly GC support, fix more WebRTC bugs

This commit is contained in:
lax1dude
2024-12-03 23:38:28 -08:00
parent 919014b4df
commit 70b52bbf7a
216 changed files with 34358 additions and 91 deletions

View File

@ -99,4 +99,9 @@ public class EagUtils {
return EaglercraftUUID.nameUUIDFromBytes(("EaglercraftXClientOld:" + name).getBytes(StandardCharsets.UTF_8));
}
public static void sleepPrint(String string) {
System.out.println(string);
PlatformRuntime.sleep(500);
}
}

View File

@ -10,7 +10,7 @@ public class EaglercraftVersion {
/// Customize these to fit your fork:
public static final String projectForkName = "EaglercraftX";
public static final String projectForkVersion = "u43";
public static final String projectForkVersion = "u44";
public static final String projectForkVendor = "lax1dude";
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 projectOriginAuthor = "lax1dude";
public static final String projectOriginRevision = "1.8";
public static final String projectOriginVersion = "u43";
public static final String projectOriginVersion = "u44";
public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace
// EPK Version Identifier
public static final String EPKVersionIdentifier = "u43"; // Set to null to disable EPK version check
public static final String EPKVersionIdentifier = "u44"; // Set to null to disable EPK version check
// Updating configuration
public static final boolean enableUpdateService = true;
public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client";
public static final int updateBundlePackageVersionInt = 43;
public static final int updateBundlePackageVersionInt = 44;
public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName;
@ -52,8 +52,8 @@ public class EaglercraftVersion {
// Miscellaneous variables:
public static final String mainMenuStringA = "Minecraft 1.8.8";
public static final String mainMenuStringB = projectOriginName + " " +
projectOriginRevision + "-" + projectOriginVersion + " ultimate";
public static final String mainMenuStringB = projectOriginName + " " + projectOriginRevision + "-"
+ projectOriginVersion + " ultimate [" + EagRuntime.getPlatformType().getName() + "]";
public static final String mainMenuStringC = "";
public static final String mainMenuStringD = "Resources Copyright Mojang AB";
@ -63,6 +63,9 @@ public class EaglercraftVersion {
public static final String mainMenuStringG = "Collector's Edition";
public static final String mainMenuStringH = "PBR Shaders";
public static final String screenRecordingFilePrefix = projectOriginName + " "
+ projectOriginRevision + "-" + projectOriginVersion;
public static final long demoWorldSeed = (long) "North Carolina".hashCode();
public static final boolean mainMenuEnableGithubButton = false;

View File

@ -16,7 +16,7 @@ package net.lax1dude.eaglercraft.v1_8.internal;
*
*/
public enum EnumPlatformType {
DESKTOP("Desktop"), JAVASCRIPT("JavaScript"), WASM_GC("ASM");
DESKTOP("Desktop"), JAVASCRIPT("JS"), WASM_GC("WASM-GC");
private final String name;

View File

@ -98,6 +98,8 @@ public interface IClientConfigAdapter {
boolean isRamdiskMode();
boolean isEnforceVSync();
IClientConfigAdapterHooks getHooks();
}

View File

@ -39,11 +39,9 @@ class VFileOutputStream extends EaglerOutputStream {
try {
copyBuffer.put(buf, 0, count);
copyBuffer.flip();
try {
vfsFile.getFS().eaglerWrite(vfsFile.path, copyBuffer);
}catch(Throwable t) {
throw new IOException("Could not write stream contents to file!", t);
}
vfsFile.getFS().eaglerWrite(vfsFile.path, copyBuffer);
}catch(Throwable t) {
throw new IOException("Could not write stream contents to file!", t);
}finally {
PlatformRuntime.freeByteBuffer(copyBuffer);
}

View File

@ -159,6 +159,10 @@ public class Logger {
}
private void logExcp(final Level level, String h, Throwable msg) {
if(msg == null) {
log(level, "{}: <null>", h);
return;
}
log(level, "{}: {}", h, msg.toString());
EagRuntime.getStackTrace(msg, (e) -> log(level, " at {}", e));
PlatformRuntime.printJSExceptionIfBrowser(msg);

View File

@ -189,11 +189,15 @@ public class EaglerFontRenderer extends FontRenderer {
if(hasStrike) {
GlStateManager.color(0.25f, 0.25f, 0.25f, 1.0f);
GlStateManager.translate(1.0f, 1.0f, 0.0f);
GlStateManager.disableTexture2D();
tessellator.draw();
GlStateManager.translate(-1.0f, -1.0f, 0.0f);
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
GlStateManager.enableTexture2D();
InstancedFontRenderer.render(8, 8, texScale, texScale, true);
GlStateManager.disableTexture2D();
EaglercraftGPU.renderAgain();
GlStateManager.enableTexture2D();
}else {
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
InstancedFontRenderer.render(8, 8, texScale, texScale, true);
@ -201,7 +205,9 @@ public class EaglerFontRenderer extends FontRenderer {
}else {
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
if(hasStrike) {
GlStateManager.disableTexture2D();
tessellator.draw();
GlStateManager.enableTexture2D();
}
InstancedFontRenderer.render(8, 8, texScale, texScale, false);
}

View File

@ -0,0 +1,51 @@
package net.lax1dude.eaglercraft.v1_8.minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
/**
* 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 GuiScreenVSyncReEnabled extends GuiScreen {
private GuiScreen cont;
public GuiScreenVSyncReEnabled(GuiScreen cont) {
this.cont = cont;
}
public void initGui() {
this.buttonList.clear();
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 6 + 136, I18n.format("options.vsyncReEnabled.continue")));
}
public void drawScreen(int par1, int par2, float par3) {
this.drawDefaultBackground();
this.drawCenteredString(fontRendererObj, I18n.format("options.vsyncReEnabled.title"), this.width / 2, 70, 11184810);
this.drawCenteredString(fontRendererObj, I18n.format("options.vsyncReEnabled.0"), this.width / 2, 95, 16777215);
this.drawCenteredString(fontRendererObj, I18n.format("options.vsyncReEnabled.1"), this.width / 2, 120, 16777215);
this.drawCenteredString(fontRendererObj, I18n.format("options.vsyncReEnabled.2"), this.width / 2, 145, 16777215);
this.drawCenteredString(fontRendererObj, I18n.format("options.vsyncReEnabled.3"), this.width / 2, 160, 16777215);
super.drawScreen(par1, par2, par3);
}
protected void actionPerformed(GuiButton par1GuiButton) {
if(par1GuiButton.id == 0) {
this.mc.displayGuiScreen(cont);
}
}
}

View File

@ -65,7 +65,7 @@ class ServerQueryImpl implements IServerQuery {
IWebSocketFrame frame = lst.get(i);
alive = true;
if(pingTimer == -1) {
pingTimer = PlatformRuntime.steadyTimeMillis() - pingStart;
pingTimer = frame.getTimestamp() - pingStart;
if(pingTimer < 1) {
pingTimer = 1;
}

View File

@ -15,6 +15,7 @@ import org.apache.commons.lang3.StringUtils;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.EnumEaglerConnectionState;
import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformType;
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
@ -84,6 +85,7 @@ public class SingleplayerServerController implements ISaveFormat {
issuesDetected.clear();
statusState = IntegratedServerState.WORLD_WORKER_BOOTING;
loggingState = true;
callFailed = false;
boolean singleThreadSupport = ClientPlatformSingleplayer.isSingleThreadModeSupported();
if(!singleThreadSupport && forceSingleThread) {
throw new UnsupportedOperationException("Single thread mode is not supported!");
@ -294,10 +296,12 @@ public class SingleplayerServerController implements ISaveFormat {
}
}
boolean logWindowState = PlatformApplication.isShowingDebugConsole();
if(loggingState != logWindowState) {
loggingState = logWindowState;
sendIPCPacket(new IPCPacket1BEnableLogging(logWindowState));
if(EagRuntime.getPlatformType() == EnumPlatformType.JAVASCRIPT) {
boolean logWindowState = PlatformApplication.isShowingDebugConsole();
if(loggingState != logWindowState) {
loggingState = logWindowState;
sendIPCPacket(new IPCPacket1BEnableLogging(logWindowState));
}
}
if(ClientPlatformSingleplayer.isRunningSingleThreadMode()) {

View File

@ -41,6 +41,8 @@ class LANClientPeer {
protected long startTime;
protected String localICECandidate = null;
protected LANClientPeer(String clientId) {
this.clientId = clientId;
this.startTime = EagRuntime.steadyTimeMillis();
@ -50,7 +52,13 @@ class LANClientPeer {
protected void handleICECandidates(String candidates) {
if(state == SENT_DESCRIPTION) {
PlatformWebRTC.serverLANPeerICECandidates(clientId, candidates);
state = RECEIVED_ICE_CANDIDATE;
if(localICECandidate != null) {
LANServerController.lanRelaySocket.writePacket(new RelayPacket03ICECandidate(clientId, localICECandidate));
localICECandidate = null;
state = SENT_ICE_CANDIDATE;
}else {
state = RECEIVED_ICE_CANDIDATE;
}
}else {
logger.error("Relay [{}] unexpected IPacket03ICECandidate for '{}'", LANServerController.lanRelaySocket.getURI(), clientId);
}
@ -100,6 +108,12 @@ class LANClientPeer {
disconnect();
}else {
switch(state) {
case SENT_DESCRIPTION:{
if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
localICECandidate = ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates;
continue read_loop;
}
}
case RECEIVED_ICE_CANDIDATE: {
if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
LANServerController.lanRelaySocket.writePacket(new RelayPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates));
@ -136,7 +150,7 @@ class LANClientPeer {
}
}
if(state != CLOSED) {
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName());
logger.error("LAN client '{}' had an accident: {} (state {})", clientId, evt.getClass().getSimpleName(), state);
}
disconnect();
return;

View File

@ -82,7 +82,7 @@ public class LANServerController {
}
}
EagUtils.sleep(50);
}while(EagRuntime.steadyTimeMillis() - millis < 1000l);
}while(EagRuntime.steadyTimeMillis() - millis < 2500l);
logger.info("Relay [{}] relay provide ICE servers timeout", sock.getURI());
closeLAN();
return null;

View File

@ -8,7 +8,6 @@ import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.MinecraftException;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
@ -88,7 +87,7 @@ public class EaglerChunkLoader extends AnvilChunkLoader {
}
@Override
public void saveChunk(World var1, Chunk var2) throws IOException, MinecraftException {
public void saveChunk(World var1, Chunk var2) throws IOException {
NBTTagCompound chunkData = new NBTTagCompound();
this.writeChunkToNBT(var2, var1, chunkData);
NBTTagCompound fileData = new NBTTagCompound();

View File

@ -485,6 +485,8 @@ public class EaglerIntegratedServerWorker {
// signal thread startup successful
sendIPCPacket(new IPCPacketFFProcessKeepAlive(0xFF));
ServerPlatformSingleplayer.setCrashCallbackWASM(EaglerIntegratedServerWorker::sendIntegratedServerCrashWASMCB);
while(true) {
mainLoop(false);
ServerPlatformSingleplayer.immediateContinue();
@ -525,4 +527,11 @@ public class EaglerIntegratedServerWorker {
mainLoop(true);
}
public static void sendIntegratedServerCrashWASMCB(String stringValue, boolean terminated) {
sendIPCPacket(new IPCPacket15Crashed(stringValue));
if(terminated) {
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacketFFProcessKeepAlive.EXITED));
}
}
}

View File

@ -0,0 +1,22 @@
package net.lax1dude.eaglercraft.v1_8.sp.server;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public interface IWASMCrashCallback {
void callback(String crashReport, boolean terminated);
}

View File

@ -139,14 +139,24 @@ public class IntegratedVoiceService {
}
public void handleVoiceSignalPacketTypeConnect(EntityPlayerMP sender) {
if (voicePlayers.containsKey(sender.getUniqueID())) {
EaglercraftUUID senderUuid = sender.getUniqueID();
if (voicePlayers.containsKey(senderUuid)) {
return;
}
boolean hasNoOtherPlayers = voicePlayers.isEmpty();
voicePlayers.put(sender.getUniqueID(), sender);
voicePlayers.put(senderUuid, sender);
if (hasNoOtherPlayers) {
return;
}
GameMessagePacket v3p = null;
GameMessagePacket v4p = null;
for(EntityPlayerMP conn : voicePlayers.values()) {
if(conn.playerNetServerHandler.getEaglerMessageProtocol().ver <= 3) {
conn.playerNetServerHandler.sendEaglerMessage(v3p == null ? (v3p = new SPacketVoiceSignalConnectV3EAG(senderUuid.msb, senderUuid.lsb, true, false)) : v3p);
} else {
conn.playerNetServerHandler.sendEaglerMessage(v4p == null ? (v4p = new SPacketVoiceSignalConnectAnnounceV4EAG(senderUuid.msb, senderUuid.lsb)) : v4p);
}
}
Collection<SPacketVoiceSignalGlobalEAG.UserData> userDatas = new ArrayList<>(voicePlayers.size());
for(EntityPlayerMP player : voicePlayers.values()) {
EaglercraftUUID uuid = player.getUniqueID();

View File

@ -94,13 +94,16 @@ public class VoiceClientController {
}
public static void handleVoiceSignalPacketTypeGlobalNew(Collection<SPacketVoiceSignalGlobalEAG.UserData> voicePlayers) {
boolean isGlobal = voiceChannel == EnumVoiceChannelType.GLOBAL;
uuidToNameLookup.clear();
for (SPacketVoiceSignalGlobalEAG.UserData player : voicePlayers) {
EaglercraftUUID uuid = new EaglercraftUUID(player.uuidMost, player.uuidLeast);
if(player.username != null) {
uuidToNameLookup.put(uuid, player.username);
}
sendPacketRequestIfNeeded(uuid);
if (isGlobal) {
sendPacketRequestIfNeeded(uuid);
}
}
}
@ -138,7 +141,7 @@ public class VoiceClientController {
}
public static void handleVoiceSignalPacketTypeConnectAnnounce(EaglercraftUUID user) {
if (voiceChannel != EnumVoiceChannelType.NONE) sendPacketRequest(user);
if (voiceChannel != EnumVoiceChannelType.NONE && (voiceChannel == EnumVoiceChannelType.GLOBAL || listeningSet.contains(user))) sendPacketRequest(user);
}
public static void handleVoiceSignalPacketTypeDisconnect(EaglercraftUUID user) {