Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import io.github.opencubicchunks.cc_core.utils.Coords;
import io.github.opencubicchunks.cubicchunks.CanBeCubic;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.ViewArea;
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
import net.minecraft.core.SectionPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
Expand All @@ -27,6 +31,13 @@ public abstract class MixinViewArea {
@Shadow private SectionPos cameraSectionPos;
@Shadow @Final protected LevelRenderer levelRenderer;

@Unique
private int cc_oldCameraX = Integer.MAX_VALUE;
@Unique
private int cc_oldCameraY = Integer.MAX_VALUE;
@Unique
private int cc_oldCameraZ = Integer.MAX_VALUE;

@Shadow protected abstract int getSectionIndex(int x, int y, int z);

// This could be multiple more specific injects, but overwriting the method is probably cleaner
Expand All @@ -49,7 +60,7 @@ private int cc_onCreateSections_getMinY(Level instance, Operation<Integer> origi
return original.call(instance);
}
return 0; // I don't really understand the logic here, but returning 0 makes the Y axis behave equivalently to X and Z, which *should* be what
// we want
// we want
}

// TODO can we do this without fully overwriting the method?
Expand All @@ -69,28 +80,108 @@ private void cc_onGetRenderSection(int sectionX, int sectionY, int sectionZ, Cal
}

