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

@ -0,0 +1,87 @@
package net.lax1dude.eaglercraft.v1_8;
import jdk_internal.bidi.Bidi;
/**
* 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 EaglerBidiReorder {
/**
* Taken from minecraft 1.6
*/
public static String bidiReorder(String par1Str) {
if (par1Str != null && Bidi.requiresBidi(par1Str.toCharArray(), 0, par1Str.length())) {
Bidi bidi = new Bidi(par1Str, -2);
byte[] abyte = new byte[bidi.getRunCount()];
String[] astring = new String[abyte.length];
int i;
for (int j = 0; j < abyte.length; ++j) {
int k = bidi.getRunStart(j);
i = bidi.getRunLimit(j);
int l = bidi.getRunLevel(j);
String s1 = par1Str.substring(k, i);
abyte[j] = (byte) l;
astring[j] = s1;
}
String[] astring1 = (String[]) astring.clone();
Bidi.reorderVisually(abyte, 0, astring, 0, abyte.length);
StringBuilder stringbuilder = new StringBuilder();
i = 0;
while (i < astring.length) {
byte b0 = abyte[i];
int i1 = 0;
while (true) {
if (i1 < astring1.length) {
if (!astring1[i1].equals(astring[i])) {
++i1;
continue;
}
b0 = abyte[i1];
}
if ((b0 & 1) == 0) {
stringbuilder.append(astring[i]);
} else {
for (i1 = astring[i].length() - 1; i1 >= 0; --i1) {
char c0 = astring[i].charAt(i1);
if (c0 == 40) {
c0 = 41;
} else if (c0 == 41) {
c0 = 40;
}
stringbuilder.append(c0);
}
}
++i;
break;
}
}
return stringbuilder.toString();
} else {
return par1Str;
}
}
}

View File

