Skip to content

Commit 88b858f

Browse files
feat: port to 26.2
1 parent 9711b42 commit 88b858f

15 files changed

Lines changed: 259 additions & 77 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## [26.2.0.1]
2+
3+
### Changed
4+
5+
- Ported to Minecraft `26.2`
6+
17
## [26.1.0.1]
28

39
### Changed

common/src/main/java/pro/mikey/xray/XRay.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ public void onOpenGuiKeyPressed() {
4343
return;
4444
}
4545

46-
Minecraft.getInstance().setScreen(new ScanManageScreen());
46+
Minecraft.getInstance().gui.setScreen(new ScanManageScreen());
4747
}
4848

4949
private boolean minecraftNotReady() {
5050
Minecraft mc = Minecraft.getInstance();
5151

52-
return mc.player == null || Minecraft.getInstance().screen != null || Minecraft.getInstance().level == null;
52+
return mc.player == null || Minecraft.getInstance().gui.screen() != null || Minecraft.getInstance().level == null;
5353
}
5454

5555
public static Identifier id(String path) {
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
//package pro.mikey.xray.core;
2+
//
3+
//import com.mojang.blaze3d.PrimitiveTopology;
4+
//import com.mojang.blaze3d.pipeline.BlendFunction;
5+
//import com.mojang.blaze3d.pipeline.ColorTargetState;
6+
//import com.mojang.blaze3d.pipeline.DepthStencilState;
7+
//import com.mojang.blaze3d.pipeline.RenderPipeline;
8+
//import com.mojang.blaze3d.platform.CompareOp;
9+
//import com.mojang.blaze3d.vertex.*;
10+
//import net.minecraft.client.Minecraft;
11+
//import net.minecraft.client.renderer.RenderPipelines;
12+
//import net.minecraft.client.renderer.SubmitNodeCollector;
13+
//import net.minecraft.client.renderer.rendertype.LayeringTransform;
14+
//import net.minecraft.client.renderer.rendertype.OutputTarget;
15+
//import net.minecraft.client.renderer.rendertype.RenderSetup;
16+
//import net.minecraft.client.renderer.rendertype.RenderType;
17+
//import net.minecraft.world.level.ChunkPos;
18+
//import net.minecraft.world.phys.Vec3;
19+
//import net.minecraft.world.phys.shapes.Shapes;
20+
//import org.joml.Vector3f;
21+
//import pro.mikey.xray.XRay;
22+
//
23+
//import java.util.*;
24+
//
25+
//public class OutlineCustomGeometryRenderer {
26+
// public static final RenderPipeline NO_DEPTH_LINES_PIPELINE = RenderPipeline.builder(
27+
// RenderPipelines.MATRICES_FOG_SNIPPET)
28+
// .withVertexShader("core/rendertype_lines")
29+
// .withFragmentShader("core/rendertype_lines")
30+
// .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT))
31+
// .withCull(false)
32+
// .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH)
33+
// .withPrimitiveTopology(PrimitiveTopology.LINES)
34+
// .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)
35+
// )
36+
// .withLocation(XRay.id("pipeline/lines_no_depth"))
37+
// .build();
38+
//
39+
// // TODO: Tell shaders this acts like the line render type as it uses the same shaders.
40+
// public static final RenderType NO_DEPTH_LINES_TYPE = RenderType.create("lines_no_depth", RenderSetup.builder(NO_DEPTH_LINES_PIPELINE)
41+
// .setLayeringTransform(LayeringTransform.NO_LAYERING)
42+
// .setOutputTarget(OutputTarget.OUTLINE_TARGET)
43+
// .createRenderSetup()
44+
// );
45+
//
46+
// public static final OutlineCustomGeometryRenderer INSTANCE = new OutlineCustomGeometryRenderer();
47+
//
48+
// private final Map<ChunkPos, List<CachedVertex>> vertexCache = new HashMap<>();
49+
// private final Set<ChunkPos> chunksToRefresh = Collections.synchronizedSet(new HashSet<>());
50+
//
51+
// public void render(PoseStack poseStack) {
52+
// if (!shouldRender()) {
53+
// return;
54+
// }
55+
//
56+
// Vec3 playerPos = Minecraft.getInstance().gameRenderer.mainCamera().position().reverse();
57+
//
58+
// poseStack.pushPose();
59+
// poseStack.translate((float) playerPos.x(), (float) playerPos.y(), (float) playerPos.z());
60+
//
61+
// _render(poseStack, Minecraft.getInstance().gameRenderer.renderBuffers().bufferSource().getBuffer(NO_DEPTH_LINES_TYPE));
62+
//
63+
// poseStack.popPose();
64+
// }
65+
//
66+
// public void _render(PoseStack stack, VertexConsumer buffer) {
67+
// flushInvalidatedChunks();
68+
//
69+
// var entries = new ArrayList<>(ScanController.INSTANCE.syncRenderList.entrySet());
70+
//
71+
// PoseStack.Pose pose = stack.last();
72+
// for (var chunkWithBlockData : entries) {
73+
// var chunkPos = chunkWithBlockData.getKey();
74+
// var blocksWithProps = chunkWithBlockData.getValue();
75+
// if (blocksWithProps.isEmpty()) continue;
76+
//
77+
// List<CachedVertex> cached = vertexCache.computeIfAbsent(chunkPos, pos -> buildChunkVertices(blocksWithProps));
78+
//
79+
// for (CachedVertex v : cached) {
80+
// buffer.addVertex(pose, v.x(), v.y(), v.z())
81+
// .setColor(v.color())
82+
// .setNormal(pose, v.nx(), v.ny(), v.nz())
83+
// .setLineWidth(v.width());
84+
// }
85+
// }
86+
// }
87+
//
88+
// private List<CachedVertex> buildChunkVertices(Set<OutlineRenderTarget> blocksWithProps) {
89+
// List<CachedVertex> result = new ArrayList<>();
90+
// Vector3f normal = new Vector3f();
91+
//
92+
// for (var blockProps : blocksWithProps) {
93+
// if (blockProps == null) continue;
94+
// final int x = blockProps.x(), y = blockProps.y(), z = blockProps.z();
95+
// int color = blockProps.color();
96+
// float width = 2.0f;
97+
//
98+
// Shapes.block().forAllEdges((x1, y1, z1, x2, y2, z2) -> {
99+
// normal.set((float)(x2 - x1), (float)(y2 - y1), (float)(z2 - z1)).normalize();
100+
// result.add(new CachedVertex((float)(x + x1), (float)(y + y1), (float)(z + z1), color, normal.x(), normal.y(), normal.z(), width));
101+
// result.add(new CachedVertex((float)(x + x2), (float)(y + y2), (float)(z + z2), color, normal.x(), normal.y(), normal.z(), width));
102+
// });
103+
// }
104+
// return result;
105+
// }
106+
//
107+
// public boolean shouldRender() {
108+
// if (!ScanController.INSTANCE.isXRayActive() || Minecraft.getInstance().player == null) {
109+
// return false;
110+
// }
111+
//
112+
// return !ScanController.INSTANCE.syncRenderList.isEmpty();
113+
// }
114+
//
115+
// private void flushInvalidatedChunks() {
116+
// if (!chunksToRefresh.isEmpty()) {
117+
// // Clear the vertex buffers for the chunks that need to be refreshed
118+
// for (ChunkPos pos : chunksToRefresh) {
119+
// vertexCache.remove(pos);
120+
// }
121+
//
122+
// chunksToRefresh.clear();
123+
// }
124+
// }
125+
//
126+
// public void clearCache() {
127+
// vertexCache.clear();
128+
// chunksToRefresh.clear();
129+
// }
130+
//
131+
// public void clearCacheFor(List<ChunkPos> removedChunks) {
132+
// if (removedChunks.isEmpty()) {
133+
// return;
134+
// }
135+
//
136+
// chunksToRefresh.addAll(removedChunks);
137+
// }
138+
//
139+
// public void refreshVBOForChunk(ChunkPos pos) {
140+
// chunksToRefresh.add(pos);
141+
// }
142+
//
143+
// private record CachedVertex(float x, float y, float z, int color, float nx, float ny, float nz, float width) {}
144+
//}

common/src/main/java/pro/mikey/xray/core/OutlineRender.java

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,53 @@
11
package pro.mikey.xray.core;
22

3+
import com.mojang.blaze3d.PrimitiveTopology;
34
import com.mojang.blaze3d.buffers.GpuBuffer;
45
import com.mojang.blaze3d.buffers.GpuBufferSlice;
56
import com.mojang.blaze3d.pipeline.BlendFunction;
7+
import com.mojang.blaze3d.pipeline.ColorTargetState;
8+
import com.mojang.blaze3d.pipeline.DepthStencilState;
69
import com.mojang.blaze3d.pipeline.RenderPipeline;
10+
import com.mojang.blaze3d.platform.CompareOp;
711
import com.mojang.blaze3d.systems.RenderPass;
812
import com.mojang.blaze3d.systems.RenderSystem;
913
import com.mojang.blaze3d.textures.GpuTextureView;
1014
import com.mojang.blaze3d.vertex.*;
1115
import net.minecraft.client.Minecraft;
1216
import net.minecraft.client.renderer.DynamicUniforms;
1317
import net.minecraft.client.renderer.RenderPipelines;
14-
import net.minecraft.client.renderer.ShapeRenderer;
15-
import net.minecraft.resources.Identifier;
1618
import net.minecraft.world.level.ChunkPos;
1719
import net.minecraft.world.phys.Vec3;
1820
import net.minecraft.world.phys.shapes.Shapes;
1921
import org.joml.Matrix4f;
2022
import org.joml.Matrix4fStack;
2123
import org.joml.Vector3f;
2224
import org.joml.Vector4f;
23-
import org.lwjgl.opengl.GL11;
25+
import pro.mikey.xray.XRay;
2426

2527
import java.io.Closeable;
2628
import java.util.*;
2729

2830
public class OutlineRender {
29-
private static final RenderSystem.AutoStorageIndexBuffer indices = RenderSystem.getSequentialBuffer(VertexFormat.Mode.LINES);
31+
public static final RenderPipeline NO_DEPTH_LINES_PIPELINE = RenderPipeline.builder(
32+
RenderPipelines.MATRICES_FOG_SNIPPET)
33+
.withVertexShader("core/rendertype_lines")
34+
.withFragmentShader("core/rendertype_lines")
35+
.withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT))
36+
.withCull(false)
37+
.withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH)
38+
.withPrimitiveTopology(PrimitiveTopology.LINES)
39+
.withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)
40+
)
41+
.withLocation(XRay.id("pipeline/lines_no_depth"))
42+
.build();
43+
44+
private static final RenderSystem.AutoStorageIndexBuffer indices = RenderSystem.getSequentialBuffer(PrimitiveTopology.LINES);
45+
3046
private static final Map<ChunkPos, VBOHolder> vertexBuffers = new HashMap<>();
3147

