Update #52 - Fixed various issues with the client

This commit is contained in:
lax1dude
2025-06-15 21:43:43 -07:00
parent 325a6826bf
commit f3281c037f
94 changed files with 882 additions and 506 deletions

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

View File

@ -30,7 +30,7 @@ public class GuiScreenVSyncReEnabled extends GuiScreen {
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")));
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 6 + 142, I18n.format("options.vsyncReEnabled.continue")));
}
public void drawScreen(int par1, int par2, float par3) {

View File

@ -49,10 +49,6 @@ public class GuiScreenVideoSettingsWarning extends GuiScreen {
if((mask & WARNING_VSYNC) != 0) {
messages.add(null);
messages.add(I18n.format("options.badVideoSettingsDetected.vsync.0"));
messages.add(I18n.format("options.badVideoSettingsDetected.vsync.1"));
messages.add(I18n.format("options.badVideoSettingsDetected.vsync.2"));
messages.add(I18n.format("options.badVideoSettingsDetected.vsync.3"));
messages.add(I18n.format("options.badVideoSettingsDetected.vsync.4"));
}
if((mask & WARNING_RENDER_DISTANCE) != 0) {
messages.add(null);

View File

@ -63,13 +63,13 @@ public class EaglerMeshLoader implements IResourceManagerReloadListener {
int intsOfVertex, intsOfIndex, intsTotal, stride;
try(DataInputStream dis = new DataInputStream(resourceManager.getResource(meshLoc).getInputStream())) {
byte[] header = new byte[8];
dis.read(header);
dis.readFully(header);
if(!Arrays.equals(header, new byte[] { (byte) 33, (byte) 69, (byte) 65, (byte) 71, (byte) 36,
(byte) 109, (byte) 100, (byte) 108 })) {
throw new IOException("File is not an eaglercraft high-poly mesh!");
}
char CT = (char)dis.read();
char CT = (char)dis.readUnsignedByte();
if(CT == 'C') {
meshStruct.hasTexture = false;

View File

@ -493,27 +493,21 @@ public class EaglercraftGPU {
}
public static void enableVertexAttribArray(int index) {
if(emulatedVAOs) {
if(currentVertexArray == null) {
logger.warn("Skipping enable attrib with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLVertexArray)currentVertexArray).enableAttrib(index, true);
}else {
if(!emulatedVAOs) {
_wglEnableVertexAttribArray(index);
}
if (currentVertexArray != null) {
currentVertexArray.setBit(1 << index);
}
}
public static void disableVertexAttribArray(int index) {
if(emulatedVAOs) {
if(currentVertexArray == null) {
logger.warn("Skipping disable attrib with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLVertexArray)currentVertexArray).enableAttrib(index, false);
}else {
if(!emulatedVAOs) {
_wglDisableVertexAttribArray(index);
}
if (currentVertexArray != null) {
currentVertexArray.unsetBit(1 << index);
}
}
public static void vertexAttribPointer(int index, int size, int format, boolean normalized, int stride, int offset) {

View File

@ -74,12 +74,15 @@ class SoftGLVertexArray implements IVertexArrayGL {
}
}
void enableAttrib(int index, boolean en) {
if(en) {
enabled |= (1 << index);
}else {
enabled &= ~(1 << index);
}
@Override
public void setBit(int bit) {
enabled |= bit;
enabledCnt = 32 - Integer.numberOfLeadingZeros(enabled);
}
@Override
public void unsetBit(int bit) {
enabled &= ~bit;
enabledCnt = 32 - Integer.numberOfLeadingZeros(enabled);
}
@ -183,6 +186,11 @@ class SoftGLVertexArray implements IVertexArrayGL {
public void free() {
}
@Override
public int getBits() {
return enabled;
}
static class Attrib {
final IBufferGL buffer;
@ -223,17 +231,4 @@ class SoftGLVertexArray implements IVertexArrayGL {
}
@Override
public int getBits() {
return enabled;
}
@Override
public void setBit(int bit) {
}
@Override
public void unsetBit(int bit) {
}
}

View File

@ -42,14 +42,6 @@ public class StreamBuffer {
}
private static PoolInstance fillPoolInstance() {
PoolInstance ret = pool[poolBufferID++];
if(poolBufferID > poolSize - 1) {
poolBufferID = 0;
}
return ret;
}
private static void resizeInstance(PoolInstance instance, int requiredMemory) {
IBufferGL buffer = instance.vertexBuffer;
if (buffer == null) {
@ -67,8 +59,6 @@ public class StreamBuffer {
protected StreamBufferInstance[] buffers;
protected int currentBufferId = 0;
protected final IStreamBufferInitializer initializer;
public static class StreamBufferInstance {
@ -94,24 +84,17 @@ public class StreamBuffer {
}
public StreamBuffer(IStreamBufferInitializer initializer) {
this(poolSize, initializer);
}
public StreamBuffer(int count, IStreamBufferInitializer initializer) {
if(count > poolSize) {
count = poolSize;
}
this.buffers = new StreamBufferInstance[count];
this.buffers = new StreamBufferInstance[poolSize];
for(int i = 0; i < this.buffers.length; ++i) {
StreamBufferInstance j = new StreamBufferInstance();
j.poolInstance = fillPoolInstance();
j.poolInstance = pool[i];
this.buffers[i] = j;
}
this.initializer = initializer;
}
public StreamBufferInstance getBuffer(int requiredMemory) {
StreamBufferInstance next = buffers[(currentBufferId++) % buffers.length];
StreamBufferInstance next = buffers[poolBufferID++ % buffers.length];
resizeInstance(next.poolInstance, requiredMemory);
if(next.vertexArray == null) {
next.vertexArray = EaglercraftGPU.createGLVertexArray();

View File

@ -0,0 +1,149 @@
/*
* 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.
*
*/
package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.Display;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL;
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
import net.lax1dude.eaglercraft.v1_8.internal.IRenderbufferGL;
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.DrawUtils;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
import net.lax1dude.eaglercraft.v1_8.opengl.GLSLHeader;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.VSHInputLayoutParser;
public class D3DCmpLod0IssueCheck {
private static final Logger logger = LogManager.getLogger("D3DCmpLod0IssueCheck");
public static boolean test() {
String rendererString = EaglercraftGPU.glGetString(GL_RENDERER);
if (rendererString == null || !rendererString.contains(" Direct3D11 ")) {
return false;
}
logger.info("Checking for D3D compiler issue...");
String vshLocalSrc = EagRuntime.getRequiredResourceString("/assets/eagler/glsl/local.vsh");
List<VSHInputLayoutParser.ShaderInput> vertLayout = VSHInputLayoutParser.getShaderInputs(vshLocalSrc);
IShaderGL vert = _wglCreateShader(GL_VERTEX_SHADER);
_wglShaderSource(vert, GLSLHeader.getVertexHeaderCompat(vshLocalSrc, DrawUtils.vertexShaderPrecision));
_wglCompileShader(vert);
if (_wglGetShaderi(vert, GL_COMPILE_STATUS) != GL_TRUE) {
Display.checkContextLost();
_wglDeleteShader(vert);
logger.error("Failed to compile vertex shader! This should not happen!");
logger.error("Don't know how to proceed");
return false;
}
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
_wglShaderSource(frag, GLSLHeader.getHeader()
+ EagRuntime.getRequiredResourceString("/assets/eagler/glsl/deferred/check_d3d_cmplod0.fsh"));
_wglCompileShader(frag);
if (_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
Display.checkContextLost();
logger.info(_wglGetShaderInfoLog(frag));
_wglDeleteShader(vert);
_wglDeleteShader(frag);
logger.error("Failed to compile fragment shader! This should not happen!");
logger.error("D3D compiler workarounds will be enabled");
return true;
}
IProgramGL program = _wglCreateProgram();
_wglAttachShader(program, vert);
_wglAttachShader(program, frag);
if (EaglercraftGPU.checkOpenGLESVersion() == 200) {
VSHInputLayoutParser.applyLayout(program, vertLayout);
}
_wglLinkProgram(program);
_wglDetachShader(program, vert);
_wglDetachShader(program, frag);
_wglDeleteShader(vert);
_wglDeleteShader(frag);
if (_wglGetProgrami(program, GL_LINK_STATUS) != GL_TRUE) {
Display.checkContextLost();
_wglDeleteProgram(program);
logger.error("Failed to link program! This should not happen!");
logger.error("D3D compiler workarounds will be enabled");
return true;
}
EaglercraftGPU.bindGLShaderProgram(program);
_wglUniform1i(_wglGetUniformLocation(program, "u_inputTexture"), 0);
int emptyTexture = GlStateManager.generateTexture();
GlStateManager.bindTexture(emptyTexture);
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
_wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_FUNC, GL_GREATER);
_wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, _GL_COMPARE_REF_TO_TEXTURE);
_wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT24, 256, 256, 0, _GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, (ByteBuffer)null);
IFramebufferGL fbo = _wglCreateFramebuffer();
_wglBindFramebuffer(_GL_FRAMEBUFFER, fbo);
IRenderbufferGL rbo = _wglCreateRenderbuffer();
_wglBindRenderbuffer(_GL_RENDERBUFFER, rbo);
_wglRenderbufferStorage(_GL_RENDERBUFFER, GL_RGBA8, 256, 256);
_wglFramebufferRenderbuffer(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, _GL_RENDERBUFFER, rbo);
_wglDrawBuffers(_GL_COLOR_ATTACHMENT0);
int err = _wglGetError();
if (err != 0) {
logger.error("Ignored OpenGL error while clearing error state: ", EaglercraftGPU.gluErrorString(err));
}
DrawUtils.drawStandardQuad2D();
err = _wglGetError();
GlStateManager.deleteTexture(emptyTexture);
_wglDeleteProgram(program);
_wglDeleteRenderbuffer(rbo);
_wglDeleteFramebuffer(fbo);
_wglBindFramebuffer(_GL_FRAMEBUFFER, null);
if (err != 0) {
logger.error("Using the test shader generated error: {}", EaglercraftGPU.gluErrorString(err));
logger.error("D3D compiler workarounds will be enabled");
return true;
} else {
return false;
}
}
}

View File

@ -1889,45 +1889,9 @@ public class EaglerDeferredPipeline {
matrixCopyBuffer.flip();
_wglUniformMatrix4x2fv(shader_reproject_ssr.uniforms.u_lastInverseProjMatrix4x2f, false, matrixCopyBuffer);
_wglUniform1f(shader_reproject_ssr.uniforms.u_sampleStep1f, 0.125f);
_wglUniform1i(shader_reproject_ssr.uniforms.u_sampleDelta1i, 5);
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]);
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]);
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]);
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]);
DrawUtils.drawStandardQuad2D(); // sample 5
}
DrawUtils.drawStandardQuad2D();
DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RUN SCREENSPACE REFLECTIONS ALGORITHM");
}
@ -2900,45 +2864,9 @@ public class EaglerDeferredPipeline {
matrixCopyBuffer.flip();
_wglUniformMatrix4x2fv(shader_reproject_ssr.uniforms.u_lastInverseProjMatrix4x2f, false, matrixCopyBuffer);
_wglUniform1f(shader_reproject_ssr.uniforms.u_sampleStep1f, 0.5f);
_wglUniform1i(shader_reproject_ssr.uniforms.u_sampleDelta1i, 5);
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]);
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]);
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]);
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]);
DrawUtils.drawStandardQuad2D(); // sample 5
}
DrawUtils.drawStandardQuad2D();
DeferredStateManager.checkGLError("endDrawRealisticWaterMask(): RUN SCREENSPACE REFLECTIONS ALGORITHM");

