Skip to content

Commit

Permalink
Add command to visualize tick times per entity and BE
Browse files Browse the repository at this point in the history
  • Loading branch information
jaskarth committed Dec 14, 2023
1 parent e233c70 commit 2b2d10c
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/main/java/net/modfest/fireblanket/FireblanketClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.modfest.fireblanket.client.command.BERMaskCommand;
import net.modfest.fireblanket.client.command.ClientRegionCommand;
import net.modfest.fireblanket.client.command.EntityMaskCommand;
import net.modfest.fireblanket.client.command.TickTimeCommand;
import net.modfest.fireblanket.client.command.WireframeCommand;
import net.modfest.fireblanket.client.screen.PlaceCommandBlockScreen;
import net.modfest.fireblanket.mixin.accessor.ClientLoginNetworkHandlerAccessor;
Expand All @@ -41,6 +42,7 @@ public void onInitializeClient() {
EntityMaskCommand.init(mask, access);
ClientRegionCommand.init(base, access);
WireframeCommand.init(base, access);
TickTimeCommand.init(base, access);
base.then(mask);
}
dispatcher.register(ClientCommandManager.literal("fbc")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ public final class ClientState {
public static final Set<EntityType<?>> MASKED_ENTITIES = new HashSet<>();

public static boolean wireframe = false;
public static boolean displayTickTimes = false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package net.modfest.fireblanket.client.command;

import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.text.Text;
import net.modfest.fireblanket.client.ClientState;

import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;

public class TickTimeCommand {
public static void init(LiteralArgumentBuilder<FabricClientCommandSource> base, CommandRegistryAccess access) {
base.then(literal("ticktimes")
.executes(cl -> {
if (!ClientState.displayTickTimes) {
cl.getSource().sendFeedback(Text.literal("Displaying tick-times in world. WARNING: Tick times are influenced by a myriad of factors and require expert results to analyze!"));
MinecraftClient.getInstance().submit(() -> ClientState.displayTickTimes = true);
} else {
MinecraftClient.getInstance().submit(() -> ClientState.displayTickTimes = false);
}
return 0;
})
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package net.modfest.fireblanket.mixin.client.timing;

import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.debug.DebugRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.BlockPos;
import net.modfest.fireblanket.client.ClientState;
import net.modfest.fireblanket.client.render.QuadEmitter;
import net.modfest.fireblanket.client.render.RenderLayers;
import net.modfest.fireblanket.mixinsupport.ObservableTicks;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(BlockEntityRenderDispatcher.class)
public class MixinBlockEntityRenderDispatcher {
@Inject(method = "render(Lnet/minecraft/block/entity/BlockEntity;FLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;)V", at = @At("HEAD"))
private <T extends BlockEntity> void fireblanket$renderMaskedBlockEntities(T blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) {
if (ClientState.displayTickTimes && blockEntity instanceof ObservableTicks observed) {
BlockPos pos = blockEntity.getPos();

long t = observed.fireblanket$getTickTime();
String s;
int color = 0xFFFFFF;
if (t > 1000) {
t /= 1000;
s = t + " us";
} else {
s = t + " ns";
}

DebugRenderer.drawString(matrices, vertexConsumers, s,
pos.getX() + 0.5,
pos.getY() + 0.5,
pos.getZ() + 0.5,
color, 0.03F, true, 0, true);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package net.modfest.fireblanket.mixin.client.timing;

import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.modfest.fireblanket.client.ClientState;
import net.modfest.fireblanket.mixinsupport.ObservableTicks;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(ClientWorld.class)
public class MixinClientWorld {
@Redirect(method = "tickEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;tick()V"))
private void fireblanket$measureTick(Entity instance) {
if (ClientState.displayTickTimes) {
ObservableTicks observe = (ObservableTicks) instance;
long start = System.nanoTime();
instance.tick();
observe.fireblanket$setTickTime(System.nanoTime() - start);
} else {
instance.tick();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package net.modfest.fireblanket.mixin.client.timing;

import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.debug.DebugRenderer;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.Box;
import net.modfest.fireblanket.client.ClientState;
import net.modfest.fireblanket.client.render.QuadEmitter;
import net.modfest.fireblanket.client.render.RenderLayers;
import net.modfest.fireblanket.mixinsupport.ObservableTicks;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(EntityRenderer.class)
public class MixinEntityRenderer {
@Inject(method = "render(Lnet/minecraft/entity/Entity;FFLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", at = @At("HEAD"))
private <T extends Entity> void fireblanket$renderMaskedEntities(T entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) {
if (ClientState.displayTickTimes && entity instanceof ObservableTicks observed) {
Box box = entity.getBoundingBox();

long t = observed.fireblanket$getTickTime();
String s;
int color = 0xFFFFFF;
if (t > 1000) {
t /= 1000;
s = t + " us";
} else {
s = t + " ns";
}

DebugRenderer.drawString(matrices, vertexConsumers, s,
box.minX + (box.maxX - box.minX) / 2.0 + 0.5,
box.minY + (box.maxY - box.minY) / 2.0 + 0.5,
box.minZ + (box.maxZ - box.minZ) / 2.0 + 0.5,
color, 0.03F, true, 0, true);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package net.modfest.fireblanket.mixin.client.timing;

import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.Entity;
import net.modfest.fireblanket.mixinsupport.ObservableTicks;
import org.spongepowered.asm.mixin.Mixin;

@Mixin(value = {Entity.class, BlockEntity.class})
public class MixinObservables implements ObservableTicks {
private long fireblanket$tickTime;

@Override
public void fireblanket$setTickTime(long val) {
fireblanket$tickTime = val;
}

@Override
public long fireblanket$getTickTime() {
return fireblanket$tickTime;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package net.modfest.fireblanket.mixin.client.timing;

import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.BlockEntityTickInvoker;
import net.minecraft.world.chunk.WorldChunk;
import net.modfest.fireblanket.client.ClientState;
import net.modfest.fireblanket.mixinsupport.ObservableTicks;
import org.jetbrains.annotations.Nullable;
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.Redirect;

@Mixin(World.class)
public abstract class MixinWorld {
@Shadow @Nullable public abstract BlockEntity getBlockEntity(BlockPos pos);

@Shadow public abstract boolean isClient();

@Redirect(method = "tickBlockEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/chunk/BlockEntityTickInvoker;tick()V"))
private void fireblanket$measureBETick(BlockEntityTickInvoker instance) {
if (this.isClient() && ClientState.displayTickTimes) {
ObservableTicks observe = (ObservableTicks) this.getBlockEntity(instance.getPos());
long start = System.nanoTime();
instance.tick();
observe.fireblanket$setTickTime(System.nanoTime() - start);
} else {
instance.tick();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package net.modfest.fireblanket.mixinsupport;

public interface ObservableTicks {
void fireblanket$setTickTime(long val);

long fireblanket$getTickTime();
}
7 changes: 6 additions & 1 deletion src/main/resources/fireblanket.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@
"client.render_regions.MixinEntityRenderDispatcher",
"client.render_regions.MixinRegionSubjects",
"client.lambdamap.MixinMapRegionFile",
"client.hooks.MixinWorldRenderer"
"client.hooks.MixinWorldRenderer",
"client.timing.MixinObservables",
"client.timing.MixinClientWorld",
"client.timing.MixinWorld",
"client.timing.MixinBlockEntityRenderDispatcher",
"client.timing.MixinEntityRenderer"
]
}

0 comments on commit 2b2d10c

Please sign in to comment.