Port to 26.3 (#3403)

Co-authored-by: XFactHD <[email protected]>
Co-authored-by: Technici4n <[email protected]>
Co-authored-by: sciwhiz12 <[email protected]>
Co-authored-by: Matyrobbrt <[email protected]>
Co-authored-by: Marc Hermans <[email protected]>
Co-authored-by: Sara Freimer <[email protected]>
This commit is contained in:
Apex
2026-09-16 03:08:09 +08:00
committed by GitHub
co-authored by XFactHD Technici4n sciwhiz12 Matyrobbrt Marc Hermans Sara Freimer
parent 1ad7d233fc
commit b160270bd5
826 changed files with 8468 additions and 14060 deletions
+2 -2
View File
@@ -39,8 +39,8 @@ jobs:
- name: Run JUnit tests with Gradle
run: ./gradlew :tests:runUnitTests
- name: Install software OpenGL rendering
run: sudo apt-get install xvfb libgl1-mesa-dri
- name: Install software Vulkan rendering
run: sudo apt-get install xvfb mesa-vulkan-drivers
- name: Run production client self-test
run: xvfb-run ./gradlew :neoforge:testProductionClient
@@ -96,16 +96,21 @@ abstract class CreateUserDevConfig extends DefaultTask {
systemProperties.put("neoforge.enableGameTest", "true");
}
List<String> jvmArgs = new ArrayList<>(List.of(
"--sun-misc-unsafe-memory-access=allow",
"--enable-native-access=ALL-UNNAMED",
"--add-opens", "java.base/java.lang.invoke=ALL-UNNAMED",
"--add-exports", "jdk.naming.dns/com.sun.jndi.dns=java.naming"));
if (runType == RunType.CLIENT) {
jvmArgs.add("-XX:StackShadowPages=32");
}
config.runs().put(runType.jsonName, new UserDevRunType(
runType != RunType.JUNIT,
// Archloom crashes when reading a userconfig without a main class
Objects.requireNonNullElse(runType.mainClass, "NONE"),
args,
List.of(
"--sun-misc-unsafe-memory-access=allow",
"--enable-native-access=ALL-UNNAMED",
"--add-opens", "java.base/java.lang.invoke=ALL-UNNAMED",
"--add-exports", "jdk.naming.dns/com.sun.jndi.dns=java.naming"),
jvmArgs,
runType == RunType.CLIENT || runType == RunType.JUNIT || runType == RunType.CLIENT_DATA,
runType == RunType.GAME_TEST_SERVER || runType == RunType.SERVER || runType == RunType.SERVER_DATA,
runType == RunType.CLIENT_DATA || runType == RunType.SERVER_DATA,
+4 -4
View File
@@ -16,11 +16,11 @@ diffpatch_version=2.1.0.43
java_version=25
minecraft_version=26.2
neoform_version=2
minecraft_version=26.3
neoform_version=1
# on snapshot versions, used to prefix the version
# should always have 3 components (major.minor.hotfix)
neoforge_snapshot_next_stable=26.2
neoforge_snapshot_next_stable=26.3
# renovate: net.neoforged.jst:jst-cli-bundle
jst_version=2.0.11
@@ -40,7 +40,7 @@ nightconfig_version=3.9.0
jetbrains_annotations_version=24.1.0
apache_maven_artifact_version=3.9.16
jarjar_version=0.5.1
fancy_mod_loader_version=11.0.16
fancy_mod_loader_version=12.0.0
typetools_version=0.6.3
mixin_extras_version=0.5.4
@@ -1,83 +0,0 @@
--- a/com/mojang/blaze3d/opengl/GlCommandEncoder.java
+++ b/com/mojang/blaze3d/opengl/GlCommandEncoder.java
@@ -239,7 +_,8 @@
@Override
public void clearDepthTexture(GpuTexture depthTexture, double clearDepth) {
- this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)depthTexture).id, 0, 36160);
+ boolean hasStencil = depthTexture.getFormat().hasStencilAspect();
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)depthTexture).id, 0, 36160, hasStencil);
GL33C.glDrawBuffer(0);
GL33C.glClearDepth(clearDepth);
GlStateManager._depthMask(true);
@@ -251,6 +_,17 @@
}
@Override
+ public void clearStencilTexture(GpuTexture texture, int value) {
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)texture).id, 0, GlConst.GL_FRAMEBUFFER, true);
+ GL33C.glDrawBuffer(GlConst.GL_NONE);
+ GL33C.glClearStencil(value);
+ GlStateManager._depthMask(true);
+ GlStateManager._clear(GL33C.GL_STENCIL_BUFFER_BIT);
+ GL33C.glDrawBuffer(GlConst.GL_COLOR_ATTACHMENT0);
+ GlStateManager._glBindFramebuffer(GlConst.GL_FRAMEBUFFER, 0);
+ }
+
+ @Override
public void writeToBuffer(GpuBufferSlice slice, ByteBuffer data) {
GlBuffer buffer = (GlBuffer)slice.buffer();
buffer.checkCanBeUsed();
@@ -364,11 +_,22 @@
boolean isDepth = source.getFormat().hasDepthAspect();
int sourceId = ((GlTexture)source).glId();
int destId = ((GlTexture)destination).glId();
- this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, isDepth ? 0 : sourceId, isDepth ? sourceId : 0, 0, 0);
- this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, isDepth ? 0 : destId, isDepth ? destId : 0, 0, 0);
+ boolean hasStencil = source.getFormat().hasStencilAspect();
+ this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, isDepth ? 0 : sourceId, isDepth ? sourceId : 0, 0, 0, hasStencil);
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, isDepth ? 0 : destId, isDepth ? destId : 0, 0, 0, hasStencil);
+ int bufferMask = 0;
+ if (source.getFormat().hasColorAspect()) {
+ bufferMask |= GlConst.GL_COLOR_BUFFER_BIT;
+ }
+ if (source.getFormat().hasDepthAspect()) {
+ bufferMask |= GlConst.GL_DEPTH_BUFFER_BIT;
+ }
+ if (source.getFormat().hasStencilAspect()) {
+ bufferMask |= GL33C.GL_STENCIL_BUFFER_BIT;
+ }
this.device
.directStateAccess()
- .blitFrameBuffers(this.readFbo, this.drawFbo, sourceX, sourceY, width, height, destX, destY, width, height, isDepth ? 256 : 16384, 9728);
+ .blitFrameBuffers(this.readFbo, this.drawFbo, sourceX, sourceY, width, height, destX, destY, width, height, bufferMask, 9728);
int error = GlStateManager._getError();
if (error != 0) {
throw new IllegalStateException(
@@ -763,6 +_,26 @@
GlStateManager._scissorBox(renderPass.getScissorX(), renderPass.getScissorY(), renderPass.getScissorWidth(), renderPass.getScissorHeight());
} else {
GlStateManager._disableScissorTest();
+ }
+
+ var stencilTestOpt = renderPass.pipeline.info().getStencilTest();
+ if (stencilTestOpt.isPresent()) {
+ var stencilTest = stencilTestOpt.get();
+ GlStateManager._enableStencilTest();
+ var front = stencilTest.front();
+ var back = stencilTest.back();
+ if (front.equals(back)) {
+ GlStateManager._stencilFunc(GlConst.toGl(front.compare()), stencilTest.referenceValue(), stencilTest.readMask());
+ GlStateManager._stencilOp(GlConst.toGl(front.fail()), GlConst.toGl(front.depthFail()), GlConst.toGl(front.pass()));
+ } else {
+ GlStateManager._stencilFuncFront(GlConst.toGl(front.compare()), stencilTest.referenceValue(), stencilTest.readMask());
+ GlStateManager._stencilFuncBack(GlConst.toGl(back.compare()), stencilTest.referenceValue(), stencilTest.readMask());
+ GlStateManager._stencilOpFront(GlConst.toGl(front.fail()), GlConst.toGl(front.depthFail()), GlConst.toGl(front.pass()));
+ GlStateManager._stencilOpBack(GlConst.toGl(back.fail()), GlConst.toGl(back.depthFail()), GlConst.toGl(back.pass()));
+ }
+ GlStateManager._stencilMask(stencilTest.writeMask());
+ } else {
+ GlStateManager._disableStencilTest();
}
return true;
@@ -1,31 +0,0 @@
--- a/com/mojang/blaze3d/opengl/GlRenderPass.java
+++ b/com/mojang/blaze3d/opengl/GlRenderPass.java
@@ -24,7 +_,7 @@
@OnlyIn(Dist.CLIENT)
class GlRenderPass implements RenderPassBackend {
- public static final boolean VALIDATION = SharedConstants.IS_RUNNING_IN_IDE;
+ public static final boolean VALIDATION = SharedConstants.IS_RUNNING_IN_IDE && !Boolean.getBoolean("neoforge.disableGlValidation");
private final GlCommandEncoder encoder;
private final GlDevice device;
private final boolean hasDepthTexture;
@@ -65,6 +_,7 @@
@Override
public void setPipeline(RenderPipeline pipeline) {
+ pipeline = com.mojang.blaze3d.systems.RenderSystem.applyPipelineModifiers(pipeline);
if (this.pipeline == null || this.pipeline.info() != pipeline) {
this.dirtyUniforms.addAll(this.uniforms.keySet());
this.dirtyUniforms.addAll(this.samplers.keySet());
@@ -94,6 +_,11 @@
public void setUniform(String name, GpuBufferSlice value) {
this.uniforms.put(name, value);
this.dirtyUniforms.add(name);
+ }
+
+ @Override
+ public void setViewport(int x, int y, int width, int height) {
+ GlStateManager._viewport(x, y, width, height);
}
@Override
@@ -1,14 +0,0 @@
--- a/com/mojang/blaze3d/opengl/GlTexture.java
+++ b/com/mojang/blaze3d/opengl/GlTexture.java
@@ -75,6 +_,11 @@
this.fboKeys.remove(fboKey);
}
+ @Override
+ public boolean hasStencilAspect() {
+ return this.getFormat().hasStencilAspect();
+ }
+
public void addViews() {
this.views++;
}
@@ -4,22 +4,12 @@
private static final MainTarget.Dimension DEFAULT_DIMENSIONS = new MainTarget.Dimension(854, 480);
public MainTarget(int desiredWidth, int desiredHeight) {
- super("Main", true, GpuFormat.RGBA8_UNORM);
+ this(desiredWidth, desiredHeight, false);
- super("Main", GpuFormat.RGBA8_UNORM, GpuFormat.D32_FLOAT);
+ this(desiredWidth, desiredHeight, GpuFormat.D32_FLOAT);
+ }
+
+ public MainTarget(int desiredWidth, int desiredHeight, boolean useStencil) {
+ super("Main", true, useStencil, GpuFormat.RGBA8_UNORM);
+ public MainTarget(int desiredWidth, int desiredHeight, GpuFormat depthFormat) {
+ super("Main", GpuFormat.RGBA8_UNORM, depthFormat);
this.createFrameBuffer(desiredWidth, desiredHeight);
}
@@ -84,7 +_,8 @@
private @Nullable GpuTexture allocateDepthAttachment(MainTarget.Dimension dimension) {
try {
- return RenderSystem.getDevice().createTexture(() -> this.label + " / Depth", 15, GpuFormat.D32_FLOAT, dimension.width, dimension.height, 1, 1);
+ var format = this.useStencil ? net.neoforged.neoforge.client.ClientHooks.getStencilFormat() : GpuFormat.D32_FLOAT;
+ return RenderSystem.getDevice().createTexture(() -> this.label + " / Depth", 15, format, dimension.width, dimension.height, 1, 1);
} catch (GpuOutOfMemoryException ignored) {
return null;
}
@@ -1,195 +0,0 @@
--- a/com/mojang/blaze3d/pipeline/RenderPipeline.java
+++ b/com/mojang/blaze3d/pipeline/RenderPipeline.java
@@ -30,21 +_,42 @@
private final @Nullable ColorTargetState[] colorTargetStates;
private final @Nullable VertexFormat[] vertexFormatPerBuffer = new VertexFormat[16];
private final PrimitiveTopology primitiveTopology;
+ private final Optional<net.neoforged.neoforge.client.stencil.StencilTest> stencilTest;
private final int sortKey;
private static int sortKeySeed;
- protected RenderPipeline(
- Identifier location,
- Identifier vertexShader,
- Identifier fragmentShader,
- ShaderDefines shaderDefines,
- List<BindGroupLayout> bindGroupLayouts,
- @Nullable ColorTargetState[] colorTargetStates,
- @Nullable DepthStencilState depthStencilState,
- PolygonMode polygonMode,
- boolean cull,
- @Nullable VertexFormat[] vertexFormatPerBuffer,
- PrimitiveTopology primitiveTopology,
+ /// @deprecated Neo: use [#RenderPipeline(Identifier, Identifier, Identifier, ShaderDefines, List, ColorTargetState\[\], DepthStencilState, PolygonMode, boolean, VertexFormat\[\], PrimitiveTopology, Optional, int)] instead
+ @Deprecated
+ protected RenderPipeline(
+ Identifier location,
+ Identifier vertexShader,
+ Identifier fragmentShader,
+ ShaderDefines shaderDefines,
+ List<BindGroupLayout> bindGroupLayouts,
+ @Nullable ColorTargetState[] colorTargetStates,
+ @Nullable DepthStencilState depthStencilState,
+ PolygonMode polygonMode,
+ boolean cull,
+ @Nullable VertexFormat[] vertexFormatPerBuffer,
+ PrimitiveTopology primitiveTopology,
+ int sortKey
+ ) {
+ this(location, vertexShader, fragmentShader, shaderDefines, bindGroupLayouts, colorTargetStates, depthStencilState, polygonMode, cull, vertexFormatPerBuffer, primitiveTopology, Optional.empty(), sortKey);
+ }
+
+ protected RenderPipeline(
+ Identifier location,
+ Identifier vertexShader,
+ Identifier fragmentShader,
+ ShaderDefines shaderDefines,
+ List<BindGroupLayout> bindGroupLayouts,
+ @Nullable ColorTargetState[] colorTargetStates,
+ @Nullable DepthStencilState depthStencilState,
+ PolygonMode polygonMode,
+ boolean cull,
+ @Nullable VertexFormat[] vertexFormatPerBuffer,
+ PrimitiveTopology primitiveTopology,
+ Optional<net.neoforged.neoforge.client.stencil.StencilTest> stencilTest,
int sortKey
) {
this.location = location;
@@ -57,6 +_,7 @@
this.cull = cull;
this.colorTargetStates = colorTargetStates;
this.primitiveTopology = primitiveTopology;
+ this.stencilTest = stencilTest;
this.sortKey = sortKey;
System.arraycopy(vertexFormatPerBuffer, 0, this.vertexFormatPerBuffer, 0, this.vertexFormatPerBuffer.length);
}
@@ -130,6 +_,48 @@
return this.depthStencilState != null;
}
+ public Optional<net.neoforged.neoforge.client.stencil.StencilTest> getStencilTest() {
+ return stencilTest;
+ }
+
+ /**
+ * Neo: Create a {@link RenderPipeline.Builder} from this {@link RenderPipeline} to adjust its configuration and
+ * build a new, modified {@link RenderPipeline} from it
+ */
+ public RenderPipeline.Builder toBuilder() {
+ RenderPipeline.Builder builder = new RenderPipeline.Builder();
+ builder.location = Optional.of(this.location);
+ builder.fragmentShader = Optional.of(this.fragmentShader);
+ builder.vertexShader = Optional.of(this.vertexShader);
+ if (!this.shaderDefines.isEmpty()) {
+ ShaderDefines.Builder defBuilder = ShaderDefines.builder();
+ for (Entry<String, String> entry : this.shaderDefines.values().entrySet()) {
+ defBuilder.define(entry.getKey(), entry.getValue());
+ }
+ for (String flag : this.shaderDefines.flags()) {
+ defBuilder.define(flag);
+ }
+ builder.definesBuilder = Optional.of(defBuilder);
+ }
+ if (!this.bindGroupLayouts.isEmpty()) {
+ builder.bindGroupLayouts = Optional.of(new ArrayList<>(this.bindGroupLayouts));
+ }
+ builder.depthStencilState = Optional.ofNullable(this.depthStencilState);
+ builder.polygonMode = Optional.of(this.polygonMode);
+ builder.cull = Optional.of(this.cull);
+ System.arraycopy(this.colorTargetStates, 0, builder.colorTargetStates, 0, this.colorTargetStates.length);
+ int activeColorTargetStateCount = 0;
+ for (int i = 0; i < this.colorTargetStates.length; i++) {
+ if (this.colorTargetStates[i] != null) {
+ activeColorTargetStateCount = i + 1;
+ }
+ }
+ System.arraycopy(this.vertexFormatPerBuffer, 0, builder.vertexFormatPerBuffer, 0, this.vertexFormatPerBuffer.length);
+ builder.primitiveTopology = Optional.of(this.primitiveTopology);
+ builder.stencilTest = this.stencilTest;
+ return builder;
+ }
+
public static RenderPipeline.Builder builder(RenderPipeline.Snippet... snippets) {
RenderPipeline.Builder builder = new RenderPipeline.Builder();
@@ -154,6 +_,7 @@
private int activeColorTargetStateCount;
private final @Nullable VertexFormat[] vertexFormatPerBuffer = new VertexFormat[16];
private Optional<PrimitiveTopology> primitiveTopology = Optional.empty();
+ private Optional<net.neoforged.neoforge.client.stencil.StencilTest> stencilTest = Optional.empty();
private Builder() {
}
@@ -270,6 +_,16 @@
return this;
}
+ public RenderPipeline.Builder withStencilTest(net.neoforged.neoforge.client.stencil.StencilTest stencilTest) {
+ this.stencilTest = Optional.of(stencilTest);
+ return this;
+ }
+
+ public RenderPipeline.Builder withoutStencilTest(){
+ this.stencilTest = Optional.empty();
+ return this;
+ }
+
private void withSnippet(RenderPipeline.Snippet snippet) {
if (snippet.vertexShader.isPresent()) {
this.vertexShader = snippet.vertexShader;
@@ -332,6 +_,10 @@
if (snippet.polygonMode.isPresent()) {
this.polygonMode = snippet.polygonMode;
}
+
+ if (snippet.stencilTest.isPresent()) {
+ this.stencilTest = snippet.stencilTest;
+ }
}
public RenderPipeline.Snippet buildSnippet() {
@@ -346,7 +_,8 @@
this.polygonMode,
this.cull,
this.vertexFormatPerBuffer,
- this.primitiveTopology
+ this.primitiveTopology,
+ this.stencilTest
);
}
@@ -411,6 +_,7 @@
this.cull.orElse(true),
this.vertexFormatPerBuffer,
this.primitiveTopology.get(),
+ this.stencilTest,
nextPipelineSortKey++
);
}
@@ -428,7 +_,25 @@
Optional<PolygonMode> polygonMode,
Optional<Boolean> cull,
@Nullable VertexFormat[] vertexFormatPerBuffer,
- Optional<PrimitiveTopology> vertexFormatMode
+ Optional<PrimitiveTopology> vertexFormatMode,
+ Optional<net.neoforged.neoforge.client.stencil.StencilTest> stencilTest
) {
+ /// @deprecated Neo: use [#Snippet(Optional, Optional, Optional, Optional, ColorTargetState\[\], int, Optional, Optional, Optional, VertexFormat\[\], Optional, Optional)] instead
+ @Deprecated
+ public Snippet(
+ Optional<Identifier> vertexShader,
+ Optional<Identifier> fragmentShader,
+ Optional<ShaderDefines> shaderDefines,
+ Optional<List<BindGroupLayout>> bindGroupLayouts,
+ @Nullable ColorTargetState[] colorTargetStates,
+ int activeColorTargetStateCount,
+ Optional<DepthStencilState> depthStencilState,
+ Optional<PolygonMode> polygonMode,
+ Optional<Boolean> cull,
+ @Nullable VertexFormat[] vertexFormatPerBuffer,
+ Optional<PrimitiveTopology> vertexFormatMode
+ ) {
+ this(vertexShader, fragmentShader, shaderDefines, bindGroupLayouts, colorTargetStates, activeColorTargetStateCount, depthStencilState, polygonMode, cull, vertexFormatPerBuffer, vertexFormatMode, Optional.empty());
+ }
}
}
@@ -1,37 +0,0 @@
--- a/com/mojang/blaze3d/pipeline/RenderTarget.java
+++ b/com/mojang/blaze3d/pipeline/RenderTarget.java
@@ -21,6 +_,7 @@
public int height;
protected final String label;
public final boolean useDepth;
+ public final boolean useStencil;
protected final GpuFormat format;
protected @Nullable GpuTexture colorTexture;
protected @Nullable GpuTextureView colorTextureView;
@@ -28,8 +_,16 @@
protected @Nullable GpuTextureView depthTextureView;
public RenderTarget(@Nullable String label, boolean useDepth, GpuFormat format) {
+ this(label, useDepth, false, format);
+ }
+
+ public RenderTarget(@Nullable String label, boolean useDepth, boolean useStencil, GpuFormat format) {
+ if (useStencil && !useDepth) {
+ throw new IllegalArgumentException("Stencil can only be enabled if depth is enabled.");
+ }
this.label = label == null ? "FBO " + UNNAMED_RENDER_TARGETS++ : label;
this.useDepth = useDepth;
+ this.useStencil = useStencil;
this.format = format;
}
@@ -83,7 +_,8 @@
this.width = width;
this.height = height;
if (this.useDepth) {
- this.depthTexture = device.createTexture(() -> this.label + " / Depth", 15, GpuFormat.D32_FLOAT, width, height, 1, 1);
+ var format = this.useStencil ? net.neoforged.neoforge.client.ClientHooks.getStencilFormat() : GpuFormat.D32_FLOAT;
+ this.depthTexture = device.createTexture(() -> this.label + " / Depth", 15, format, width, height, 1, 1);
this.depthTextureView = device.createTextureView(this.depthTexture);
}
@@ -1,15 +0,0 @@
--- a/com/mojang/blaze3d/pipeline/TextureTarget.java
+++ b/com/mojang/blaze3d/pipeline/TextureTarget.java
@@ -9,7 +_,11 @@
@OnlyIn(Dist.CLIENT)
public class TextureTarget extends RenderTarget {
public TextureTarget(@Nullable String label, int width, int height, boolean useDepth, GpuFormat format) {
- super(label, useDepth, format);
+ this(label, width, height, useDepth, false, format);
+ }
+
+ public TextureTarget(@Nullable String label, int width, int height, boolean useDepth, boolean useStencil, GpuFormat format) {
+ super(label, useDepth, useStencil, format);
RenderSystem.assertOnRenderThread();
this.resize(width, height);
}
@@ -1,47 +0,0 @@
--- a/com/mojang/blaze3d/platform/Window.java
+++ b/com/mojang/blaze3d/platform/Window.java
@@ -102,6 +_,16 @@
this.windowedWidth = this.width = allowedWindowMinSize(displayData.width());
this.windowedHeight = this.height = allowedWindowMinSize(displayData.height());
this.handle = this.createWindow(backend, this.width, this.height, title, this.fullscreen && initialMonitor != null ? initialMonitor.monitor() : 0L);
+ // Neo: If the window was taken over from EarlyLoadingScreen, inherit a potentially resized window size
+ var earlyLoadingScreen = net.neoforged.fml.loading.EarlyLoadingScreenController.current();
+ if (earlyLoadingScreen != null) {
+ var width = new int[1];
+ var height = new int[1];
+ GLFW.glfwGetWindowSize(this.handle, width, height);
+ // The window height and width can be 0 if minimized
+ this.width = this.windowedWidth = Math.max(width[0], 1);
+ this.height = this.windowedHeight = Math.max(height[0], 1);
+ }
this.backend = backend;
if (initialMonitor != null) {
VideoMode mode = initialMonitor.getPreferredVidMode(this.fullscreen ? this.preferredFullscreenVideoMode : Optional.empty());
@@ -132,6 +_,11 @@
try (GLFWErrorScope var9 = new GLFWErrorScope(glfwErrors)) {
backend.setWindowHints();
GLFW.glfwWindowHint(131076, 0);
+ var earlyLoadingScreen = net.neoforged.fml.loading.EarlyLoadingScreenController.current();
+ if (earlyLoadingScreen != null) {
+ windowHandle = earlyLoadingScreen.takeOverGlfwWindow();
+ GLFW.glfwSetWindowTitle(windowHandle, title);
+ } else
windowHandle = GLFW.glfwCreateWindow(width, height, title, monitor, 0L);
if (windowHandle == 0L) {
backend.handleWindowCreationErrors(glfwErrors.firstError());
@@ -237,11 +_,11 @@
}
public void defaultErrorCallback(int errorCode, long description) {
- if (!RenderSystem.isOnRenderThread()) {
- LOGGER.error("Error callback from invalid thread ({})", Thread.currentThread().getName());
- }
-
String errorString = MemoryUtil.memUTF8(description);
+ if (!RenderSystem.isOnRenderThread()) {
+ LOGGER.error("Error callback from invalid thread ({}): {}: {}", Thread.currentThread().getName(), errorCode, errorString);
+ }
+
LOGGER.error("########## GL ERROR ##########");
LOGGER.error("@ {}", this.errorSection);
LOGGER.error("{}: {}", errorCode, errorString);
@@ -1,37 +0,0 @@
--- a/com/mojang/blaze3d/resource/RenderTargetDescriptor.java
+++ b/com/mojang/blaze3d/resource/RenderTargetDescriptor.java
@@ -9,10 +_,14 @@
import org.joml.Vector4fc;
@OnlyIn(Dist.CLIENT)
-public record RenderTargetDescriptor(int width, int height, boolean useDepth, Vector4fc clearColor, GpuFormat format)
+public record RenderTargetDescriptor(int width, int height, boolean useDepth, boolean useStencil, Vector4fc clearColor, GpuFormat format)
implements ResourceDescriptor<RenderTarget> {
+ public RenderTargetDescriptor(int width, int height, boolean useDepth, Vector4fc clearColor, GpuFormat format) {
+ this(width, height, useDepth, false, clearColor, format);
+ }
+
public RenderTarget allocate() {
- return new TextureTarget(null, this.width, this.height, this.useDepth, this.format);
+ return new TextureTarget(null, this.width, this.height, this.useDepth, this.useStencil, this.format);
}
public void prepare(RenderTarget resource) {
@@ -23,6 +_,9 @@
} else {
RenderSystem.getDevice().createCommandEncoder().clearColorTexture(resource.getColorTexture(), this.clearColor);
}
+ if (this.useStencil) {
+ RenderSystem.getDevice().createCommandEncoder().clearStencilTexture(resource.getDepthTexture(), 0);
+ }
}
public void free(RenderTarget resource) {
@@ -33,6 +_,6 @@
public boolean canUsePhysicalResource(ResourceDescriptor<?> other) {
return !(other instanceof RenderTargetDescriptor descriptor)
? false
- : this.width == descriptor.width && this.height == descriptor.height && this.useDepth == descriptor.useDepth && this.format == descriptor.format;
+ : this.width == descriptor.width && this.height == descriptor.height && this.useDepth == descriptor.useDepth && this.format == descriptor.format && this.useStencil == descriptor.useStencil;
}
}
@@ -1,19 +0,0 @@
--- a/com/mojang/blaze3d/systems/RenderPass.java
+++ b/com/mojang/blaze3d/systems/RenderPass.java
@@ -116,6 +_,16 @@
this.backend.setUniform(name, value);
}
+ public void setViewport(int x, int y, int width, int height) {
+ if (width < 0 || height < 0) {
+ throw new IllegalArgumentException("Viewport size must be >0, was " + width + "x" + height);
+ }
+ if (x < this.renderArea.x() || y < this.renderArea.y() || x + width > this.renderArea.x() + this.renderArea.width() || y + height > this.renderArea.height()) {
+ throw new IllegalArgumentException("Viewport at " + x + ", " + y + " with size " + width + "x" + height + " is out of bounds for render area " + this.renderArea);
+ }
+ this.backend.setViewport(x, y, width, height);
+ }
+
public void enableScissor(int x, int y, int width, int height) {
if (width > 0 && height > 0) {
if (x >= this.renderArea.x()
@@ -1,11 +0,0 @@
--- a/com/mojang/blaze3d/systems/RenderPassBackend.java
+++ b/com/mojang/blaze3d/systems/RenderPassBackend.java
@@ -28,6 +_,8 @@
void setUniform(final String name, final GpuBufferSlice value);
+ void setViewport(int x, int y, int width, int height);
+
void enableScissor(final int x, final int y, final int width, final int height);
void disableScissor();
@@ -1,14 +1,23 @@
--- a/com/mojang/blaze3d/systems/RenderSystem.java
+++ b/com/mojang/blaze3d/systems/RenderSystem.java
@@ -71,6 +_,7 @@
private static @Nullable DynamicUniforms dynamicUniforms;
private static final ScissorState scissorStateForRenderTypeDraws = new ScissorState();
@@ -83,6 +_,7 @@
private static final SamplerCache samplerCache = new SamplerCache();
private static @Nullable PipelineCache fallbackPipelineCache;
private static @Nullable PipelineCache currentPipelineCache;
+ private static final net.neoforged.neoforge.client.pipeline.PipelineModifierStack PIPELINE_MODIFIERS = new net.neoforged.neoforge.client.pipeline.PipelineModifierStack();
public static SamplerCache getSamplerCache() {
return samplerCache;
@@ -377,5 +_,33 @@
@@ -103,6 +_,8 @@
}
public static @Nullable CompiledRenderPipeline getCompiledPipelineNullable(RenderPipeline pipeline) {
+ pipeline = PIPELINE_MODIFIERS.apply(pipeline);
+
if (currentPipelineCache != null) {
CompiledRenderPipeline cachedPipeline = currentPipelineCache.get(pipeline);
if (cachedPipeline != null) {
@@ -491,5 +_,28 @@
}
private record GpuAsyncTask(Runnable callback, GpuFence fence) {
@@ -33,11 +42,6 @@
+ }
+
+ @org.jetbrains.annotations.ApiStatus.Internal
+ public static com.mojang.blaze3d.pipeline.RenderPipeline applyPipelineModifiers(com.mojang.blaze3d.pipeline.RenderPipeline pipeline) {
+ return PIPELINE_MODIFIERS.apply(pipeline);
+ }
+
+ @org.jetbrains.annotations.ApiStatus.Internal
+ public static void ensurePipelineModifiersEmpty() {
+ PIPELINE_MODIFIERS.ensureEmpty();
}
@@ -1,6 +1,6 @@
--- a/com/mojang/blaze3d/vertex/VertexConsumer.java
+++ b/com/mojang/blaze3d/vertex/VertexConsumer.java
@@ -59,7 +_,7 @@
@@ -62,7 +_,7 @@
for (int vertex = 0; vertex < 4; vertex++) {
Vector3fc pos = quad.position(vertex);
long packedUv = quad.packedUV(vertex);
@@ -9,7 +9,7 @@
int light = instance.getLightCoordsWithEmission(vertex, lightEmission);
float u = UVPair.unpackU(packedUv);
float v = UVPair.unpackV(packedUv);
@@ -76,11 +_,12 @@
@@ -79,11 +_,12 @@
for (int vertex = 0; vertex < 4; vertex++) {
Vector3fc position = quad.position(vertex);
long packedUv = quad.packedUV(vertex);
@@ -1,26 +0,0 @@
--- a/com/mojang/blaze3d/vulkan/VulkanDevice.java
+++ b/com/mojang/blaze3d/vulkan/VulkanDevice.java
@@ -279,12 +_,12 @@
);
if (vertexShader == IntermediaryShaderModule.INVALID) {
LOGGER.error("Couldn't compile pipeline {}: vertex shader {} was invalid", pipeline.getLocation(), pipeline.getVertexShader());
- return new VulkanRenderPipeline(pipeline, this, 0L, 0L, 0L, VulkanBindGroupLayout.INVALID_LAYOUT, 0L, 0L);
+ return new VulkanRenderPipeline(pipeline, this, 0L, 0L, 0L, 0L, VulkanBindGroupLayout.INVALID_LAYOUT, 0L, 0L);
}
if (fragmentShader == IntermediaryShaderModule.INVALID) {
LOGGER.error("Couldn't compile pipeline {}: fragment shader {} was invalid", pipeline.getLocation(), pipeline.getFragmentShader());
- return new VulkanRenderPipeline(pipeline, this, 0L, 0L, 0L, VulkanBindGroupLayout.INVALID_LAYOUT, 0L, 0L);
+ return new VulkanRenderPipeline(pipeline, this, 0L, 0L, 0L, 0L, VulkanBindGroupLayout.INVALID_LAYOUT, 0L, 0L);
}
try {
@@ -292,7 +_,7 @@
return VulkanRenderPipeline.compile(this, modules.layout(), pipeline, modules.vertex(), modules.fragment());
} catch (ShaderCompileException e) {
LOGGER.error("Couldn't compile pipeline {}: {}", pipeline.getLocation(), e.getMessage());
- return new VulkanRenderPipeline(pipeline, this, 0L, 0L, 0L, VulkanBindGroupLayout.INVALID_LAYOUT, 0L, 0L);
+ return new VulkanRenderPipeline(pipeline, this, 0L, 0L, 0L, 0L, VulkanBindGroupLayout.INVALID_LAYOUT, 0L, 0L);
}
}
@@ -1,53 +0,0 @@
--- a/com/mojang/blaze3d/vulkan/VulkanRenderPipeline.java
+++ b/com/mojang/blaze3d/vulkan/VulkanRenderPipeline.java
@@ -36,6 +_,7 @@
public record VulkanRenderPipeline(
RenderPipeline info,
VulkanDevice device,
+ long withDepthStencilPipeline,
long withDepthPipeline,
long withoutDepthPipeline,
long pipelineLayout,
@@ -152,6 +_,27 @@
depthStencilState.depthCompareOp(VulkanConst.toVk(pipeline.getDepthStencilState().depthTest()));
}
+ if (pipeline.getStencilTest().isPresent()) {
+ final var stencilTest = pipeline.getStencilTest().get();
+ depthStencilState.stencilTestEnable(true);
+ final var frontState = depthStencilState.front();
+ frontState.failOp(VulkanConst.toVk(stencilTest.front().fail()));
+ frontState.passOp(VulkanConst.toVk(stencilTest.front().pass()));
+ frontState.depthFailOp(VulkanConst.toVk(stencilTest.front().depthFail()));
+ frontState.compareOp(VulkanConst.toVk(stencilTest.front().compare()));
+ frontState.compareMask(stencilTest.readMask());
+ frontState.writeMask(stencilTest.writeMask());
+ frontState.reference(stencilTest.referenceValue());
+ final var backState = depthStencilState.back();
+ backState.failOp(VulkanConst.toVk(stencilTest.back().fail()));
+ backState.passOp(VulkanConst.toVk(stencilTest.back().pass()));
+ backState.depthFailOp(VulkanConst.toVk(stencilTest.back().depthFail()));
+ backState.compareOp(VulkanConst.toVk(stencilTest.back().compare()));
+ backState.compareMask(stencilTest.readMask());
+ backState.writeMask(stencilTest.writeMask());
+ backState.reference(stencilTest.referenceValue()); // note: must match front unless portability feature is required and checked for (if on portability device)
+ }
+
ColorTargetState[] colorTargetStates = pipeline.getColorTargetStates();
org.lwjgl.vulkan.VkPipelineColorBlendAttachmentState.Buffer blendAttachments = VkPipelineColorBlendAttachmentState.calloc(
colorTargetStates.length, stack
@@ -219,8 +_,13 @@
} else {
withoutDepthPipeline = 0L;
}
+ renderingInfo.depthAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT);
+ renderingInfo.stencilAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT);
+ VulkanUtils.crashIfFailure(device, VK12.vkCreateGraphicsPipelines(device.vkDevice(), 0L, createInfo, null, pointer), "Can't compile pipeline " + pipeline.getLocation());
+ final long withDepthStencilPipeline = pointer.get(0);
+ device.instance().debug().setObjectName(device.vkDevice(), VK12.VK_OBJECT_TYPE_PIPELINE, withDepthStencilPipeline, () -> "Pipeline " + pipeline.getLocation());
- return new VulkanRenderPipeline(pipeline, device, withDepthPipeline, withoutDepthPipeline, pipelineLayout, layout, vertexModule, fragmentModule);
+ return new VulkanRenderPipeline(pipeline, device, withDepthStencilPipeline, withDepthPipeline, withoutDepthPipeline, pipelineLayout, layout, vertexModule, fragmentModule);
}
}
@@ -1,6 +1,6 @@
--- a/com/mojang/blaze3d/systems/CommandEncoderBackend.java
+++ b/com/mojang/blaze3d/systems/CommandEncoderBackend.java
@@ -29,6 +_,8 @@
--- a/com/mojang/renderpearl/api/commands/CommandEncoder.java
+++ b/com/mojang/renderpearl/api/commands/CommandEncoder.java
@@ -70,6 +_,8 @@
void clearDepthTexture(GpuTexture depthTexture, double clearDepth);
@@ -0,0 +1,11 @@
--- a/com/mojang/renderpearl/api/commands/RenderPass.java
+++ b/com/mojang/renderpearl/api/commands/RenderPass.java
@@ -39,6 +_,8 @@
void pushConstants(ByteBuffer value);
+ void setViewport(int x, int y, int width, int height);
+
void enableScissor(int x, int y, int width, int height);
void disableScissor();
@@ -0,0 +1,16 @@
--- a/com/mojang/renderpearl/api/pipeline/DepthStencilState.java
+++ b/com/mojang/renderpearl/api/pipeline/DepthStencilState.java
@@ -4,8 +_,12 @@
import net.neoforged.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
-public record DepthStencilState(CompareOp depthTest, boolean writeDepth, float depthBiasScaleFactor, float depthBiasConstant) {
+public record DepthStencilState(CompareOp depthTest, boolean writeDepth, float depthBiasScaleFactor, float depthBiasConstant, net.neoforged.neoforge.client.stencil.@org.jspecify.annotations.Nullable StencilTest stencilTest) {
public static final DepthStencilState DEFAULT = new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, true);
+
+ public DepthStencilState(CompareOp depthTest, boolean writeDepth, float depthBiasScaleFactor, float depthBiasConstant) {
+ this(depthTest, writeDepth, depthBiasScaleFactor, depthBiasConstant, null);
+ }
public DepthStencilState(CompareOp depthTest, boolean depthWrite) {
this(depthTest, depthWrite, 0.0F, 0.0F);
@@ -0,0 +1,47 @@
--- a/com/mojang/renderpearl/api/pipeline/RenderPipeline.java
+++ b/com/mojang/renderpearl/api/pipeline/RenderPipeline.java
@@ -130,6 +_,44 @@
return this.pushConstantSize;
}
+ /// Neo: Create a [RenderPipeline.Builder] from this [RenderPipeline] to adjust its configuration and
+ /// build a new, modified [RenderPipeline] from it
+ public RenderPipeline.Builder toBuilder() {
+ RenderPipeline.Builder builder = new RenderPipeline.Builder();
+ builder.location = Optional.of(this.location);
+ builder.shaders.putAll(this.shaders);
+ if (!this.shaderDefines.isEmpty()) {
+ ShaderDefines.Builder defBuilder = ShaderDefines.builder();
+ for (Entry<String, String> entry : this.shaderDefines.values().entrySet()) {
+ defBuilder.define(entry.getKey(), entry.getValue());
+ }
+ for (String flag : this.shaderDefines.flags()) {
+ defBuilder.define(flag);
+ }
+ builder.definesBuilder = Optional.of(defBuilder);
+ }
+ if (!this.bindGroupLayouts.isEmpty()) {
+ builder.bindGroupLayouts = Optional.of(new ObjectOpenHashSet<>(this.bindGroupLayouts));
+ }
+ builder.depthStencilState = Optional.ofNullable(this.depthStencilState);
+ builder.polygonMode = Optional.of(this.polygonMode);
+ builder.cull = Optional.of(this.cull);
+ for (int i = 0; i < builder.colorTargetStates.length && i < this.colorTargetStates.size(); i++) {
+ builder.colorTargetStates[i] = this.colorTargetStates.get(i);
+ }
+ for (int i = 0; i < this.colorTargetStates.size(); i++) {
+ if (this.colorTargetStates.get(i) != null) {
+ builder.activeColorTargetStateCount = i + 1;
+ }
+ }
+ for (int i = 0; i < builder.vertexFormatPerBuffer.length && i < this.vertexFormatPerBuffer.size(); i++) {
+ builder.vertexFormatPerBuffer[i] = this.vertexFormatPerBuffer.get(i);
+ }
+ builder.primitiveTopology = Optional.of(this.primitiveTopology);
+ builder.pushConstantSize = this.pushConstantSize;
+ return builder;
+ }
+
public static RenderPipeline.Builder builder(RenderPipeline.Snippet... snippets) {
RenderPipeline.Builder builder = new RenderPipeline.Builder();
@@ -1,5 +1,5 @@
--- a/com/mojang/blaze3d/shaders/ShaderType.java
+++ b/com/mojang/blaze3d/shaders/ShaderType.java
--- a/com/mojang/renderpearl/api/pipeline/ShaderType.java
+++ b/com/mojang/renderpearl/api/pipeline/ShaderType.java
@@ -7,6 +_,7 @@
import org.jspecify.annotations.Nullable;
@@ -1,10 +1,10 @@
--- a/com/mojang/blaze3d/shaders/UniformType.java
+++ b/com/mojang/blaze3d/shaders/UniformType.java
--- a/com/mojang/renderpearl/api/pipeline/UniformType.java
+++ b/com/mojang/renderpearl/api/pipeline/UniformType.java
@@ -4,6 +_,7 @@
import net.neoforged.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
[email protected](reason = "Further uniform types such as SSBO and StorageTexelBuffer may be added")
public enum UniformType {
COMBINED_IMAGE_SAMPLER,
UNIFORM_BUFFER,
TEXEL_BUFFER;
@@ -1,5 +1,5 @@
--- a/com/mojang/blaze3d/textures/AddressMode.java
+++ b/com/mojang/blaze3d/textures/AddressMode.java
--- a/com/mojang/renderpearl/api/textures/AddressMode.java
+++ b/com/mojang/renderpearl/api/textures/AddressMode.java
@@ -4,6 +_,7 @@
import net.neoforged.api.distmarker.OnlyIn;
@@ -0,0 +1,11 @@
--- a/com/mojang/renderpearl/backend/api/CommandEncoderBackend.java
+++ b/com/mojang/renderpearl/backend/api/CommandEncoderBackend.java
@@ -40,6 +_,8 @@
void clearDepthTexture(GpuTexture depthTexture, double clearDepth);
+ void clearStencilTexture(GpuTexture texture, int value);
+
void writeToBuffer(GpuBufferSlice destination, ByteBuffer data);
void copyToBuffer(GpuBufferSlice source, GpuBufferSlice target);
@@ -0,0 +1,11 @@
--- a/com/mojang/renderpearl/backend/api/RenderPassBackend.java
+++ b/com/mojang/renderpearl/backend/api/RenderPassBackend.java
@@ -24,6 +_,8 @@
void pushConstants(ByteBuffer value);
+ void setViewport(int x, int y, int width, int height);
+
void enableScissor(final int x, final int y, final int width, final int height);
void disableScissor();
@@ -1,5 +1,5 @@
--- a/com/mojang/blaze3d/opengl/DirectStateAccess.java
+++ b/com/mojang/blaze3d/opengl/DirectStateAccess.java
--- a/com/mojang/renderpearl/backend/opengl/DirectStateAccess.java
+++ b/com/mojang/renderpearl/backend/opengl/DirectStateAccess.java
@@ -40,10 +_,18 @@
public abstract int createFrameBufferObject();
@@ -1,5 +1,5 @@
--- a/com/mojang/blaze3d/opengl/FrameBufferAttachment.java
+++ b/com/mojang/blaze3d/opengl/FrameBufferAttachment.java
--- a/com/mojang/renderpearl/backend/opengl/FrameBufferAttachment.java
+++ b/com/mojang/renderpearl/backend/opengl/FrameBufferAttachment.java
@@ -12,4 +_,8 @@
void addAssociatedFbo(FrameBufferCache.CacheKey fboKey);
@@ -1,6 +1,6 @@
--- a/com/mojang/blaze3d/opengl/FrameBufferCache.java
+++ b/com/mojang/blaze3d/opengl/FrameBufferCache.java
@@ -46,7 +_,7 @@
--- a/com/mojang/renderpearl/backend/opengl/FrameBufferCache.java
+++ b/com/mojang/renderpearl/backend/opengl/FrameBufferCache.java
@@ -51,7 +_,7 @@
}
dsa.bindFrameBufferTextures(
@@ -9,19 +9,19 @@
);
return fbo;
}
@@ -71,7 +_,7 @@
@@ -76,7 +_,7 @@
public CacheKey(List<@Nullable FrameBufferAttachment> colorAttachments, @Nullable FrameBufferAttachment depthAttachment) {
public CacheKey(List<@Nullable FrameBufferAttachment> colorAttachments, @Nullable FrameBufferAttachment depthAttachment, int mipOffset) {
int colorAttachmentCount = colorAttachments.size();
- this.data = new int[(colorAttachmentCount + (depthAttachment != null ? 1 : 0)) * 2];
+ this.data = new int[(colorAttachmentCount * 2) + (depthAttachment != null ? 3 : 0)];
for (int i = 0; i < colorAttachmentCount; i++) {
FrameBufferAttachment attachment = colorAttachments.get(i);
@@ -88,6 +_,7 @@
@@ -93,6 +_,7 @@
if (depthAttachment != null) {
this.data[colorAttachmentCount * 2] = depthAttachment.glId();
this.data[colorAttachmentCount * 2 + 1] = depthAttachment.fboMipLevel();
this.data[colorAttachmentCount * 2 + 1] = depthAttachment.fboMipLevel() + mipOffset;
+ this.data[colorAttachmentCount * 2 + 2] = depthAttachment.hasStencilAspect() ? 1 : 0;
this.associatedAttachments.add(depthAttachment);
}
@@ -0,0 +1,57 @@
--- a/com/mojang/renderpearl/backend/opengl/GlCommandEncoder.java
+++ b/com/mojang/renderpearl/backend/opengl/GlCommandEncoder.java
@@ -262,8 +_,9 @@
GlStateManager._depthMask(true);
GlStateManager._disableScissorTest();
+ boolean hasStencil = depthTexture.getFormat().hasStencilAspect();
for (int i = 0; i < depthTexture.getMipLevels(); i++) {
- this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)depthTexture).id, i, 36160);
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)depthTexture).id, i, 36160, hasStencil);
GL33C.glDrawBuffer(0);
GlStateManager._clear(256);
}
@@ -274,6 +_,17 @@
}
@Override
+ public void clearStencilTexture(GpuTexture texture, int value) {
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, 0, ((GlTexture)texture).id, 0, GlConst.GL_FRAMEBUFFER, true);
+ GL33C.glDrawBuffer(GlConst.GL_NONE);
+ GL33C.glClearStencil(value);
+ GlStateManager._depthMask(true);
+ GlStateManager._clear(GL33C.GL_STENCIL_BUFFER_BIT);
+ GL33C.glDrawBuffer(GlConst.GL_COLOR_ATTACHMENT0);
+ GlStateManager._glBindFramebuffer(GlConst.GL_FRAMEBUFFER, 0);
+ }
+
+ @Override
public void writeToBuffer(GpuBufferSlice slice, ByteBuffer data) {
GlBuffer buffer = (GlBuffer)slice.buffer();
buffer.checkCanBeUsed();
@@ -396,11 +_,22 @@
boolean isDepth = source.getFormat().hasDepthAspect();
int sourceId = ((GlTexture)source).glId();
int destId = ((GlTexture)destination).glId();
- this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, isDepth ? 0 : sourceId, isDepth ? sourceId : 0, mipLevel, 0);
- this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, isDepth ? 0 : destId, isDepth ? destId : 0, mipLevel, 0);
+ boolean hasStencil = source.getFormat().hasStencilAspect();
+ this.device.directStateAccess().bindFrameBufferTextures(this.readFbo, isDepth ? 0 : sourceId, isDepth ? sourceId : 0, 0, 0, hasStencil);
+ this.device.directStateAccess().bindFrameBufferTextures(this.drawFbo, isDepth ? 0 : destId, isDepth ? destId : 0, 0, 0, hasStencil);
+ int bufferMask = 0;
+ if (source.getFormat().hasColorAspect()) {
+ bufferMask |= GlConst.GL_COLOR_BUFFER_BIT;
+ }
+ if (source.getFormat().hasDepthAspect()) {
+ bufferMask |= GlConst.GL_DEPTH_BUFFER_BIT;
+ }
+ if (source.getFormat().hasStencilAspect()) {
+ bufferMask |= GL33C.GL_STENCIL_BUFFER_BIT;
+ }
this.device
.directStateAccess()
- .blitFrameBuffers(this.readFbo, this.drawFbo, sourceX, sourceY, width, height, destX, destY, width, height, isDepth ? 256 : 16384, 9728);
+ .blitFrameBuffers(this.readFbo, this.drawFbo, sourceX, sourceY, width, height, destX, destY, width, height, bufferMask, 9728);
int error = GlStateManager._getError();
if (error != 0) {
throw new IllegalStateException(
@@ -1,5 +1,5 @@
--- a/com/mojang/blaze3d/opengl/GlConst.java
+++ b/com/mojang/blaze3d/opengl/GlConst.java
--- a/com/mojang/renderpearl/backend/opengl/GlConst.java
+++ b/com/mojang/renderpearl/backend/opengl/GlConst.java
@@ -363,4 +_,17 @@
return 35044;
}
@@ -0,0 +1,14 @@
--- a/com/mojang/renderpearl/backend/opengl/GlRenderPass.java
+++ b/com/mojang/renderpearl/backend/opengl/GlRenderPass.java
@@ -95,6 +_,11 @@
}
@Override
+ public void setViewport(int x, int y, int width, int height) {
+ GlStateManager._viewport(x, y, width, height);
+ }
+
+ @Override
public void enableScissor(int x, int y, int width, int height) {
this.scissorState.enable(x, y, width, height);
this.scissorStateDirty = true;
@@ -0,0 +1,83 @@
--- a/com/mojang/renderpearl/backend/opengl/GlRenderPipeline.java
+++ b/com/mojang/renderpearl/backend/opengl/GlRenderPipeline.java
@@ -29,6 +_,19 @@
private final int srcAlpha;
private final int dstAlpha;
private final int modeAlpha;
+ private final boolean hasStencilTest;
+ private final boolean hasPerFaceStencilTest;
+ private final int stencilReferenceValue;
+ private final int stencilReadMask;
+ private final int stencilWriteMask;
+ private final int stencilFrontCompare;
+ private final int stencilFrontFail;
+ private final int stencilFrontDepthFail;
+ private final int stencilFrontPass;
+ private final int stencilBackCompare;
+ private final int stencilBackFail;
+ private final int stencilBackDepthFail;
+ private final int stencilBackPass;
private boolean closed = false;
GlRenderPipeline(GlDevice device, BackendRenderPipeline.CreateInfo createInfo, GlProgram program, VertexArray vertexArray) {
@@ -88,6 +_,37 @@
this.dstAlpha = 1280;
this.modeAlpha = 1280;
}
+
+ var stencilTest = this.depthEnabled ? createInfo.depthStencilState().stencilTest() : null;
+ if (stencilTest != null) {
+ this.hasStencilTest = true;
+ this.hasPerFaceStencilTest = !stencilTest.front().equals(stencilTest.back());
+ this.stencilReferenceValue = stencilTest.referenceValue();
+ this.stencilReadMask = stencilTest.readMask();
+ this.stencilWriteMask = stencilTest.writeMask();
+ this.stencilFrontCompare = GlConst.toGl(stencilTest.front().compare());
+ this.stencilFrontFail = GlConst.toGl(stencilTest.front().fail());
+ this.stencilFrontDepthFail = GlConst.toGl(stencilTest.front().depthFail());
+ this.stencilFrontPass = GlConst.toGl(stencilTest.front().pass());
+ this.stencilBackCompare = GlConst.toGl(stencilTest.back().compare());
+ this.stencilBackFail = GlConst.toGl(stencilTest.back().fail());
+ this.stencilBackDepthFail = GlConst.toGl(stencilTest.back().depthFail());
+ this.stencilBackPass = GlConst.toGl(stencilTest.back().pass());
+ } else {
+ this.hasStencilTest = false;
+ this.hasPerFaceStencilTest = false;
+ this.stencilReferenceValue = 0;
+ this.stencilReadMask = 0;
+ this.stencilWriteMask = 0;
+ this.stencilFrontCompare = 0;
+ this.stencilFrontFail = 0;
+ this.stencilFrontDepthFail = 0;
+ this.stencilFrontPass = 0;
+ this.stencilBackCompare = 0;
+ this.stencilBackFail = 0;
+ this.stencilBackDepthFail = 0;
+ this.stencilBackPass = 0;
+ }
}
@Override
@@ -157,6 +_,22 @@
}
GlStateManager._polygonMode(1032, this.polygonMode);
+
+ if (this.hasStencilTest) {
+ GlStateManager._enableStencilTest();
+ if (this.hasPerFaceStencilTest) {
+ GlStateManager._stencilFuncFront(this.stencilFrontCompare, this.stencilReferenceValue, this.stencilReadMask);
+ GlStateManager._stencilFuncBack(this.stencilBackCompare, this.stencilReferenceValue, this.stencilReadMask);
+ GlStateManager._stencilOpFront(this.stencilFrontFail, this.stencilFrontDepthFail, this.stencilFrontPass);
+ GlStateManager._stencilOpBack(this.stencilBackFail, this.stencilBackDepthFail, this.stencilBackPass);
+ } else {
+ GlStateManager._stencilFunc(this.stencilFrontCompare, this.stencilReferenceValue, this.stencilReadMask);
+ GlStateManager._stencilOp(this.stencilFrontFail, this.stencilFrontDepthFail, this.stencilFrontPass);
+ }
+ GlStateManager._stencilMask(this.stencilWriteMask);
+ } else {
+ GlStateManager._disableStencilTest();
+ }
}
public int primitiveTopology() {
@@ -1,6 +1,6 @@
--- a/com/mojang/blaze3d/opengl/GlStateManager.java
+++ b/com/mojang/blaze3d/opengl/GlStateManager.java
@@ -29,6 +_,7 @@
--- a/com/mojang/renderpearl/backend/opengl/GlStateManager.java
+++ b/com/mojang/renderpearl/backend/opengl/GlStateManager.java
@@ -31,6 +_,7 @@
private static final GlStateManager.CullState CULL = new GlStateManager.CullState();
private static final GlStateManager.PolygonOffsetState POLY_OFFSET = new GlStateManager.PolygonOffsetState();
private static final GlStateManager.ColorLogicState COLOR_LOGIC = new GlStateManager.ColorLogicState();
@@ -8,10 +8,11 @@
private static final GlStateManager.ScissorState SCISSOR = new GlStateManager.ScissorState();
private static int activeTexture;
private static final int TEXTURE_COUNT = 12;
@@ -625,4 +_,119 @@
@@ -634,5 +_,114 @@
private static class TextureState {
public int binding;
}
+ }
+
+ public static void _disableStencilTest() {
+ RenderSystem.assertOnRenderThread();
@@ -65,11 +66,9 @@
+ }
+ }
+
+ /**
+ * @param stencilFail The action to take if the stencil test fails.
+ * @param depthFail The action to take if the depth buffer test fails.
+ * @param pass The action to take if both tests pass.
+ */
+ /// @param stencilFail The action to take if the stencil test fails.
+ /// @param depthFail The action to take if the depth buffer test fails.
+ /// @param pass The action to take if both tests pass.
+ public static void _stencilOp(int stencilFail, int depthFail, int pass) {
+ RenderSystem.assertOnRenderThread();
+ if (stencilFail != STENCIL.frontStencilFail || depthFail != STENCIL.frontDepthFail || pass != STENCIL.frontPass
@@ -84,9 +83,7 @@
+ }
+ }
+
+ /**
+ * Same as {@link #_stencilOp}, but affects only front-faces.
+ */
+ /// Same as [#_stencilOp], but affects only front-faces.
+ public static void _stencilOpFront(int stencilFail, int depthFail, int pass) {
+ RenderSystem.assertOnRenderThread();
+ if (stencilFail != STENCIL.frontStencilFail || depthFail != STENCIL.frontDepthFail || pass != STENCIL.frontPass) {
@@ -97,9 +94,7 @@
+ }
+ }
+
+ /**
+ * Same as {@link #_stencilOp}, but affects only back-faces.
+ */
+ /// Same as [#_stencilOp], but affects only back-faces.
+ public static void _stencilOpBack(int stencilFail, int depthFail, int pass) {
+ RenderSystem.assertOnRenderThread();
+ if (stencilFail != STENCIL.backStencilFail || depthFail != STENCIL.backDepthFail || pass != STENCIL.backPass) {
@@ -126,5 +121,5 @@
+ public int backStencilFail = GL33C.GL_KEEP;
+ public int backDepthFail = GL33C.GL_KEEP;
+ public int backPass = GL33C.GL_KEEP;
+ }
}
}
@@ -0,0 +1,12 @@
--- a/com/mojang/renderpearl/backend/opengl/GlTexture.java
+++ b/com/mojang/renderpearl/backend/opengl/GlTexture.java
@@ -86,4 +_,9 @@
this.destroyImmediately();
}
}
+
+ @Override
+ public boolean hasStencilAspect() {
+ return this.getFormat().hasStencilAspect();
+ }
}
@@ -1,5 +1,5 @@
--- a/com/mojang/blaze3d/opengl/GlTextureView.java
+++ b/com/mojang/blaze3d/opengl/GlTextureView.java
--- a/com/mojang/renderpearl/backend/opengl/GlTextureView.java
+++ b/com/mojang/renderpearl/backend/opengl/GlTextureView.java
@@ -59,4 +_,9 @@
public void removeAssociatedFbo(FrameBufferCache.CacheKey fboKey) {
this.fboKeys.remove(fboKey);
@@ -1,6 +1,6 @@
--- a/com/mojang/blaze3d/vulkan/VulkanCommandEncoder.java
+++ b/com/mojang/blaze3d/vulkan/VulkanCommandEncoder.java
@@ -302,6 +_,15 @@
--- a/com/mojang/renderpearl/backend/vulkan/VulkanCommandEncoder.java
+++ b/com/mojang/renderpearl/backend/vulkan/VulkanCommandEncoder.java
@@ -320,11 +_,21 @@
}
renderingInfo.pDepthAttachment(depthAttachmentInfo);
@@ -16,15 +16,14 @@
}
KHRDynamicRendering.vkCmdBeginRenderingKHR(this.commandBuffer(), renderingInfo);
@@ -314,6 +_,7 @@
width,
height,
depthAttachment != null,
+ depthAttachment != null && depthAttachment.textureView().texture().getFormat().hasStencilAspect(),
descriptor.label()
+ boolean hasStencil = depthAttachment != null && depthAttachment.textureView().texture().getFormat().hasStencilAspect();
this.currentRenderPass = new VulkanRenderPass(
- this.device, this, this.commandBuffer(), this.checkpointStorage, renderArea, width, height, depthAttachment != null, descriptor.label()
+ this.device, this, this.commandBuffer(), this.checkpointStorage, renderArea, width, height, depthAttachment != null, hasStencil, descriptor.label()
);
}
@@ -418,6 +_,21 @@
@@ -437,6 +_,21 @@
public void clearDepthTexture(GpuTexture depthTexture, double clearDepth) {
try (MemoryStack stack = MemoryStack.stackPush()) {
this.clearDepthTextureUnsynced(stack, depthTexture, clearDepth);
@@ -1,7 +1,7 @@
--- a/com/mojang/blaze3d/vulkan/VulkanConst.java
+++ b/com/mojang/blaze3d/vulkan/VulkanConst.java
@@ -261,4 +_,17 @@
case FIFO_RELAXED -> 3;
--- a/com/mojang/renderpearl/backend/vulkan/VulkanConst.java
+++ b/com/mojang/renderpearl/backend/vulkan/VulkanConst.java
@@ -269,4 +_,17 @@
case FRAGMENT -> 16;
};
}
+
@@ -1,6 +1,6 @@
--- a/com/mojang/blaze3d/vulkan/VulkanRenderPass.java
+++ b/com/mojang/blaze3d/vulkan/VulkanRenderPass.java
@@ -52,6 +_,7 @@
--- a/com/mojang/renderpearl/backend/vulkan/VulkanRenderPass.java
+++ b/com/mojang/renderpearl/backend/vulkan/VulkanRenderPass.java
@@ -50,6 +_,7 @@
private final int outputWidth;
private final int outputHeight;
private final boolean hasDepth;
@@ -8,7 +8,7 @@
private final Supplier<String> label;
protected int pushedDebugGroups = 0;
private final VkCommandBuffer commandBuffer;
@@ -69,6 +_,7 @@
@@ -66,6 +_,7 @@
int outputWidth,
int outputHeight,
boolean hasDepth,
@@ -16,7 +16,7 @@
Supplier<String> label
) {
this.device = device;
@@ -79,6 +_,7 @@
@@ -76,6 +_,7 @@
this.outputWidth = outputWidth;
this.outputHeight = outputHeight;
this.hasDepth = hasDepth;
@@ -24,21 +24,21 @@
this.label = label;
try (MemoryStack stack = MemoryStack.stackPush()) {
@@ -122,6 +_,10 @@
}
this.anyDescriptorDirty = true;
+ if (this.hasStencil) {
+ VK12.vkCmdBindPipeline(this.commandBuffer(), VK12.VK_PIPELINE_BIND_POINT_GRAPHICS, this.pipeline.withDepthStencilPipeline());
+ return;
+ }
VK12.vkCmdBindPipeline(this.commandBuffer(), 0, this.hasDepth ? this.pipeline.withDepthPipeline() : this.pipeline.withoutDepthPipeline());
}
@@ -147,6 +_,18 @@
public void setUniform(String name, GpuBufferSlice value) {
this.uniforms.put(name, value);
this.anyDescriptorDirty = true;
@@ -118,6 +_,10 @@
this.anyDescriptorDirty = true;
this.uniforms.clear();
this.uniforms.size(vulkanRenderPipeline.uniforms().size());
+ if (this.hasStencil) {
+ VK12.vkCmdBindPipeline(this.commandBuffer(), VK12.VK_PIPELINE_BIND_POINT_GRAPHICS, this.pipeline.withDepthStencilPipeline());
+ return;
+ }
VK12.vkCmdBindPipeline(this.commandBuffer(), 0, this.hasDepth ? this.pipeline.withDepthPipeline() : this.pipeline.withoutDepthPipeline());
} else {
throw new IllegalArgumentException("Pipeline must be instance of VulkanRenderPipeline");
@@ -134,6 +_,18 @@
public void pushConstants(ByteBuffer value) {
assert this.pipeline != null;
VK12.vkCmdPushConstants(this.commandBuffer(), this.pipeline.pipelineLayout(), Integer.MAX_VALUE, 0, value);
+ }
+
+ @Override
@@ -0,0 +1,93 @@
--- a/com/mojang/renderpearl/backend/vulkan/VulkanRenderPipeline.java
+++ b/com/mojang/renderpearl/backend/vulkan/VulkanRenderPipeline.java
@@ -41,6 +_,7 @@
@OnlyIn(Dist.CLIENT)
public final class VulkanRenderPipeline implements BackendRenderPipeline, Destroyable {
private final VulkanDevice device;
+ private final long withDepthStencilPipeline;
private final long withDepthPipeline;
private final long withoutDepthPipeline;
private final long pipelineLayout;
@@ -51,6 +_,7 @@
public VulkanRenderPipeline(
VulkanDevice device,
+ long withDepthStencilPipeline,
long withDepthPipeline,
long withoutDepthPipeline,
long pipelineLayout,
@@ -59,6 +_,7 @@
List<BindGroupLayout.UniformDescription> uniforms
) {
this.device = device;
+ this.withDepthStencilPipeline = withDepthStencilPipeline;
this.withDepthPipeline = withDepthPipeline;
this.withoutDepthPipeline = withoutDepthPipeline;
this.pipelineLayout = pipelineLayout;
@@ -232,6 +_,27 @@
vkDepthStencilState.depthTestEnable(true);
vkDepthStencilState.depthWriteEnable(depthStencilState.writeDepth());
vkDepthStencilState.depthCompareOp(VulkanConst.toVk(depthStencilState.depthTest()));
+
+ final var stencilTest = depthStencilState.stencilTest();
+ if (stencilTest != null) {
+ vkDepthStencilState.stencilTestEnable(true);
+ final var frontState = vkDepthStencilState.front();
+ frontState.failOp(VulkanConst.toVk(stencilTest.front().fail()));
+ frontState.passOp(VulkanConst.toVk(stencilTest.front().pass()));
+ frontState.depthFailOp(VulkanConst.toVk(stencilTest.front().depthFail()));
+ frontState.compareOp(VulkanConst.toVk(stencilTest.front().compare()));
+ frontState.compareMask(stencilTest.readMask());
+ frontState.writeMask(stencilTest.writeMask());
+ frontState.reference(stencilTest.referenceValue());
+ final var backState = vkDepthStencilState.back();
+ backState.failOp(VulkanConst.toVk(stencilTest.back().fail()));
+ backState.passOp(VulkanConst.toVk(stencilTest.back().pass()));
+ backState.depthFailOp(VulkanConst.toVk(stencilTest.back().depthFail()));
+ backState.compareOp(VulkanConst.toVk(stencilTest.back().compare()));
+ backState.compareMask(stencilTest.readMask());
+ backState.writeMask(stencilTest.writeMask());
+ backState.reference(stencilTest.referenceValue()); // note: must match front unless portability feature is required and checked for (if on portability device)
+ }
}
List<ColorTargetState> colorTargetStates = pipelineCreateInfo.colorTargetStates();
@@ -289,6 +_,7 @@
long withDepthPipeline = pointer.get(0);
device.instance().debug().setObjectName(device.vkDevice(), 19, withDepthPipeline, () -> "Pipeline " + pipelineCreateInfo.name());
long withoutDepthPipeline;
+ long withDepthStencilPipeline = 0L;
if (depthStencilState == null) {
renderingInfo.depthAttachmentFormat(0);
VulkanUtils.crashIfFailure(
@@ -300,10 +_,18 @@
device.instance().debug().setObjectName(device.vkDevice(), 19, withoutDepthPipeline, () -> "Pipeline " + pipelineCreateInfo.name());
} else {
withoutDepthPipeline = 0L;
+
+ if (depthStencilState.stencilTest() != null) {
+ renderingInfo.depthAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT);
+ renderingInfo.stencilAttachmentFormat(VK12.VK_FORMAT_D32_SFLOAT_S8_UINT);
+ VulkanUtils.crashIfFailure(device, VK12.vkCreateGraphicsPipelines(device.vkDevice(), 0L, createInfo, null, pointer), "Can't compile pipeline " + pipelineCreateInfo.name());
+ withDepthStencilPipeline = pointer.get(0);
+ device.instance().debug().setObjectName(device.vkDevice(), VK12.VK_OBJECT_TYPE_PIPELINE, withDepthStencilPipeline, () -> "Pipeline " + pipelineCreateInfo.name());
+ }
}
return new VulkanRenderPipeline(
- device, withDepthPipeline, withoutDepthPipeline, pipelineLayout, descriptorSetLayout, compiledShaderModules, pipelineCreateInfo.uniforms()
+ device, withDepthStencilPipeline, withDepthPipeline, withoutDepthPipeline, pipelineLayout, descriptorSetLayout, compiledShaderModules, pipelineCreateInfo.uniforms()
);
}
}
@@ -334,6 +_,10 @@
public VulkanDevice device() {
return this.device;
+ }
+
+ public long withDepthStencilPipeline() {
+ return this.withDepthStencilPipeline;
}
public long withDepthPipeline() {
@@ -1,9 +1,9 @@
--- a/com/mojang/blaze3d/systems/CommandEncoder.java
+++ b/com/mojang/blaze3d/systems/CommandEncoder.java
@@ -249,6 +_,15 @@
this.backend.clearDepthTexture(depthTexture, clearDepth);
--- a/com/mojang/renderpearl/frontend/FrontendCommandEncoder.java
+++ b/com/mojang/renderpearl/frontend/FrontendCommandEncoder.java
@@ -288,6 +_,16 @@
}
@Override
+ public void clearStencilTexture(GpuTexture texture, int value) {
+ if (this.isInRenderPass) {
+ throw new IllegalStateException("Close the existing render pass before creating a new one!");
@@ -13,10 +13,11 @@
+ this.backend.clearStencilTexture(texture, value);
+ }
+
+ @Override
public void writeToBuffer(GpuBufferSlice destination, ByteBuffer data) {
if (this.isInRenderPass) {
throw new IllegalStateException("Close the existing render pass before performing additional commands");
@@ -696,6 +_,25 @@
@@ -743,6 +_,24 @@
throw new UnsupportedOperationException("Textures with multiple depths or layers are not yet supported for copying");
}
@@ -37,12 +38,11 @@
+ + sourceFormat + ", Destination: " + destFormat
+ );
+ }
+
+
this.backend.copyTextureToTexture(source, destination, mipLevel, destX, destY, sourceX, sourceY, width, height);
} else {
throw new IllegalArgumentException(
@@ -761,6 +_,24 @@
@@ -810,6 +_,24 @@
if (depthTexture.getDepthOrLayers() > 1) {
throw new UnsupportedOperationException("Clearing a texture with multiple layers or depths is not yet supported");
@@ -0,0 +1,11 @@
--- a/com/mojang/renderpearl/frontend/FrontendGpuDevice.java
+++ b/com/mojang/renderpearl/frontend/FrontendGpuDevice.java
@@ -36,7 +_,7 @@
@OnlyIn(Dist.CLIENT)
public class FrontendGpuDevice implements GpuDevice {
private static final Logger LOGGER = LogUtils.getLogger();
- public static final boolean STRICT_VALIDATION = SharedConstants.IS_RUNNING_IN_IDE;
+ public static final boolean STRICT_VALIDATION = SharedConstants.IS_RUNNING_IN_IDE && !Boolean.getBoolean("neoforge.disableBlaze3DValidation");
private final GpuDeviceBackend backend;
private final @Nullable TracyGpuProfiler profiler;
private final CommandEncoder encoder;
@@ -0,0 +1,14 @@
--- a/com/mojang/renderpearl/frontend/FrontendRenderPass.java
+++ b/com/mojang/renderpearl/frontend/FrontendRenderPass.java
@@ -189,6 +_,11 @@
}
@Override
+ public void setViewport(int x, int y, int width, int height) {
+ this.backend.setViewport(x, y, width, height);
+ }
+
+ @Override
public void enableScissor(int x, int y, int width, int height) {
if (width > 0 && height > 0) {
if (x >= this.renderArea.x()
@@ -1,16 +1,17 @@
--- a/net/minecraft/SharedConstants.java
+++ b/net/minecraft/SharedConstants.java
@@ -125,7 +_,8 @@
@@ -125,8 +_,9 @@
public static final float MAXIMUM_BLOCK_EXPLOSION_RESISTANCE = 3600000.0F;
public static final boolean USE_DEVONLY = false;
public static boolean CHECK_DATA_FIXER_SCHEMA = true;
- public static boolean IS_RUNNING_IN_IDE;
public static boolean IS_RENDERDOC_ATTACHED = false;
+ public static boolean IS_RUNNING_IN_IDE = !net.neoforged.fml.loading.FMLEnvironment.isProduction();
+ public static final boolean IS_RUNNING_WITH_JDWP = java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments().stream().anyMatch(str -> str.startsWith("-agentlib:jdwp"));
public static final int WORLD_RESOLUTION = 16;
public static final int MAX_CHAT_LENGTH = 256;
public static final int MAX_USER_INPUT_COMMAND_LENGTH = 32500;
@@ -218,6 +_,7 @@
@@ -219,6 +_,7 @@
}
static {
@@ -1,10 +1,16 @@
--- a/net/minecraft/advancements/Advancement.java
+++ b/net/minecraft/advancements/Advancement.java
@@ -55,6 +_,7 @@
)
.validate(Advancement::validate);
public static final StreamCodec<RegistryFriendlyByteBuf, Advancement> STREAM_CODEC = StreamCodec.ofMember(Advancement::write, Advancement::read);
+ public static final Codec<Optional<net.neoforged.neoforge.common.conditions.WithConditions<Advancement>>> CONDITIONAL_CODEC = net.neoforged.neoforge.common.conditions.ConditionalOps.createConditionalCodecWithConditions(CODEC);
@@ -225,8 +_,12 @@
}
public Advancement(
Optional<Identifier> parent,
public AdvancementHolder save(BootstrapContext<Advancement> output, String name) {
+ return this.save(output, name, new net.neoforged.neoforge.common.conditions.ICondition[0]);
+ }
+
+ public AdvancementHolder save(BootstrapContext<Advancement> output, String name, net.neoforged.neoforge.common.conditions.ICondition... conditions) {
AdvancementHolder advancement = this.build(Identifier.parse(name));
- advancement.register(output);
+ advancement.register(output, conditions);
return advancement;
}
}
@@ -0,0 +1,15 @@
--- a/net/minecraft/advancements/AdvancementHolder.java
+++ b/net/minecraft/advancements/AdvancementHolder.java
@@ -13,7 +_,11 @@
);
public void register(BootstrapContext<Advancement> output) {
- output.register(ResourceKey.create(Registries.ADVANCEMENT, this.id), this.value);
+ this.register(output, new net.neoforged.neoforge.common.conditions.ICondition[0]);
+ }
+
+ public void register(BootstrapContext<Advancement> output, net.neoforged.neoforge.common.conditions.ICondition... conditions) {
+ output.register(ResourceKey.create(Registries.ADVANCEMENT, this.id), this.value, conditions);
}
@Override
@@ -1,6 +1,6 @@
--- a/net/minecraft/advancements/AdvancementRewards.java
+++ b/net/minecraft/advancements/AdvancementRewards.java
@@ -43,6 +_,7 @@
@@ -46,6 +_,7 @@
LootParams params = new LootParams.Builder(level)
.withParameter(LootContextParams.THIS_ENTITY, player)
.withParameter(LootContextParams.ORIGIN, player.position())
@@ -1,6 +1,6 @@
--- a/net/minecraft/advancements/predicates/entity/EntityPredicate.java
+++ b/net/minecraft/advancements/predicates/entity/EntityPredicate.java
@@ -91,6 +_,11 @@
@@ -89,6 +_,11 @@
return entity == null ? false : this.combinedPart.matches(entity, level, position);
}
@@ -12,7 +12,7 @@
public static LootContext createContext(ServerPlayer player, Entity entity) {
LootParams lootParams = new LootParams.Builder(player.level())
.withParameter(LootContextParams.THIS_ENTITY, entity)
@@ -140,6 +_,19 @@
@@ -138,6 +_,19 @@
public static EntityPredicate.Builder entity() {
return new EntityPredicate.Builder();
@@ -8,9 +8,9 @@
private final Quaternionf rotation = new Quaternionf();
private boolean detached;
private float eyeHeight;
@@ -142,6 +_,9 @@
cameraState.entityRenderState.hurtTime = livingEntity.hurtTime - cameraEntityPartialTicks;
cameraState.entityRenderState.deathTime = livingEntity.deathTime + cameraEntityPartialTicks;
@@ -144,6 +_,9 @@
cameraState.entityRenderState.hurtTime = livingEntity.hurtTime - cameraState.cameraEntityPartialTicks;
cameraState.entityRenderState.deathTime = livingEntity.deathTime + cameraState.cameraEntityPartialTicks;
cameraState.entityRenderState.hurtDuration = livingEntity.hurtDuration;
+ // Neo: Prevent screen shake if the damage type is marked as "forge:no_flinch"
+ var lastDamage = livingEntity.getLastDamageSource();
@@ -18,7 +18,7 @@
} else {
cameraState.entityRenderState.isLiving = false;
cameraState.entityRenderState.isSleeping = false;
@@ -243,6 +_,7 @@
@@ -247,6 +_,7 @@
fov *= Mth.lerp(effectScale, 1.0F, 0.85714287F);
}
@@ -26,7 +26,7 @@
return fov;
}
@@ -258,7 +_,10 @@
@@ -262,7 +_,10 @@
this.setRotation(this.entity.getViewYRot(partialTicks), this.entity.getViewXRot(partialTicks));
this.setPosition(behavior.getCartLerpPosition(partialTicks).add(positionOffset));
} else {
@@ -38,7 +38,7 @@
this.setPosition(
Mth.lerp(partialTicks, this.entity.xo, this.entity.getX()),
Mth.lerp(partialTicks, this.entity.yo, this.entity.getY()) + Mth.lerp(partialTicks, this.eyeHeightOld, this.eyeHeight),
@@ -269,7 +_,7 @@
@@ -273,7 +_,7 @@
this.detached = !this.minecraft.options.getCameraType().isFirstPerson();
if (this.detached) {
if (this.minecraft.options.getCameraType().isMirrored()) {
@@ -47,7 +47,7 @@
}
float cameraDistance = 4.0F;
@@ -286,7 +_,7 @@
@@ -290,7 +_,7 @@
mountDistance = (float)mount.getAttributeValue(Attributes.CAMERA_DISTANCE);
}
@@ -56,7 +56,7 @@
} else if (this.entity instanceof LivingEntity && ((LivingEntity)this.entity).isSleeping()) {
Direction bedOrientation = ((LivingEntity)this.entity).getBedOrientation();
this.setRotation(bedOrientation != null ? bedOrientation.toYRot() - 180.0F : 0.0F, 0.0F);
@@ -336,10 +_,17 @@
@@ -340,10 +_,17 @@
this.setPosition(new Vec3(this.position.x + offset.x, this.position.y + offset.y, this.position.z + offset.z));
}
@@ -75,7 +75,7 @@
FORWARDS.rotate(this.rotation, this.forwards);
UP.rotate(this.rotation, this.up);
LEFT.rotate(this.rotation, this.left);
@@ -499,6 +_,17 @@
@@ -503,6 +_,17 @@
public void disablePanoramicMode() {
this.isPanoramicMode = false;
@@ -1,15 +0,0 @@
--- a/net/minecraft/client/ClientClockManager.java
+++ b/net/minecraft/client/ClientClockManager.java
@@ -46,6 +_,12 @@
return this.getInstance(definition).totalTicks;
}
+
+ @Override
+ public float getPartialTick(Holder<WorldClock> definition) {
+ return this.getInstance(definition).partialTick;
+ }
+
private static class ClockInstance {
private long totalTicks;
private float partialTick;
@@ -145,7 +145,7 @@
return this.key.equals(that.key);
}
@@ -181,11 +_,13 @@
@@ -179,11 +_,13 @@
}
public Component getTranslatedKeyMessage() {
@@ -160,7 +160,7 @@
}
public String saveString() {
@@ -197,7 +_,7 @@
@@ -195,7 +_,7 @@
}
private void registerMapping(InputConstants.Key key) {
@@ -169,7 +169,7 @@
}
public static @Nullable KeyMapping get(String name) {
@@ -219,6 +_,10 @@
@@ -217,6 +_,10 @@
return register(Identifier.withDefaultNamespace(name));
}
@@ -1,9 +1,9 @@
--- a/net/minecraft/client/KeyboardHandler.java
+++ b/net/minecraft/client/KeyboardHandler.java
@@ -478,7 +_,11 @@
@@ -496,7 +_,11 @@
if (screen != null) {
try {
if (action != 1 && action != 2) {
if (action != 1 && action != -1) {
- if (action == 0 && screen.keyReleased(event)) {
+ if (action == 0 && (
+ net.neoforged.neoforge.client.ClientHooks.onScreenKeyReleasedPre(screen, event) ||
@@ -13,7 +13,7 @@
if (options.keyDebugModifier.matches(event)) {
this.usedDebugKeyAsModifier = false;
}
@@ -487,7 +_,11 @@
@@ -505,7 +_,11 @@
}
} else {
screen.afterKeyboardAction();
@@ -26,7 +26,7 @@
if (this.minecraft.gui.screen() == null) {
InputConstants.Key key = InputConstants.getKey(event);
KeyMapping.set(key, false);
@@ -562,6 +_,7 @@
@@ -578,6 +_,7 @@
}
}
}
@@ -34,7 +34,7 @@
}
}
@@ -570,7 +_,9 @@
@@ -586,7 +_,9 @@
Screen screen = this.minecraft.gui.screen();
if (screen != null && this.minecraft.gui.overlay() == null) {
try {
@@ -44,8 +44,8 @@
+ net.neoforged.neoforge.client.ClientHooks.onScreenCharTypedPost(screen, event);
} catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "charTyped event handler");
screen.fillCrashDetails(report);
@@ -598,7 +_,9 @@
CrashReportCategory keyDetails = report.addCategory("Key");
@@ -618,7 +_,9 @@
public static void submitPreeditEvent(GuiEventListener element, @Nullable PreeditEvent event) {
try {
@@ -55,4 +55,4 @@
+ if (element instanceof Screen screen) net.neoforged.neoforge.client.ClientHooks.onScreenPreeditPost(screen, event);
} catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "IME pre-edit event handler");
if (element instanceof Screen screen) {
CrashReportCategory keyDetails = report.addCategory("Event");
+98 -126
View File
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/Minecraft.java
+++ b/net/minecraft/client/Minecraft.java
@@ -282,6 +_,7 @@
@@ -291,6 +_,7 @@
public final LevelExtractor levelExtractor;
public final LevelRenderer levelRenderer;
private final EntityRenderDispatcher entityRenderDispatcher;
@@ -8,7 +8,7 @@
private final ItemModelResolver itemModelResolver;
private final MapRenderer mapRenderer;
public final ParticleEngine particleEngine;
@@ -412,7 +_,6 @@
@@ -422,7 +_,6 @@
}
}, Util.nonCriticalIoPool());
LOGGER.info("Setting user: {}", this.user.getName());
@@ -16,43 +16,28 @@
this.demo = gameConfig.game.demo;
this.allowsMultiplayer = !gameConfig.game.disableMultiplayer;
this.allowsChat = !gameConfig.game.disableChat;
@@ -445,6 +_,7 @@
StringBuilder errorMsgBuilder = new StringBuilder("No supported graphics backend was found.");
Window windowCandidate = null;
GpuDevice device = null;
+
PreferredGraphicsApi forcedGraphicsApi = gameConfig.game.forcedGraphicsApi;
if (forcedGraphicsApi != null) {
LOGGER.warn(
@@ -468,6 +_,8 @@
@@ -484,6 +_,8 @@
}
String initialWindowTitle = this.createTitle();
+ // Neo: Enable GL debug labels and synchronous GL debug output via FML config
+ boolean enableGlDebug = net.neoforged.fml.loading.FMLConfig.getBoolConfigValue(net.neoforged.fml.loading.FMLConfig.ConfigValue.DEBUG_OPENGL);
for (GpuBackend backend : preferredGraphicsBackend.getBackendsToTry()) {
try {
@@ -488,8 +_,8 @@
(id, type) -> this.getShaderManager().getShader(id, type),
new GpuDebugOptions(
this.options.glDebugVerbosity,
- SharedConstants.DEBUG_SYNCHRONOUS_GL_LOGS,
- gameConfig.game.renderDebugLabels,
+ SharedConstants.DEBUG_SYNCHRONOUS_GL_LOGS || enableGlDebug,
+ gameConfig.game.renderDebugLabels || enableGlDebug,
gameConfig.game.vulkanValidation
),
this::loadCriticalShaders
@@ -549,12 +_,14 @@
LOGGER.error("Couldn't set icon", e);
}
+ // Neo: Move mouse and keyboard handler setup further below
this.mouseHandler = new MouseHandler(this);
- this.mouseHandler.setup(this.window);
for (GpuBackend backendToTry : backendsToTry) {
boolean libraryLoaded = false;
@@ -494,8 +_,8 @@
device = backendToTry.createDevice(
new GpuDebugOptions(
this.options.glDebugVerbosity,
- SharedConstants.DEBUG_SYNCHRONOUS_GL_LOGS,
- gameConfig.game.renderDebugLabels,
+ SharedConstants.DEBUG_SYNCHRONOUS_GL_LOGS || enableGlDebug,
+ gameConfig.game.renderDebugLabels || enableGlDebug,
gameConfig.game.vulkanValidation
)
);
@@ -570,6 +_,9 @@
this.keyboardHandler = new KeyboardHandler(this);
- this.keyboardHandler.setup(this.window);
this.options.applyGraphicsPreset(this.options.graphicsPreset().get());
this.resourceManager = new ReloadableResourceManager(PackType.CLIENT_RESOURCES);
+ net.neoforged.neoforge.client.loading.ClientModLoader.setupModResourcePacks(this.resourcePackRepository);
@@ -60,10 +45,10 @@
+ ClientBootstrap.bootstrap();
this.resourcePackRepository.reload();
this.options.loadSelectedResourcePacks(this.resourcePackRepository);
this.languageManager = new LanguageManager(this.options.languageCode, var1 -> {
@@ -590,11 +_,13 @@
this.languageManager = new LanguageManager(this, this.options.languageCode, var1 -> {
@@ -603,11 +_,13 @@
this.resourceManager.registerReloadListener(new DryFoliageColorReloadListener());
RenderSystem.setupDefaultState();
this.window.setErrorSection("Post startup");
this.blockColors = BlockColors.createDefault();
+ net.neoforged.neoforge.client.model.UnbakedModelParser.init();
this.modelManager = new ModelManager(this.blockColors, this.atlasManager, this.playerSkinRenderCache);
@@ -73,35 +58,25 @@
BlockModelResolver blockModelResolver = new BlockModelResolver(this.modelManager);
+ this.blockModelResolver = blockModelResolver;
this.itemModelResolver = new ItemModelResolver(this.modelManager);
this.mapTextureManager = new MapTextureManager(this.textureManager);
this.mapRenderer = new MapRenderer(this.atlasManager, this.mapTextureManager);
@@ -633,6 +_,7 @@
this.palettedTextureManager = new PalettedTextureManager(this.resourceManager, this.textureManager);
this.resourceManager.registerReloadListener(this.palettedTextureManager);
@@ -648,6 +_,7 @@
this.resourceManager.registerReloadListener(particleResources);
this.particleEngine = new ParticleEngine(this.level, particleResources);
particleResources.onReload(this.particleEngine::clearParticles);
+ net.neoforged.neoforge.client.ClientHooks.onRegisterParticleProviders(particleResources);
this.gameRenderer = new GameRenderer(this, this.entityRenderDispatcher.getItemInHandRenderer(), this.modelManager);
this.gameRenderer = new GameRenderer(this, new FirstPersonHandsAndItemsRenderer(this), this.modelManager, this.itemModelResolver);
this.resourceManager.registerReloadListener(this.gameRenderer);
WindowRenderState windowRenderState = this.gameRenderer.gameRenderState().windowRenderState;
windowRenderState.width = this.window.getWidth();
@@ -654,6 +_,9 @@
this.gpuWarnlistManager = new GpuWarnlistManager();
this.resourceManager.registerReloadListener(this.gpuWarnlistManager);
this.resourceManager.registerReloadListener(this.regionalCompliancies);
+ // NEO: Moved keyboard and mouse handler setup below ingame gui creation to prevent NPEs in them.
+ this.mouseHandler.setup(this.window);
+ this.keyboardHandler.setup(this.window);
this.gui = new Gui(this, new Hud(this), this.gameRenderer.gameRenderState().guiRenderState);
this.gui.registerReloadListeners(this.resourceManager);
RealmsClient realmsClient = RealmsClient.getOrCreate(this);
@@ -688,6 +_,7 @@
}
@@ -696,6 +_,7 @@
MessageBox.error(message.toString());
}
+ net.neoforged.neoforge.client.ClientHooks.initClientHooks(this, this.resourceManager);
this.window.updateRawMouseInput(this.options.rawMouseInput().get());
this.window.setAllowCursorChanges(this.options.allowCursorChanges().get());
this.window.setDefaultErrorCallback();
@@ -704,6 +_,7 @@
this.window.setQuitShortcuts(this.options.quitShortcuts().get());
if (InputQuirks.EMULATE_RIGHT_CLICK_WITH_CTRL_KEY) {
@@ -715,6 +_,7 @@
TitleScreen.registerTextures(this.textureManager);
LoadingOverlay.registerTextures(this.textureManager);
this.gameRenderer.registerPanoramaTextures(this.textureManager);
@@ -109,7 +84,7 @@
this.timerQuery = new TimerQuery();
this.gui.setScreen(new GenericMessageScreen(Component.translatable("gui.loadingMinecraft")));
List<PackResources> packs = this.resourcePackRepository.openAllSelected();
@@ -713,7 +_,7 @@
@@ -724,7 +_,7 @@
GameLoadTimesEvent.INSTANCE.beginStep(TelemetryProperty.LOAD_TIME_LOADING_OVERLAY_MS);
GameLoadCookie loadCookie = new GameLoadCookie(realmsClient, gameConfig.quickPlay);
this.gui.setOverlay(new LoadingOverlay(this, reloadInstance, maybeT -> Util.ifElse(maybeT, t -> this.rollbackResourcePacks(t, loadCookie), () -> {
@@ -118,7 +93,7 @@
this.selfTest();
}
@@ -767,6 +_,7 @@
@@ -778,6 +_,7 @@
}
private void onResourceLoadFinished(@Nullable GameLoadCookie loadCookie) {
@@ -126,7 +101,7 @@
if (!this.gameLoadFinished) {
this.gameLoadFinished = true;
this.onGameLoadFinished(loadCookie);
@@ -802,7 +_,7 @@
@@ -813,7 +_,7 @@
private String createTitle() {
StringBuilder builder = new StringBuilder("Minecraft");
if (checkModStatus().shouldReportAsModified()) {
@@ -135,7 +110,7 @@
}
builder.append(" ");
@@ -842,7 +_,7 @@
@@ -853,7 +_,7 @@
}
private void rollbackResourcePacks(Throwable t, @Nullable GameLoadCookie loadCookie) {
@@ -144,7 +119,7 @@
this.clearResourcePacksOnError(t, null, loadCookie);
} else {
Util.throwAsRuntime(t);
@@ -898,6 +_,8 @@
@@ -909,6 +_,8 @@
DiscontinuousFrame tickFrame = TracyClient.createDiscontinuousFrame("Client Tick");
try {
@@ -153,7 +128,7 @@
boolean oomRecovery = false;
while (this.running) {
@@ -959,7 +_,7 @@
@@ -965,7 +_,7 @@
CrashReport finalReport = this.fillReport(partialReport);
int exitCode = saveReportAndShutdownSoundManager(this, this.gameDirectory, finalReport, -1);
this.emergencySave();
@@ -162,7 +137,7 @@
}
public static void saveReport(File gameDirectory, CrashReport crash) {
@@ -996,7 +_,7 @@
@@ -1002,7 +_,7 @@
public static void crash(@Nullable Minecraft minecraft, File gameDirectory, CrashReport crash, int exitCode) {
int actualExitCode = saveReportAndShutdownSoundManager(minecraft, gameDirectory, crash, exitCode);
@@ -171,7 +146,7 @@
}
public static int saveReportAndShutdownSoundManager(@Nullable Minecraft minecraft, File gameDirectory, CrashReport crash, int exitCode) {
@@ -1100,6 +_,7 @@
@@ -1106,6 +_,7 @@
public void exitWorldAndClose() {
try {
@@ -179,8 +154,8 @@
LOGGER.info("Stopping!");
if (this.level != null) {
this.level.disconnect(ClientLevel.DEFAULT_QUIT_MESSAGE);
@@ -1141,6 +_,8 @@
Util.shutdownExecutors();
@@ -1148,6 +_,8 @@
FreeTypeUtil.destroy();
this.windowSurface.close();
RenderSystem.shutdownRenderer();
+
@@ -188,7 +163,7 @@
} catch (Throwable t) {
LOGGER.error("Shutdown failure!", t);
throw t;
@@ -1220,7 +_,11 @@
@@ -1229,7 +_,11 @@
this.window.setErrorSection("Post render");
boolean var28 = this.pause;
@@ -201,17 +176,17 @@
if (!var28 && this.pause) {
this.soundManager.pauseAllExcept(SoundSource.MUSIC, SoundSource.UI);
}
@@ -1301,7 +_,9 @@
@@ -1305,7 +_,9 @@
profiler.popPush("gpuAsync");
RenderSystem.executePendingTasks();
profiler.pop();
+ net.neoforged.neoforge.client.ClientHooks.fireRenderFramePre(this.deltaTracker);
this.gameRenderer.render(this.deltaTracker, advanceGameTime);
this.gameRenderer.render();
+ net.neoforged.neoforge.client.ClientHooks.fireRenderFramePost(this.deltaTracker);
}
profiler.push("present");
@@ -1336,6 +_,7 @@
profiler.push("swapchainBlit");
@@ -1343,6 +_,7 @@
RenderSystem.getDynamicUniforms().reset();
this.levelRenderer.endFrame();
@@ -219,7 +194,7 @@
profiler.popPush("frameLimiter");
int framerateLimit = this.gameRenderer.gameRenderState().framerateLimit;
if (framerateLimit < 260) {
@@ -1423,8 +_,10 @@
@@ -1430,8 +_,10 @@
public void resizeGui() {
int guiScale = this.window.calculateScale(this.options.guiScale().get(), this.isEnforceUnicode());
this.window.setGuiScale(guiScale);
@@ -229,8 +204,8 @@
+ this.gui.resizeScreenLayers(this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
}
this.mouseHandler.setIgnoreFirstMove();
@@ -1576,6 +_,7 @@
this.mouseHandler.resyncMousePosition();
@@ -1595,6 +_,7 @@
}
public void stop() {
@@ -238,97 +213,94 @@
this.running = false;
}
@@ -1601,8 +_,16 @@
@@ -1624,7 +_,8 @@
BlockPos pos = blockHit.getBlockPos();
if (!this.level.getBlockState(pos).isAir()) {
Direction direction = blockHit.getDirection();
- if (this.gameMode.continueDestroyBlock(pos, direction)) {
- this.level.addBreakingBlockEffect(pos, direction);
+ var inputEvent = net.neoforged.neoforge.client.ClientHooks.onClickInput(0, this.options.keyAttack, InteractionHand.MAIN_HAND);
+ if (inputEvent.isCanceled()) {
+ if (inputEvent.shouldSwingHand()) {
+ this.level.addBreakingBlockEffect(pos, direction, blockHit);
+ this.player.swing(InteractionHand.MAIN_HAND);
+ }
+ return;
+ }
+ if (this.gameMode.continueDestroyBlock(pos, direction) && inputEvent.shouldSwingHand()) {
+ this.level.addBreakingBlockEffect(pos, direction, blockHit);
this.player.swing(InteractionHand.MAIN_HAND);
+ if ((inputEvent.isCanceled() || this.gameMode.continueDestroyBlock(pos, direction)) && inputEvent.shouldSwingHand()) {
this.player.swing(InteractionHand.MAIN_HAND, swingAnimation, false);
this.player.connection.send(ServerboundPunchPacket.INSTANCE);
}
}
@@ -1649,9 +_,16 @@
}
@@ -1673,8 +_,16 @@
SwingAnimation attackAnimation = heldItem.getAttackAnimation();
boolean endAttack = false;
+ var inputEvent = net.neoforged.neoforge.client.ClientHooks.onClickInput(0, this.options.keyAttack, InteractionHand.MAIN_HAND);
+ if (inputEvent.isCanceled()) {
+ if (inputEvent.shouldSwingHand())
+ this.player.swing(InteractionHand.MAIN_HAND);
+ if (inputEvent.shouldSwingHand()) {
+ this.player.swing(InteractionHand.MAIN_HAND, attackAnimation, false);
+ }
+ return endAttack;
+ }
PiercingWeapon piercingWeapon = heldItem.get(DataComponents.PIERCING_WEAPON);
if (piercingWeapon != null) {
this.gameMode.piercingAttack(piercingWeapon);
+ if (inputEvent.shouldSwingHand())
this.player.swing(InteractionHand.MAIN_HAND);
this.gameMode.piercingAttack(attackAnimation, piercingWeapon);
return true;
}
@@ -1679,8 +_,10 @@
@@ -1702,10 +_,13 @@
}
this.player.resetAttackStrengthTicker();
+ net.neoforged.neoforge.common.CommonHooks.onEmptyLeftClick(this.player);
}
+ if (inputEvent.shouldSwingHand())
this.player.swing(InteractionHand.MAIN_HAND);
+ if (inputEvent.shouldSwingHand()) {
this.player.swing(InteractionHand.MAIN_HAND, attackAnimation, false);
this.player.connection.send(ServerboundPunchPacket.INSTANCE);
+ }
return endAttack;
}
@@ -1696,6 +_,11 @@
}
}
@@ -1726,6 +_,13 @@
}
for (InteractionHand hand : InteractionHand.values()) {
SwingAnimation swingAnimation = heldItem.getInteractAnimation();
+ var inputEvent = net.neoforged.neoforge.client.ClientHooks.onClickInput(1, this.options.keyUse, hand);
+ if (inputEvent.isCanceled()) {
+ if (inputEvent.shouldSwingHand()) this.player.swing(hand);
+ if (inputEvent.shouldSwingHand()) {
+ this.player.swing(hand, swingAnimation, false);
+ }
+ return;
+ }
ItemStack heldItem = this.player.getItemInHand(hand);
if (!heldItem.isItemEnabled(this.level.enabledFeatures())) {
return;
@@ -1712,7 +_,7 @@
if (this.hitResult != null) {
switch (this.hitResult.getType()) {
case ENTITY:
@@ -1737,7 +_,7 @@
if (this.player.isWithinEntityInteractionRange(entity, 0.0)
&& this.gameMode.interact(this.player, entity, entityHit, hand) instanceof InteractionResult.Success success) {
- if (success.swingSource() == InteractionResult.SwingSource.CLIENT) {
+ if (success.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
this.player.swing(hand);
- if (success.swingSource() == InteractionResult.SwingSource.PREDICTED) {
+ if (success.swingSource() == InteractionResult.SwingSource.PREDICTED && inputEvent.shouldSwingHand()) {
this.player.swing(hand, swingAnimation, false);
}
@@ -1724,7 +_,7 @@
@@ -1749,7 +_,7 @@
int oldCount = heldItem.getCount();
InteractionResult useResult = this.gameMode.useItemOn(this.player, hand, blockHit);
if (useResult instanceof InteractionResult.Success success) {
- if (success.swingSource() == InteractionResult.SwingSource.CLIENT) {
+ if (success.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
this.player.swing(hand);
- if (success.swingSource() == InteractionResult.SwingSource.PREDICTED) {
+ if (success.swingSource() == InteractionResult.SwingSource.PREDICTED && inputEvent.shouldSwingHand()) {
this.player.swing(hand, swingAnimation, false);
if (!heldItem.isEmpty() && (heldItem.getCount() != oldCount || this.player.hasInfiniteMaterials())) {
this.gameRenderer.itemInHandRenderer.itemUsed(hand);
@@ -1740,8 +_,11 @@
this.player.itemUsed(hand);
@@ -1765,8 +_,12 @@
}
}
+ if (heldItem.isEmpty() && (this.hitResult == null || this.hitResult.getType() == HitResult.Type.MISS))
+ if (heldItem.isEmpty() && (this.hitResult == null || this.hitResult.getType() == HitResult.Type.MISS)) {
+ net.neoforged.neoforge.common.CommonHooks.onEmptyClick(this.player, hand);
+ }
+
if (!heldItem.isEmpty() && this.gameMode.useItem(this.player, hand) instanceof InteractionResult.Success success) {
- if (success.swingSource() == InteractionResult.SwingSource.CLIENT) {
+ if (success.swingSource() == InteractionResult.SwingSource.CLIENT && inputEvent.shouldSwingHand()) {
this.player.swing(hand);
- if (success.swingSource() == InteractionResult.SwingSource.PREDICTED) {
+ if (success.swingSource() == InteractionResult.SwingSource.PREDICTED && inputEvent.shouldSwingHand()) {
this.player.swing(hand, swingAnimation, false);
}
@@ -1759,6 +_,10 @@
@@ -1784,6 +_,10 @@
public void tick() {
this.clientTickCount++;
@@ -339,7 +311,7 @@
if (this.level != null && !this.pause) {
this.level.tickRateManager().tick();
}
@@ -1817,6 +_,7 @@
@@ -1845,6 +_,7 @@
this.tutorial.tick();
@@ -347,7 +319,7 @@
try {
this.level.tick(() -> true);
} catch (Throwable t) {
@@ -1830,6 +_,7 @@
@@ -1858,6 +_,7 @@
throw new ReportedException(report);
}
@@ -355,7 +327,7 @@
}
profiler.popPush("animateTick");
@@ -1854,6 +_,10 @@
@@ -1882,6 +_,10 @@
profiler.popPush("keyboard");
this.keyboardHandler.tick();
profiler.pop();
@@ -366,7 +338,7 @@
}
private boolean isLevelRunningNormally() {
@@ -2059,6 +_,7 @@
@@ -2088,6 +_,7 @@
}
public void setLevel(ClientLevel level) {
@@ -374,7 +346,7 @@
this.level = level;
this.updateLevelInEngines(level);
}
@@ -2120,13 +_,16 @@
@@ -2149,13 +_,16 @@
IntegratedServer server = this.singleplayerServer;
this.singleplayerServer = null;
this.gameRenderer.resetData();
@@ -391,7 +363,7 @@
}
this.level = null;
@@ -2150,6 +_,7 @@
@@ -2180,6 +_,7 @@
} finally {
this.gui.setClientLevelTeardownInProgress(false);
}
@@ -399,7 +371,7 @@
}
public void clearDownloadedResourcePacks() {
@@ -2175,6 +_,7 @@
@@ -2205,6 +_,7 @@
try {
this.setScreenAndShow(screen);
this.gui.hud.onDisconnected();
@@ -407,7 +379,7 @@
this.level = null;
this.updateLevelInEngines(null);
this.player = null;
@@ -2354,6 +_,7 @@
@@ -2403,6 +_,7 @@
private void pickBlockOrEntity() {
if (this.hitResult != null && this.hitResult.getType() != HitResult.Type.MISS) {
@@ -415,7 +387,7 @@
boolean includeData = this.hasControlDown();
switch (this.hitResult) {
case BlockHitResult blockHitResult:
@@ -2903,6 +_,10 @@
@@ -2957,6 +_,10 @@
}
return defaultTickTargetMillis;
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/MouseHandler.java
+++ b/net/minecraft/client/MouseHandler.java
@@ -77,6 +_,8 @@
@@ -79,6 +_,8 @@
this.activeButton = null;
}
@@ -8,8 +8,8 @@
+ boolean screenHandled = false;
if (this.minecraft.gui.overlay() == null) {
if (pressed
&& this.minecraft.handleGlobalKeyPress(InputConstants.Type.MOUSE.getOrCreate(buttonInfo.button()), buttonInfo.hasControlDownWithQuirk())) {
@@ -101,10 +_,14 @@
&& this.minecraft
@@ -104,10 +_,14 @@
&& currentTime - this.lastClick.time() < 250L
&& this.lastClick.screen() == screen
&& this.lastClickButton == event.button();
@@ -21,12 +21,12 @@
+ }
+ if (screenHandled) {
this.lastClick = new MouseHandler.LastClick(currentTime, screen);
this.lastClickButton = buttonInfo.button();
this.lastClickButton = rawButtonInfo.button();
- return;
}
} catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "mouseClicked event handler");
@@ -116,8 +_,10 @@
@@ -118,8 +_,10 @@
}
} else {
try {
@@ -39,7 +39,7 @@
}
} catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "mouseReleased event handler");
@@ -131,6 +_,10 @@
@@ -132,6 +_,10 @@
}
}
@@ -48,9 +48,9 @@
+ // vanilla's fallback handle it
+ if (!screenHandled) {
if (this.minecraft.gui.screen() == null && this.minecraft.gui.overlay() == null) {
if (buttonInfo.button() == 0) {
if (rawButtonInfo.button() == 1) {
this.isLeftPressed = pressed;
@@ -146,6 +_,8 @@
@@ -147,6 +_,8 @@
KeyMapping.click(mouseKey);
}
}
@@ -59,7 +59,7 @@
}
}
@@ -197,7 +_,11 @@
@@ -182,7 +_,11 @@
if (this.minecraft.gui.screen() != null) {
double xm = this.getScaledXPos(this.minecraft.getWindow());
double ym = this.getScaledYPos(this.minecraft.getWindow());
@@ -72,7 +72,7 @@
this.minecraft.gui.screen().afterMouseAction();
} else if (this.minecraft.player != null) {
Vector2i wheelXY = this.scrollWheelHandler.onMouseScroll(scaledXOffset, scaledYOffset);
@@ -206,6 +_,7 @@
@@ -191,6 +_,7 @@
}
int wheel = wheelXY.y == 0 ? -wheelXY.x : wheelXY.y;
@@ -80,7 +80,7 @@
if (this.minecraft.player.isSpectator()) {
if (this.minecraft.gui.hud.getSpectatorGui().isMenuActive()) {
this.minecraft.gui.hud.getSpectatorGui().onMouseScrolled(-wheel);
@@ -312,7 +_,12 @@
@@ -285,7 +_,12 @@
double dy = getScaledYPos(window, this.accumulatedDY);
try {
@@ -93,8 +93,8 @@
+ }
} catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "mouseDragged event handler");
screen.fillCrashDetails(report);
@@ -351,12 +_,13 @@
CrashReportCategory mouseDetails = report.addCategory("Mouse");
@@ -323,12 +_,13 @@
}
private void turnPlayer(double mousea) {
@@ -110,7 +110,7 @@
double dx = this.smoothTurnX.getNewDeltaValue(this.accumulatedDX * sens, mousea * sens);
double dy = this.smoothTurnY.getNewDeltaValue(this.accumulatedDY * sens, mousea * sens);
xo = dx;
@@ -397,6 +_,14 @@
@@ -369,6 +_,14 @@
public double ypos() {
return this.ypos;
+16 -15
View File
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/Options.java
+++ b/net/minecraft/client/Options.java
@@ -1095,7 +_,7 @@
@@ -1119,7 +_,7 @@
this.incompatibleResourcePacks.clear();
for (Pack entry : packRepository.getSelectedPacks()) {
@@ -9,7 +9,7 @@
this.resourcePacks.add(entry.getId());
if (!entry.getCompatibility().isCompatible()) {
this.incompatibleResourcePacks.add(entry.getId());
@@ -1474,6 +_,7 @@
@@ -1510,6 +_,7 @@
}
public Options(Minecraft minecraft, File workingDirectory) {
@@ -17,7 +17,7 @@
this.minecraft = minecraft;
this.optionsFile = new File(workingDirectory, "options.txt");
boolean largeDistances = Runtime.getRuntime().maxMemory() >= 1000000000L;
@@ -1494,6 +_,7 @@
@@ -1530,6 +_,7 @@
var1 -> this.setGraphicsPresetToCustom()
);
this.syncWrites = Util.getPlatform() == Util.OS.WINDOWS;
@@ -25,7 +25,7 @@
this.load();
}
@@ -1626,10 +_,15 @@
@@ -1665,11 +_,17 @@
access.process("musicFrequency", this.musicFrequency);
for (KeyMapping keyMapping : this.keyMappings) {
@@ -33,17 +33,18 @@
+ String currentValue = keyMapping.saveString() + (keyMapping.getKeyModifier() != net.neoforged.neoforge.client.settings.KeyModifier.NONE ? ":" + keyMapping.getKeyModifier() : "");
String newValue = access.process("key_" + keyMapping.getName(), currentValue);
if (!currentValue.equals(newValue)) {
- keyMapping.setKey(InputConstants.getKey(newValue));
+ if (newValue.indexOf(':') != -1) {
+ String[] pts = newValue.split(":");
+ keyMapping.setKeyModifierAndCode(net.neoforged.neoforge.client.settings.KeyModifier.valueFromString(pts[1]), InputConstants.getKey(pts[0]));
+ } else {
+ keyMapping.setKeyModifierAndCode(net.neoforged.neoforge.client.settings.KeyModifier.NONE, InputConstants.getKey(newValue));
+ }
}
}
@@ -1924,6 +_,23 @@
try {
keyMapping.setKey(InputConstants.getKey(newValue));
+ if (newValue.indexOf(':') != -1) {
+ String[] pts = newValue.split(":");
+ keyMapping.setKeyModifierAndCode(net.neoforged.neoforge.client.settings.KeyModifier.valueFromString(pts[1]), InputConstants.getKey(pts[0]));
+ } else {
+ keyMapping.setKeyModifierAndCode(net.neoforged.neoforge.client.settings.KeyModifier.NONE, InputConstants.getKey(newValue));
+ }
} catch (IllegalArgumentException e) {
LOGGER.warn("Invalid keyMapping {} = {}, unbinding", keyMapping.getName(), newValue, e);
keyMapping.setKey(InputConstants.UNKNOWN);
@@ -1967,6 +_,23 @@
}
repository.setSelected(selected);
@@ -1,8 +1,8 @@
--- a/net/minecraft/client/color/item/ItemTintSources.java
+++ b/net/minecraft/client/color/item/ItemTintSources.java
@@ -21,5 +_,7 @@
@@ -20,5 +_,7 @@
ID_MAPPER.put(Identifier.withDefaultNamespace("firework"), Firework.MAP_CODEC);
ID_MAPPER.put(Identifier.withDefaultNamespace("potion"), Potion.MAP_CODEC);
ID_MAPPER.put(Identifier.withDefaultNamespace("map_color"), MapColor.MAP_CODEC);
ID_MAPPER.put(Identifier.withDefaultNamespace("team"), TeamColor.MAP_CODEC);
+
+ net.neoforged.fml.ModLoader.postEvent(new net.neoforged.neoforge.client.event.RegisterColorHandlersEvent.ItemTintSources(ID_MAPPER));
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/data/Main.java
+++ b/net/minecraft/client/data/Main.java
@@ -28,17 +_,37 @@
@@ -28,17 +_,38 @@
OptionSpec<Void> clientOption = parser.accepts("client", "Include client generators");
OptionSpec<Void> allOption = parser.accepts("all", "Include all generators");
OptionSpec<String> outputOption = parser.accepts("output", "Output folder").withRequiredArg().defaultsTo("generated");
@@ -36,8 +36,9 @@
+ ClientBootstrap.bootstrap();
+ net.neoforged.neoforge.client.ClientHooks.initClientRegistries();
+ }, net.neoforged.neoforge.data.event.GatherDataEvent.Client::new, generator, packConsumer -> {
+ if (assetsDirValue != null && assetIndexValue != null)
+ packConsumer.accept(net.minecraft.client.resources.ClientPackSource.createVanillaPackSource(net.minecraft.client.resources.IndexedAssetSource.createIndexFs(assetsDirValue.toPath(), assetIndexValue)));
+ if (assetsDirValue != null && assetIndexValue != null) {
+ packConsumer.accept(net.minecraft.client.resources.ClientPackSource.createVanillaPackSource(net.minecraft.client.resources.IndexedAssetSource.createIndexFs(assetsDirValue.toPath(), assetIndexValue)).fullResources());
+ }
+ });
} else {
parser.printHelpOn(System.out);
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/data/models/BlockModelGenerators.java
+++ b/net/minecraft/client/data/models/BlockModelGenerators.java
@@ -4554,4 +_,16 @@
@@ -4623,4 +_,16 @@
return this;
}
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/data/models/EquipmentAssetProvider.java
+++ b/net/minecraft/client/data/models/EquipmentAssetProvider.java
@@ -26,6 +_,10 @@
@@ -27,6 +_,10 @@
this.pathProvider = output.createPathProvider(PackOutput.Target.RESOURCE_PACK, "equipment");
}
@@ -11,23 +11,22 @@
private static void bootstrap(BiConsumer<ResourceKey<EquipmentAsset>, EquipmentClientInfo> consumer) {
consumer.accept(
EquipmentAssets.LEATHER,
@@ -127,21 +_,21 @@
@@ -140,20 +_,20 @@
}
public static EquipmentClientInfo onlyHumanoid(String name) {
- return EquipmentClientInfo.builder().addHumanoidLayers(Identifier.withDefaultNamespace(name)).build();
+ return EquipmentClientInfo.builder().addHumanoidLayers(Identifier.parse(name)).build();
public static EquipmentClientInfo.Builder onlyHumanoid(String name) {
- return EquipmentClientInfo.builder().addHumanoidLayers(Identifier.withDefaultNamespace(name));
+ return EquipmentClientInfo.builder().addHumanoidLayers(Identifier.parse(name));
}
public static EquipmentClientInfo humanoidAndMountArmor(String name) {
public static EquipmentClientInfo.Builder humanoidAndMountArmor(String name) {
return EquipmentClientInfo.builder()
- .addHumanoidLayers(Identifier.withDefaultNamespace(name))
- .addLayers(EquipmentClientInfo.LayerType.HORSE_BODY, EquipmentClientInfo.Layer.leatherDyeable(Identifier.withDefaultNamespace(name), false))
- .addLayers(EquipmentClientInfo.LayerType.NAUTILUS_BODY, EquipmentClientInfo.Layer.leatherDyeable(Identifier.withDefaultNamespace(name), false))
- .addLayers(EquipmentClientInfo.LayerType.NAUTILUS_BODY, EquipmentClientInfo.Layer.leatherDyeable(Identifier.withDefaultNamespace(name), false));
+ .addHumanoidLayers(Identifier.parse(name))
+ .addLayers(EquipmentClientInfo.LayerType.HORSE_BODY, EquipmentClientInfo.Layer.leatherDyeable(Identifier.parse(name), false))
+ .addLayers(EquipmentClientInfo.LayerType.NAUTILUS_BODY, EquipmentClientInfo.Layer.leatherDyeable(Identifier.parse(name), false))
.build();
+ .addLayers(EquipmentClientInfo.LayerType.NAUTILUS_BODY, EquipmentClientInfo.Layer.leatherDyeable(Identifier.parse(name), false));
}
@Override
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/data/models/ItemModelGenerators.java
+++ b/net/minecraft/client/data/models/ItemModelGenerators.java
@@ -232,6 +_,49 @@
@@ -251,6 +_,49 @@
this.itemModelOutput.accept(armor, ItemModelUtils.select(new TrimMaterialProperty(), untrimmedModel, cases));
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/data/models/model/ModelTemplates.java
+++ b/net/minecraft/client/data/models/model/ModelTemplates.java
@@ -249,18 +_,18 @@
@@ -251,18 +_,18 @@
}
public static ModelTemplate create(String id, TextureSlot... slots) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/Gui.java
+++ b/net/minecraft/client/gui/Gui.java
@@ -78,6 +_,8 @@
@@ -83,6 +_,8 @@
private final ToastManager toastManager;
private final ChatListener chatListener;
private @Nullable TutorialToast socialInteractionsToast;
@@ -9,7 +9,7 @@
public Gui(Minecraft minecraft, Hud hud, GuiRenderState guiRenderState) {
this.minecraft = minecraft;
@@ -175,7 +_,8 @@
@@ -174,7 +_,8 @@
profiler.push("screen");
try {
@@ -19,18 +19,20 @@
} catch (Throwable t) {
CrashReport report = CrashReport.forThrowable(t, "Rendering screen");
CrashReportCategory category = report.addCategory("Screen render details");
@@ -224,9 +_,7 @@
LOGGER.error("setScreen called from non-game thread");
@@ -228,11 +_,7 @@
this.screenTracySection = null;
}
- if (this.screen != null) {
- this.screen.clearFocus();
- this.minecraft.textInputManager().stopTextInput();
- this.screen.removed();
- } else {
+ if (this.screen == null) {
this.minecraft.setLastInputType(InputType.NONE);
}
@@ -248,6 +_,19 @@
@@ -254,6 +_,21 @@
}
}
@@ -44,13 +46,15 @@
+
+ if (old != null && screen != old) {
+ net.neoforged.neoforge.common.NeoForge.EVENT_BUS.post(new net.neoforged.neoforge.client.event.ScreenEvent.Closing(old));
+ old.clearFocus();
+ this.minecraft.textInputManager().stopTextInput();
+ old.removed();
+ }
+
this.screen = screen;
if (this.screen != null) {
this.screen.added();
@@ -375,6 +_,8 @@
@@ -384,6 +_,8 @@
nextStep = () -> this.setScreen(screen);
}
@@ -59,7 +63,7 @@
return nextStep;
}
@@ -465,5 +_,48 @@
@@ -474,5 +_,48 @@
}
)
);
@@ -8,7 +8,7 @@
private GuiGraphicsExtractor(Minecraft minecraft, Matrix3x2fStack pose, GuiRenderState guiRenderState, int mouseX, int mouseY) {
this.minecraft = minecraft;
@@ -877,6 +_,7 @@
@@ -879,6 +_,7 @@
this.itemCooldown(itemStack, x, y);
this.itemCount(font, itemStack, x, y, countText);
this.pose.popMatrix();
@@ -16,42 +16,55 @@
}
}
@@ -1017,9 +_,21 @@
@@ -1020,9 +_,34 @@
}
public void setTooltipForNextFrame(Font font, ItemStack itemStack, int xo, int yo) {
+ this.tooltipStack = itemStack;
this.setTooltipForNextFrame(
font, Screen.getTooltipFromItem(this.minecraft, itemStack), itemStack.getTooltipImage(), xo, yo, itemStack.get(DataComponents.TOOLTIP_STYLE)
font, Screen.getTooltipFromItem(this.minecraft, itemStack), itemStack.getTooltipImage(), xo, yo, itemStack.get(DataComponents.TOOLTIP_STYLE), true
);
+ this.tooltipStack = ItemStack.EMPTY;
+ }
+
+ public void setTooltipForNextFrame(Font font, List<Component> textComponents, Optional<TooltipComponent> tooltipComponent, ItemStack stack, int mouseX, int mouseY) {
+ setTooltipForNextFrame(font, textComponents, tooltipComponent, stack, mouseX, mouseY, null);
+ public void setTooltipForNextFrame(Font font, List<Component> texts, Optional<TooltipComponent> optionalImage, ItemStack stack, int mouseX, int mouseY) {
+ setTooltipForNextFrame(font, texts, optionalImage, stack, mouseX, mouseY, null);
+ }
+
+ public void setTooltipForNextFrame(Font font, List<Component> textComponents, Optional<TooltipComponent> tooltipComponent, ItemStack stack, int mouseX, int mouseY, @Nullable Identifier backgroundTexture) {
+ public void setTooltipForNextFrame(Font font, List<Component> texts, Optional<TooltipComponent> optionalImage, ItemStack stack, int mouseX, int mouseY, @Nullable Identifier style) {
+ this.setTooltipForNextFrame(font, texts, optionalImage, stack, mouseX, mouseY, style, false);
+ }
+
+ public void setTooltipForNextFrame(
+ Font font,
+ List<Component> texts,
+ Optional<TooltipComponent> optionalImage,
+ ItemStack stack,
+ int mouseX,
+ int mouseY,
+ @Nullable Identifier style,
+ boolean extraSpaceAfterFirstLine
+ ) {
+ this.tooltipStack = stack;
+ this.setTooltipForNextFrame(font, textComponents, tooltipComponent, mouseX, mouseY, backgroundTexture);
+ this.setTooltipForNextFrame(font, texts, optionalImage, mouseX, mouseY, style, extraSpaceAfterFirstLine);
+ this.tooltipStack = ItemStack.EMPTY;
}
public void setTooltipForNextFrame(Font font, List<Component> texts, Optional<TooltipComponent> optionalImage, int xo, int yo) {
@@ -1027,11 +_,7 @@
}
public void setTooltipForNextFrame(Font font, List<Component> texts, Optional<TooltipComponent> optionalImage, int xo, int yo, @Nullable Identifier style) {
@@ -1042,11 +_,7 @@
@Nullable Identifier style,
boolean extraSpaceAfterFirstLine
) {
- List<ClientTooltipComponent> components = texts.stream()
- .map(Component::getVisualOrderText)
- .map(ClientTooltipComponent::create)
- .collect(Util.toMutableList());
- optionalImage.ifPresent(image -> components.add(components.isEmpty() ? 0 : 1, ClientTooltipComponent.create(image)));
+ List<ClientTooltipComponent> components = net.neoforged.neoforge.client.ClientHooks.gatherTooltipComponents(this.tooltipStack, texts, optionalImage, xo, guiWidth(), guiHeight(), font);
this.setTooltipForNextFrameInternal(font, components, xo, yo, DefaultTooltipPositioner.INSTANCE, style, false);
this.setTooltipForNextFrameInternal(font, components, xo, yo, DefaultTooltipPositioner.INSTANCE, style, false, extraSpaceAfterFirstLine);
}
@@ -1059,13 +_,14 @@
@@ -1074,13 +_,14 @@
}
public void setComponentTooltipForNextFrame(Font font, List<Component> lines, int xo, int yo) {
@@ -68,7 +81,7 @@
xo,
yo,
DefaultTooltipPositioner.INSTANCE,
@@ -1074,6 +_,28 @@
@@ -1089,6 +_,28 @@
);
}
@@ -97,22 +110,33 @@
public void setTooltipForNextFrame(Font font, List<? extends FormattedCharSequence> lines, int xo, int yo) {
this.setTooltipForNextFrame(font, lines, xo, yo, null);
}
@@ -1097,12 +_,24 @@
@@ -1125,7 +_,8 @@
) {
if (!lines.isEmpty()) {
if (this.deferredTooltip == null || replaceExisting) {
- this.deferredTooltip = () -> this.tooltip(font, lines, xo, yo, positioner, style);
- this.deferredTooltip = () -> this.tooltip(font, lines, xo, yo, positioner, style, extraSpaceAfterFirstLine);
+ ItemStack capturedTooltipStack = this.tooltipStack;
+ this.deferredTooltip = () -> this.tooltip(font, lines, xo, yo, positioner, style, capturedTooltipStack);
+ this.deferredTooltip = () -> this.tooltip(font, lines, xo, yo, positioner, style, extraSpaceAfterFirstLine, capturedTooltipStack);
}
}
}
public void tooltip(Font font, List<ClientTooltipComponent> lines, int xo, int yo, ClientTooltipPositioner positioner, @Nullable Identifier style) {
+ this.tooltip(font, lines, xo, yo, positioner, style, ItemStack.EMPTY);
@@ -1139,6 +_,26 @@
@Nullable Identifier style,
boolean extraSpaceAfterFirstLine
) {
+ this.tooltip(font, lines, xo, yo, positioner, style, extraSpaceAfterFirstLine, ItemStack.EMPTY);
+ }
+
+ public void tooltip(Font font, List<ClientTooltipComponent> lines, int xo, int yo, ClientTooltipPositioner positioner, @Nullable Identifier style, ItemStack tooltipStack) {
+ public void tooltip(
+ Font font,
+ List<ClientTooltipComponent> lines,
+ int xo,
+ int yo,
+ ClientTooltipPositioner positioner,
+ @Nullable Identifier style,
+ boolean extraSpaceAfterFirstLine,
+ ItemStack tooltipStack
+ ) {
+ var preEvent = net.neoforged.neoforge.client.ClientHooks.onRenderTooltipPre(tooltipStack, this, xo, yo, guiWidth(), guiHeight(), lines, font, positioner);
+ if (preEvent.isCanceled()) return;
+
@@ -121,9 +145,9 @@
+ yo = preEvent.getY();
+
int textWidth = 0;
int tempHeight = lines.size() == 1 ? -2 : 0;
int tempHeight = extraSpaceAfterFirstLine && lines.size() != 1 ? 0 : -2;
@@ -1121,7 +_,8 @@
@@ -1157,7 +_,8 @@
int x = positionedTooltip.x();
int y = positionedTooltip.y();
this.pose.pushMatrix();
@@ -133,7 +157,7 @@
int localY = y;
for (int i = 0; i < lines.size(); i++) {
@@ -1183,6 +_,31 @@
@@ -1219,6 +_,31 @@
default:
}
}
+21 -21
View File
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/Hud.java
+++ b/net/minecraft/client/gui/Hud.java
@@ -85,6 +_,8 @@
@@ -86,6 +_,8 @@
import org.jspecify.annotations.Nullable;
import net.neoforged.fml.common.asm.enumextension.IExtensibleEnum;
@@ -9,7 +9,7 @@
@OnlyIn(Dist.CLIENT)
public class Hud {
@@ -180,6 +_,11 @@
@@ -181,6 +_,11 @@
private Pair<Hud.ContextualInfo, ContextualBar> contextualInfoBar = Pair.of(Hud.ContextualInfo.EMPTY, ContextualBar.EMPTY);
private final Map<Hud.ContextualInfo, Supplier<ContextualBar>> contextualInfoBars;
private float scopeScale;
@@ -21,7 +21,7 @@
public Hud(Minecraft minecraft) {
this.minecraft = minecraft;
@@ -200,6 +_,7 @@
@@ -201,6 +_,7 @@
() -> new JumpableVehicleBar(minecraft)
);
this.resetTitleTimes();
@@ -29,7 +29,7 @@
}
public void registerReloadListeners(ReloadableResourceManager resourceManager) {
@@ -223,28 +_,48 @@
@@ -224,28 +_,48 @@
public void extractRenderState(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker) {
this.minecraft.gameRenderer.gameRenderState().guiRenderState.isHudHidden = this.isHidden;
if (!(this.minecraft.gui.screen() instanceof LevelLoadingScreen)) {
@@ -96,7 +96,7 @@
}
private void extractBossOverlay(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker) {
@@ -288,8 +_,12 @@
@@ -289,8 +_,12 @@
for (EquipmentSlot slot : EquipmentSlot.values()) {
ItemStack item = player.getItemBySlot(slot);
Equippable equippable = item.get(DataComponents.EQUIPPABLE);
@@ -110,7 +110,7 @@
}
}
}
@@ -342,7 +_,11 @@
@@ -343,7 +_,11 @@
if (alpha > 0) {
graphics.nextStratum();
graphics.pose().pushMatrix();
@@ -123,7 +123,7 @@
int color;
if (this.animateOverlayMessageColor) {
color = Mth.hsvToArgb(t / 50.0F, 0.7F, 0.6F, alpha);
@@ -403,10 +_,19 @@
@@ -404,10 +_,19 @@
private void extractChat(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker) {
if (this.minecraft.player != null && !this.chat.isChatFocused()) {
Window window = this.minecraft.getWindow();
@@ -143,7 +143,7 @@
}
}
@@ -498,6 +_,8 @@
@@ -501,6 +_,8 @@
int harmfulCount = 0;
for (MobEffectInstance instance : Ordering.natural().reverse().sortedCopy(activeEffects)) {
@@ -152,7 +152,7 @@
Holder<MobEffect> effect = instance.getEffect();
if (instance.showIcon()) {
int x = graphics.guiWidth();
@@ -529,6 +_,7 @@
@@ -532,6 +_,7 @@
}
}
@@ -160,7 +160,7 @@
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, getMobEffectSprite(effect), x + 3, y + 3, 18, 18, ARGB.white(alpha));
}
}
@@ -539,32 +_,51 @@
@@ -542,32 +_,51 @@
return effect.unwrapKey().map(ResourceKey::identifier).map(id -> id.withPrefix("mob_effect/")).orElseGet(MissingTextureAtlasSprite::getLocation);
}
@@ -221,7 +221,7 @@
this.spectatorGui.extractAction(graphics);
}
}
@@ -631,15 +_,20 @@
@@ -634,15 +_,20 @@
}
private void extractSelectedItemName(GuiGraphicsExtractor graphics) {
@@ -245,7 +245,7 @@
if (!this.minecraft.gameMode.canHurtPlayer()) {
y += 14;
}
@@ -650,7 +_,13 @@
@@ -653,7 +_,13 @@
}
if (alpha > 0) {
@@ -260,7 +260,7 @@
}
}
}
@@ -767,7 +_,15 @@
@@ -770,7 +_,15 @@
return (int)Math.ceil(hearts / 10.0);
}
@@ -276,7 +276,7 @@
Player player = this.getCameraPlayer();
if (player != null) {
int currentHealth = Mth.ceil(player.getHealth());
@@ -791,33 +_,62 @@
@@ -794,33 +_,62 @@
this.random.setSeed(this.tickCount * 312871);
int xLeft = graphics.guiWidth() / 2 - 91;
int xRight = graphics.guiWidth() / 2 + 91;
@@ -347,7 +347,7 @@
Profiler.get().pop();
}
}
@@ -906,7 +_,7 @@
@@ -909,7 +_,7 @@
private void extractAirBubbles(GuiGraphicsExtractor graphics, Player player, int vehicleHearts, int yLineAir, int xRight) {
int maxAirSupplyTicks = player.getMaxAirSupply();
int currentAirSupplyTicks = Math.clamp(player.getAirSupply(), 0, maxAirSupplyTicks);
@@ -356,7 +356,7 @@
if (isUnderWater || currentAirSupplyTicks < maxAirSupplyTicks) {
yLineAir = this.getAirBubbleYLine(vehicleHearts, yLineAir);
int fullAirBubbles = getCurrentAirSupplyBubble(currentAirSupplyTicks, maxAirSupplyTicks, -2);
@@ -930,6 +_,8 @@
@@ -933,6 +_,8 @@
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, AIR_EMPTY_SPRITE, airBubbleXPos, yLineAir + wobbleYOffset, 9, 9);
}
}
@@ -365,7 +365,7 @@
}
}
@@ -997,7 +_,7 @@
@@ -1000,7 +_,7 @@
if (hearts != 0) {
int currentHealth = (int)Math.ceil(vehicleWithHearts.getHealth());
Profiler.get().popPush("mountHealth");
@@ -374,7 +374,7 @@
int xRight = graphics.guiWidth() / 2 + 91;
int yo = yLine1;
@@ -1018,6 +_,7 @@
@@ -1021,6 +_,7 @@
}
yo -= 10;
@@ -382,7 +382,7 @@
}
}
}
@@ -1050,7 +_,9 @@
@@ -1053,7 +_,9 @@
int top = (graphics.guiHeight() - height) / 2;
int right = left + width;
int bottom = top + height;
@@ -393,7 +393,7 @@
graphics.fill(RenderPipelines.GUI, 0, bottom, graphics.guiWidth(), graphics.guiHeight(), -16777216);
graphics.fill(RenderPipelines.GUI, 0, 0, graphics.guiWidth(), top, -16777216);
graphics.fill(RenderPipelines.GUI, 0, top, left, bottom, -16777216);
@@ -1199,7 +_,7 @@
@@ -1202,7 +_,7 @@
this.toolHighlightTimer = 0;
} else if (this.lastToolHighlight.isEmpty()
|| !selected.is(this.lastToolHighlight.getItem())
@@ -402,7 +402,7 @@
this.toolHighlightTimer = (int)(40.0 * this.minecraft.options.notificationDisplayTime().get());
} else if (this.toolHighlightTimer > 0) {
this.toolHighlightTimer--;
@@ -1476,7 +_,18 @@
@@ -1479,7 +_,18 @@
type = NORMAL;
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/components/EditBox.java
+++ b/net/minecraft/client/gui/components/EditBox.java
@@ -630,6 +_,10 @@
@@ -632,6 +_,10 @@
this.hint = hasNoStyle ? hint.copy().withStyle(DEFAULT_HINT_STYLE) : hint;
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/components/debug/DebugScreenEntries.java
+++ b/net/minecraft/client/gui/components/debug/DebugScreenEntries.java
@@ -56,6 +_,13 @@
@@ -57,6 +_,13 @@
public static final Identifier VISUALIZE_SKY_LIGHT_SECTIONS = register("visualize_sky_light_sections", new DebugEntryNoop());
public static final Identifier CHUNK_SECTION_VISIBILITY = register("chunk_section_visibility", new DebugEntryNoop());
public static final Map<DebugScreenProfile, Map<Identifier, DebugScreenEntryStatus>> PROFILES;
@@ -14,7 +14,7 @@
private static Identifier register(String id, DebugScreenEntry entry) {
return register(Identifier.withDefaultNamespace(id), entry);
@@ -107,6 +_,23 @@
@@ -108,6 +_,23 @@
SIMPLE_PERFORMANCE_IMPACTORS,
DebugScreenEntryStatus.IN_OVERLAY
);
@@ -29,7 +29,7 @@
}
public void endFrame() {
@@ -134,6 +_,7 @@
@@ -135,6 +_,7 @@
this.renderState.reset();
this.firstDrawIndexAfterBlur = Integer.MAX_VALUE;
this.clearUnusedOversizedItemRenderers();
@@ -37,7 +37,7 @@
if (SharedConstants.DEBUG_SHUFFLE_UI_RENDERING_ORDER) {
RenderPipeline.updateSortKeySeed();
TextureSetup.updateSortKeySeed();
@@ -224,6 +_,7 @@
@@ -229,6 +_,7 @@
ScreenRectangle scissorArea = elementState.scissorArea();
if (this.previousDraw == null
|| pipeline != this.previousPipeline
@@ -45,7 +45,7 @@
|| this.scissorChanged(scissorArea, this.previousScissorArea)
|| !textureSetup.equals(this.previousTextureSetup)) {
this.previousPipeline = pipeline;
@@ -287,14 +_,31 @@
@@ -292,14 +_,31 @@
private void preparePictureInPicture() {
int guiScale = Minecraft.getInstance().gameRenderer.gameRenderState().windowRenderState.guiScale;
@@ -80,7 +80,7 @@
}
private void submitBlitFromItemAtlas(GuiItemRenderState itemState, GuiItemAtlas.SlotView slotView) {
@@ -422,7 +_,7 @@
@@ -427,7 +_,7 @@
this.itemAtlas = null;
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/render/pip/PictureInPictureRenderer.java
+++ b/net/minecraft/client/gui/render/pip/PictureInPictureRenderer.java
@@ -96,7 +_,9 @@
@@ -105,7 +_,9 @@
if (this.texture == null) {
this.texture = device.createTexture(() -> "UI " + this.getTextureLabel() + " texture", 13, GpuFormat.RGBA8_UNORM, width, height, 1, 1);
this.textureView = device.createTextureView(this.texture);
@@ -11,7 +11,7 @@
this.depthTextureView = device.createTextureView(this.depthTexture);
}
@@ -139,4 +_,11 @@
@@ -148,4 +_,11 @@
protected abstract void renderToTexture(T renderState, PoseStack poseStack, SubmitNodeCollector submitNodeCollector);
protected abstract String getTextureLabel();
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/PauseScreen.java
+++ b/net/minecraft/client/gui/screens/PauseScreen.java
@@ -102,6 +_,7 @@
@@ -109,6 +_,7 @@
helper.addChild(this.openScreenButton(ADVANCEMENTS, () -> new AdvancementsScreen(this.minecraft.player.connection.getAdvancements(), this)));
helper.addChild(this.openScreenButton(STATS, () -> new StatsScreen(this, this.minecraft.player.getStats())));
LinearLayout iconButtonRow = LinearLayout.horizontal().spacing(4);
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/Screen.java
+++ b/net/minecraft/client/gui/screens/Screen.java
@@ -107,8 +_,12 @@
@@ -108,8 +_,12 @@
public final void extractRenderStateWithTooltipAndSubtitles(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
graphics.nextStratum();
this.extractBackground(graphics, mouseX, mouseY, a);
@@ -13,7 +13,7 @@
graphics.extractDeferredElements(mouseX, mouseY, a);
}
@@ -196,7 +_,7 @@
@@ -202,7 +_,7 @@
}
public void onClose() {
@@ -22,7 +22,7 @@
}
protected <T extends GuiEventListener & Renderable & NarratableEntry> T addRenderableWidget(T widget) {
@@ -239,9 +_,9 @@
@@ -245,9 +_,9 @@
public static List<Component> getTooltipFromItem(Minecraft minecraft, ItemStack itemStack) {
return itemStack.getTooltipLines(
@@ -34,7 +34,7 @@
);
}
@@ -327,8 +_,11 @@
@@ -333,8 +_,11 @@
this.width = width;
this.height = height;
if (!this.initialized) {
@@ -46,7 +46,7 @@
} else {
this.repositionElements();
}
@@ -345,8 +_,11 @@
@@ -351,8 +_,11 @@
protected void rebuildWidgets() {
this.clearWidgets();
this.clearFocus();
@@ -58,7 +58,7 @@
}
protected void fadeWidgets(float widgetFade) {
@@ -466,6 +_,10 @@
@@ -467,6 +_,10 @@
public void onFilesDrop(List<Path> files) {
}
@@ -66,10 +66,10 @@
+ return this.minecraft;
+ }
+
private void scheduleNarration(long delay, boolean ignoreSuppression) {
private void scheduleNarration(long delay, boolean ignoreSuppression, NarrationTrigger narrationTrigger) {
this.nextNarrationTime = Util.getMillis() + delay;
if (ignoreSuppression) {
@@ -613,6 +_,16 @@
this.nextNarrationTriggeredBy = narrationTrigger;
@@ -619,6 +_,16 @@
public @Nullable Music getBackgroundMusic() {
return null;
@@ -20,7 +20,7 @@
this.friends = this.addRenderableWidget(
CommonButtons.friends(
@@ -130,17 +_,17 @@
!this.minecraft.isDemo()
!this.minecraft.isDemo() && !this.minecraft.isOfflineDeveloperMode()
)
);
- this.friends.setPosition(this.getHorizontalPosition(++currentButton, 3, 20), topPos);
@@ -38,7 +38,7 @@
- accessibility.setPosition(this.getHorizontalPosition(++currentButton, 3, 20), topPos);
+ accessibility.setPosition(this.getHorizontalPosition(++currentButton, numberOfButtons, 20), topPos);
Button.Builder var10001 = Button.builder(
Component.translatable("menu.options"), var1x -> this.minecraft.gui.setScreen(new OptionsScreen(this, this.minecraft.options, false))
Component.translatable("menu.options"), var1x -> this.minecraft.gui.setScreen(new OptionsScreen(this, this.minecraft.options))
);
@@ -310,6 +_,7 @@
this.extractPanorama(graphics, a);
@@ -1,19 +1,29 @@
--- a/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
+++ b/net/minecraft/client/gui/screens/advancements/AdvancementTab.java
@@ -41,6 +_,7 @@
@@ -38,6 +_,7 @@
private float fade;
private boolean centered;
private @Nullable AdvancementWidget hovered;
+ private int page;
public AdvancementTab(Minecraft minecraft, AdvancementsScreen screen, AdvancementTabType type, int index, AdvancementNode rootNode, DisplayInfo display) {
this.minecraft = minecraft;
@@ -55,6 +_,15 @@
this.addWidget(this.root, rootNode.holder());
public AdvancementTab(
Minecraft minecraft,
@@ -60,6 +_,25 @@
this.addWidget(root);
}
+ public AdvancementTab(Minecraft mc, AdvancementsScreen screen, AdvancementTabType type, int index, int page, AdvancementNode adv, DisplayInfo info) {
+ this(mc, screen, type, index, adv, info);
+ public AdvancementTab(
+ Minecraft minecraft,
+ AdvancementsScreen screen,
+ AdvancementTabType type,
+ int index,
+ int page,
+ AdvancementWidget root,
+ ItemStackTemplate icon,
+ Component title,
+ Identifier background
+ ) {
+ this(minecraft, screen, type, index, root, icon, title, background);
+ this.page = page;
+ }
+
@@ -21,17 +31,17 @@
+ return page;
+ }
+
public AdvancementTabType getType() {
return this.type;
}
@@ -162,8 +_,8 @@
}
public void copyPosition(AdvancementTab source) {
this.scrollX = source.scrollX;
this.scrollY = source.scrollY;
@@ -179,8 +_,8 @@
Identifier background = rootDisplay.background().get().texturePath();
for (AdvancementTabType type : AdvancementTabType.values()) {
- if (index < type.getMax()) {
- return new AdvancementTab(minecraft, screen, type, index, root, display.get());
- return new AdvancementTab(minecraft, screen, type, index, rootWidget, rootDisplay.icon(), rootDisplay.title(), background);
+ if ((index % AdvancementTabType.MAX_TABS) < type.getMax()) {
+ return new AdvancementTab(minecraft, screen, type, index % AdvancementTabType.MAX_TABS, index / AdvancementTabType.MAX_TABS, root, display.get());
+ return new AdvancementTab(minecraft, screen, type, index % AdvancementTabType.MAX_TABS, index / AdvancementTabType.MAX_TABS, rootWidget, rootDisplay.icon(), rootDisplay.title(), background);
}
index -= type.getMax();
@@ -9,7 +9,7 @@
public AdvancementsScreen(ClientAdvancements advancements) {
this(advancements, null);
@@ -76,6 +_,16 @@
this.advancements.setSelectedTab(this.selectedTab == null ? null : this.selectedTab.getRootNode().holder(), true);
this.advancements.setSelectedTab(this.selectedTab == null ? null : this.selectedTab.getRootAdvancement(), true);
}
+ if (this.tabs.size() > AdvancementTabType.MAX_TABS) {
@@ -31,10 +31,10 @@
for (AdvancementTab tab : this.tabs.values()) {
- if (tab.isMouseOver(xo, yo, event.x(), event.y())) {
+ if (tab.getPage() == tabPage && tab.isMouseOver(xo, yo, event.x(), event.y())) {
this.advancements.setSelectedTab(tab.getRootNode().holder(), true);
this.advancements.setSelectedTab(tab.getRootAdvancement(), true);
break;
}
@@ -143,6 +_,11 @@
@@ -147,6 +_,11 @@
@Override
public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
super.extractRenderState(graphics, mouseX, mouseY, a);
@@ -46,7 +46,7 @@
graphics.nextStratum();
this.extractInside(graphics);
graphics.nextStratum();
@@ -208,10 +_,12 @@
@@ -212,10 +_,12 @@
graphics.blit(RenderPipelines.GUI_TEXTURED, WINDOW_LOCATION, this.leftPos, this.topPos, 0.0F, 0.0F, 252, 140, 256, 256);
if (this.tabs.size() > 1) {
for (AdvancementTab tab : this.tabs.values()) {
@@ -59,7 +59,7 @@
tab.extractIcon(graphics, this.leftPos, this.topPos);
}
}
@@ -230,7 +_,7 @@
@@ -234,7 +_,7 @@
if (this.tabs.size() > 1) {
for (AdvancementTab tab : this.tabs.values()) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/debug/DebugOptionsScreen.java
+++ b/net/minecraft/client/gui/screens/debug/DebugOptionsScreen.java
@@ -178,6 +_,10 @@
@@ -174,6 +_,10 @@
DebugScreenEntry entry = DebugScreenEntries.getEntry(location);
this.isAllowed = entry != null && entry.isAllowed(DebugOptionsScreen.this.minecraft.showOnlyReducedInfo());
String name = location.getPath();
@@ -11,7 +11,7 @@
if (this.isAllowed) {
this.name = name;
} else {
@@ -238,8 +_,11 @@
@@ -234,8 +_,11 @@
public void extractContent(GuiGraphicsExtractor graphics, int mouseX, int mouseY, boolean hovered, float a) {
int x = this.getContentX();
int y = this.getContentY();
@@ -24,7 +24,7 @@
if (!this.isAllowed && hovered && mouseX < buttonsStartX) {
graphics.setTooltipForNextFrame(DebugOptionsScreen.NOT_ALLOWED_TOOLTIP, mouseX, mouseY);
}
@@ -301,6 +_,9 @@
@@ -297,6 +_,9 @@
public void updateSearch(String value) {
this.clearEntries();
@@ -34,7 +34,7 @@
List<Map.Entry<Identifier, DebugScreenEntry>> all = new ArrayList<>(DebugScreenEntries.allEntries().entrySet());
all.sort(COMPARATOR);
DebugEntryCategory currentCategory = null;
@@ -315,6 +_,7 @@
@@ -311,6 +_,7 @@
this.addEntry(DebugOptionsScreen.this.new OptionEntry(entry.getKey()));
}
@@ -12,8 +12,8 @@
ItemStack item = this.hoveredSlot.getItem();
if (this.menu.getCarried().isEmpty() || this.showTooltipWithItemInHand(item)) {
graphics.setTooltipForNextFrame(
- this.font, this.getTooltipFromContainerItem(item), item.getTooltipImage(), mouseX, mouseY, item.get(DataComponents.TOOLTIP_STYLE)
+ this.font, this.getTooltipFromContainerItem(item), item.getTooltipImage(), item, mouseX, mouseY, item.get(DataComponents.TOOLTIP_STYLE)
- this.font, this.getTooltipFromContainerItem(item), item.getTooltipImage(), mouseX, mouseY, item.get(DataComponents.TOOLTIP_STYLE), true
+ this.font, this.getTooltipFromContainerItem(item), item.getTooltipImage(), item, mouseX, mouseY, item.get(DataComponents.TOOLTIP_STYLE), true
);
}
}
@@ -51,7 +51,7 @@
}
}
@@ -285,7 +_,8 @@
@@ -297,7 +_,8 @@
return true;
}
@@ -61,7 +61,7 @@
Slot slot = this.getHoveredSlot(event.x(), event.y());
this.doubleclick = this.lastClickSlot == slot && doubleClick;
this.skipNextRelease = false;
@@ -295,6 +_,7 @@
@@ -307,6 +_,7 @@
int xo = this.leftPos;
int yo = this.topPos;
boolean clickedOutside = this.hasClickedOutside(event.x(), event.y(), xo, yo);
@@ -69,7 +69,7 @@
int slotId = -1;
if (slot != null) {
slotId = slot.index;
@@ -374,10 +_,13 @@
@@ -386,10 +_,13 @@
@Override
public boolean mouseReleased(MouseButtonEvent event) {
@@ -83,25 +83,25 @@
int slotId = -1;
if (slot != null) {
slotId = slot.index;
@@ -394,7 +_,7 @@
@@ -406,7 +_,7 @@
if (target != null
&& target.mayPickup(this.minecraft.player)
&& target.hasItem()
- && target.container == slot.container
+ && target.isSameInventory(slot)
&& AbstractContainerMenu.canItemQuickReplace(target, this.lastQuickMoved, true)) {
this.slotClicked(target, target.index, event.button(), ContainerInput.QUICK_MOVE);
this.slotClicked(target, target.index, event, ContainerInput.QUICK_MOVE);
}
@@ -421,7 +_,7 @@
@@ -433,7 +_,7 @@
if (this.isQuickCrafting && !this.quickCraftSlots.isEmpty()) {
this.quickCraftToSlots();
} else if (!this.menu.getCarried().isEmpty()) {
- if (this.minecraft.options.keyPickItem.matchesMouse(event)) {
+ if (this.minecraft.options.keyPickItem.isActiveAndMatches(mouseKey)) {
this.slotClicked(slot, slotId, event.button(), ContainerInput.CLONE);
this.slotClicked(slot, slotId, event, ContainerInput.CLONE);
} else {
boolean quickKey = slotId != -999 && event.hasShiftDown();
@@ -489,32 +_,38 @@
@@ -501,32 +_,38 @@
return true;
}
@@ -146,7 +146,7 @@
this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, i, ContainerInput.SWAP);
return true;
}
@@ -576,6 +_,59 @@
@@ -588,6 +_,59 @@
@Override
public T getMenu() {
return this.menu;
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/inventory/CreativeModeInventoryScreen.java
+++ b/net/minecraft/client/gui/screens/inventory/CreativeModeInventoryScreen.java
@@ -116,6 +_,8 @@
@@ -117,6 +_,8 @@
private final Set<TagKey<Item>> visibleTags = new HashSet<>();
private final boolean displayOperatorCreativeTab;
private final EffectsInInventory effects;
@@ -9,7 +9,7 @@
public CreativeModeInventoryScreen(LocalPlayer player, FeatureFlagSet enabledFeatures, boolean displayOperatorCreativeTab) {
super(new CreativeModeInventoryScreen.ItemPickerMenu(player), player.getInventory(), CommonComponents.EMPTY, 195, 136);
@@ -153,9 +_,11 @@
@@ -154,9 +_,11 @@
}
if (searchTrees != null) {
@@ -24,7 +24,7 @@
}
return true;
@@ -164,7 +_,7 @@
@@ -165,7 +_,7 @@
private void refreshCurrentTabContents(Collection<ItemStack> displayList) {
int oldRowIndex = this.menu.getRowIndexForScroll(this.scrollOffs);
this.menu.items.clear();
@@ -33,7 +33,7 @@
this.refreshSearchResults();
} else {
this.menu.items.addAll(displayList);
@@ -330,6 +_,34 @@
@@ -331,6 +_,34 @@
protected void init() {
if (this.minecraft.player.hasInfiniteMaterials()) {
super.init();
@@ -68,7 +68,7 @@
this.searchBox = new EditBox(this.font, this.leftPos + 82, this.topPos + 6, 80, 9, Component.translatable("itemGroup.search"));
this.searchBox.setMaxLength(50);
this.searchBox.setBordered(false);
@@ -379,7 +_,7 @@
@@ -380,7 +_,7 @@
return false;
}
@@ -77,7 +77,7 @@
return false;
}
@@ -407,7 +_,7 @@
@@ -408,7 +_,7 @@
@Override
public boolean keyPressed(KeyEvent event) {
this.ignoreTextInput = false;
@@ -86,7 +86,7 @@
if (this.minecraft.options.keyChat.matches(event)) {
this.ignoreTextInput = true;
this.selectTab(CreativeModeTabs.searchTab());
@@ -443,6 +_,7 @@
@@ -449,6 +_,7 @@
}
private void refreshSearchResults() {
@@ -94,7 +94,7 @@
this.menu.items.clear();
this.visibleTags.clear();
String searchTerm = this.searchBox.getValue();
@@ -455,10 +_,10 @@
@@ -461,10 +_,10 @@
SearchTree<ItemStack> tree;
if (searchTerm.startsWith("#")) {
searchTerm = searchTerm.substring(1);
@@ -107,7 +107,7 @@
}
this.menu.items.addAll(tree.search(searchTerm.toLowerCase(Locale.ROOT)));
@@ -486,7 +_,7 @@
@@ -492,7 +_,7 @@
@Override
protected void extractLabels(GuiGraphicsExtractor graphics, int xm, int ym) {
if (selectedTab.showTitle()) {
@@ -116,7 +116,7 @@
}
}
@@ -496,7 +_,7 @@
@@ -502,7 +_,7 @@
double xm = event.x() - this.leftPos;
double ym = event.y() - this.topPos;
@@ -125,7 +125,7 @@
if (this.checkTabClicked(tab, xm, ym)) {
return true;
}
@@ -518,7 +_,7 @@
@@ -524,7 +_,7 @@
double ym = event.y() - this.topPos;
this.scrolling = false;
@@ -134,7 +134,7 @@
if (this.checkTabClicked(tab, xm, ym)) {
this.selectTab(tab);
return true;
@@ -611,13 +_,15 @@
@@ -617,13 +_,15 @@
this.originalSlots = null;
}
@@ -151,7 +151,7 @@
this.refreshSearchResults();
} else {
@@ -682,8 +_,14 @@
@@ -688,8 +_,14 @@
this.effects.extractRenderState(graphics, mouseX, mouseY);
super.extractRenderState(graphics, mouseX, mouseY, a);
@@ -168,7 +168,7 @@
break;
}
}
@@ -704,10 +_,10 @@
@@ -710,10 +_,10 @@
public List<Component> getTooltipFromContainerItem(ItemStack itemStack) {
boolean isCreativeSlot = this.hoveredSlot != null && this.hoveredSlot instanceof CreativeModeInventoryScreen.CustomCreativeSlot;
boolean isSingleCategoryTab = selectedTab.getType() == CreativeModeTab.Type.CATEGORY;
@@ -181,7 +181,7 @@
if (originalLines.isEmpty()) {
return originalLines;
}
@@ -728,7 +_,7 @@
@@ -734,7 +_,7 @@
int i = 1;
for (CreativeModeTab tab : CreativeModeTabs.tabs()) {
@@ -190,7 +190,7 @@
linesToDisplay.add(i++, tab.getDisplayName().copy().withStyle(ChatFormatting.BLUE));
}
}
@@ -740,7 +_,7 @@
@@ -746,7 +_,7 @@
public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
super.extractBackground(graphics, mouseX, mouseY, a);
@@ -199,7 +199,7 @@
if (tab != selectedTab) {
this.extractTabButton(graphics, mouseX, mouseY, tab);
}
@@ -771,10 +_,11 @@
@@ -777,10 +_,11 @@
int yscr = this.topPos + 18;
int yscr2 = yscr + 112;
if (selectedTab.canScroll()) {
@@ -213,7 +213,7 @@
this.extractTabButton(graphics, mouseX, mouseY, selectedTab);
if (selectedTab.getType() == CreativeModeTab.Type.INVENTORY) {
InventoryScreen.extractEntityInInventoryFollowsMouse(
@@ -784,7 +_,7 @@
@@ -790,7 +_,7 @@
}
private int getTabX(CreativeModeTab tab) {
@@ -222,7 +222,7 @@
int spacing = 27;
int x = 27 * pos;
if (tab.isAlignedRight()) {
@@ -796,7 +_,7 @@
@@ -802,7 +_,7 @@
private int getTabY(CreativeModeTab tab) {
int y = 0;
@@ -231,7 +231,7 @@
y -= 32;
} else {
y += this.imageHeight;
@@ -824,8 +_,8 @@
@@ -830,8 +_,8 @@
protected void extractTabButton(GuiGraphicsExtractor graphics, int mouseX, int mouseY, CreativeModeTab tab) {
boolean selected = tab == selectedTab;
@@ -242,7 +242,7 @@
int x = this.leftPos + this.getTabX(tab);
int y = this.topPos - (isTop ? 28 : -(this.imageHeight - 4));
Identifier[] sprites;
@@ -839,6 +_,7 @@
@@ -845,6 +_,7 @@
graphics.requestCursor(CursorTypes.POINTING_HAND);
}
@@ -250,7 +250,7 @@
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, sprites[Mth.clamp(pos, 0, sprites.length)], x, y, 26, 32);
int iconX = x + 13 - 8;
int iconY = y + 16 - 8 + (isTop ? 1 : -1);
@@ -875,6 +_,14 @@
@@ -881,6 +_,14 @@
}
}
@@ -265,7 +265,7 @@
private static class CustomCreativeSlot extends Slot {
public CustomCreativeSlot(Container container, int slot, int x, int y) {
super(container, slot, x, y);
@@ -1052,6 +_,22 @@
@@ -1058,6 +_,22 @@
@Override
public boolean mayPickup(Player player) {
return this.target.mayPickup(player);
@@ -1,11 +1,11 @@
--- a/net/minecraft/client/gui/screens/inventory/HangingSignEditScreen.java
+++ b/net/minecraft/client/gui/screens/inventory/HangingSignEditScreen.java
@@ -16,7 +_,7 @@
@@ -17,7 +_,7 @@
private static final Vector3fc TEXT_SCALE = new Vector3f(1.0F, 1.0F, 1.0F);
private static final int TEXTURE_WIDTH = 16;
private static final int TEXTURE_HEIGHT = 16;
- private final Identifier texture = Identifier.withDefaultNamespace("textures/gui/hanging_signs/" + this.woodType.name() + ".png");
+ private final Identifier texture = Identifier.parse(this.woodType.name() + ".png").withPrefix("textures/gui/hanging_signs/");
public HangingSignEditScreen(SignBlockEntity sign, boolean isFrontText, boolean shouldFilter) {
super(sign, isFrontText, shouldFilter, Component.translatable("hanging_sign.edit"));
public HangingSignEditScreen(SignBlockEntity sign, SignTextSlot slot, boolean shouldFilter) {
super(sign, slot, shouldFilter, Component.translatable("hanging_sign.edit"));
@@ -1,11 +1,11 @@
--- a/net/minecraft/client/gui/screens/inventory/SignEditScreen.java
+++ b/net/minecraft/client/gui/screens/inventory/SignEditScreen.java
@@ -19,7 +_,7 @@
@@ -20,7 +_,7 @@
private static final int POST_HEIGHT = 14;
private static final Vector3fc TEXT_SCALE = new Vector3f(0.9765628F, 0.9765628F, 0.9765628F);
private final int displayedHeight;
- private final Identifier texture = Identifier.withDefaultNamespace("textures/gui/signs/" + this.woodType.name() + ".png");
+ private final Identifier texture = Identifier.parse(this.woodType.name() + ".png").withPrefix("textures/gui/signs/");
public SignEditScreen(SignBlockEntity sign, boolean isFrontText, boolean shouldFilter) {
super(sign, isFrontText, shouldFilter);
public SignEditScreen(SignBlockEntity sign, SignTextSlot slot, boolean shouldFilter) {
super(sign, slot, shouldFilter);
@@ -9,7 +9,7 @@
int width = minecraft.font.width(name);
if (width > this.maxNameWidth) {
this.maxNameWidth = width;
@@ -121,8 +_,19 @@
@@ -123,8 +_,19 @@
? Component.translatable("narrator.controls.unbound", name)
: Component.translatable("narrator.controls.bound", name, defaultNarrationSupplier.get())
)
@@ -30,7 +30,7 @@
key.setKey(key.getDefaultKey());
KeyBindsList.this.resetMappingAndUpdateButtons();
}).bounds(0, 0, 50, 20).createNarration(defaultNarrationSupplier -> Component.translatable("narrator.controls.reset", name)).build();
@@ -164,13 +_,13 @@
@@ -166,13 +_,13 @@
MutableComponent tooltip = Component.empty();
if (!this.key.isUnbound()) {
for (KeyMapping otherKey : KeyBindsList.this.minecraft.options.keyMappings) {
@@ -23,7 +23,7 @@
}
this.keyBindsList.resetMappingAndUpdateButtons();
@@ -73,18 +_,68 @@
@@ -77,18 +_,65 @@
@Override
public boolean keyPressed(KeyEvent event) {
if (this.selectedKey != null) {
@@ -43,10 +43,7 @@
+
+ @Override
+ public boolean keyReleased(KeyEvent event) {
+ // We ignore events from keys with the scan code 63 as they're emitted
+ // (only as RELEASE, not PRESS) by Mac systems to indicate that "Fn" is being pressed
+ // See https://github.com/neoforged/NeoForge/issues/1683
+ if (!ignoreNextRelease && this.selectedKey != null && (!net.minecraft.client.input.InputQuirks.ON_OSX || event.scancode() != 63)) {
+ if (!ignoreNextRelease && this.selectedKey != null) {
if (event.isEscape()) {
+ this.selectedKey.setKeyModifierAndCode(net.neoforged.neoforge.client.settings.KeyModifier.NONE, InputConstants.UNKNOWN);
this.selectedKey.setKey(InputConstants.UNKNOWN);
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/worldselection/AbstractGameRulesScreen.java
+++ b/net/minecraft/client/gui/screens/worldselection/AbstractGameRulesScreen.java
@@ -293,6 +_,12 @@
@@ -286,6 +_,12 @@
this.addEntry(gameRule, (x$0, x$1, x$2, x$3) -> AbstractGameRulesScreen.this.new IntegerRuleEntry(x$0, x$1, x$2, x$3));
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/gui/screens/worldselection/WorldOpenFlows.java
+++ b/net/minecraft/client/gui/screens/worldselection/WorldOpenFlows.java
@@ -254,7 +_,9 @@
@@ -255,7 +_,9 @@
backupWarning = Component.translatable("selectWorld.backupWarning.customized");
} else {
backupQuestion = Component.translatable("selectWorld.backupQuestion.experimental");
@@ -11,7 +11,7 @@
}
this.minecraft
@@ -318,6 +_,7 @@
@@ -319,6 +_,7 @@
try {
levelDataTag = worldAccess.getUnfixedDataTag(false);
summary = worldAccess.fixAndGetSummaryFromTag(levelDataTag);
@@ -19,7 +19,7 @@
} catch (IOException | NbtException | ReportedNbtException e) {
this.minecraft.gui.setScreen(new RecoverWorldDataScreen(this.minecraft, success -> {
if (success) {
@@ -524,11 +_,20 @@
@@ -533,11 +_,20 @@
WorldData data = worldDataAndGenSettings.data();
boolean oldCustomized = worldDataAndGenSettings.genSettings().options().isOldCustomizedWorld();
boolean unstable = data.worldGenSettingsLifecycle() != Lifecycle.stable();
@@ -1,26 +1,26 @@
--- a/net/minecraft/client/model/HumanoidModel.java
+++ b/net/minecraft/client/model/HumanoidModel.java
@@ -391,6 +_,9 @@
@@ -380,6 +_,9 @@
break;
case SPEAR:
SpearAnimations.thirdPersonHandUse(this.rightArm, this.head, true, state.getUseItemStackForArm(HumanoidArm.RIGHT), state);
SpearAnimations.thirdPersonHandUse(this.rightArm, this.head, HumanoidArm.RIGHT, state.getUseItemStackForArm(HumanoidArm.RIGHT), state);
+ break;
+ default:
+ state.rightArmPose.applyTransform(this, state, net.minecraft.world.entity.HumanoidArm.RIGHT);
}
}
@@ -436,6 +_,9 @@
@@ -425,6 +_,9 @@
break;
case SPEAR:
SpearAnimations.thirdPersonHandUse(this.leftArm, this.head, false, state.getUseItemStackForArm(HumanoidArm.LEFT), state);
SpearAnimations.thirdPersonHandUse(this.leftArm, this.head, HumanoidArm.LEFT, state.getUseItemStackForArm(HumanoidArm.LEFT), state);
+ break;
+ default:
+ state.leftArmPose.applyTransform(this, state, net.minecraft.world.entity.HumanoidArm.LEFT);
}
}
@@ -519,9 +_,20 @@
@@ -509,9 +_,20 @@
private final boolean twoHanded;
private final boolean affectsOffhandPose;
@@ -41,7 +41,7 @@
}
public boolean isTwoHanded() {
@@ -530,6 +_,14 @@
@@ -520,6 +_,14 @@
public boolean affectsOffhandPose() {
return this.affectsOffhandPose;
@@ -1,9 +1,9 @@
--- a/net/minecraft/client/model/geom/LayerDefinitions.java
+++ b/net/minecraft/client/model/geom/LayerDefinitions.java
@@ -557,6 +_,7 @@
result.put(ModelLayers.PALE_OAK_CHEST_BOAT, chestBoatModel);
result.put(ModelLayers.MANGROVE_BOAT, boatModel);
@@ -561,6 +_,7 @@
result.put(ModelLayers.MANGROVE_CHEST_BOAT, chestBoatModel);
result.put(ModelLayers.POPLAR_BOAT, boatModel);
result.put(ModelLayers.POPLAR_CHEST_BOAT, chestBoatModel);
+ net.neoforged.neoforge.client.ClientHooks.loadLayerDefinitions(result);
ImmutableMap<ModelLayerLocation, LayerDefinition> definitions = result.build();
List<ModelLayerLocation> missingDefinitions = ModelLayers.getKnownLocations().filter(l -> !definitions.containsKey(l)).toList();
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/ClientChunkCache.java
+++ b/net/minecraft/client/multiplayer/ClientChunkCache.java
@@ -64,6 +_,7 @@
@@ -61,6 +_,7 @@
int index = this.storage.getIndex(pos.x(), pos.z());
LevelChunk currentChunk = this.storage.getChunk(index);
if (isValidChunk(currentChunk, pos.x(), pos.z())) {
@@ -8,7 +8,7 @@
this.storage.drop(index, currentChunk);
}
}
@@ -124,6 +_,7 @@
@@ -115,6 +_,7 @@
}
this.level.onChunkLoaded(pos);
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/ClientCommonPacketListenerImpl.java
+++ b/net/minecraft/client/multiplayer/ClientCommonPacketListenerImpl.java
@@ -93,6 +_,10 @@
@@ -94,6 +_,10 @@
private ServerLinks serverLinks;
protected final Map<UUID, PlayerInfo> seenPlayers;
protected boolean seenInsecureChatWarning;
@@ -11,7 +11,7 @@
protected ClientCommonPacketListenerImpl(Minecraft minecraft, Connection connection, CommonListenerCookie cookie) {
this.minecraft = minecraft;
@@ -106,6 +_,8 @@
@@ -107,6 +_,8 @@
this.serverLinks = cookie.serverLinks();
this.seenPlayers = new HashMap<>(cookie.seenPlayers());
this.seenInsecureChatWarning = cookie.seenInsecureChatWarning();
@@ -20,7 +20,7 @@
}
public ServerLinks serverLinks() {
@@ -157,6 +_,33 @@
@@ -158,6 +_,33 @@
@Override
public void handleCustomPayload(ClientboundCustomPayloadPacket packet) {
@@ -54,7 +54,7 @@
CustomPacketPayload payload = packet.payload();
if (!(payload instanceof DiscardedPayload)) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.minecraft.packetProcessor());
@@ -347,6 +_,8 @@
@@ -358,6 +_,8 @@
}
public void send(Packet<?> packet) {
@@ -63,7 +63,7 @@
this.connection.send(packet);
}
@@ -494,5 +_,15 @@
@@ -505,5 +_,15 @@
private record PendingRequest(UUID id, URL url, String hash) {
}
@@ -51,7 +51,7 @@
@Override
public boolean hasInfiniteMaterials() {
return true;
@@ -206,6 +_,59 @@
@@ -211,6 +_,59 @@
public void onDisconnect(DisconnectionDetails reason) {
super.onDisconnect(reason);
this.minecraft.clearDownloadedResourcePacks();
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/ClientLevel.java
+++ b/net/minecraft/client/multiplayer/ClientLevel.java
@@ -156,7 +_,7 @@
@@ -159,7 +_,7 @@
private final @Nullable EndFlashState endFlashState;
private final Minecraft minecraft = Minecraft.getInstance();
private final List<AbstractClientPlayer> players = Lists.newArrayList();
@@ -9,7 +9,7 @@
private final Map<MapId, MapItemSavedData> mapData = Maps.newHashMap();
private int skyFlashTime;
private int rainSoundTime;
@@ -165,6 +_,7 @@
@@ -168,6 +_,7 @@
cache.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache(pos -> this.calculateBlockTint(pos, BiomeColors.FOLIAGE_COLOR_RESOLVER)));
cache.put(BiomeColors.DRY_FOLIAGE_COLOR_RESOLVER, new BlockTintCache(pos -> this.calculateBlockTint(pos, BiomeColors.DRY_FOLIAGE_COLOR_RESOLVER)));
cache.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache(pos -> this.calculateBlockTint(pos, BiomeColors.WATER_COLOR_RESOLVER)));
@@ -17,7 +17,7 @@
});
private final ClientChunkCache chunkSource;
private final Deque<Runnable> lightUpdateQueue = Queues.newArrayDeque();
@@ -178,6 +_,7 @@
@@ -181,6 +_,7 @@
private final Long2ObjectMap<SortedSet<BlockDestructionProgress>> destructionProgress = new Long2ObjectOpenHashMap<>();
private final int seaLevel;
private static final Set<Item> MARKER_PARTICLE_ITEMS = Set.of(Items.BARRIER, Items.LIGHT);
@@ -25,7 +25,7 @@
public void handleBlockChangedAck(int sequence) {
if (SharedConstants.DEBUG_BLOCK_BREAK) {
@@ -223,10 +_,15 @@
@@ -226,10 +_,15 @@
@Override
public boolean setBlock(BlockPos pos, BlockState blockState, @Block.UpdateFlags int updateFlags, int updateLimit) {
if (this.blockStatePredictionHandler.isPredicting()) {
@@ -41,7 +41,7 @@
}
return success;
@@ -260,6 +_,7 @@
@@ -263,6 +_,7 @@
this.serverSimulationDistance = serverSimulationDistance;
this.environmentAttributes = this.addEnvironmentAttributeLayers(EnvironmentAttributeSystem.builder()).build();
this.updateSkyBrightness();
@@ -49,7 +49,7 @@
}
private EnvironmentAttributeSystem.Builder addEnvironmentAttributeLayers(EnvironmentAttributeSystem.Builder environmentAttributes) {
@@ -339,6 +_,11 @@
@@ -342,6 +_,11 @@
}
public void tickWeatherEffects() {
@@ -61,20 +61,22 @@
ParticleStatus particleStatus = this.minecraft.options.particles().get();
int weatherRadius = this.minecraft.options.weatherRadius().get();
float rainLevel = this.getRainLevel(1.0F);
@@ -471,7 +_,11 @@
entity.setOldPosAndRot();
entity.tickCount++;
@@ -472,8 +_,12 @@
public void tickNonPassenger(Entity entity) {
Profiler.get().push(entity.typeHolder()::getRegisteredName);
- entity.commonTick();
- entity.tick();
+ // Neo: Permit cancellation of Entity#tick via EntityTickEvent.Pre
+ if (!net.neoforged.neoforge.event.EventHooks.fireEntityTickPre(entity).isCanceled()) {
+ entity.commonTick();
+ entity.tick();
+ net.neoforged.neoforge.event.EventHooks.fireEntityTickPost(entity);
+ }
Profiler.get().pop();
for (Entity passenger : entity.getPassengers()) {
@@ -527,8 +_,10 @@
@@ -528,8 +_,10 @@
}
public void addEntity(Entity entity) {
@@ -85,7 +87,7 @@
}
public void removeEntity(int id, Entity.RemovalReason reason) {
@@ -676,6 +_,13 @@
@@ -677,6 +_,13 @@
public void playSeededSound(
@Nullable Entity except, double x, double y, double z, Holder<SoundEvent> sound, SoundSource source, float volume, float pitch, long seed
) {
@@ -99,7 +101,7 @@
if (except == this.minecraft.player) {
this.playSound(x, y, z, sound.value(), source, volume, pitch, false, seed);
}
@@ -685,6 +_,12 @@
@@ -686,6 +_,12 @@
public void playSeededSound(
@Nullable Entity except, Entity sourceEntity, Holder<SoundEvent> sound, SoundSource source, float volume, float pitch, long seed
) {
@@ -112,7 +114,7 @@
if (except == this.minecraft.player) {
this.minecraft.getSoundManager().play(new EntityBoundSoundInstance(sound.value(), source, volume, pitch, sourceEntity, seed));
}
@@ -913,7 +_,7 @@
@@ -920,7 +_,7 @@
return this.players;
}
@@ -121,7 +123,7 @@
return this.dragonParts;
}
@@ -1009,7 +_,7 @@
@@ -1016,7 +_,7 @@
@Override
public void addDestroyBlockEffect(BlockPos pos, BlockState blockState) {
@@ -130,7 +132,7 @@
VoxelShape shape = blockState.getShape(this, pos);
double density = 0.25;
shape.forAllBoxes(
@@ -1035,7 +_,7 @@
@@ -1042,7 +_,7 @@
.add(
new TerrainParticle(
this, pos.getX() + x, pos.getY() + y, pos.getZ() + z, relX - 0.5, relY - 0.5, relZ - 0.5, blockState, pos
@@ -139,34 +141,30 @@
);
}
}
@@ -1045,9 +_,16 @@
}
}
+ /**
+ * @deprecated Neo: use {@link #addBreakingBlockEffect(BlockPos, Direction, net.minecraft.world.phys.HitResult)} instead
+ */
public void addBreakingBlockEffect(BlockPos pos, Direction direction) {
+ this.addBreakingBlockEffect(pos, direction, null);
+ }
+
+ public void addBreakingBlockEffect(BlockPos pos, Direction direction, net.minecraft.world.phys.@Nullable HitResult hitResult) {
@@ -1055,11 +_,11 @@
public void addBreakingBlockEffects(BlockPos pos, Direction direction, boolean playSound) {
BlockState blockState = this.getBlockState(pos);
- if (blockState.getRenderShape() != RenderShape.INVISIBLE && blockState.shouldSpawnTerrainParticles()) {
+ if (blockState.getRenderShape() != RenderShape.INVISIBLE && !net.neoforged.neoforge.client.extensions.common.IClientBlockExtensions.of(blockState).addHitEffects(blockState, this, hitResult, this.minecraft.particleEngine)) {
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
@@ -1080,7 +_,7 @@
xp = x + shape.maxX + 0.1F;
if (!blockState.isAir()) {
- if (playSound) {
+ if (playSound && !net.neoforged.neoforge.client.extensions.common.IClientBlockExtensions.of(blockState).playHitSound(blockState, this, pos, direction, this.minecraft.getSoundManager())) {
this.playBreakingSound(pos, blockState);
}
- this.minecraft.particleEngine.add(new TerrainParticle(this, xp, yp, zp, 0.0, 0.0, 0.0, blockState, pos).setPower(0.2F).scale(0.6F));
+ this.minecraft.particleEngine.add(new TerrainParticle(this, xp, yp, zp, 0.0, 0.0, 0.0, blockState, pos).updateSprite(blockState, pos).setPower(0.2F).scale(0.6F));
- if (blockState.getRenderShape() != RenderShape.INVISIBLE && blockState.shouldSpawnTerrainParticles()) {
+ if (blockState.getRenderShape() != RenderShape.INVISIBLE && !net.neoforged.neoforge.client.extensions.common.IClientBlockExtensions.of(blockState).addHitEffects(blockState, this, pos, direction, this.minecraft.particleEngine)) {
this.addBreakingParticles(pos, direction, blockState);
}
}
@@ -1098,7 +_,7 @@
xp = x + shape.maxX + 0.1F;
}
- this.minecraft.particleEngine.add(new TerrainParticle(this, xp, yp, zp, 0.0, 0.0, 0.0, blockState, pos).setPower(0.2F).scale(0.6F));
+ this.minecraft.particleEngine.add(new TerrainParticle(this, xp, yp, zp, 0.0, 0.0, 0.0, blockState, pos).updateSprite(blockState, pos).setPower(0.2F).scale(0.6F));
}
@@ -1200,6 +_,7 @@
private void playBreakingSound(BlockPos pos, BlockState blockState) {
@@ -1223,6 +_,7 @@
}
public void setDifficulty(Difficulty difficulty) {
@@ -174,7 +172,7 @@
this.difficulty = difficulty;
}
@@ -1240,6 +_,9 @@
@@ -1263,6 +_,9 @@
ClientLevel.this.dragonParts.addAll(Arrays.asList(dragon.getSubEntities()));
break;
default:
@@ -184,7 +182,7 @@
}
}
@@ -1253,10 +_,26 @@
@@ -1276,10 +_,26 @@
ClientLevel.this.dragonParts.removeAll(Arrays.asList(dragon.getSubEntities()));
break;
default:
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/ClientPacketListener.java
+++ b/net/minecraft/client/multiplayer/ClientPacketListener.java
@@ -417,6 +_,7 @@
@@ -422,6 +_,7 @@
private final ChunkBatchSizeCalculator chunkBatchSizeCalculator = new ChunkBatchSizeCalculator();
private final PingDebugMonitor pingDebugMonitor;
private final ClientDebugSubscriber debugSubscriber;
@@ -8,17 +8,15 @@
private @Nullable LevelLoadTracker levelLoadTracker;
private boolean serverEnforcesSecureChat;
private boolean onlineMode;
@@ -450,7 +_,8 @@
@@ -455,6 +_,7 @@
minecraft.gui.hud.getChat().restoreState(cookie.chatState());
}
- this.potionBrewing = PotionBrewing.bootstrap(this.enabledFeatures);
+ this.connectionType = cookie.connectionType();
+ this.potionBrewing = PotionBrewing.bootstrap(this.enabledFeatures, this.registryAccess);
this.fuelValues = FuelValues.vanillaBurnTimes(cookie.receivedRegistries(), this.enabledFeatures);
this.levelLoadTracker = cookie.levelLoadTracker();
this.clockManager = new ClientClockManager();
@@ -529,12 +_,13 @@
}
@@ -532,12 +_,13 @@
this.debugSubscriber.clear();
this.minecraft.levelExtractor.debugRenderer.refreshRendererList();
this.minecraft.player.resetPos();
@@ -33,7 +31,7 @@
this.minecraft.player.setReducedDebugInfo(packet.reducedDebugInfo());
this.minecraft.player.setShowDeathScreen(packet.showDeathScreen());
this.minecraft.player.setDoLimitedCrafting(packet.doLimitedCrafting());
@@ -963,7 +_,8 @@
@@ -953,7 +_,8 @@
this.customReportDetails,
this.serverLinks(),
this.seenPlayers,
@@ -43,7 +41,7 @@
)
)
);
@@ -1291,7 +_,7 @@
@@ -1302,7 +_,7 @@
}
this.setClientLoaded(false);
@@ -52,7 +50,7 @@
newPlayer.setId(oldPlayer.getId());
this.minecraft.player = newPlayer;
if (dimensionChanged) {
@@ -1319,6 +_,7 @@
@@ -1330,6 +_,7 @@
newPlayer.getAttributes().assignBaseValues(oldPlayer.getAttributes());
}
@@ -60,7 +58,7 @@
this.level.addEntity(newPlayer);
newPlayer.input = new KeyboardInput(this.minecraft.options);
this.minecraft.gameMode.adjustPlayer(newPlayer);
@@ -1472,7 +_,7 @@
@@ -1486,7 +_,7 @@
ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(blockEntity.problemPath(), LOGGER);
try {
@@ -69,7 +67,7 @@
} catch (Throwable t$) {
try {
reporter.close();
@@ -1621,7 +_,12 @@
@@ -1635,7 +_,12 @@
);
}
@@ -82,7 +80,7 @@
if (this.levelLoadTracker == null) {
this.levelLoadTracker = new LevelLoadTracker();
}
@@ -1631,7 +_,7 @@
@@ -1645,7 +_,7 @@
loadingScreen.update(this.levelLoadTracker, reason);
} else {
this.minecraft.gui.hud.getChat().preserveCurrentChatScreen();
@@ -91,7 +89,7 @@
}
}
@@ -1680,7 +_,9 @@
@@ -1694,7 +_,9 @@
@Override
public void handleCommands(ClientboundCommandsPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.minecraft.packetProcessor());
@@ -102,19 +100,19 @@
}
@Override
@@ -1699,6 +_,8 @@
@@ -1713,6 +_,8 @@
public void handleUpdateRecipes(ClientboundUpdateRecipesPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.minecraft.packetProcessor());
this.recipes = new ClientRecipeContainer(packet.itemSets(), packet.stonecutterRecipes());
+
+ net.neoforged.neoforge.client.ClientHooks.handleUpdateRecipes(this, v -> this.fuelValues = v);
+ net.neoforged.neoforge.client.ClientHooks.handleUpdateRecipes(this);
}
@Override
@@ -1820,8 +_,11 @@
@@ -1833,8 +_,11 @@
pendingTags.forEach(Registry.PendingTags::apply);
}
this.fuelValues = FuelValues.vanillaBurnTimes(this.registryAccess, this.enabledFeatures);
- List<ItemStack> searchItems = List.copyOf(CreativeModeTabs.searchTab().getDisplayItems());
- this.searchTrees.updateCreativeTags(searchItems);
+ net.neoforged.neoforge.common.NeoForge.EVENT_BUS.post(new net.neoforged.neoforge.event.TagsUpdatedEvent.ClientPacketReceived(this.registryAccess, this.connection.isMemoryConnection()));
@@ -125,7 +123,7 @@
}
@Override
@@ -2643,6 +_,8 @@
@@ -2661,6 +_,8 @@
}
public void sendChat(String content) {
@@ -134,7 +132,7 @@
Instant timeStamp = Instant.now();
long salt = Crypt.SaltSupplier.getLong();
LastSeenMessagesTracker.Update lastSeenUpdate = this.lastSeenMessages.generateAndApplyUpdate();
@@ -2651,6 +_,7 @@
@@ -2669,6 +_,7 @@
}
public void sendCommand(String command) {
@@ -142,7 +140,7 @@
SignableCommand<ClientSuggestionProvider> signableCommand = SignableCommand.of(this.commands.parse(command, this.suggestionsProvider));
if (signableCommand.arguments().isEmpty()) {
this.send(new ServerboundChatCommandPacket(command));
@@ -2667,6 +_,8 @@
@@ -2685,6 +_,8 @@
}
public void sendUnattendedCommand(String command, @Nullable Screen screenAfterCommand) {
@@ -151,7 +149,7 @@
switch (this.verifyCommand(command)) {
case NO_ISSUES:
this.send(new ServerboundChatCommandPacket(command));
@@ -2831,6 +_,10 @@
@@ -2849,6 +_,10 @@
public Scoreboard scoreboard() {
return this.scoreboard;
@@ -161,4 +159,4 @@
+ return this.connectionType;
}
public PotionBrewing potionBrewing() {
public void updateSearchTrees() {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/MultiPlayerGameMode.java
+++ b/net/minecraft/client/multiplayer/MultiPlayerGameMode.java
@@ -115,13 +_,21 @@
@@ -120,13 +_,21 @@
}
public boolean destroyBlock(BlockPos pos) {
@@ -23,7 +23,7 @@
return false;
}
@@ -134,11 +_,12 @@
@@ -139,11 +_,12 @@
return false;
}
@@ -38,7 +38,7 @@
}
if (SharedConstants.DEBUG_BLOCK_BREAK) {
@@ -165,6 +_,7 @@
@@ -170,6 +_,7 @@
}
this.startPrediction(this.minecraft.level, sequence -> {
@@ -46,7 +46,7 @@
this.destroyBlock(pos);
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, pos, direction, sequence);
});
@@ -178,6 +_,7 @@
@@ -183,6 +_,7 @@
this.connection
.send(new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK, this.destroyBlockPos, direction));
}
@@ -54,7 +54,7 @@
BlockState state = this.minecraft.level.getBlockState(pos);
this.minecraft.getTutorial().onDestroyBlock(this.minecraft.level, pos, state, 0.0F);
@@ -188,9 +_,12 @@
@@ -193,9 +_,12 @@
this.startPrediction(this.minecraft.level, sequence -> {
boolean notAir = !state.isAir();
if (notAir && this.destroyProgress == 0.0F) {
@@ -67,8 +67,8 @@
if (notAir && state.getDestroyProgress(this.minecraft.player, this.minecraft.player.level(), pos) >= 1.0F) {
this.destroyBlock(pos);
} else {
@@ -202,7 +_,7 @@
this.minecraft.level.destroyBlockProgress(this.minecraft.player.getId(), this.destroyBlockPos, this.getDestroyStage());
@@ -209,7 +_,7 @@
this.minecraft.level.addBreakingBlockEffects(this.destroyBlockPos, this.destroyDirection, true);
}
- return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, pos, direction, sequence);
@@ -76,7 +76,7 @@
});
}
@@ -242,6 +_,7 @@
@@ -249,6 +_,7 @@
}
this.startPrediction(this.minecraft.level, sequence -> {
@@ -84,26 +84,15 @@
this.destroyBlock(pos);
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, pos, direction, sequence);
});
@@ -254,8 +_,8 @@
}
@@ -263,6 +_,7 @@
this.destroyProgress = this.destroyProgress + state.getDestroyProgress(this.minecraft.player, this.minecraft.player.level(), pos);
- if (this.destroyTicks % 4.0F == 0.0F) {
- SoundType soundType = state.getSoundType();
+ if (this.destroyTicks % 4.0F == 0.0F && !net.neoforged.neoforge.client.extensions.common.IClientBlockExtensions.of(state).playHitSound(state, this.minecraft.level, pos, direction, this.minecraft.getSoundManager())) {
+ SoundType soundType = state.getSoundType(this.minecraft.level, pos, this.minecraft.player);
this.minecraft
.getSoundManager()
.play(
@@ -272,6 +_,7 @@
this.destroyTicks++;
this.minecraft.getTutorial().onDestroyBlock(this.minecraft.level, pos, state, Mth.clamp(this.destroyProgress, 0.0F, 1.0F));
+ if (net.neoforged.neoforge.common.CommonHooks.onClientMineHold(this.minecraft.player, pos, direction).getUseItem().isFalse()) return true;
if (this.destroyProgress >= 1.0F) {
this.isDestroying = false;
if (SharedConstants.DEBUG_BLOCK_BREAK) {
@@ -313,7 +_,7 @@
@@ -308,7 +_,7 @@
private boolean sameDestroyTarget(BlockPos pos) {
ItemStack selected = this.minecraft.player.getMainHandItem();
@@ -112,7 +101,7 @@
}
private void ensureHasSentCarriedItem() {
@@ -341,13 +_,24 @@
@@ -336,13 +_,24 @@
private InteractionResult performUseItemOn(LocalPlayer player, InteractionHand hand, BlockHitResult blockHit) {
BlockPos pos = blockHit.getBlockPos();
ItemStack itemStack = player.getItemInHand(hand);
@@ -139,7 +128,7 @@
BlockState blockState = this.minecraft.level.getBlockState(pos);
if (!this.connection.isFeatureEnabled(blockState.getBlock().requiredFeatures())) {
return InteractionResult.FAIL;
@@ -366,7 +_,10 @@
@@ -361,7 +_,10 @@
}
}
@@ -149,9 +138,9 @@
+ }
+ if (event.getUseItem().isTrue() || (!itemStack.isEmpty() && !player.getCooldowns().isOnCooldown(itemStack))) {
UseOnContext context = new UseOnContext(player, hand, blockHit);
InteractionResult success;
InteractionResult result;
if (player.hasInfiniteMaterials()) {
@@ -398,6 +_,12 @@
@@ -399,6 +_,12 @@
return packet;
}
@@ -164,7 +153,7 @@
InteractionResult resultHolder = itemStack.use(this.minecraft.level, player, hand);
ItemStack result;
if (resultHolder instanceof InteractionResult.Success success) {
@@ -408,6 +_,8 @@
@@ -409,6 +_,8 @@
if (result != itemStack) {
player.setItemInHand(hand, result);
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/chat/ChatListener.java
+++ b/net/minecraft/client/multiplayer/chat/ChatListener.java
@@ -142,7 +_,9 @@
@@ -138,7 +_,9 @@
LocalPlayer receiver = this.minecraft.player;
if (receiver != null && receiver.chatAbilities().canReceivePlayerMessages()) {
Component decoratedMessage = boundChatType.decorate(message);
@@ -11,7 +11,7 @@
this.narrateChatMessage(boundChatType, message);
this.logSystemMessage(decoratedMessage, received);
this.previousMessageTime = Util.getMillis();
@@ -172,12 +_,16 @@
@@ -168,12 +_,16 @@
MessageSignature signature = message.signature();
FilterMask filterMask = message.filterMask();
if (filterMask.isEmpty()) {
@@ -30,7 +30,7 @@
this.narrateChatMessage(boundChatType, filteredContent);
}
}
@@ -214,6 +_,8 @@
@@ -210,6 +_,8 @@
public void handleSystemMessage(Component message, boolean remote) {
UUID guessedUUID = this.guessChatUUID(message);
if (!this.minecraft.options.hideMatchedNames().get() || !this.minecraft.isBlocked(guessedUUID)) {
@@ -39,7 +39,7 @@
if (guessedUUID == Util.NIL_UUID || !this.minecraft.isFriendOnlyRestricted(guessedUUID)) {
LocalPlayer receiver = this.minecraft.player;
if (receiver != null && receiver.chatAbilities().canReceiveSystemMessages()) {
@@ -231,6 +_,8 @@
@@ -227,6 +_,8 @@
}
public void handleOverlay(Component message) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/particle/FireworkParticles.java
+++ b/net/minecraft/client/particle/FireworkParticles.java
@@ -217,6 +_,10 @@
@@ -228,6 +_,10 @@
colors = IntList.of(DyeColor.BLACK.getFireworkColor());
}
@@ -9,7 +9,7 @@
private @Nullable Runnable onReload;
public ParticleResources() {
@@ -183,14 +_,18 @@
@@ -186,14 +_,18 @@
this.register(ParticleTypes.SULFUR_CUBE_GOO, BreakingItemParticle.SulfurCubeProvider::new);
}
@@ -30,7 +30,7 @@
}
@Override
@@ -280,7 +_,7 @@
@@ -283,7 +_,7 @@
}
}
@@ -0,0 +1,34 @@
--- a/net/minecraft/client/player/FirstPersonHandsAndItems.java
+++ b/net/minecraft/client/player/FirstPersonHandsAndItems.java
@@ -44,9 +_,20 @@
this.mainHandHeight = Mth.clamp(this.mainHandHeight - 0.4F, 0.0F, 1.0F);
this.offHandHeight = Mth.clamp(this.offHandHeight - 0.4F, 0.0F, 1.0F);
} else {
+ // Neo: allow suppressing re-equip animation when only the stack's data changes
+ boolean swapAnimMain = net.neoforged.neoforge.client.ClientHooks.shouldCauseReequipAnimation(this.mainHandItem, nextMainHand, player.getInventory().getSelectedSlot());
+ boolean swapAnimOff = net.neoforged.neoforge.client.ClientHooks.shouldCauseReequipAnimation(this.offHandItem, nextOffHand, -1);
+
+ if (!swapAnimMain && this.mainHandItem != nextMainHand) {
+ this.mainHandItem = nextMainHand;
+ }
+ if (!swapAnimOff && this.offHandItem != nextOffHand) {
+ this.offHandItem = nextOffHand;
+ }
+
float attackAnim = player.getItemSwapScale(1.0F);
- float mainHandTargetHeight = this.mainHandItem != nextMainHand ? 0.0F : attackAnim * attackAnim * attackAnim;
- float offHandTargetHeight = this.offHandItem != nextOffHand ? 0.0F : 1.0F;
+ float mainHandTargetHeight = swapAnimMain ? 0.0F : attackAnim * attackAnim * attackAnim;
+ float offHandTargetHeight = swapAnimOff ? 0.0F : 1.0F;
this.mainHandHeight = this.mainHandHeight + Mth.clamp(mainHandTargetHeight - this.mainHandHeight, -0.4F, 0.4F);
this.offHandHeight = this.offHandHeight + Mth.clamp(offHandTargetHeight - this.offHandHeight, -0.4F, 0.4F);
}
@@ -122,7 +_,7 @@
private boolean extractMapRenderState(LocalPlayer player, ItemStack itemStack, MapRenderState state) {
MapId mapId = itemStack.get(DataComponents.MAP_ID);
- MapItemSavedData mapData = mapId == null ? null : MapItem.getSavedData(mapId, player.level());
+ MapItemSavedData mapData = mapId == null ? null : MapItem.getSavedData(itemStack, player.level());
if (mapId != null && mapData != null) {
player.minecraft.getMapRenderer().extractRenderState(mapId, mapData, state);
return true;
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/player/LocalPlayer.java
+++ b/net/minecraft/client/player/LocalPlayer.java
@@ -545,7 +_,14 @@
@@ -560,7 +_,14 @@
@Override
public void playSound(SoundEvent sound, float volume, float pitch) {
@@ -16,7 +16,7 @@
}
@Override
@@ -787,6 +_,7 @@
@@ -803,6 +_,7 @@
&& this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.CROUCHING)
&& (this.isShiftKeyDown() || !this.isSleeping() && !this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.STANDING));
this.input.tick();
@@ -24,7 +24,7 @@
this.minecraft.getTutorial().onInput(this.input);
boolean wasAutoJump = false;
if (this.autoJumpTime > 0) {
@@ -831,7 +_,7 @@
@@ -847,7 +_,7 @@
}
boolean justToggledCreativeFlight = false;
@@ -33,7 +33,7 @@
if (this.minecraft.gameMode.isSpectator()) {
if (!abilities.flying) {
abilities.flying = true;
@@ -928,7 +_,7 @@
@@ -944,7 +_,7 @@
}
private boolean shouldStopSwimSprinting() {
@@ -42,23 +42,17 @@
}
public Portal.Transition getActivePortalLocalTransition() {
@@ -971,8 +_,19 @@
}
@@ -999,6 +_,13 @@
@Override
public float getSpinningEffectAngle(float partialTick) {
return this.spinningEffectTime + partialTick * this.spinningEffectSpeed;
+ }
+
+ @Override
+ protected boolean canGlide() {
+ // Neo: Override canGlide for the client to check if it is connected to a neo forge server, and if not then fall back to checking the worn items.
+ // This way when Player#tryToStartFallFlying is called, on the client, it is able to check for the vanilla components on equipped items
+ return !getAbilities().flying && canGlide(connection.getConnectionType().isNeoForge());
+ }
+
+ @Override
public void rideTick() {
super.rideTick();
+ if (this.wantsToStopRiding() && this.isPassenger()) {
+ Input input = this.input.keyPresses;
+ this.input.keyPresses = new Input(input.forward(), input.backward(), input.left(), input.right(), input.jump(), false, input.sprint());
+ }
this.handsBusy = false;
if (this.getControlledVehicle() instanceof AbstractBoat boat) {
boat.setInput(this.input.keyPresses.left(), this.input.keyPresses.right(), this.input.keyPresses.forward(), this.input.keyPresses.backward());
}
@Override
@@ -0,0 +1,54 @@
--- a/net/minecraft/client/renderer/FirstPersonHandsAndItemsRenderer.java
+++ b/net/minecraft/client/renderer/FirstPersonHandsAndItemsRenderer.java
@@ -120,8 +_,10 @@
AvatarRenderer<?> avatarRenderer = this.minecraft.getEntityRenderDispatcher().getRenderer(avatarRenderState);
Identifier skinTexture = avatarRenderState.skin.body().texturePath();
if (arm == HumanoidArm.RIGHT) {
+ if(!net.neoforged.neoforge.client.ClientHooks.renderSpecificFirstPersonArm(poseStack, submitNodeCollector, lightCoords, skinTexture, avatarRenderState.showRightSleeve, playerState, HumanoidArm.RIGHT, avatarRenderer.getModel().rightArm))
avatarRenderer.renderRightHand(poseStack, submitNodeCollector, lightCoords, skinTexture, avatarRenderState.showRightSleeve);
} else {
+ if(!net.neoforged.neoforge.client.ClientHooks.renderSpecificFirstPersonArm(poseStack, submitNodeCollector, lightCoords, skinTexture, avatarRenderState.showLeftSleeve, playerState, HumanoidArm.LEFT, avatarRenderer.getModel().leftArm))
avatarRenderer.renderLeftHand(poseStack, submitNodeCollector, lightCoords, skinTexture, avatarRenderState.showLeftSleeve);
}
}
@@ -338,6 +_,7 @@
if (state.handRenderSelection.renderMainHand) {
float mainHandAttack = attackHand == InteractionHand.MAIN_HAND ? attackValue : 0.0F;
float mainhandInverseArmHeight = state.mainHandSwapScale * (1.0F - Mth.lerp(partialTicks, state.oldMainHandHeight, state.mainHandHeight));
+ if(!net.neoforged.neoforge.client.ClientHooks.renderSpecificFirstPersonHand(InteractionHand.MAIN_HAND, poseStack, submitNodeCollector, playerState.avatarRenderState.lightCoords, partialTicks, xRot, mainHandAttack, mainhandInverseArmHeight, state.mainHandItem))
this.submitArmWithItem(
playerState,
state,
@@ -356,6 +_,7 @@
if (state.handRenderSelection.renderOffHand) {
float offHandAttack = attackHand == InteractionHand.OFF_HAND ? attackValue : 0.0F;
float offhandInverseArmHeight = state.offHandSwapScale * (1.0F - Mth.lerp(partialTicks, state.oldOffHandHeight, state.offHandHeight));
+ if(!net.neoforged.neoforge.client.ClientHooks.renderSpecificFirstPersonHand(InteractionHand.OFF_HAND, poseStack, submitNodeCollector, playerState.avatarRenderState.lightCoords, partialTicks, xRot, offHandAttack, offhandInverseArmHeight, state.offHandItem))
this.submitArmWithItem(
playerState,
state,
@@ -398,13 +_,13 @@
if (isMainHand && !avatarRenderState.isInvisible) {
this.renderPlayerArm(poseStack, submitNodeCollector, lightCoords, inverseArmHeight, attack, arm, playerState);
}
- } else if (itemStack.has(DataComponents.MAP_ID)) {
+ } else if (itemStack.getItem() instanceof net.minecraft.world.item.MapItem) {
if (isMainHand && state.offHandItem.isEmpty()) {
this.renderTwoHandedMap(poseStack, submitNodeCollector, lightCoords, xRot, inverseArmHeight, attack, playerState, state);
} else {
this.renderOneHandedMap(poseStack, submitNodeCollector, lightCoords, inverseArmHeight, arm, attack, itemStack, playerState, state);
}
- } else if (itemStack.is(Items.CROSSBOW)) {
+ } else if (itemStack.getItem() instanceof CrossbowItem) {
this.applyItemArmTransform(poseStack, arm, inverseArmHeight);
boolean charged = CrossbowItem.isCharged(itemStack);
boolean isRightArm = arm == HumanoidArm.RIGHT;
@@ -443,6 +_,8 @@
} else {
boolean isRightArm = arm == HumanoidArm.RIGHT;
int invert = isRightArm ? 1 : -1;
+ // Neo: Allow items to define custom arm animation
+ if (!net.neoforged.neoforge.client.extensions.common.IClientItemExtensions.of(itemStack).applyForgeHandTransform(poseStack, playerState, arm, itemStack, partialTicks, inverseArmHeight, attack))
if (avatarRenderState.isUsingItem && state.useItemRemainingTicks > 0 && avatarRenderState.useItemHand == hand) {
ItemUseAnimation useAnimation = itemStack.getUseAnimation();
if (!useAnimation.hasCustomArmTransform()) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/renderer/GameRenderer.java
+++ b/net/minecraft/client/renderer/GameRenderer.java
@@ -150,17 +_,17 @@
@@ -165,18 +_,18 @@
this.guiRenderer = new GuiRenderer(
this.gameRenderState.guiRenderState,
this.featureRenderDispatcher,
@@ -19,22 +19,23 @@
+ new net.neoforged.neoforge.client.gui.PictureInPictureRendererRegistration<>(net.minecraft.client.renderer.state.gui.pip.GuiProfilerChartRenderState.class, GuiProfilerChartRenderer::new)
+ ))
);
this.screenEffectRenderer = new ScreenEffectRenderer(minecraft, atlasManager);
this.screenEffectRenderer = new ScreenEffectRenderer(this, atlasManager);
this.debugCrosshairRenderer = new DebugCrosshairRenderer();
- this.mainRenderTarget = new MainTarget(minecraft.getWindow().getWidth(), minecraft.getWindow().getHeight());
this.hud3DTarget = new TextureTarget("hud_3d_depth", minecraft.getWindow().getWidth(), minecraft.getWindow().getHeight(), null, GpuFormat.D32_FLOAT);
+ this.mainRenderTarget = net.neoforged.neoforge.client.ClientHooks.instantiateMainTarget(minecraft.getWindow().getWidth(), minecraft.getWindow().getHeight());
}
@Override
@@ -219,6 +_,7 @@
@@ -236,6 +_,7 @@
break;
case null:
default:
+ if (!net.neoforged.neoforge.client.ClientHooks.loadEntityShader(cameraEntity, this))
this.clearPostEffect();
this.clearSpectatedEntityPostEffect();
}
}
@@ -309,6 +_,9 @@
@@ -348,6 +_,9 @@
return;
}
@@ -44,13 +45,13 @@
hurt /= cameraState.entityRenderState.hurtDuration;
hurt = Mth.sin(hurt * hurt * hurt * hurt * (float) Math.PI);
float rr = cameraState.entityRenderState.hurtDir;
@@ -563,6 +_,9 @@
@@ -672,6 +_,9 @@
this.minecraft
.levelRenderer
.render(this.resourcePool, deltaTracker, renderOutline, cameraState, modelViewMatrix, terrainFog, cameraState.fogData.color, !shouldCreateBossFog);
.render(this.resourcePool, renderOutline, cameraState, terrainFog, cameraState.fogData.color, !shouldCreateBossFog, consistentDepthRequired);
+ profiler.popPush("neoforge_render_after_level");
+ LevelRenderer levelRenderer = this.minecraft.levelRenderer;
+ net.neoforged.neoforge.common.NeoForge.EVENT_BUS.post(new net.neoforged.neoforge.client.event.RenderLevelStageEvent.AfterLevel(levelRenderer, levelRenderer.levelRenderState, null, modelViewMatrix, levelRenderer.visibleSections()));
profiler.popPush("hand");
boolean isSleeping = cameraState.entityRenderState.isSleeping;
this.hudProjection
+ net.neoforged.neoforge.common.NeoForge.EVENT_BUS.post(new net.neoforged.neoforge.client.event.RenderLevelStageEvent.AfterLevel(levelRenderer, levelRenderer.levelRenderState, null, cameraState.viewRotationMatrix, levelRenderer.visibleSections()));
this.render3dHud(cameraState, playerState, optionsState, consistentDepthRequired);
}
@@ -1,99 +0,0 @@
--- a/net/minecraft/client/renderer/ItemInHandRenderer.java
+++ b/net/minecraft/client/renderer/ItemInHandRenderer.java
@@ -157,11 +_,11 @@
Identifier skinTexture = this.minecraft.player.getSkin().body().texturePath();
if (arm == HumanoidArm.RIGHT) {
avatarRenderer.renderRightHand(
- poseStack, submitNodeCollector, lightCoords, skinTexture, this.minecraft.player.isModelPartShown(PlayerModelPart.RIGHT_SLEEVE)
+ poseStack, submitNodeCollector, lightCoords, skinTexture, this.minecraft.player.isModelPartShown(PlayerModelPart.RIGHT_SLEEVE), this.minecraft.player
);
} else {
avatarRenderer.renderLeftHand(
- poseStack, submitNodeCollector, lightCoords, skinTexture, this.minecraft.player.isModelPartShown(PlayerModelPart.LEFT_SLEEVE)
+ poseStack, submitNodeCollector, lightCoords, skinTexture, this.minecraft.player.isModelPartShown(PlayerModelPart.LEFT_SLEEVE), this.minecraft.player
);
}
@@ -231,7 +_,7 @@
poseStack.translate(-0.5F, -0.5F, 0.0F);
poseStack.scale(0.0078125F, 0.0078125F, 0.0078125F);
MapId id = itemStack.get(DataComponents.MAP_ID);
- MapItemSavedData data = MapItem.getSavedData(id, this.minecraft.level);
+ MapItemSavedData data = MapItem.getSavedData(itemStack, this.minecraft.level);
RenderType renderType = data == null ? MAP_BACKGROUND : MAP_BACKGROUND_CHECKERBOARD;
submitNodeCollector.submitCustomGeometry(poseStack, renderType, (pose, buffer) -> {
buffer.addVertex(pose, -7.0F, 135.0F, 0.0F).setColor(-1).setUv(0.0F, 1.0F).setLight(lightCoords);
@@ -270,9 +_,9 @@
AvatarRenderer<AbstractClientPlayer> avatarRenderer = this.entityRenderDispatcher.getPlayerRenderer(player);
Identifier skinTexture = player.getSkin().body().texturePath();
if (isRightArm) {
- avatarRenderer.renderRightHand(poseStack, submitNodeCollector, lightCoords, skinTexture, player.isModelPartShown(PlayerModelPart.RIGHT_SLEEVE));
+ avatarRenderer.renderRightHand(poseStack, submitNodeCollector, lightCoords, skinTexture, player.isModelPartShown(PlayerModelPart.RIGHT_SLEEVE), player);
} else {
- avatarRenderer.renderLeftHand(poseStack, submitNodeCollector, lightCoords, skinTexture, player.isModelPartShown(PlayerModelPart.LEFT_SLEEVE));
+ avatarRenderer.renderLeftHand(poseStack, submitNodeCollector, lightCoords, skinTexture, player.isModelPartShown(PlayerModelPart.LEFT_SLEEVE), player);
}
}
@@ -345,6 +_,7 @@
float mainHandAttack = attackHand == InteractionHand.MAIN_HAND ? attackValue : 0.0F;
float mainhandInverseArmHeight = this.itemModelResolver.swapAnimationScale(this.mainHandItem)
* (1.0F - Mth.lerp(frameInterp, this.oMainHandHeight, this.mainHandHeight));
+ if(!net.neoforged.neoforge.client.ClientHooks.renderSpecificFirstPersonHand(InteractionHand.MAIN_HAND, poseStack, submitNodeCollector, lightCoords, frameInterp, xRot, mainHandAttack, mainhandInverseArmHeight, this.mainHandItem))
this.submitArmWithItem(
player,
frameInterp,
@@ -363,6 +_,7 @@
float offHandAttack = attackHand == InteractionHand.OFF_HAND ? attackValue : 0.0F;
float offhandInverseArmHeight = this.itemModelResolver.swapAnimationScale(this.offHandItem)
* (1.0F - Mth.lerp(frameInterp, this.oOffHandHeight, this.offHandHeight));
+ if(!net.neoforged.neoforge.client.ClientHooks.renderSpecificFirstPersonHand(InteractionHand.OFF_HAND, poseStack, submitNodeCollector, lightCoords, frameInterp, xRot, offHandAttack, offhandInverseArmHeight, this.offHandItem))
this.submitArmWithItem(
player,
frameInterp,
@@ -431,13 +_,13 @@
if (isMainHand && !player.isInvisible()) {
this.renderPlayerArm(poseStack, submitNodeCollector, lightCoords, inverseArmHeight, attack, arm);
}
- } else if (itemStack.has(DataComponents.MAP_ID)) {
+ } else if (itemStack.getItem() instanceof MapItem) {
if (isMainHand && this.offHandItem.isEmpty()) {
this.renderTwoHandedMap(poseStack, submitNodeCollector, lightCoords, xRot, inverseArmHeight, attack);
} else {
this.renderOneHandedMap(poseStack, submitNodeCollector, lightCoords, inverseArmHeight, arm, attack, itemStack);
}
- } else if (itemStack.is(Items.CROSSBOW)) {
+ } else if (itemStack.getItem() instanceof CrossbowItem) {
this.applyItemArmTransform(poseStack, arm, inverseArmHeight);
boolean charged = CrossbowItem.isCharged(itemStack);
boolean isRightArm = arm == HumanoidArm.RIGHT;
@@ -482,6 +_,8 @@
} else {
boolean isRightArm = arm == HumanoidArm.RIGHT;
int invert = isRightArm ? 1 : -1;
+ // Neo: Allow items to define custom arm animation
+ if (!net.neoforged.neoforge.client.extensions.common.IClientItemExtensions.of(itemStack).applyForgeHandTransform(poseStack, minecraft.player, arm, itemStack, frameInterp, inverseArmHeight, attack))
if (player.isUsingItem() && player.getUseItemRemainingTicks() > 0 && player.getUsedItemHand() == hand) {
ItemUseAnimation useAnimation = itemStack.getUseAnimation();
if (!useAnimation.hasCustomArmTransform()) {
@@ -629,9 +_,18 @@
this.mainHandHeight = Mth.clamp(this.mainHandHeight - 0.4F, 0.0F, 1.0F);
this.offHandHeight = Mth.clamp(this.offHandHeight - 0.4F, 0.0F, 1.0F);
} else {
+ // Neo: allow suppressing re-equip animation when only the stack's data changes
+ boolean swapAnimMain = net.neoforged.neoforge.client.ClientHooks.shouldCauseReequipAnimation(this.mainHandItem, nextMainHand, player.getInventory().getSelectedSlot());
+ boolean swapAnimOff = net.neoforged.neoforge.client.ClientHooks.shouldCauseReequipAnimation(this.offHandItem, nextOffHand, -1);
+
+ if (!swapAnimMain && this.mainHandItem != nextMainHand)
+ this.mainHandItem = nextMainHand;
+ if (!swapAnimOff && this.offHandItem != nextOffHand)
+ this.offHandItem = nextOffHand;
+
float attackAnim = player.getItemSwapScale(1.0F);
- float mainHandTargetHeight = this.mainHandItem != nextMainHand ? 0.0F : attackAnim * attackAnim * attackAnim;
- float offHandTargetHeight = this.offHandItem != nextOffHand ? 0.0F : 1.0F;
+ float mainHandTargetHeight = swapAnimMain ? 0.0F : attackAnim * attackAnim * attackAnim;
+ float offHandTargetHeight = swapAnimOff ? 0.0F : 1.0F;
this.mainHandHeight = this.mainHandHeight + Mth.clamp(mainHandTargetHeight - this.mainHandHeight, -0.4F, 0.4F);
this.offHandHeight = this.offHandHeight + Mth.clamp(offHandTargetHeight - this.offHandHeight, -0.4F, 0.4F);
}
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/renderer/LevelEventHandler.java
+++ b/net/minecraft/client/renderer/LevelEventHandler.java
@@ -304,8 +_,8 @@
@@ -311,8 +_,8 @@
break;
case 2001:
BlockState blockState = Block.stateById(data);

Some files were not shown because too many files have changed in this diff Show More