View File

@ -28,6 +28,7 @@ import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.IExtPipelineCompiler;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.GBufferExtPipelineShader;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.ShaderCompiler;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.ShaderSource;
import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f;
import net.lax1dude.eaglercraft.v1_8.vector.Vector4f;
@ -59,6 +60,11 @@ public class GBufferPipelineCompiler implements IExtPipelineCompiler {
userPointer[0] = new GBufferPipelineProgramInstance(stateCoreBits, stateExtBits);
EaglerDeferredConfig conf = Minecraft.getMinecraft().gameSettings.deferredShaderConf;
StringBuilder macros = new StringBuilder();
if (ShaderCompiler.isBrokenD3DCompiler()) {
macros.append("#define CMPLOD0_D3D_WORKAROUND(a, b) texture(a, b)\n");
} else {
macros.append("#define CMPLOD0_D3D_WORKAROUND(a, b) textureLod(a, b, 0.0)\n");
}
if((stateExtBits & STATE_SHADOW_RENDER) != 0) {
if((stateExtBits & STATE_CLIP_PLANE) != 0) {
macros.append("#define STATE_CLIP_PLANE\n");

View File

@ -186,12 +186,12 @@ public class LensFlareMeshRenderer {
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
_wglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
int mip = 0;
while(dis.read() == 'E') {
while(dis.readUnsignedByte() == 'E') {
int w = dis.readShort();
int h = dis.readShort();
copyBuffer.clear();
for(int i = 0, l = w * h; i < l; ++i) {
copyBuffer.put((byte)dis.read());
copyBuffer.put((byte)dis.readUnsignedByte());
}
copyBuffer.flip();
_wglTexImage2D(GL_TEXTURE_2D, mip++, _GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, copyBuffer);

View File

@ -54,18 +54,19 @@ public class LightSourceMesh {
destroy();
try (DataInputStream is = new DataInputStream(
Minecraft.getMinecraft().getResourceManager().getResource(meshLocation).getInputStream())) {
if(is.read() != 0xEE || is.read() != 0xAA || is.read() != 0x66 || is.read() != '%') {
if(is.readUnsignedByte() != 0xEE || is.readUnsignedByte() != 0xAA || is.readUnsignedByte() != 0x66
|| is.readUnsignedByte() != '%') {
throw new IOException("Bad file type for: " + meshLocation.toString());
}
byte[] bb = new byte[is.read()];
is.read(bb);
byte[] bb = new byte[is.readUnsignedByte()];
is.readFully(bb);
if(!Arrays.equals(bb, typeBytes)) {
throw new IOException("Bad file type \"" + new String(bb, StandardCharsets.UTF_8) + "\" for: " + meshLocation.toString());
}
int vboLength = is.readInt() * 6;
byte[] readBuffer = new byte[vboLength];
is.read(readBuffer);
is.readFully(readBuffer);
ByteBuffer buf = EagRuntime.allocateByteBuffer(readBuffer.length);
buf.put(readBuffer);
@ -78,7 +79,7 @@ public class LightSourceMesh {
EagRuntime.freeByteBuffer(buf);
int iboLength = meshIndexCount = is.readInt();
int iboType = is.read();
int iboType = is.readUnsignedByte();
iboLength *= iboType;
switch(iboType) {
case 1:
@ -95,7 +96,7 @@ public class LightSourceMesh {
}
readBuffer = new byte[iboLength];
is.read(readBuffer);
is.readFully(readBuffer);
buf = EagRuntime.allocateByteBuffer(readBuffer.length);
buf.put(readBuffer);

View File

@ -63,18 +63,19 @@ public class SkyboxRenderer {
destroy();
try (DataInputStream is = new DataInputStream(
Minecraft.getMinecraft().getResourceManager().getResource(skyboxLocation).getInputStream())) {
if(is.read() != 0xEE || is.read() != 0xAA || is.read() != 0x66 || is.read() != '%') {
if(is.readUnsignedByte() != 0xEE || is.readUnsignedByte() != 0xAA || is.readUnsignedByte() != 0x66
|| is.readUnsignedByte() != '%') {
throw new IOException("Bad file type for: " + skyboxLocation.toString());
}
byte[] bb = new byte[is.read()];
is.read(bb);
is.readFully(bb);
if(!Arrays.equals(bb, new byte[] { 's', 'k', 'y', 'b', 'o', 'x' })) {
throw new IOException("Bad file type \"" + new String(bb, StandardCharsets.UTF_8) + "\" for: " + skyboxLocation.toString());
}
atmosphereLUTWidth = is.readUnsignedShort();
atmosphereLUTHeight = is.readUnsignedShort();
byte[] readBuffer = new byte[atmosphereLUTWidth * atmosphereLUTHeight * 4];
is.read(readBuffer);
is.readFully(readBuffer);
ByteBuffer buf = EagRuntime.allocateByteBuffer(readBuffer.length);
buf.put(readBuffer);
@ -97,7 +98,7 @@ public class SkyboxRenderer {
int vboLength = is.readInt() * 8;
readBuffer = new byte[vboLength];
is.read(readBuffer);
is.readFully(readBuffer);
buf = EagRuntime.allocateByteBuffer(readBuffer.length);
buf.put(readBuffer);
@ -110,7 +111,7 @@ public class SkyboxRenderer {
EagRuntime.freeByteBuffer(buf);
int iboLength = skyboxIndexCount = is.readInt();
int iboType = is.read();
int iboType = is.readUnsignedByte();
iboLength *= iboType;
switch(iboType) {
case 1:
@ -129,7 +130,7 @@ public class SkyboxRenderer {
skyboxIndexStride = iboType;
readBuffer = new byte[iboLength];
is.read(readBuffer);
is.readFully(readBuffer);
buf = EagRuntime.allocateByteBuffer(readBuffer.length);
buf.put(readBuffer);

View File

@ -28,12 +28,27 @@ import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.GLSLHeader;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.D3DCmpLod0IssueCheck;
import net.minecraft.util.ResourceLocation;
public class ShaderCompiler {
private static final Logger logger = LogManager.getLogger("DeferredPipelineCompiler");
private static boolean isBrokenD3DCompiler = false;
private static boolean isBrokenD3DChecked = false;
/**
* Warning: binds a different framebuffer
*/
public static boolean isBrokenD3DCompiler() {
if (!isBrokenD3DChecked) {
isBrokenD3DCompiler = D3DCmpLod0IssueCheck.test();
isBrokenD3DChecked = true;
}
return isBrokenD3DCompiler;
}
public static IShaderGL compileShader(String name, int stage, ResourceLocation filename, String... compileFlags) throws ShaderCompileException {
String src = ShaderSource.getSourceFor(filename);
if(src == null) {
@ -58,7 +73,13 @@ public class ShaderCompiler {
logger.info("Compiling Shader: " + filename);
StringBuilder srcCat = new StringBuilder();
srcCat.append(GLSLHeader.getHeader()).append('\n');
if (isBrokenD3DCompiler()) {
srcCat.append("#define CMPLOD0_D3D_WORKAROUND(a, b) texture(a, b)\n");
} else {
srcCat.append("#define CMPLOD0_D3D_WORKAROUND(a, b) textureLod(a, b, 0.0)\n");
}
if(compileFlags != null && compileFlags.size() > 0) {
for(int i = 0, l = compileFlags.size(); i < l; ++i) {
srcCat.append("#define ").append(compileFlags.get(i)).append('\n');

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 lax1dude. All Rights Reserved.
* Copyright (c) 2023-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,6 +16,7 @@
package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@ -34,53 +35,72 @@ public class EaglerBitwisePackedTexture {
}
}
public static ImageData loadTexture(InputStream is, int alpha) throws IOException {
if(is.read() != '%' || is.read() != 'E' || is.read() != 'B' || is.read() != 'P') {
private static int readByte(InputStream is) throws IOException {
int i = is.read();
if (i < 0) {
throw new EOFException();
}
return i;
}
public static ImageData loadTexture(InputStream is) throws IOException {
if(readByte(is) != '%' || readByte(is) != 'E' || readByte(is) != 'B' || readByte(is) != 'P') {
throw new IOException("Not an EBP file!");
}
int v = is.read();
int v = readByte(is);
if(v != 1) {
throw new IOException("Unknown EBP version: " + v);
}
v = is.read();
if(v != 3) {
throw new IOException("Invalid component count: " + v);
int c = readByte(is);
if(c != 3 && c != 4) {
throw new IOException("Invalid component count: " + c);
}
int w = is.read() | (is.read() << 8);
int h = is.read() | (is.read() << 8);
int w = readByte(is) | (readByte(is) << 8);
int h = readByte(is) | (readByte(is) << 8);
ImageData img = new ImageData(w, h, true);
alpha <<= 24;
v = is.read();
v = readByte(is);
if(v == 0) {
for(int i = 0, l = w * h; i < l; ++i) {
img.pixels[i] = is.read() | (is.read() << 8) | (is.read() << 16) | alpha;
if(c == 3) {
for(int i = 0, l = w * h; i < l; ++i) {
img.pixels[i] = readByte(is) | (readByte(is) << 8) | (readByte(is) << 16) | 0xFF000000;
}
}else {
for(int i = 0, l = w * h; i < l; ++i) {
img.pixels[i] = readByte(is) | (readByte(is) << 8) | (readByte(is) << 16) | (readByte(is) << 24);
}
}
}else if(v == 1) {
int paletteSize = is.read();
int[] palette = new int[paletteSize + 1];
palette[0] = alpha;
for(int i = 0; i < paletteSize; ++i) {
palette[i + 1] = is.read() | (is.read() << 8) | (is.read() << 16) | alpha;
int paletteSize = readByte(is) + 1;
int[] palette = new int[paletteSize];
palette[0] = 0xFF000000;
if(c == 3) {
for(int i = 1; i < paletteSize; ++i) {
palette[i] = readByte(is) | (readByte(is) << 8) | (readByte(is) << 16) | 0xFF000000;
}
}else {
for(int i = 1; i < paletteSize; ++i) {
palette[i] = readByte(is) | (readByte(is) << 8) | (readByte(is) << 16) | (readByte(is) << 24);
}
}
int bpp = is.read();
byte[] readSet = new byte[is.read() | (is.read() << 8) | (is.read() << 16)];
is.read(readSet);
int bpp = readByte(is);
byte[] readSet = new byte[readByte(is) | (readByte(is) << 8) | (readByte(is) << 16)];
IOUtils.readFully(is, readSet);
for(int i = 0, l = w * h; i < l; ++i) {
img.pixels[i] = palette[getFromBits(i * bpp, bpp, readSet)];
}
}else {
throw new IOException("Unknown EBP storage type: " + v);
}
if(is.read() != ':' || is.read() != '>') {
if(readByte(is) != ':' || readByte(is) != '>') {
throw new IOException("Invalid footer! (:>)");
}
return img;
}
public static ImageData loadTextureSafe(InputStream is, int alpha) throws IOException {
public static ImageData loadTextureSafe(InputStream is) throws IOException {
ImageData bufferedimage;
try {
bufferedimage = loadTexture(is, alpha);
bufferedimage = loadTexture(is);
} finally {
IOUtils.closeQuietly(is);
}

View File

@ -52,11 +52,13 @@ public class PBRTextureMapUtils {
if(res.getResourcePackName().equals(resourcePack)) {
ImageData toRet = TextureUtil.readBufferedImage(res.getInputStream());
if(ext.equals("_s")) {
for(int i = 0, j; i < toRet.pixels.length; ++i) {
// swap B and A, because labPBR support
int a = (toRet.pixels[i] >>> 24) & 0xFF;
for(int i = 0, j, a, b; i < toRet.pixels.length; ++i) {
j = toRet.pixels[i];
a = (j >>> 24) & 0xFF;
if(a == 0xFF) a = 0;
toRet.pixels[i] = (toRet.pixels[i] & 0x0000FFFF) | Math.min(a << 18, 0xFF0000) | 0xFF000000;
b = (((j >>> 16) & 0xFF) - 65) * 255 / 190;
if(b < 0) b = 0;
toRet.pixels[i] = (j & 0x0000FFFF) | Math.min(a << 18, 0xFF0000) | ((255 - b) << 24);
}
}
return toRet;
@ -74,7 +76,7 @@ public class PBRTextureMapUtils {
}catch(Throwable t) {
}
try {
return EaglerBitwisePackedTexture.loadTextureSafe(resMgr.getResource(new ResourceLocation("eagler:glsl/deferred/assets_pbr/" + fname + ".ebp")).getInputStream(), 255);
return EaglerBitwisePackedTexture.loadTextureSafe(resMgr.getResource(new ResourceLocation("eagler:glsl/deferred/assets_pbr/" + fname + ".ebp")).getInputStream());
}catch(Throwable t) {
// dead code because teavm
t.toString();

View File

@ -70,7 +70,7 @@ public class ClientV5MessageHandler extends ClientV4MessageHandler {
}
public void handleServer(SPacketClientStateFlagV5EAG packet) {
StateFlags.setFlag(new EaglercraftUUID(packet.uuidMost, packet.uuidLeast), packet.state);
StateFlags.setFlag(netHandler, new EaglercraftUUID(packet.uuidMost, packet.uuidLeast), packet.state);
}
public void handleServer(SPacketDisplayWebViewURLV5EAG packet) {

View File

@ -17,6 +17,7 @@
package net.lax1dude.eaglercraft.v1_8.socket.protocol.client;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.minecraft.client.network.NetHandlerPlayClient;
public class StateFlags {
@ -29,18 +30,23 @@ public class StateFlags {
public static final EaglercraftUUID DISABLE_SKIN_URL_LOOKUP = new EaglercraftUUID(0xC41D641BE2DA4094L,
0xB1B2DFF2E9D08180L);
public static final EaglercraftUUID SET_MAX_MULTI_PACKET = new EaglercraftUUID(0x877BC5F5A2154DDBL,
0xB493BE790A763E90L);
public static boolean eaglerPlayerFlag = false;
public static boolean eaglerPlayerFlagSupervisor = false;
public static boolean disableSkinURLLookup = false;
public static void setFlag(EaglercraftUUID flag, int value) {
public static void setFlag(NetHandlerPlayClient handler, EaglercraftUUID flag, int value) {
if (flag.equals(EAGLER_PLAYER_FLAG_PRESENT)) {
eaglerPlayerFlag = (value & 1) != 0;
eaglerPlayerFlagSupervisor = (value & 2) != 0;
} else if (flag.equals(DISABLE_SKIN_URL_LOOKUP)) {
disableSkinURLLookup = value != 0;
} else if (flag.equals(SET_MAX_MULTI_PACKET)) {
handler.getEaglerMessageController().setMaxMultiPacket(value);
}
}

View File

@ -57,6 +57,9 @@ public class InjectedMessageController extends MessageController {
byteInputStreamSingleton.feedBuffer(data, offset);
inputStreamSingleton.readByte();
if(data[offset + 1] == (byte) 0xFF) {
if(inputStreamSingleton.available() > 32768) {
throw new IOException("Impossible large multi-packet received: " + inputStreamSingleton.available());
}
inputStreamSingleton.readByte();
int count = inputStreamSingleton.readVarInt();
for(int i = 0, j, k; i < count; ++i) {
@ -134,7 +137,7 @@ public class InjectedMessageController extends MessageController {
lastLen = GamePacketOutputBuffer.getVarIntSize(i) + i;
totalLen += lastLen;
++sendCount;
}while(totalLen < 32760 && sendCount < total - start);
}while(totalLen < 32760 && sendCount < total - start && sendCount < maxMultiPacket);
if(totalLen >= 32760) {
--sendCount;
totalLen -= lastLen;

View File

@ -138,7 +138,7 @@ public class LegacyMessageController extends MessageController {
lastLen = GamePacketOutputBuffer.getVarIntSize(i) + i;
totalLen += lastLen;
++sendCount;
}while(totalLen < 32760 && sendCount < total - start);
}while(totalLen < 32760 && sendCount < total - start && sendCount < maxMultiPacket);
if(totalLen >= 32760) {
--sendCount;
totalLen -= lastLen;

View File

@ -37,6 +37,7 @@ public abstract class MessageController {
protected final int sendDirection;
protected final int receiveDirection;
protected List<GameMessagePacket> sendQueue;
protected int maxMultiPacket = 64;
public MessageController(GamePluginMessageProtocol protocol, GameMessageHandler handler, int direction) {
this.protocol = protocol;
@ -57,6 +58,10 @@ public abstract class MessageController {
return sendQueue != null;
}
public void setMaxMultiPacket(int max) {
this.maxMultiPacket = max;
}
public void sendPacket(GameMessagePacket packet) {
if(sendQueue != null) {
sendQueue.add(packet);

View File

@ -227,9 +227,11 @@ public class PacketBufferInputWrapper implements GamePacketInputBuffer {
}
@Override
public byte[] readByteArrayMC() throws IOException {
public byte[] readByteArrayMC(int maxLen) throws IOException {
try {
return buffer.readByteArray();
return buffer.readByteArray(maxLen);
}catch(DecoderException ex) {
throw new IOException(ex.getMessage());
}catch(IndexOutOfBoundsException ex) {
throw new EOFException();
}

View File

@ -18,6 +18,7 @@ package net.lax1dude.eaglercraft.v1_8.sp.server.export;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
@ -67,13 +68,13 @@ public class EPKDecompiler implements Closeable {
throw new IOException("Unknown or invalid EPK version: " + vers);
}
IOUtils.skipFully(is, is.read()); // skip filename
IOUtils.skipFully(is, loadByte(is)); // skip filename
IOUtils.skipFully(is, loadShort(is)); // skip comment
IOUtils.skipFully(is, 8); // skip millis date
numFiles = loadInt(is);
char compressionType = (char)is.read();
char compressionType = (char)loadByte(is);
switch(compressionType) {
case 'G':
@ -137,7 +138,7 @@ public class EPKDecompiler implements Closeable {
throw new IOException("File '" + name + "' has an invalid checksum");
}
if(zis.read() != ':') {
if(loadByte(zis) != ':') {
throw new IOException("File '" + name + "' is incomplete");
}
}else {
@ -145,7 +146,7 @@ public class EPKDecompiler implements Closeable {
IOUtils.readFully(zis, data);
}
if(zis.read() != '>') {
if(loadByte(zis) != '>') {
throw new IOException("Object '" + name + "' is incomplete");
}
@ -155,15 +156,23 @@ public class EPKDecompiler implements Closeable {
}
}
public static final int loadShort(InputStream is) throws IOException {
return (is.read() << 8) | is.read();
public static int loadByte(InputStream is) throws IOException {
int i = is.read();
if (i < 0) {
throw new EOFException();
}
return i;
}
public static final int loadInt(InputStream is) throws IOException {
return (is.read() << 24) | (is.read() << 16) | (is.read() << 8) | is.read();
public static int loadShort(InputStream is) throws IOException {
return (loadByte(is) << 8) | loadByte(is);
}
public static final String readASCII(byte[] bytesIn) throws IOException {
public static int loadInt(InputStream is) throws IOException {
return (loadByte(is) << 24) | (loadByte(is) << 16) | (loadByte(is) << 8) | loadByte(is);
}
public static String readASCII(byte[] bytesIn) throws IOException {
char[] charIn = new char[bytesIn.length];
for(int i = 0; i < bytesIn.length; ++i) {
charIn[i] = (char)((int)bytesIn[i] & 0xFF);
@ -171,11 +180,11 @@ public class EPKDecompiler implements Closeable {
return new String(charIn);
}
public static final String readASCII(InputStream bytesIn) throws IOException {
int len = bytesIn.read();
public static String readASCII(InputStream bytesIn) throws IOException {
int len = loadByte(bytesIn);
char[] charIn = new char[len];
for(int i = 0; i < len; ++i) {
charIn[i] = (char)(bytesIn.read() & 0xFF);
charIn[i] = (char)loadByte(bytesIn);
}
return new String(charIn);
}