@ -26,15 +26,33 @@ public class EaglerZLIB {
public static OutputStream newDeflaterOutputStream(OutputStream os) throws IOException {
return PlatformRuntime.newDeflaterOutputStream(os);
}
public static int deflateFull(byte[] input, byte[] output) throws IOException {
return PlatformRuntime.deflateFull(input, 0, input.length, output, 0, output.length);
}
public static int deflateFull(byte[] input, int inputOff, int inputLen, byte[] output, int outputOff,
int outputLen) throws IOException {
return PlatformRuntime.deflateFull(input, inputOff, inputLen, output, outputOff, outputLen);
}
public static OutputStream newGZIPOutputStream(OutputStream os) throws IOException {
return PlatformRuntime.newGZIPOutputStream(os);
}
public static InputStream newInflaterInputStream(InputStream is) throws IOException {
return PlatformRuntime.newInflaterInputStream(is);
}
public static int inflateFull(byte[] input, byte[] output) throws IOException {
return PlatformRuntime.inflateFull(input, 0, input.length, output, 0, output.length);
}
public static int inflateFull(byte[] input, int inputOff, int inputLen, byte[] output, int outputOff,
int outputLen) throws IOException {
return PlatformRuntime.inflateFull(input, inputOff, inputLen, output, outputOff, outputLen);
}
public static InputStream newGZIPInputStream(InputStream is) throws IOException {
return PlatformRuntime.newGZIPInputStream(is);
}

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 = "u46";
public static final String projectForkVersion = "u47";
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 = "u46";
public static final String projectOriginVersion = "u47";
public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace
// EPK Version Identifier
public static final String EPKVersionIdentifier = "u46"; // Set to null to disable EPK version check
public static final String EPKVersionIdentifier = "u47"; // 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 = 46;
public static final int updateBundlePackageVersionInt = 47;
public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName;

View File

@ -2,7 +2,7 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
/**
* Copyright (c) 2022 lax1dude. All Rights Reserved.
* Copyright (c) 2022-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
@ -16,88 +16,100 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public interface ByteBuffer extends Buffer {
public abstract class ByteBuffer implements Buffer {
ByteBuffer duplicate();
public abstract ByteBuffer duplicate();
byte get();
public abstract byte get();
ByteBuffer put(byte b);
public abstract ByteBuffer put(byte b);
byte get(int index);
public abstract byte get(int index);
ByteBuffer put(int index, byte b);
public abstract ByteBuffer put(int index, byte b);
ByteBuffer get(byte[] dst, int offset, int length);
public abstract ByteBuffer get(byte[] dst, int offset, int length);
ByteBuffer get(byte[] dst);
public abstract ByteBuffer get(byte[] dst);
ByteBuffer put(ByteBuffer src);
public abstract ByteBuffer put(ByteBuffer src);
ByteBuffer put(byte[] src, int offset, int length);
public abstract ByteBuffer put(byte[] src, int offset, int length);
ByteBuffer put(byte[] src);
public abstract ByteBuffer put(byte[] src);
char getChar();
public abstract char getChar();
ByteBuffer putChar(char value);
public abstract ByteBuffer putChar(char value);
char getChar(int index);
public abstract char getChar(int index);
ByteBuffer putChar(int index, char value);
public abstract ByteBuffer putChar(int index, char value);
short getShort();
public abstract short getShort();
ByteBuffer putShort(short value);
public abstract ByteBuffer putShort(short value);
short getShort(int index);
public abstract short getShort(int index);
ByteBuffer putShort(int index, short value);
public abstract ByteBuffer putShort(int index, short value);
ShortBuffer asShortBuffer();
public abstract ShortBuffer asShortBuffer();
int getInt();
public abstract int getInt();
ByteBuffer putInt(int value);
public abstract ByteBuffer putInt(int value);
int getInt(int index);
public abstract int getInt(int index);
ByteBuffer putInt(int index, int value);
public abstract ByteBuffer putInt(int index, int value);
IntBuffer asIntBuffer();
public abstract IntBuffer asIntBuffer();
long getLong();
public abstract long getLong();
ByteBuffer putLong(long value);
public abstract ByteBuffer putLong(long value);
long getLong(int index);
public abstract long getLong(int index);
ByteBuffer putLong(int index, long value);
public abstract ByteBuffer putLong(int index, long value);
float getFloat();
public abstract float getFloat();
ByteBuffer putFloat(float value);
public abstract ByteBuffer putFloat(float value);
float getFloat(int index);
public abstract float getFloat(int index);
ByteBuffer putFloat(int index, float value);
public abstract ByteBuffer putFloat(int index, float value);
FloatBuffer asFloatBuffer();
public abstract FloatBuffer asFloatBuffer();
ByteBuffer mark();
public abstract ByteBuffer mark();
ByteBuffer reset();
public abstract ByteBuffer reset();
ByteBuffer clear();
public abstract ByteBuffer clear();
ByteBuffer flip();
public abstract ByteBuffer flip();
ByteBuffer rewind();
public abstract ByteBuffer rewind();
ByteBuffer limit(int newLimit);
public abstract ByteBuffer limit(int newLimit);
ByteBuffer position(int newPosition);
public abstract int limit();
byte[] array();
public abstract ByteBuffer position(int newPosition);
public abstract int position();
public abstract int remaining();
public abstract boolean hasRemaining();
public abstract int capacity();
public abstract boolean hasArray();
public abstract byte[] array();
}

View File

@ -1,7 +1,7 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
/**
* Copyright (c) 2022 lax1dude. All Rights Reserved.
* Copyright (c) 2022-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
@ -15,49 +15,61 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public interface FloatBuffer extends Buffer {
public abstract class FloatBuffer implements Buffer {
FloatBuffer duplicate();
public abstract FloatBuffer duplicate();
float get();
public abstract float get();
FloatBuffer put(float b);
public abstract FloatBuffer put(float b);
float get(int index);
public abstract float get(int index);
FloatBuffer put(int index, float b);
public abstract FloatBuffer put(int index, float b);
float getElement(int index);
public abstract float getElement(int index);
void putElement(int index, float value);
public abstract void putElement(int index, float value);
FloatBuffer get(float[] dst, int offset, int length);
public abstract FloatBuffer get(float[] dst, int offset, int length);
FloatBuffer get(float[] dst);
public abstract FloatBuffer get(float[] dst);
FloatBuffer put(FloatBuffer src);
public abstract FloatBuffer put(FloatBuffer src);
FloatBuffer put(float[] src, int offset, int length);
public abstract FloatBuffer put(float[] src, int offset, int length);
FloatBuffer put(float[] src);
public abstract FloatBuffer put(float[] src);
boolean isDirect();
public abstract boolean isDirect();
FloatBuffer mark();
public abstract FloatBuffer mark();
FloatBuffer reset();
public abstract FloatBuffer reset();
FloatBuffer clear();
public abstract FloatBuffer clear();
FloatBuffer flip();
public abstract FloatBuffer flip();
FloatBuffer rewind();
public abstract FloatBuffer rewind();
FloatBuffer limit(int newLimit);
public abstract FloatBuffer limit(int newLimit);
FloatBuffer position(int newPosition);
public abstract int limit();
float[] array();
public abstract FloatBuffer position(int newPosition);
public abstract int position();
public abstract int remaining();
public abstract boolean hasRemaining();
public abstract int capacity();
public abstract boolean hasArray();
public abstract float[] array();
}

View File

@ -15,49 +15,61 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public interface IntBuffer extends Buffer {
public abstract class IntBuffer implements Buffer {
IntBuffer duplicate();
public abstract IntBuffer duplicate();
int get();
public abstract int get();
IntBuffer put(int b);
public abstract IntBuffer put(int b);
int get(int index);
public abstract int get(int index);
IntBuffer put(int index, int b);
public abstract IntBuffer put(int index, int b);
int getElement(int index);
public abstract int getElement(int index);
void putElement(int index, int value);
public abstract void putElement(int index, int value);
IntBuffer get(int[] dst, int offset, int length);
public abstract IntBuffer get(int[] dst, int offset, int length);
IntBuffer get(int[] dst);
public abstract IntBuffer get(int[] dst);
IntBuffer put(IntBuffer src);
public abstract IntBuffer put(IntBuffer src);
IntBuffer put(int[] src, int offset, int length);
public abstract IntBuffer put(int[] src, int offset, int length);
IntBuffer put(int[] src);
public abstract IntBuffer put(int[] src);
boolean isDirect();
public abstract boolean isDirect();
IntBuffer mark();
public abstract IntBuffer mark();
IntBuffer reset();
public abstract IntBuffer reset();
IntBuffer clear();
public abstract IntBuffer clear();
IntBuffer flip();
public abstract IntBuffer flip();
IntBuffer rewind();
public abstract IntBuffer rewind();
IntBuffer limit(int newLimit);
public abstract IntBuffer limit(int newLimit);
IntBuffer position(int newPosition);
public abstract int limit();
int[] array();
public abstract IntBuffer position(int newPosition);
public abstract int position();
public abstract int remaining();
public abstract boolean hasRemaining();
public abstract int capacity();
public abstract boolean hasArray();
public abstract int[] array();
}

View File

@ -1,7 +1,7 @@
package net.lax1dude.eaglercraft.v1_8.internal.buffer;
/**
* Copyright (c) 2022 lax1dude. All Rights Reserved.
* Copyright (c) 2022-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
@ -15,48 +15,60 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer;
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public interface ShortBuffer extends Buffer {
public abstract class ShortBuffer implements Buffer {
ShortBuffer duplicate();
public abstract ShortBuffer duplicate();
short get();
public abstract short get();
ShortBuffer put(short b);
public abstract ShortBuffer put(short b);
short get(int index);
public abstract short get(int index);
ShortBuffer put(int index, short b);
public abstract ShortBuffer put(int index, short b);
short getElement(int index);
public abstract short getElement(int index);
void putElement(int index, short value);
public abstract void putElement(int index, short value);
ShortBuffer get(short[] dst, int offset, int length);
public abstract ShortBuffer get(short[] dst, int offset, int length);
ShortBuffer get(short[] dst);
public abstract ShortBuffer get(short[] dst);
ShortBuffer put(ShortBuffer src);
public abstract ShortBuffer put(ShortBuffer src);
ShortBuffer put(short[] src, int offset, int length);
public abstract ShortBuffer put(short[] src, int offset, int length);
ShortBuffer put(short[] src);
public abstract ShortBuffer put(short[] src);
boolean isDirect();
public abstract boolean isDirect();
ShortBuffer mark();
public abstract ShortBuffer mark();
ShortBuffer reset();
public abstract ShortBuffer reset();
ShortBuffer clear();
public abstract ShortBuffer clear();
ShortBuffer flip();
public abstract ShortBuffer flip();
ShortBuffer rewind();
public abstract ShortBuffer rewind();
ShortBuffer limit(int newLimit);
public abstract ShortBuffer limit(int newLimit);
ShortBuffer position(int newPosition);
public abstract int limit();
short[] array();
public abstract ShortBuffer position(int newPosition);
public abstract int position();
public abstract int remaining();
public abstract boolean hasRemaining();
public abstract int capacity();
public abstract boolean hasArray();
public abstract short[] array();
}

View File

@ -1,10 +1,10 @@
package net.lax1dude.eaglercraft.v1_8.minecraft;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import com.carrotsearch.hppc.cursors.IntCursor;
import com.google.common.collect.Lists;
import net.lax1dude.eaglercraft.v1_8.HString;
@ -228,10 +228,8 @@ public class EaglerTextureAtlasSprite {
int l = i;
this.height = this.width;
if (meta.getFrameCount() > 0) {
Iterator<Integer> iterator = meta.getFrameIndexSet().iterator();
while (iterator.hasNext()) {
int i1 = iterator.next().intValue();
for (IntCursor cur : meta.getFrameIndexSet()) {
int i1 = cur.value;
if (i1 >= j1) {
throw new RuntimeException("invalid frameindex " + i1);
}

View File

@ -49,6 +49,7 @@ public class EaglerMeshLoader implements IResourceManagerReloadListener {
if(theMesh == null) {
theMesh = new HighPolyMesh();
reloadMesh(meshLoc, theMesh, Minecraft.getMinecraft().getResourceManager());
meshCache.put(meshLoc, theMesh);
}
meshLoc.cachedPointerType = ResourceLocation.CACHED_POINTER_EAGLER_MESH;
meshLoc.cachedPointer = theMesh;

View File

@ -7,8 +7,8 @@ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.minecraft.util.MathHelper;
import java.util.HashMap;
import java.util.Map;
import com.carrotsearch.hppc.IntObjectHashMap;
import com.carrotsearch.hppc.IntObjectMap;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.GLObjectMap;
@ -213,15 +213,18 @@ public class EaglercraftGPU {
++GlStateManager.stateNormalSerial;
}
private static final Map<Integer,String> stringCache = new HashMap<>();
private static final IntObjectMap<String> stringCache = new IntObjectHashMap<>();
public static final String glGetString(int param) {
String str = stringCache.get(param);
if(str == null) {
str = _wglGetString(param);
if(str == null) {
str = "";
}
stringCache.put(param, str);
}
return str;
return str.length() == 0 ? null : str;
}
public static final void glGetInteger(int param, int[] values) {

View File

@ -3,9 +3,10 @@ package net.lax1dude.eaglercraft.v1_8.opengl;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Comparator;
import java.util.function.IntBinaryOperator;
import com.carrotsearch.hppc.sorting.QuickSort;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
@ -84,12 +85,37 @@ public class WorldRenderer {
}
}
private float[] sortArrayCacheA = null;
private int[] sortArrayCacheB = null;
private BitSet sortBitSetCache = null;
private final IntBinaryOperator sortArrayCacheLambda = this::sortFunction_func_181674_a;
private final IntBinaryOperator swapArrayCacheLambda = this::swapFunction_func_181674_a;
protected int sortFunction_func_181674_a(int integer, int integer1) {
return Float.compare(sortArrayCacheA[sortArrayCacheB[integer1]], sortArrayCacheA[sortArrayCacheB[integer]]);
}
protected int swapFunction_func_181674_a(int i, int j) {
int swap = sortArrayCacheB[i];
sortArrayCacheB[i] = sortArrayCacheB[j];
sortArrayCacheB[j] = swap;
return 0;
}
/**
* MOST LIKELY USED TO SORT QUADS BACK TO FRONT
*/
public void func_181674_a(float parFloat1, float parFloat2, float parFloat3) {
int i = this.vertexCount / 4;
final float[] afloat = new float[i];
if(i == 0) {
return;
}
float[] afloat = sortArrayCacheA;
if(afloat == null || afloat.length < i) {
afloat = new float[i];
sortArrayCacheA = afloat;
}
for (int j = 0; j < i; ++j) {
afloat[j] = func_181665_a(this.floatBuffer, (float) ((double) parFloat1 + this.xOffset),
@ -97,30 +123,38 @@ public class WorldRenderer {
this.vertexFormat.attribStride >> 2, j * this.vertexFormat.attribStride);
}
Integer[] ainteger = new Integer[i];
for (int k = 0; k < ainteger.length; ++k) {
ainteger[k] = Integer.valueOf(k);
int[] ainteger = sortArrayCacheB;
if(ainteger == null || ainteger.length < i) {
ainteger = new int[i];
sortArrayCacheB = ainteger;
}
for (int k = 0; k < i; ++k) {
ainteger[k] = k;
}
QuickSort.sort(0, i, sortArrayCacheLambda, swapArrayCacheLambda);
BitSet bitset = sortBitSetCache;
if(bitset == null) {
bitset = new BitSet();
sortBitSetCache = bitset;
}else {
bitset.clear();
}
Arrays.sort(ainteger, new Comparator<Integer>() {
public int compare(Integer integer, Integer integer1) {
return Float.compare(afloat[integer1.intValue()], afloat[integer.intValue()]);
}
});
BitSet bitset = new BitSet();
int l = this.vertexFormat.attribStride;
int[] aint = new int[l];
for (int l1 = 0; (l1 = bitset.nextClearBit(l1)) < ainteger.length; ++l1) {
int i1 = ainteger[l1].intValue();
for (int l1 = 0; (l1 = bitset.nextClearBit(l1)) < i; ++l1) {
int i1 = ainteger[l1];
if (i1 != l1) {
this.intBuffer.limit(i1 * l + l);
this.intBuffer.position(i1 * l);
this.intBuffer.get(aint);
int j1 = i1;
for (int k1 = ainteger[i1].intValue(); j1 != l1; k1 = ainteger[k1].intValue()) {
for (int k1 = ainteger[i1]; j1 != l1; k1 = ainteger[k1]) {
this.intBuffer.limit(k1 * l + l);
this.intBuffer.position(k1 * l);
IntBuffer intbuffer = this.intBuffer.duplicate();

View File

@ -3,8 +3,8 @@ package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import com.carrotsearch.hppc.ObjectIntHashMap;
import com.carrotsearch.hppc.ObjectIntMap;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
@ -32,7 +32,7 @@ public class BlockVertexIDs implements IResourceManagerReloadListener {
private static final Logger logger = LogManager.getLogger("BlockVertexIDsCSV");
public static final Map<String,Integer> modelToID = new HashMap<>();
public static final ObjectIntMap<String> modelToID = new ObjectIntHashMap<>();
public static int builtin_water_still_vertex_id = 0;
public static int builtin_water_flow_vertex_id = 0;

View File

@ -316,6 +316,14 @@ public class DebugFramebufferView {
GlStateManager.bindTexture(pipeline.realisticWaterMaskTexture);
DrawUtils.drawStandardQuad2D();
})),
(new DebugFramebufferView("Water: Combined Normals", (pipeline) -> {
if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException();
PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(1);
EaglerDeferredPipeline.uniformMatrixHelper(dbv.uniforms.u_inverseViewMatrix, DeferredStateManager.inverseViewMatrix);
GlStateManager.setActiveTexture(GL_TEXTURE0);
GlStateManager.bindTexture(pipeline.realisticWaterCombinedNormalsTexture);
DrawUtils.drawStandardQuad2D();
})),
(new DebugFramebufferView("Water: Surface Depth", (pipeline) -> {
if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException();
float depthStart = 0.001f;

View File

@ -34,6 +34,7 @@ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderP
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderRealisticWaterControl;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderRealisticWaterNoise;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderRealisticWaterNormalMap;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderRealisticWaterNormalsMix;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderReprojControl;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderReprojSSR;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderSSAOGenerate;
@ -43,6 +44,7 @@ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderS
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderSkyboxRender;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderSkyboxRenderEnd;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderTonemap;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.ShaderMissingException;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.MetalsLUT;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.TemperaturesLUT;
import net.lax1dude.eaglercraft.v1_8.vector.Matrix3f;
@ -291,6 +293,7 @@ public class EaglerDeferredPipeline {
public PipelineShaderRealisticWaterControl shader_realistic_water_control = null;
public PipelineShaderRealisticWaterNoise shader_realistic_water_noise = null;
public PipelineShaderRealisticWaterNormalMap shader_realistic_water_normals = null;
public PipelineShaderRealisticWaterNormalsMix shader_realistic_water_normals_mix = null;
public PipelineShaderHandDepthMask shader_hand_depth_mask = null;
public PipelineShaderFXAA shader_post_fxaa = null;
public SkyboxRenderer skybox = null;
@ -913,6 +916,12 @@ public class EaglerDeferredPipeline {
shader_realistic_water_normals = PipelineShaderRealisticWaterNormalMap.compile();
shader_realistic_water_normals.loadUniforms();
_wglUniform2f(shader_realistic_water_normals.uniforms.u_sampleOffset2f, 0.00390625f, 0.00390625f);
try {
shader_realistic_water_normals_mix = PipelineShaderRealisticWaterNormalsMix.compile();
shader_realistic_water_normals_mix.loadUniforms();
}catch(ShaderMissingException exx) {
shader_realistic_water_normals_mix = null;
}
if(!config.is_rendering_raytracing) {
shader_reproject_ssr = PipelineShaderReprojSSR.compile();
shader_reproject_ssr.loadUniforms();
@ -1083,7 +1092,7 @@ public class EaglerDeferredPipeline {
double distX = worldX - reprojectionOriginCoordinateX;
double distY = worldY - reprojectionOriginCoordinateY;
double distZ = worldZ - reprojectionOriginCoordinateZ;
if(distX * distX + distY * distY + distZ * distZ > 48.0 * 48.0) {
if(distX * distX + distY * distY + distZ * distZ > 72.0 * 72.0) {
reprojectionOriginCoordinateX = worldX;
reprojectionOriginCoordinateY = worldY;
reprojectionOriginCoordinateZ = worldZ;
@ -1098,7 +1107,7 @@ public class EaglerDeferredPipeline {
}
distX = worldX - cloudRenderOriginCoordinateX;
distZ = worldZ - cloudRenderOriginCoordinateZ;
if(distX * distX + distZ * distZ > 256.0 * 256.0) {
if(distX * distX + distZ * distZ > 384.0 * 384.0) {
cloudRenderOriginCoordinateX = worldX;
cloudRenderOriginCoordinateZ = worldZ;
cloudRenderViewerOffsetX = 0.0f;
@ -1844,39 +1853,44 @@ public class EaglerDeferredPipeline {
_wglUniformMatrix4x2fv(shader_reproject_ssr.uniforms.u_lastInverseProjMatrix4x2f, false, matrixCopyBuffer);
_wglUniform1f(shader_reproject_ssr.uniforms.u_sampleStep1f, 0.125f);
DrawUtils.drawStandardQuad2D(); // sample 1
if(shader_reproject_ssr.uniforms.u_sampleDelta1i != null) {
_wglUniform1i(shader_reproject_ssr.uniforms.u_sampleDelta1i, 5);
DrawUtils.drawStandardQuad2D();
}else {
DrawUtils.drawStandardQuad2D(); // sample 1
_wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[0]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(reprojectionSSRHitVector[1]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(reprojectionSSRTexture[1]);
_wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[0]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(reprojectionSSRHitVector[1]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(reprojectionSSRTexture[1]);
DrawUtils.drawStandardQuad2D(); // sample 2
DrawUtils.drawStandardQuad2D(); // sample 2
_wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[1]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(reprojectionSSRHitVector[0]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(reprojectionSSRTexture[0]);
_wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[1]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(reprojectionSSRHitVector[0]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(reprojectionSSRTexture[0]);
DrawUtils.drawStandardQuad2D(); // sample 3
DrawUtils.drawStandardQuad2D(); // sample 3
_wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[0]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(reprojectionSSRHitVector[1]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(reprojectionSSRTexture[1]);
_wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[0]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(reprojectionSSRHitVector[1]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(reprojectionSSRTexture[1]);
DrawUtils.drawStandardQuad2D(); // sample 4
DrawUtils.drawStandardQuad2D(); // sample 4
_wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[1]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(reprojectionSSRHitVector[0]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(reprojectionSSRTexture[0]);
_wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[1]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(reprojectionSSRHitVector[0]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(reprojectionSSRTexture[0]);
DrawUtils.drawStandardQuad2D(); // sample 5
DrawUtils.drawStandardQuad2D(); // sample 5
}
DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RUN SCREENSPACE REFLECTIONS ALGORITHM");
}
@ -2663,14 +2677,24 @@ public class EaglerDeferredPipeline {
_wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterCombinedNormalsFramebuffer);
GlStateManager.viewport(0, 0, currentWidth, currentHeight);
GlStateManager.bindTexture(gBufferNormalsTexture);
TextureCopyUtil.blitTexture();
GlStateManager.bindTexture(realisticWaterMaskTexture);
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
TextureCopyUtil.blitTexture();
GlStateManager.disableBlend();
if(shader_realistic_water_normals_mix != null) {
GlStateManager.disableBlend();
GlStateManager.setActiveTexture(GL_TEXTURE1);
GlStateManager.bindTexture(realisticWaterMaskTexture);
GlStateManager.setActiveTexture(GL_TEXTURE0);
GlStateManager.bindTexture(gBufferNormalsTexture);
shader_realistic_water_normals_mix.useProgram();
DrawUtils.drawStandardQuad2D();
}else {
GlStateManager.bindTexture(gBufferNormalsTexture);
TextureCopyUtil.blitTexture();
GlStateManager.bindTexture(realisticWaterMaskTexture);
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
TextureCopyUtil.blitTexture();
GlStateManager.disableBlend();
}
DeferredStateManager.checkGLError("endDrawRealisticWaterMask(): COMBINE NORMALS");
@ -2773,39 +2797,44 @@ public class EaglerDeferredPipeline {
_wglUniformMatrix4x2fv(shader_reproject_ssr.uniforms.u_lastInverseProjMatrix4x2f, false, matrixCopyBuffer);
_wglUniform1f(shader_reproject_ssr.uniforms.u_sampleStep1f, 0.5f);
DrawUtils.drawStandardQuad2D(); // sample 1
if(shader_reproject_ssr.uniforms.u_sampleDelta1i != null) {
_wglUniform1i(shader_reproject_ssr.uniforms.u_sampleDelta1i, 5);
DrawUtils.drawStandardQuad2D();
}else {
DrawUtils.drawStandardQuad2D(); // sample 1
_wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[0]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[1]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(realisticWaterControlReflectionTexture[1]);
_wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[0]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[1]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(realisticWaterControlReflectionTexture[1]);
DrawUtils.drawStandardQuad2D(); // sample 2
DrawUtils.drawStandardQuad2D(); // sample 2
_wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[1]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[0]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(realisticWaterControlReflectionTexture[0]);
_wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[1]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[0]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(realisticWaterControlReflectionTexture[0]);
DrawUtils.drawStandardQuad2D(); // sample 3
DrawUtils.drawStandardQuad2D(); // sample 3
_wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[0]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[1]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(realisticWaterControlReflectionTexture[1]);
_wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[0]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[1]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(realisticWaterControlReflectionTexture[1]);
DrawUtils.drawStandardQuad2D(); // sample 4
DrawUtils.drawStandardQuad2D(); // sample 4
_wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[1]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[0]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(realisticWaterControlReflectionTexture[0]);
_wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[1]);
GlStateManager.setActiveTexture(GL_TEXTURE3);
GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[0]);
GlStateManager.setActiveTexture(GL_TEXTURE2);
GlStateManager.bindTexture(realisticWaterControlReflectionTexture[0]);
DrawUtils.drawStandardQuad2D(); // sample 5
DrawUtils.drawStandardQuad2D(); // sample 5
}
DeferredStateManager.checkGLError("endDrawRealisticWaterMask(): RUN SCREENSPACE REFLECTIONS ALGORITHM");
@ -3066,6 +3095,8 @@ public class EaglerDeferredPipeline {
GlStateManager.clear(GL_DEPTH_BUFFER_BIT);
GlStateManager.enableDepth();
DeferredStateManager.setDefaultMaterialConstants();
DeferredStateManager.disableFog();
updateForwardRenderWorldLightingData();
DeferredStateManager.checkGLError("Post: beginDrawHandOverlay()");
}
@ -3838,6 +3869,10 @@ public class EaglerDeferredPipeline {
shader_realistic_water_normals.destroy();
shader_realistic_water_normals = null;
}
if(shader_realistic_water_normals_mix != null) {
shader_realistic_water_normals_mix.destroy();
shader_realistic_water_normals_mix = null;
}
if(shader_post_fxaa != null) {
shader_post_fxaa.destroy();
shader_post_fxaa = null;

View File

@ -0,0 +1,57 @@
package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
/**
* 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 PipelineShaderRealisticWaterNormalsMix extends ShaderProgram<PipelineShaderRealisticWaterNormalsMix.Uniforms> {
public static PipelineShaderRealisticWaterNormalsMix compile() throws ShaderException {
IShaderGL normalsMix = ShaderCompiler.compileShader("realistic_water_normals_mix", GL_FRAGMENT_SHADER,
ShaderSource.realistic_water_normals_mix_fsh);
try {
IProgramGL prog = ShaderCompiler.linkProgram("realistic_water_normals_mix",
SharedPipelineShaders.deferred_local, normalsMix);
return new PipelineShaderRealisticWaterNormalsMix(prog);
}finally {
if(normalsMix != null) {
normalsMix.free();
}
}
}
private PipelineShaderRealisticWaterNormalsMix(IProgramGL program) {
super(program, new Uniforms());
}
public static class Uniforms implements IProgramUniforms {
private Uniforms() {
}
@Override
public void loadUniforms(IProgramGL prog) {
_wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferNormalsTexture"), 0);
_wglUniform1i(_wglGetUniformLocation(prog, "u_surfaceNormalsTexture"), 1);
}
}
}

View File

@ -48,6 +48,7 @@ public class PipelineShaderReprojSSR extends ShaderProgram<PipelineShaderReprojS
public IUniformGL u_inverseProjectionMatrix4f;
public IUniformGL u_sampleStep1f;
public IUniformGL u_pixelAlignment4f = null;
public IUniformGL u_sampleDelta1i;
@Override
public void loadUniforms(IProgramGL prog) {
@ -62,6 +63,7 @@ public class PipelineShaderReprojSSR extends ShaderProgram<PipelineShaderReprojS
u_inverseProjectionMatrix4f = _wglGetUniformLocation(prog, "u_inverseProjectionMatrix4f");
u_sampleStep1f = _wglGetUniformLocation(prog, "u_sampleStep1f");
u_pixelAlignment4f = _wglGetUniformLocation(prog, "u_pixelAlignment4f");
u_sampleDelta1i = _wglGetUniformLocation(prog, "u_sampleDelta1i");
}
}

View File

@ -33,7 +33,11 @@ public class ShaderCompiler {
private static final Logger logger = LogManager.getLogger("DeferredPipelineCompiler");
public static IShaderGL compileShader(String name, int stage, ResourceLocation filename, String... compileFlags) throws ShaderCompileException {
return compileShader(name, stage, filename.toString(), ShaderSource.getSourceFor(filename), Arrays.asList(compileFlags));
String src = ShaderSource.getSourceFor(filename);
if(src == null) {
throw new ShaderMissingException(name, "File not found: " + filename);
}
return compileShader(name, stage, filename.toString(), src, Arrays.asList(compileFlags));
}
public static IShaderGL compileShader(String name, int stage, String filename, String source, String... compileFlags) throws ShaderCompileException {
@ -41,7 +45,11 @@ public class ShaderCompiler {
}
public static IShaderGL compileShader(String name, int stage, ResourceLocation filename, List<String> compileFlags) throws ShaderCompileException {
return compileShader(name, stage, filename.toString(), ShaderSource.getSourceFor(filename), compileFlags);
String src = ShaderSource.getSourceFor(filename);
if(src == null) {
throw new ShaderMissingException(name, "File not found: " + filename);
}
return compileShader(name, stage, filename.toString(), src, compileFlags);
}
public static IShaderGL compileShader(String name, int stage, String filename, String source, List<String> compileFlags) throws ShaderCompileException {

View File

@ -0,0 +1,24 @@
package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program;
/**
* 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 ShaderMissingException extends ShaderException {
public ShaderMissingException(String shaderName, String msg) {
super(shaderName, msg);
}
}

View File

@ -54,6 +54,7 @@ public class ShaderSource {
public static final ResourceLocation realistic_water_render_fsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_render.fsh");
public static final ResourceLocation realistic_water_control_fsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_control.fsh");
public static final ResourceLocation realistic_water_normals_fsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_normals.fsh");
public static final ResourceLocation realistic_water_normals_mix_fsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_normals_mix.fsh");
public static final ResourceLocation realistic_water_noise_fsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_noise.fsh");
public static final ResourceLocation gbuffer_debug_view_fsh = new ResourceLocation("eagler:glsl/deferred/gbuffer_debug_view.fsh");
public static final ResourceLocation ssao_generate_fsh = new ResourceLocation("eagler:glsl/deferred/ssao_generate.fsh");

View File

@ -1,10 +1,10 @@
package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import com.carrotsearch.hppc.cursors.IntCursor;
import com.google.common.collect.Lists;
import net.lax1dude.eaglercraft.v1_8.HString;
@ -104,10 +104,8 @@ public class EaglerTextureAtlasSpritePBR extends EaglerTextureAtlasSprite {
int l = i;
this.height = this.width;
if (meta.getFrameCount() > 0) {
Iterator iterator = meta.getFrameIndexSet().iterator();
while (iterator.hasNext()) {
int i1 = ((Integer) iterator.next()).intValue();
for (IntCursor cur : meta.getFrameIndexSet()) {
int i1 = cur.value;
if (i1 >= j1) {
throw new RuntimeException("invalid frameindex " + i1);
}

View File

@ -201,7 +201,7 @@ public class ServerSkinCache {
}
public SkinCacheEntry getSkin(String url, SkinModel skinModelResponse) {
if(url.length() > 0xFFFF) {
if(url.length() > 0x7F00) {
return skinModelResponse == SkinModel.ALEX ? defaultSlimCacheEntry : defaultCacheEntry;
}
EaglercraftUUID generatedUUID = SkinPackets.createEaglerURLSkinUUID(url);

View File

@ -10,7 +10,6 @@ import net.lax1dude.eaglercraft.v1_8.internal.EnumServerRateLimit;
import net.lax1dude.eaglercraft.v1_8.internal.IServerQuery;
import net.lax1dude.eaglercraft.v1_8.internal.IWebSocketClient;
import net.lax1dude.eaglercraft.v1_8.internal.IWebSocketFrame;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.QueryResponse;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;

View File

@ -1,6 +1,7 @@
package net.lax1dude.eaglercraft.v1_8.socket.protocol.client;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@ -149,10 +150,12 @@ public class GameProtocolMessageController {
while(sendQueueV4.size() > 0) {
sendCount = 0;
totalLen = 0;
Iterator<PacketBuffer> itr = sendQueueV4.iterator();
do {
i = sendQueueV4.get(sendCount++).readableBytes();
i = itr.next().readableBytes();
totalLen += GamePacketOutputBuffer.getVarIntSize(i) + i;
}while(totalLen < 32760 && sendCount < sendQueueV4.size());
++sendCount;
}while(totalLen < 32760 && itr.hasNext());
if(totalLen >= 32760) {
--sendCount;
}

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

View File

@ -7,6 +7,10 @@ import net.minecraft.client.gui.ScaledResolution;
import java.util.*;
import com.carrotsearch.hppc.IntObjectHashMap;
import com.carrotsearch.hppc.IntObjectMap;
import com.carrotsearch.hppc.cursors.ObjectCursor;
/**
* Copyright (c) 2024 lax1dude, ayunami2000. All Rights Reserved.
*
@ -24,7 +28,7 @@ import java.util.*;
*/
public class TouchControls {
public static final Map<Integer, TouchControlInput> touchControls = new HashMap<>();
public static final IntObjectMap<TouchControlInput> touchControls = new IntObjectHashMap<>();
protected static Set<EnumTouchControl> touchControlPressed = EnumSet.noneOf(EnumTouchControl.class);
protected static boolean isSneakToggled = false;
@ -112,7 +116,8 @@ public class TouchControls {
if(!touchControls.isEmpty()) {
Set<EnumTouchControl> newPressed = EnumSet.noneOf(EnumTouchControl.class);
TouchOverlayRenderer renderer = Minecraft.getMinecraft().touchOverlayRenderer;
for (TouchControlInput input : touchControls.values()) {
for (ObjectCursor<TouchControlInput> input_ : touchControls.values()) {
TouchControlInput input = input_.value;
TouchAction action = input.control.getAction();
if(action != null) {
action.call(input.control, input.x, input.y);

View File

@ -17,6 +17,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import java.util.Set;
import com.carrotsearch.hppc.cursors.ObjectCursor;
import com.google.common.collect.Sets;
/**
@ -103,8 +104,8 @@ public class TouchOverlayRenderer {
GlStateManager.clear(GL_COLOR_BUFFER_BIT);
}
Set<EnumTouchControl> controls = Sets.newHashSet(EnumTouchControl._VALUES);
for (TouchControlInput input : TouchControls.touchControls.values()) {
controls.remove(input.control);
for (ObjectCursor<TouchControlInput> input : TouchControls.touchControls.values()) {
controls.remove(input.value.control);
}
for (EnumTouchControl control : controls) {
if(invalidDeep || control.invalid) {
@ -115,7 +116,8 @@ public class TouchOverlayRenderer {
control.invalid = false;
}
}
for (TouchControlInput input : TouchControls.touchControls.values()) {
for (ObjectCursor<TouchControlInput> input_ : TouchControls.touchControls.values()) {
TouchControlInput input = input_.value;
EnumTouchControl control = input.control;
if(invalidDeep || control.invalid) {
if(control.visible) {