This commit is contained in:
gnembon committed 2025-10-22 10:03:35 +02:00
1 parent 983d8658f9
commit f12ce62460
8 files changed
+92 -279

No files matched your search

+1 -1
View File
@@ -7,7 +7,7 @@ org.gradle.configuration-cache=false
# Fabric Properties
# check https://fabricmc.net/develop/
minecraft_version=25w42a
minecraft_version=25w43a
loader_version=0.17.3
jsr305_version=3.0.2
fabric_version=0.134.0+1.21.9
-42
View File
@@ -1011,48 +1011,6 @@ public class CarpetSettings
)
public static int sculkSensorRange = 8;
/**
* Listener, we need to update world borders to change whether
* they are currently moving in real time or in game time.
*/
private static class WorldBorderValidator extends Validator<Boolean>
{
@Override
public Boolean validate(CommandSourceStack source, CarpetRule<Boolean> changingRule, Boolean newValue, String userInput)
{
if (changingRule.value() ^ newValue)
{
// Needed for the update
tickSyncedWorldBorders = newValue;
MinecraftServer server = CarpetServer.minecraft_server;
if (server == null)
{
return newValue;
}
for (ServerLevel level : server.getAllLevels())
{
WorldBorder worldBorder = level.getWorldBorder();
if (worldBorder.getStatus() != BorderStatus.STATIONARY)
{
double from = worldBorder.getSize();
double to = worldBorder.getLerpTarget();
long time = worldBorder.getLerpTime();
worldBorder.lerpSizeBetween(from, to, time);
}
}
}
return newValue;
}
}
@Rule(
desc = "Makes world borders move based on in game time instead of real time",
extra = "This has the effect that when the tick rate changes the world border speed also changes proportional to it",
category = FEATURE,
validate = WorldBorderValidator.class
)
public static boolean tickSyncedWorldBorders = false;
public enum FungusGrowthMode {
FALSE, RANDOM, ALL;
}
@@ -2,9 +2,11 @@ package carpet.mixins;
import carpet.network.CarpetClient;
import carpet.script.utils.ShapesRenderer;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.blaze3d.buffers.GpuBufferSlice;
import com.mojang.blaze3d.framegraph.FrameGraphBuilder;
import com.mojang.blaze3d.framegraph.FramePass;
import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
import net.minecraft.client.Camera;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
@@ -12,12 +14,11 @@ import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.LevelTargetBundle;
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.client.renderer.feature.FeatureRenderDispatcher;
import net.minecraft.client.renderer.state.LevelRenderState;
import net.minecraft.util.profiling.ProfilerFiller;
import org.joml.Matrix4f;
import org.joml.Vector4f;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -34,14 +35,20 @@ public class LevelRenderer_scarpetRenderMixin
@Shadow @Final private RenderBuffers renderBuffers;
@Shadow @Final private LevelRenderState levelRenderState;
@Inject(method = "<init>", at = @At("RETURN"))
private void addRenderers(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers, LevelRenderState levelRenderState, FeatureRenderDispatcher featureRenderDispatcher, CallbackInfo ci)
{
CarpetClient.shapes = new ShapesRenderer(minecraft);
}
@Inject(method = "addMainPass", at = @At("RETURN"))
private void renderScarpetThingsLate(FrameGraphBuilder frameGraphBuilder, Frustum frustum, Matrix4f matrix4f, GpuBufferSlice gpuBufferSlice, boolean bl, LevelRenderState levelRenderState, DeltaTracker deltaTracker, ProfilerFiller profilerFiller, CallbackInfo ci)
@Inject(method = "renderLevel", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/renderer/LevelRenderer;addLateDebugPass(Lcom/mojang/blaze3d/framegraph/FrameGraphBuilder;Lnet/minecraft/client/renderer/state/CameraRenderState;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;Lorg/joml/Matrix4f;)V",
shift = At.Shift.AFTER
))
private void renderStarpetThingsLate(GraphicsResourceAllocator graphicsResourceAllocator, DeltaTracker deltaTracker, boolean bl, Camera camera, Matrix4f matrix4f, Matrix4f arg5, Matrix4f matrix4f3, GpuBufferSlice gpuBufferSlice, Vector4f vector4f, boolean bl2, CallbackInfo ci, @Local FrameGraphBuilder frameGraphBuilder)
{
// in normal circumstances we want to render shapes at the very end so it appears correctly behind stuff.
// we might actually not need to play with render hooks here.
@@ -1,25 +0,0 @@
package carpet.mixins;
import carpet.CarpetSettings;
import carpet.patches.TickSyncedBorderExtent;
import net.minecraft.world.level.border.WorldBorder;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(WorldBorder.class)
public class WorldBorder_syncedWorldBorderMixin
{
@Shadow private WorldBorder.BorderExtent extent;
@Inject(method = "lerpSizeBetween", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/border/WorldBorder;getListeners()Ljava/util/List;"))
private void getExtent(double d, double e, long l, CallbackInfo ci)
{
if (d != e && CarpetSettings.tickSyncedWorldBorders)
{
this.extent = new TickSyncedBorderExtent((WorldBorder) (Object) this, l, d, e);
}
}
}
@@ -1,170 +0,0 @@
package carpet.patches;
import carpet.CarpetServer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ServerTickRateManager;
import net.minecraft.util.Mth;
import net.minecraft.util.TimeUtil;
import net.minecraft.world.level.border.BorderChangeListener;
import net.minecraft.world.level.border.BorderStatus;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.NotNull;
/**
* This class is essentially a copy of {@link net.minecraft.world.level.border.WorldBorder.MovingBorderExtent}
* but instead of using real time to lerp the border
* this class uses the in game ticks.
*/
@SuppressWarnings("JavadocReference")
public class TickSyncedBorderExtent implements WorldBorder.BorderExtent
{
private final WorldBorder border;
private final long realDuration;
private final double tickDuration;
private final double from;
private final double to;
private int ticks;
public TickSyncedBorderExtent(WorldBorder border, long realDuration, double from, double to)
{
this.border = border;
this.realDuration = realDuration;
this.tickDuration = realDuration / 50.0;
this.from = from;
this.to = to;
this.ticks = 0;
}
@Override
public double getMinX()
{
int maxSize = this.border.getAbsoluteMaxSize();
return Mth.clamp(this.border.getCenterX() - this.getSize() / 2.0, -maxSize, maxSize);
}
@Override
public double getMaxX()
{
int maxSize = this.border.getAbsoluteMaxSize();
return Mth.clamp(this.border.getCenterX() + this.getSize() / 2.0, -maxSize, maxSize);
}
@Override
public double getMinZ()
{
int maxSize = this.border.getAbsoluteMaxSize();
return Mth.clamp(this.border.getCenterZ() - this.getSize() / 2.0, -maxSize, maxSize);
}
@Override
public double getMaxZ()
{
int maxSize = this.border.getAbsoluteMaxSize();
return Mth.clamp(this.border.getCenterZ() + this.getSize() / 2.0, -maxSize, maxSize);
}
@Override
public double getSize()
{
double progress = this.ticks / this.tickDuration;
return progress < 1.0 ? Mth.lerp(progress, this.from, this.to) : this.to;
}
@Override
public double getLerpSpeed()
{
return Math.abs(this.from - this.to) / this.realDuration;
}
@Override
public long getLerpTime()
{
// Rough estimation
MinecraftServer server = CarpetServer.minecraft_server;
double ms;
if (server == null)
{
// can this even happen?
ms = 50.0;
}
else
{
ms = ((double)server.getAverageTickTimeNanos())/ TimeUtil.NANOSECONDS_PER_MILLISECOND;
ServerTickRateManager trm = server.tickRateManager();
if (!trm.isSprinting())
{
ms = Math.max(ms, trm.millisecondsPerTick());
}
}
double tps = 1_000.0D / ms;
return (long) ((this.tickDuration - this.ticks) / tps * 1_000);
}
@Override
public double getLerpTarget()
{
return this.to;
}
@NotNull
@Override
public BorderStatus getStatus()
{
return this.to < this.from ? BorderStatus.SHRINKING : BorderStatus.GROWING;
}
@Override
public void onAbsoluteMaxSizeChange()
{
}
@Override
public void onCenterChange()
{
}
@NotNull
@Override
public WorldBorder.BorderExtent update()
{
if (this.ticks++ % 20 == 0)
{
// We need to update any listeners
// Most importantly those that send updates to the client
// This is because the client logic uses real time
// So if the tick speed has changed we need to tell the client
for (BorderChangeListener listener : this.border.getListeners())
{
// We do not want to update DelegateBorderChangeListener
// This updates borders in other dimensions
listener.onLerpSize(this.border, this.from, this.to, this.realDuration);
}
}
return this.ticks >= this.tickDuration ? this.border.new StaticBorderExtent(this.to) : this;
}
@NotNull
@Override
public VoxelShape getCollisionShape()
{
return Shapes.join(
Shapes.INFINITY,
Shapes.box(
Math.floor(this.getMinX()),
Double.NEGATIVE_INFINITY,
Math.floor(this.getMinZ()),
Math.ceil(this.getMaxX()),
Double.POSITIVE_INFINITY,
Math.ceil(this.getMaxZ())
),
BooleanOp.ONLY_FIRST
);
}
}
@@ -17,6 +17,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.function.BiFunction;
import net.minecraft.client.Camera;
@@ -28,12 +29,13 @@ import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.rendertype.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState;
import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.client.renderer.gizmos.DrawableGizmoPrimitives;
import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.renderer.rendertype.RenderTypes;
import net.minecraft.client.renderer.state.LevelRenderState;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.core.BlockPos;
@@ -428,7 +430,7 @@ public class ShapesRenderer
float blue = (color & 0xFF) / 255.0F;
RenderType type;
if (blockState.getBlock() instanceof LeavesBlock && !Minecraft.getInstance().options.cutoutLeaves().get()) {
type = RenderType.solid();
type = RenderTypes.solid();
} else {
type = ItemBlockRenderTypes.getRenderType(blockState);
}
@@ -661,14 +663,14 @@ public class ShapesRenderer
Mode.LINES, Mode.LINES, Mode.DEBUG_LINES, Mode.DEBUG_LINE_STRIP, Mode.TRIANGLES, Mode.TRIANGLE_STRIP, Mode.TRIANGLE_FAN, Mode.QUADS};
private static final RenderType [] renderTypes = new RenderType[] {
RenderType.lines(),
RenderType.lines(),
RenderType.lines(),
RenderType.lines(),
RenderType.debugTriangleFan(), // TODO wrong
RenderType.debugTriangleFan(), // TODO wrong
RenderType.debugTriangleFan(),
RenderType.debugQuads()
RenderTypes.lines(),
RenderTypes.lines(),
RenderTypes.lines(),
RenderTypes.lines(),
RenderTypes.debugTriangleFan(), // TODO wrong
RenderTypes.debugTriangleFan(), // TODO wrong
RenderTypes.debugTriangleFan(),
RenderTypes.debugQuads()
};
public RenderedPolyface(Minecraft client, ShapeDispatcher.ExpiringShape shape)
@@ -957,32 +959,46 @@ public class ShapesRenderer
boolean xthick, boolean ythick, boolean zthick,
int argb)
{
Vec3 v111 = new Vec3(x1, y1, z1);
Vec3 v211 = new Vec3(x2, y1, z1);
Vec3 v221 = new Vec3(x2, y2, z1);
Vec3 v121 = new Vec3(x1, y2, z1);
Vec3 v112 = new Vec3(x1, y1, z2);
Vec3 v122 = new Vec3(x1, y2, z2);
Vec3 v222 = new Vec3(x2, y2, z2);
Vec3 v212 = new Vec3(x2, y1, z2);
if (xthick && ythick)
{
primitives.addQuad(new Vec3(x1, y1, z1), new Vec3(x2, y1, z1), new Vec3(x2, y2, z1), new Vec3(x1, y2, z1), argb);
primitives.addQuad(v111, v211, v221, v121, argb);
primitives.addQuad(v111, v121, v221, v211, argb);
if (zthick)
{
primitives.addQuad(new Vec3(x1, y1, z2), new Vec3(x1, y2, z2), new Vec3(x2, y2, z2), new Vec3(x2, y1, z2), argb);
primitives.addQuad(v112, v122, v222, v212, argb);
primitives.addQuad(v112, v212, v222, v122, argb);
}
}
if (zthick && ythick)
{
primitives.addQuad(new Vec3(x1, y1, z1), new Vec3(x1, y2, z1), new Vec3(x1, y2, z2), new Vec3(x1, y1, z2), argb);
primitives.addQuad(v111, v121, v122, v112, argb);
primitives.addQuad(v111, v112, v122, v121, argb);
if (xthick)
{
primitives.addQuad(new Vec3(x2, y1, z1), new Vec3(x2, y1, z2), new Vec3(x2, y2, z2), new Vec3(x2, y2, z1), argb);
primitives.addQuad(v211, v212, v222, v221, argb);
primitives.addQuad(v211, v221, v222, v212, argb);
}
}
// now at least drawing one
if (zthick && xthick)
{
primitives.addQuad(new Vec3(x1, y1, z1), new Vec3(x2, y1, z1), new Vec3(x2, y1, z2), new Vec3(x1, y1, z2), argb);
primitives.addQuad(v111, v211, v212, v112, argb);
primitives.addQuad(v111, v112, v212, v211, argb);
if (ythick)
{
primitives.addQuad(new Vec3(x1, y2, z1), new Vec3(x1, y2, z2), new Vec3(x2, y2, z2), new Vec3(x2, y2, z1), argb);
primitives.addQuad(v121, v122, v222, v221, argb);
primitives.addQuad(v121, v221, v222, v122, argb);
}
}
}
@@ -1174,6 +1190,7 @@ public class ShapesRenderer
float z = r * Mth.sin(theta);
points[i + 1] = new Vec3(x + cx, cy, z + cz);
}
// for some reason triangle fans are double sided
primitives.addTriangleFan(points, argb);
}
@@ -1188,19 +1205,25 @@ public class ShapesRenderer
float z = r * Mth.sin(theta);
points[i + 1] = new Vec3(x + cx, cy + h, z + cz);
}
// for some reason triangle fans are double sided
primitives.addTriangleFan(points, argb);
float xp = r * 1;
float zp = r * 0;
Vec3 previousBottom = new Vec3(cx + xp, cy + 0, cz + zp);
Vec3 previousTop = new Vec3(cx + xp, cy + h, cz + zp);
for (int i = 1; i <= num_steps360; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
primitives.addQuad(new Vec3(cx + xp, cy + 0, cz + zp), new Vec3(cx + xp, cy + h, cz + zp),
new Vec3(cx + x, cy + h, cz + z), new Vec3(cx - x, cy + h, cz + z), argb);
xp = x;
zp = z;
Vec3 nextTop = new Vec3(cx + x, cy + h, cz + z);
Vec3 nextBottom = new Vec3(cx + x, cy + 0, cz + z);
primitives.addQuad(previousBottom, previousTop, nextTop, nextBottom, argb);
primitives.addQuad(previousBottom, nextBottom, nextTop, previousTop, argb);
previousTop = nextTop;
previousBottom = nextBottom;
}
}
@@ -1235,16 +1258,20 @@ public class ShapesRenderer
float yp = r * 1;
float zp = r * 0;
Vec3 previousBottom = new Vec3(cx + 0, cy + yp, cz + zp);
Vec3 previousTop = new Vec3(cx + h, cy + yp, cz + zp);
for (int i = 1; i <= num_steps360; i++)
{
float theta = step * i;
float y = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
primitives.addQuad(new Vec3(cx + 0, cy + yp, cz + zp), new Vec3(cx + h, cy + yp, cz + zp),
new Vec3(cx + h, cy + y, cz + z), new Vec3(cx + 0, cy + y, cz + z), argb);
yp = y;
zp = z;
Vec3 nextTop = new Vec3(cx + h, cy + y, cz + z);
Vec3 nextBottom = new Vec3(cx + 0, cy + y, cz + z);
primitives.addQuad(previousBottom, previousTop, nextTop, nextBottom, argb);
primitives.addQuad(previousBottom, nextBottom, nextTop, previousTop, argb);
previousTop = nextTop;
previousBottom = nextBottom;
}
}
}
@@ -1276,20 +1303,32 @@ public class ShapesRenderer
float xp = r;
float yp = 0;
Vec3 previousBottom = new Vec3(cx + xp, cy + yp, cz + 0);
Vec3 previousTop = new Vec3(cx + xp, cy + yp, cz + h);
for (int i = 1; i <= num_steps360; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float y = r * Mth.sin(theta);
primitives.addQuad(new Vec3(cx + xp, cy + yp, cz + 0), new Vec3(cx + xp, cy + yp, cz + h),
new Vec3(cx + x, cy + y, cz + h), new Vec3(cx + x, cy + y, cz + 0), argb);
xp = x;
yp = y;
Vec3 nextTop = new Vec3(cx + x, cy + y, cz + h);
Vec3 nextBottom = new Vec3(cx + x, cy + y, cz + 0);
primitives.addQuad(previousBottom, previousTop, nextTop, nextBottom, argb);
primitives.addQuad(previousBottom, nextBottom, nextTop, previousTop, argb);
previousTop = nextTop;
previousBottom = nextBottom;
}
}
}
}
private static int shuffleColor(int argb) {
int a = 0xff000000 & argb;
argb = (new Random(argb)).nextInt();
argb = (a) | (0x00ffffff & argb);
return argb;
}
public static void drawSphereWireframe(DrawableGizmoPrimitives primitives,
float cx, float cy, float cz,
float r, int subd,
@@ -1363,8 +1402,13 @@ public class ShapesRenderer
float xp = r * Mth.sin(phi) * Mth.cos(thetaprime);
float zp = r * Mth.sin(phi) * Mth.sin(thetaprime);
primitives.addQuad(new Vec3(xb + cx, yp + cy, zb + cz), new Vec3(xbp + cx, yp + cy, zbp + cz),
new Vec3(xp + cx, y + cy, zp + cz), new Vec3(x + cx, y + cy, z + cz), argb);
Vec3 v1 = new Vec3(xb + cx, yp + cy, zb + cz);
Vec3 v2 = new Vec3(xbp + cx, yp + cy, zbp + cz);
Vec3 v3 = new Vec3(xp + cx, y + cy, zp + cz);
Vec3 v4 = new Vec3(x + cx, y + cy, z + cz);
primitives.addQuad(v1, v2, v3, v4, argb);
primitives.addQuad(v1, v4, v3, v2, argb);
xb = x;
zb = z;
@@ -17,14 +17,14 @@ test_shapes(duration) -> (
set(x+10, y+10, z+10, 'air');
));
loop(10,
draw_shape('line', duration, 'from', [x, y, z], 'to', [x+_, y+10, z+10], 'color', 0xff0000ff);
draw_shape('line', duration, 'from', [x, y, z], 'to', [x+10, y+_, z+10], 'color', 0x00ff00ff);
draw_shape('line', duration, 'from', [x, y, z], 'to', [x+10, y+10, z+_], 'color', 0x0000ffff);
draw_shape('line', duration, 'from', [x, y, z], 'to', [x-_, y+10, z+10], 'color', 0xff0000ff);
draw_shape('line', duration, 'from', [x, y, z], 'to', [x-10, y+_, z+10], 'color', 0x00ff00ff);
draw_shape('line', duration, 'from', [x, y, z], 'to', [x-10, y+10, z+_], 'color', 0x0000ffff);
);
loop(20,
sq = _ * _ / 10;
draw_shape('box', duration, 'from', [x+_, y + sq, z], 'to', [x+_ + 2, y+sq + 2, z+2], 'color', 0xff0000ff, 'fill', 0xff000080);
draw_shape('box', duration, 'from', [x, y + _, z + sq], 'to', [x+2, y+_ + 2, z+sq + 2], 'color', 0x00ff00ff, 'fill', 0x00ff0080);
draw_shape('box', duration, 'from', [x + sq, y, z + _], 'to', [x+sq + 2, y+2, z+_ + 2], 'color', 0x0000ffff, 'fill', 0x0000ff80);
draw_shape('box', duration, 'from', [x+_, y + sq, z], 'to', [x+_ + 2, y+sq + 2, z+2], 'color', 0xff0000ff, 'fill', 0xff000030);
draw_shape('box', duration, 'from', [x, y + _, z + sq], 'to', [x+2, y+_ + 2, z+sq + 2], 'color', 0x00ff00ff, 'fill', 0x00ff0030);
draw_shape('box', duration, 'from', [x + sq, y, z + _], 'to', [x+sq + 2, y+2, z+_ + 2], 'color', 0x0000ffff, 'fill', 0x0000ff30);
);
);
-1
View File
@@ -36,7 +36,6 @@
"ServerChunkCache_profilerMixin",
"ChunkMap_profilerMixin",
"ServerFunctionManager_profilerMixin",
"WorldBorder_syncedWorldBorderMixin",
"ChunkMap_scarpetChunkCreationMixin",
"LevelEntityGetterAdapter_scarpetMixin",
"ChunkHolder_scarpetChunkCreationMixin",