Update #47 - Singleplayer lag fixes

This commit is contained in:
lax1dude
2025-01-19 13:26:27 -08:00
parent 3f5ee57068
commit 1f0d593a8c
2052 changed files with 133581 additions and 2339 deletions

View File

@ -3,9 +3,11 @@ package net.lax1dude.eaglercraft.v1_8.sp.ipc;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.function.Supplier;
import com.carrotsearch.hppc.IntObjectHashMap;
import com.carrotsearch.hppc.IntObjectMap;
/**
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
*
@ -23,7 +25,7 @@ import java.util.function.Supplier;
*/
public class IPCPacketManager {
public static final HashMap<Integer, Supplier<IPCPacketBase>> mappings = new HashMap<>();
public static final IntObjectMap<Supplier<IPCPacketBase>> mappings = new IntObjectHashMap<>();
public final IPCInputStream IPC_INPUT_STREAM = new IPCInputStream();
public final IPCOutputStream IPC_OUTPUT_STREAM = new IPCOutputStream();

View File

@ -2,9 +2,7 @@ package net.lax1dude.eaglercraft.v1_8.sp.lan;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.EagUtils;
import net.lax1dude.eaglercraft.v1_8.EaglerInputStream;
import net.lax1dude.eaglercraft.v1_8.EaglerZLIB;
import net.lax1dude.eaglercraft.v1_8.IOUtils;
import net.lax1dude.eaglercraft.v1_8.internal.EnumEaglerConnectionState;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
@ -21,7 +19,6 @@ import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.IChatComponent;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@ -308,13 +305,26 @@ public class LANClientNetworkManager extends EaglercraftNetworkManager {
}
for(int k = 0, l = packets.size(); k < l; ++k) {
byte[] data = packets.get(k);
if(firstPacket) {
// 1.5 kick packet
if(data.length == 31 && data[0] == (byte)0xFF && data[1] == (byte)0x00 && data[2] == (byte)0x0E) {
logger.error("Detected a 1.5 LAN server!");
this.closeChannel(new ChatComponentTranslation("singleplayer.outdatedLANServerKick"));
firstPacket = false;
return;
}
firstPacket = false;
}
byte[] fullData;
boolean compressed = false;
int off = 0;
if (data[0] == 0 || data[0] == 2) {
if(fragmentedPacket.isEmpty()) {
fullData = new byte[data.length - 1];
System.arraycopy(data, 1, fullData, 0, fullData.length);
fullData = data;
off = 1;
}else {
fragmentedPacket.add(data);
int len = 0;
@ -341,34 +351,23 @@ public class LANClientNetworkManager extends EaglercraftNetworkManager {
}
if(compressed) {
if(fullData.length < 4) {
if(fullData.length < 4 + off) {
throw new IOException("Recieved invalid " + fullData.length + " byte compressed packet");
}
EaglerInputStream bi = new EaglerInputStream(fullData);
int i = (bi.read() << 24) | (bi.read() << 16) | (bi.read() << 8) | bi.read();
fullData = new byte[i];
int r;
try(InputStream inflaterInputStream = EaglerZLIB.newInflaterInputStream(bi)) {
r = IOUtils.readFully(inflaterInputStream, fullData);
}
int i = (((int) fullData[off] & 0xFF) << 24) | (((int) fullData[off + 1] & 0xFF) << 16)
| (((int) fullData[off + 2] & 0xFF) << 8) | ((int) fullData[off + 3] & 0xFF);
byte[] fullData2 = new byte[i];
int r = EaglerZLIB.inflateFull(fullData, off + 4, fullData.length - off - 4, fullData2, 0, i);
fullData = fullData2;
off = 0;
if (i != r) {
logger.warn("Decompressed packet expected size {} differs from actual size {}!", i, r);
}
}
if(firstPacket) {
// 1.5 kick packet
if(fullData.length == 31 && fullData[0] == (byte)0xFF && fullData[1] == (byte)0x00 && fullData[2] == (byte)0x0E) {
logger.error("Detected a 1.5 LAN server!");
this.closeChannel(new ChatComponentTranslation("singleplayer.outdatedLANServerKick"));
firstPacket = false;
return;
}
firstPacket = false;
}
ByteBuf nettyBuffer = Unpooled.buffer(fullData, fullData.length);
nettyBuffer.writerIndex(fullData.length);
nettyBuffer.readerIndex(off);
PacketBuffer input = new PacketBuffer(nettyBuffer);
int pktId = input.readVarIntFromBuffer();

View File

@ -0,0 +1,107 @@
package net.lax1dude.eaglercraft.v1_8.sp.server;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.gen.layer.GenLayer;
import net.minecraft.world.gen.layer.IntCache;
/**
* Copyright (c) 2025 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 GenLayerEaglerRivers extends GenLayer {
private static final int[] pattern = new int[] {
0b111000011100001110000111,
0b111000111110011111000111,
0b011100011100001110001110,
0b011100000000000000001110,
0b001110000000000000011100,
0b001110000000000000011100,
0b000111000000000000111000,
0b000111000000000000111000,
0b000011100000000001110000,
0b000011100000000001110000,
0b000001110000000011100000,
0b000001110000000011100000,
0b000000111000000111000000,
0b000000111000000111000000,
0b000000011100001110000000,
0b000000011100001110000000,
0b000000001110011100000000,
0b000000001110011100000000,
0b000000000111111000000000,
0b000000000111111000000000,
0b000000000011110000000000,
0b000000000011110000000000,
0b000000000001100000000000,
0b000000000001100000000000,
};
private static final int patternSize = 24;
public GenLayerEaglerRivers(long parLong1, GenLayer p) {
super(parLong1);
this.parent = p;
}
@Override
public int[] getInts(int x, int y, int w, int h) {
int[] aint = this.parent.getInts(x, y, w, h);
int[] aint1 = IntCache.getIntCache(w * h);
long a = worldGenSeed * 6364136223846793005L + 1442695040888963407L;
long b = ((a & 112104l) == 0) ? (((a & 534l) == 0) ? 1l : 15l) : 746l;
for (int yy = 0; yy < h; ++yy) {
for (int xx = 0; xx < w; ++xx) {
int i = xx + yy * w;
aint1[i] = aint[i];
long xxx = (long)(x + xx) & 0xFFFFFFFFl;
long yyy = (long)(y + yy) & 0xFFFFFFFFl;
long hash = a + (xxx / patternSize);
hash *= hash * 6364136223846793005L + 1442695040888963407L;
hash += (yyy / patternSize);
hash *= hash * 6364136223846793005L + 1442695040888963407L;
hash += a;
if ((hash & b) == 0l) {
xxx %= (long)patternSize;
yyy %= (long)patternSize;
long tmp;
switch((int)((hash >>> 16l) & 3l)) {
case 1:
tmp = xxx;
xxx = yyy;
yyy = (long)patternSize - tmp - 1l;
break;
case 2:
tmp = xxx;
xxx = (long)patternSize - yyy - 1l;
yyy = tmp;
break;
case 3:
tmp = xxx;
xxx = (long)patternSize - yyy - 1l;
yyy = (long)patternSize - tmp - 1l;
break;
}
if((pattern[(int)yyy] & (1 << (int)xxx)) != 0) {
aint1[i] = BiomeGenBase.river.biomeID;
}
}
}
}
return aint1;
}
}

View File

@ -2,8 +2,8 @@ package net.lax1dude.eaglercraft.v1_8.sp.server.socket;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.EaglerOutputStream;
@ -48,10 +48,9 @@ public class IntegratedServerPlayerNetworkManager {
public final String playerChannel;
private EnumConnectionState packetState = EnumConnectionState.HANDSHAKING;
private static PacketBuffer temporaryBuffer;
private static EaglerOutputStream temporaryOutputStream;
private static byte[] compressedPacketTmp;
private int debugPacketCounter = 0;
private byte[][] recievedPacketBuffer = new byte[16384][];
private int recievedPacketBufferCounter = 0;
private final List<byte[]> recievedPacketBuffer = new LinkedList<>();
private final boolean enableSendCompression;
private boolean firstPacket = true;
@ -69,11 +68,6 @@ public class IntegratedServerPlayerNetworkManager {
}
this.playerChannel = playerChannel;
this.enableSendCompression = !SingleplayerServerController.PLAYER_CHANNEL.equals(playerChannel);
if(this.enableSendCompression) {
if(temporaryOutputStream == null) {
temporaryOutputStream = new EaglerOutputStream(16386);
}
}
}
public void connect() {
@ -97,19 +91,14 @@ public class IntegratedServerPlayerNetworkManager {
}
public void addRecievedPacket(byte[] next) {
if(recievedPacketBufferCounter < recievedPacketBuffer.length - 1) {
recievedPacketBuffer[recievedPacketBufferCounter++] = next;
}else {
logger.error("Dropping packets on recievedPacketBuffer for channel \"{}\"! (overflow)", playerChannel);
}
recievedPacketBuffer.add(next);
}
public void processReceivedPackets() {
if(nethandler == null) return;
for(int i = 0; i < recievedPacketBufferCounter; ++i) {
byte[] data = recievedPacketBuffer[i];
while(!recievedPacketBuffer.isEmpty()) {
byte[] data = recievedPacketBuffer.remove(0);
byte[] fullData;
if(enableSendCompression) {
@ -132,7 +121,6 @@ public class IntegratedServerPlayerNetworkManager {
ServerPlatformSingleplayer.sendPacket(new IPCPacketData(playerChannel, kickPacketBAO.toByteArray()));
closeChannel(new ChatComponentText("Recieved unsuppoorted connection from an Eaglercraft 1.5.2 client!"));
firstPacket = false;
recievedPacketBufferCounter = 0;
return;
}
firstPacket = false;
@ -169,7 +157,6 @@ public class IntegratedServerPlayerNetworkManager {
fullData = data;
}
recievedPacketBuffer[i] = null;
++debugPacketCounter;
try {
ByteBuf nettyBuffer = Unpooled.buffer(fullData, fullData.length);
@ -206,7 +193,6 @@ public class IntegratedServerPlayerNetworkManager {
logger.error(t);
}
}
recievedPacketBufferCounter = 0;
}
public void sendPacket(Packet pkt) {
@ -234,22 +220,24 @@ public class IntegratedServerPlayerNetworkManager {
int len = temporaryBuffer.readableBytes();
if(enableSendCompression) {
if(len > compressionThreshold) {
temporaryOutputStream.reset();
byte[] compressedData;
if(compressedPacketTmp == null || compressedPacketTmp.length < len) {
compressedPacketTmp = new byte[len];
}
int cmpLen;
try {
temporaryOutputStream.write(2);
temporaryOutputStream.write((len >>> 24) & 0xFF);
temporaryOutputStream.write((len >>> 16) & 0xFF);
temporaryOutputStream.write((len >>> 8) & 0xFF);
temporaryOutputStream.write(len & 0xFF);
try(OutputStream os = EaglerZLIB.newDeflaterOutputStream(temporaryOutputStream)) {
temporaryBuffer.readBytes(os, len);
}
compressedData = temporaryOutputStream.toByteArray();
cmpLen = EaglerZLIB.deflateFull(temporaryBuffer.array(), 0, len, compressedPacketTmp, 0, compressedPacketTmp.length);
}catch(IOException ex) {
logger.error("Failed to compress packet {}!", pkt.getClass().getSimpleName());
logger.error(ex);
return;
}
byte[] compressedData = new byte[5 + cmpLen];
compressedData[0] = (byte)2;
compressedData[1] = (byte)((len >>> 24) & 0xFF);
compressedData[2] = (byte)((len >>> 16) & 0xFF);
compressedData[3] = (byte)((len >>> 8) & 0xFF);
compressedData[4] = (byte)(len & 0xFF);
System.arraycopy(compressedPacketTmp, 0, compressedData, 5, cmpLen);
if(compressedData.length > fragmentSize) {
int fragmentSizeN1 = fragmentSize - 1;
for (int j = 1; j < compressedData.length; j += fragmentSizeN1) {

View File

@ -1,6 +1,8 @@
package net.lax1dude.eaglercraft.v1_8.sp.socket;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.internal.EnumEaglerConnectionState;
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
@ -34,8 +36,7 @@ import net.minecraft.util.IChatComponent;
public class ClientIntegratedServerNetworkManager extends EaglercraftNetworkManager {
private int debugPacketCounter = 0;
private byte[][] recievedPacketBuffer = new byte[16384][];
private int recievedPacketBufferCounter = 0;
private final List<byte[]> recievedPacketBuffer = new LinkedList<>();
public boolean isPlayerChannelOpen = false;
public ClientIntegratedServerNetworkManager(String channel) {
@ -65,20 +66,15 @@ public class ClientIntegratedServerNetworkManager extends EaglercraftNetworkMana
}
public void addRecievedPacket(byte[] next) {
if(recievedPacketBufferCounter < recievedPacketBuffer.length - 1) {
recievedPacketBuffer[recievedPacketBufferCounter++] = next;
}else {
logger.error("Dropping packets on recievedPacketBuffer for channel \"{}\"! (overflow)", address);
}
recievedPacketBuffer.add(next);
}
@Override
public void processReceivedPackets() throws IOException {
if(nethandler == null) return;
for(int i = 0; i < recievedPacketBufferCounter; ++i) {
byte[] next = recievedPacketBuffer[i];
recievedPacketBuffer[i] = null;
while(!recievedPacketBuffer.isEmpty()) {
byte[] next = recievedPacketBuffer.remove(0);
++debugPacketCounter;
try {
ByteBuf nettyBuffer = Unpooled.buffer(next, next.length);
@ -115,7 +111,6 @@ public class ClientIntegratedServerNetworkManager extends EaglercraftNetworkMana
logger.error(t);
}
}
recievedPacketBufferCounter = 0;
}
@Override
@ -170,9 +165,6 @@ public class ClientIntegratedServerNetworkManager extends EaglercraftNetworkMana
}
public void clearRecieveQueue() {
for(int i = 0; i < recievedPacketBufferCounter; ++i) {
recievedPacketBuffer[i] = null;
}
recievedPacketBufferCounter = 0;
recievedPacketBuffer.clear();
}
}