3248
private static final Set<ChunkPos> chunksToRefresh = Collections.synchronizedSet(new HashSet<>());
3349

34-
public static void renderBlocks(PoseStack poseStack) {
50+
public static void renderBlocks() {
3551
if (!ScanController.INSTANCE.isXRayActive() || Minecraft.getInstance().player == null) {
3652
return;
3753
}
@@ -65,27 +81,34 @@ public static void renderBlocks(PoseStack poseStack) {
6581

6682
VBOHolder holder = vertexBuffers.get(chunkPos);
6783
if (holder == null) {
68-
BufferBuilder bufferBuilder = Tesselator.getInstance().begin(RenderPipelines.LINES.getVertexFormatMode(), RenderPipelines.LINES.getVertexFormat());
69-
70-
// More concurrent modification exceptions can happen here, so we clone the list
71-
var blockPropsClone = new ArrayList<>(blocksWithProps);
72-
73-
for (var blockProps : blockPropsClone) {
74-
if (blockProps == null) {
75-
continue;
84+
try (ByteBufferBuilder byteBufferBuilder = new ByteBufferBuilder(NO_DEPTH_LINES_PIPELINE.getVertexFormatBinding(0).getVertexSize() * 1024)) {
85+
BufferBuilder bufferBuilder = new BufferBuilder(
86+
byteBufferBuilder,
87+
NO_DEPTH_LINES_PIPELINE.getPrimitiveTopology(),
88+
NO_DEPTH_LINES_PIPELINE.getVertexFormatBinding(0)
89+
);
90+
91+
var blockPropsClone = new ArrayList<>(blocksWithProps);
92+
for (var blockProps : blockPropsClone) {
93+
Vector3f normal = new Vector3f();
94+
if (blockProps == null) continue;
95+
final int x = blockProps.x(), y = blockProps.y(), z = blockProps.z();
96+
int color = blockProps.color();
97+
float width = 2.0f;
98+
99+
Shapes.block().forAllEdges((x1, y1, z1, x2, y2, z2) -> {
100+
normal.set((float)(x2 - x1), (float)(y2 - y1), (float)(z2 - z1)).normalize();
101+
bufferBuilder.addVertex((float)(x + x1), (float)(y + y1), (float)(z + z1)).setColor(color).setNormal(normal.x(), normal.y(), normal.z()).setLineWidth(width);
102+
bufferBuilder.addVertex((float)(x + x2), (float)(y + y2), (float)(z + z2)).setColor(color).setNormal(normal.x(), normal.y(), normal.z()).setLineWidth(width);
103+
});
76104
}
77105

78-
final int x = blockProps.x(), y = blockProps.y(), z = blockProps.z();
79-
80-
ShapeRenderer.renderShape(poseStack, bufferBuilder, Shapes.block(), x, y, z, blockProps.color(), 1f);
81-
}
82-
83-
try (MeshData meshData = bufferBuilder.buildOrThrow()) {
84-
int indexCount = meshData.drawState().indexCount();
85-
GpuBuffer vertexBuffer = RenderSystem.getDevice()
86-
.createBuffer(() -> "Xray vertex buffer", GpuBuffer.USAGE_VERTEX, meshData.vertexBuffer());
87-
88-
vertexBuffers.put(chunkPos, new VBOHolder(vertexBuffer, indexCount));
106+
try (MeshData meshData = bufferBuilder.buildOrThrow()) {
107+
int indexCount = meshData.drawState().indexCount();
108+
GpuBuffer vertexBuffer = RenderSystem.getDevice()
109+
.createBuffer(() -> "Xray vertex buffer", GpuBuffer.USAGE_VERTEX, meshData.vertexBuffer());
110+
vertexBuffers.put(chunkPos, new VBOHolder(vertexBuffer, indexCount));
111+
}
89112
}
90113
}
91114

@@ -94,33 +117,31 @@ public static void renderBlocks(PoseStack poseStack) {
94117
continue;
95118
}
96119

97-
Vec3 playerPos = Minecraft.getInstance().gameRenderer.getMainCamera().position().reverse();
120+
Vec3 playerPos = Minecraft.getInstance().gameRenderer.mainCamera().position().reverse();
98121

99122
Matrix4fStack matrix4fStack = RenderSystem.getModelViewStack();
100-
GpuTextureView colorTextureView = Minecraft.getInstance().getMainRenderTarget().getColorTextureView();
101-
GpuTextureView depthTextureView = Minecraft.getInstance().getMainRenderTarget().getDepthTextureView();
123+
GpuTextureView colorTextureView = Minecraft.getInstance().gameRenderer.mainRenderTarget().getColorTextureView();
124+
GpuTextureView depthTextureView = Minecraft.getInstance().gameRenderer.mainRenderTarget().getDepthTextureView();
102125

103126
matrix4fStack.pushMatrix();
104127
matrix4fStack.translate((float) playerPos.x(), (float) playerPos.y(), (float) playerPos.z());
105128
GpuBufferSlice[] gpubufferslice = RenderSystem.getDynamicUniforms().writeTransforms(new DynamicUniforms.Transform(new Matrix4f(matrix4fStack), new Vector4f(1.0F, 1.0F, 1.0F, 1.0F), new Vector3f(), new Matrix4f()));
106129

107-
GL11.glDisable(GL11.GL_DEPTH_TEST);
108130
RenderSystem.setShaderFog(gpubufferslice[0]);
109131

110132
GpuBuffer gpuBuffer = indices.getBuffer(holder.indexCount);
111133
try (RenderPass renderPass = RenderSystem.getDevice()
112134
.createCommandEncoder()
113-
.createRenderPass(() -> "xray", colorTextureView, OptionalInt.empty(), depthTextureView, OptionalDouble.empty())) {
135+
.createRenderPass(() -> "xray", colorTextureView, Optional.empty(), depthTextureView, OptionalDouble.empty())) {
114136

115137
RenderSystem.bindDefaultUniforms(renderPass);
116-
renderPass.setVertexBuffer(0, holder.vertexBuffer);
138+
renderPass.setVertexBuffer(0, holder.vertexBuffer.slice());
117139
renderPass.setIndexBuffer(gpuBuffer, indices.type());
118140
renderPass.setUniform("DynamicTransforms", gpubufferslice[0]);
119-
renderPass.setPipeline(RenderPipelines.LINES);
120-
renderPass.drawIndexed(0, 0, holder.indexCount, 1);
141+
renderPass.setPipeline(NO_DEPTH_LINES_PIPELINE);
142+
renderPass.drawIndexed(holder.indexCount, 1, 0, 0, 0);
121143
}
122144

123-
GL11.glEnable(GL11.GL_DEPTH_TEST);
124145
matrix4fStack.popMatrix();
125146
}
126147
}

common/src/main/java/pro/mikey/xray/core/ScanController.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,22 @@
99
import net.minecraft.world.level.block.Block;
1010
import net.minecraft.world.level.block.Blocks;
1111
import net.minecraft.world.level.block.state.BlockState;
12-
import org.jetbrains.annotations.NotNull;
1312
import pro.mikey.xray.XRay;
1413
import pro.mikey.xray.core.scanner.ScanStore;
1514
import pro.mikey.xray.core.scanner.ScanType;
1615

1716
import java.util.*;
1817
import java.util.concurrent.ExecutorService;
1918
import java.util.concurrent.Executors;
20-
import java.util.concurrent.ThreadFactory;
2119

2220
public enum ScanController {
2321
INSTANCE;
2422

2523
// Ensure this thread is shutdown when the game exists.
26-
private final ExecutorService SCANNER = Executors.newFixedThreadPool(4, new ThreadFactory() {
27-
@Override
28-
public Thread newThread(@NotNull Runnable r) {
29-
Thread thread = new Thread(r, "XRay-Scanner");
30-
thread.setDaemon(true); // Daemon threads do not prevent the JVM from exiting
31-
return thread;
32-
}
24+
private final ExecutorService SCANNER = Executors.newFixedThreadPool(4, r -> {
25+
Thread thread = new Thread(r, "XRay-Scanner");
26+
thread.setDaemon(true); // Daemon threads do not prevent the JVM from exiting
27+
return thread;
3328
});
3429

3530
private final int maxStepsToScan = 5;
@@ -193,7 +188,8 @@ public static void onBlockChange(Level level, BlockPos pos, BlockState state) {
193188
return;
194189
}
195190

196-
var chunkPos = new ChunkPos(pos.getX(), pos.getZ());
191+
var chunkPos = new ChunkPos(pos.getX() >> 4, pos.getZ() >> 4);
192+
197193
Set<OutlineRenderTarget> outlineRenderTargets = ScanController.INSTANCE.syncRenderList.get(chunkPos);
198194
if (outlineRenderTargets == null) {
199195
// It's not being rendered, so we don't care

common/src/main/java/pro/mikey/xray/screens/FindBlockScreen.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public void init() {
3737
search.setFocused(true);
3838
this.setFocused(search);
3939

40-
addRenderableWidget(Button.builder(Component.translatable("xray.single.cancel"), b -> Minecraft.getInstance().setScreen(new ScanManageScreen()))
40+
addRenderableWidget(Button.builder(Component.translatable("xray.single.cancel"), b -> Minecraft.getInstance().gui.setScreen(new ScanManageScreen()))
4141
.pos(getWidth() / 2 + 43, getHeight() / 2 + 84)
4242
.size(60, 20)
4343
.build());
@@ -118,7 +118,7 @@ public void setSelected(@Nullable BlockSlot entry) {
118118
return;
119119
}
120120

121-
Minecraft.getInstance().setScreen(new ScanConfigureScreen(entry.getBlock(), FindBlockScreen::new));
121+
Minecraft.getInstance().gui.setScreen(new ScanConfigureScreen(entry.getBlock(), FindBlockScreen::new));
122122
}
123123

124124
void updateEntries(List<Block> blocks) {

common/src/main/java/pro/mikey/xray/screens/HelpScreen.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public void init() {
2828
areas.add(new LinedText("xray.message.help.gui"));
2929
areas.add(new LinedText("xray.message.help.warning"));
3030

31-
this.addRenderableWidget(Button.builder(Component.translatable("xray.single.close"), btn -> Minecraft.getInstance().setScreen(new ScanManageScreen()))
31+
this.addRenderableWidget(Button.builder(Component.translatable("xray.single.close"), btn -> Minecraft.getInstance().gui.setScreen(new ScanManageScreen()))
3232
.pos((getWidth() / 2) - 100, (getHeight() / 2) + 80)
3333
.size(200, 20)
3434
.build()

0 commit comments

Comments
 (0)