// TODO can we do this with dasm + mixin? probably too messy
// I don't really understand the coordinate maths here, but we replicate it for the Y axis
// 1.21.6+ port by Zonix-Official of daporkchop_'s fast-path logic that was implemented to 1.12.2
@SuppressWarnings({ "checkstyle:CyclomaticComplexity", "checkstyle:JavaNCSS", "checkstyle:NPathComplexity" })
@Inject(method = "repositionCamera", at = @At("HEAD"), cancellable = true)
private void cc_onRepositionCamera(SectionPos newSectionPos, CallbackInfo ci) {
if (!((CanBeCubic) level).cc_isCubic()) {
return;
}
ci.cancel();
for (int sectionX = 0; sectionX < this.sectionGridSizeX; sectionX++) {
int i1 = newSectionPos.x() - this.viewDistance;
int originX = i1 + Math.floorMod(sectionX - i1, this.sectionGridSizeX);

for (int sectionZ = 0; sectionZ < this.sectionGridSizeZ; sectionZ++) {
int i2 = newSectionPos.z() - this.viewDistance;
int originZ = i2 + Math.floorMod(sectionZ - i2, this.sectionGridSizeZ);

for (int sectionY = 0; sectionY < this.sectionGridSizeY; sectionY++) {
int i3 = newSectionPos.y() - this.viewDistance;
int originY = i3 + Math.floorMod(sectionY - i3, this.sectionGridSizeY);
SectionRenderDispatcher.RenderSection renderSection = this.sections[this.getSectionIndex(sectionX, sectionY, sectionZ)];
long oldSectionNode = renderSection.getSectionNode();
if (oldSectionNode != SectionPos.asLong(originX, originY, originZ)) {
renderSection.setSectionNode(SectionPos.asLong(originX, originY, originZ));

Entity cameraEntity = Minecraft.getInstance().getCameraEntity();
if (cameraEntity == null) {
return;
}

int cameraX = Coords.blockToCube(cameraEntity.getX());
int cameraY = Coords.blockToCube(cameraEntity.getY());
int cameraZ = Coords.blockToCube(cameraEntity.getZ());

int dx = this.sectionGridSizeX;
int dy = this.sectionGridSizeY;
int dz = this.sectionGridSizeZ;

int px = newSectionPos.x() - this.viewDistance;
int py = newSectionPos.y() - this.viewDistance;
int pz = newSectionPos.z() - this.viewDistance;

int minX = cameraX - (dx >> 1);
int minY = cameraY - (dy >> 1);
int minZ = cameraZ - (dz >> 1);

long changeX = (long) cameraX - this.cc_oldCameraX;
long changeY = (long) cameraY - this.cc_oldCameraY;
long changeZ = (long) cameraZ - this.cc_oldCameraZ;
this.cc_oldCameraX = cameraX;
this.cc_oldCameraY = cameraY;
this.cc_oldCameraZ = cameraZ;

if (Math.abs(changeX) <= 1 && Math.abs(changeY) <= 1 && Math.abs(changeZ) <= 1) {
if (changeX != 0) {
int indexX = Math.floorMod(changeX < 0 ? minX - px : minX - px - 1, dx);
int originX = px + Math.floorMod(indexX - px, dx);

for (int indexZ = 0; indexZ < dz; indexZ++) {
int idxz = indexZ * dy * dx;
int originZ = pz + Math.floorMod(indexZ - pz, dz);

for (int indexY = 0; indexY < dy; indexY++) {
int idxyz = idxz + indexY * dx;
int originY = py + Math.floorMod(indexY - py, dy);

cc_refreshSectionNode(idxyz + indexX, originX, originY, originZ);
}
}
}

if (changeY != 0) {
int indexY = Math.floorMod(changeY < 0 ? minY - py : minY - py - 1, dy);
int originY = py + Math.floorMod(indexY - py, dy);

for (int indexZ = 0; indexZ < dz; indexZ++) {
int originZ = pz + Math.floorMod(indexZ - pz, dz);
int idxZ = indexZ * dy * dx;

int idxyz = idxZ + indexY * dx;

for (int indexX = 0; indexX < dx; indexX++) {
int originX = px + Math.floorMod(indexX - px, dx);

cc_refreshSectionNode(idxyz + indexX, originX, originY, originZ);
}
}
}

if (changeZ != 0) {
int indexZ = Math.floorMod(changeZ < 0 ? minZ - pz : minZ - pz - 1, dz);
int originZ = pz + Math.floorMod(indexZ - pz, dz);
int idxz = indexZ * dy * dx;

for (int indexY = 0; indexY < dy; indexY++) {
int originY = py + Math.floorMod(indexY - py, dy);
int idxyz = idxz + indexY * dx;

for (int indexX = 0; indexX < dx; indexX++) {
int originX = px + Math.floorMod(indexX - px, dx);

cc_refreshSectionNode(idxyz + indexX, originX, originY, originZ);
}
}
}
} else {
for (int indexZ = 0; indexZ < dz; indexZ++) {
int idxz = indexZ * dy * dx;
int originZ = pz + Math.floorMod(indexZ - pz, dz);

for (int indexY = 0; indexY < dy; indexY++) {
int idxyz = idxz + indexY * dx;
int originY = py + Math.floorMod(indexY - py, dy);

for (int indexX = 0; indexX < dx; indexX++) {
int originX = px + Math.floorMod(indexX - px, dx);

cc_refreshSectionNode(idxyz + indexX, originX, originY, originZ);
}
}
}
Expand All @@ -100,6 +191,16 @@ private void cc_onRepositionCamera(SectionPos newSectionPos, CallbackInfo ci) {
this.levelRenderer.getSectionOcclusionGraph().invalidate();
}

@Unique
private void cc_refreshSectionNode(int sectionIndex, int originX, int originY, int originZ) {
Comment thread
NotStirred marked this conversation as resolved.
SectionRenderDispatcher.RenderSection renderSection = this.sections[sectionIndex];
long oldSectionNode = renderSection.getSectionNode();
if (oldSectionNode != SectionPos.asLong(originX, originY, originZ)) {
renderSection.setSectionNode(SectionPos.asLong(originX, originY, originZ));
}
}

@Unique
private boolean cc_containsSection(int x, int y, int z) {
Comment thread
NotStirred marked this conversation as resolved.
return x >= this.cameraSectionPos.x() - this.viewDistance && x <= this.cameraSectionPos.x() + this.viewDistance
&& y >= this.cameraSectionPos.y() - this.viewDistance && y <= this.cameraSectionPos.y() + this.viewDistance
Expand Down
Loading