Skip to content

Commit

Permalink
feat: Highlight century cake slice players
Browse files Browse the repository at this point in the history
  • Loading branch information
nea89o committed Feb 1, 2025
1 parent c2aefe0 commit 89bceb6
Show file tree
Hide file tree
Showing 18 changed files with 559 additions and 3 deletions.
76 changes: 73 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,21 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/

import com.google.common.hash.Hashing
import com.google.devtools.ksp.gradle.KspTaskJvm
import com.google.gson.Gson
import com.google.gson.JsonObject
import moe.nea.licenseextractificator.LicenseDiscoveryTask
import moe.nea.mcautotranslations.gradle.CollectTranslations
import net.fabricmc.loom.LoomGradleExtension
import org.apache.tools.ant.taskdefs.condition.Os
import org.gradle.platform.OperatingSystem
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin.Companion.kotlinNodeJsEnvSpec
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.nio.charset.StandardCharsets
import java.util.Base64

plugins {
java
Expand Down Expand Up @@ -337,9 +343,9 @@ loom {
named("client") {
property("devauth.enabled", "true")
vmArg("-ea")
vmArg("-XX:+AllowEnhancedClassRedefinition")
vmArg("-XX:HotswapAgent=external")
vmArg("-javaagent:${hotswap.resolve().single().absolutePath}")
// vmArg("-XX:+AllowEnhancedClassRedefinition")
// vmArg("-XX:HotswapAgent=external")
// vmArg("-javaagent:${hotswap.resolve().single().absolutePath}")
}
}
}
Expand Down Expand Up @@ -463,6 +469,70 @@ tasks.create("printAllLicenses", LicenseDiscoveryTask::class.java, licensing).ap
}
outputs.upToDateWhen { false }
}
fun patchRenderDoc(
javaLauncher: JavaLauncher,
): JavaLauncher {
val wrappedJavaExecutable = javaLauncher.executablePath.asFile.absolutePath
require("\"" !in wrappedJavaExecutable)
val hashBytes = Hashing.sha256().hashString(wrappedJavaExecutable, StandardCharsets.UTF_8)
val hash = Base64.getUrlEncoder().encodeToString(hashBytes.asBytes())
.replace("=", "")
val wrapperJavaRoot = rootProject.layout.buildDirectory
.dir("binaries/renderdoc-wrapped-java/$hash/")
.get()
val isWindows = Os.isFamily(Os.FAMILY_WINDOWS)
val wrapperJavaExe =
if (isWindows) wrapperJavaRoot.file("java.cmd")
else wrapperJavaRoot.file("java")
return object : JavaLauncher {
override fun getMetadata(): JavaInstallationMetadata {
return object : JavaInstallationMetadata by javaLauncher.metadata {
override fun isCurrentJvm(): Boolean {
return false
}
}
}

override fun getExecutablePath(): RegularFile {
val fileF = wrapperJavaExe.asFile
if (!fileF.exists()) {
fileF.parentFile.mkdirs()
if (isWindows) {
fileF.writeText("""
setlocal enableextensions
start "" renderdoccmd.exe capture --opt-hook-children --wait-for-exit --working-dir . "$wrappedJavaExecutable" %*
endlocal
""".trimIndent())
} else {
fileF.writeText("""
#!/usr/bin/env bash
exec renderdoccmd capture --opt-hook-children --wait-for-exit --working-dir . "$wrappedJavaExecutable" "$@"
""".trimIndent())
fileF.setExecutable(true)
}
}
return wrapperJavaExe
}
}
}
tasks.runClient {
javaLauncher.set(javaToolchains.launcherFor(java.toolchain).map { patchRenderDoc(it) })
}
//tasks.register<Exec>("runRenderDoc") {
// val runClient = tasks.runClient.get()
// commandLine(
// "renderdoc",
// "capture",
// "--opt-hook-children",
// "--wait-for-exit",
// "--working-dir",
// runClient.workingDir,
// runClient.javaLauncher.get().executablePath.asFile.absoluteFile,
// )
// args(runClient.allJvmArgs)
// args()
//
//}

tasks.withType<AbstractArchiveTask>().configureEach {
isPreserveFileTimestamps = false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package moe.nea.firmament.mixins.render.entitytints;

import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import moe.nea.firmament.events.EntityRenderTintEvent;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.render.entity.state.LivingEntityRenderState;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
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.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

/**
* Applies various rendering modifications from {@link EntityRenderTintEvent}
*/
@Mixin(LivingEntityRenderer.class)
public class ChangeColorOfLivingEntities<T extends LivingEntity, S extends LivingEntityRenderState, M extends EntityModel<? super S>> {
@ModifyReturnValue(method = "getMixColor", at = @At("RETURN"))
private int changeColor(int original, @Local(argsOnly = true) S state) {
var tintState = EntityRenderTintEvent.HasTintRenderState.cast(state);
if (tintState.getHasTintOverride_firmament())
return tintState.getTint_firmament();
return original;
}

@ModifyArg(
method = "getOverlay",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/OverlayTexture;getU(F)I"),
allow = 1
)
private static float modifyLightOverlay(float originalWhiteOffset, @Local(argsOnly = true) LivingEntityRenderState state) {
var tintState = EntityRenderTintEvent.HasTintRenderState.cast(state);
if (tintState.getHasTintOverride_firmament() || tintState.getOverlayTexture_firmament() != null) {
return 1F; // TODO: add interpolation percentage to render state extension
}
return originalWhiteOffset;
}

@Inject(method = "render(Lnet/minecraft/client/render/entity/state/LivingEntityRenderState;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/math/MatrixStack;pop()V"))
private void afterRender(S livingEntityRenderState, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo ci) {
var tintState = EntityRenderTintEvent.HasTintRenderState.cast(livingEntityRenderState);
var overlayTexture = tintState.getOverlayTexture_firmament();
if (overlayTexture != null && vertexConsumerProvider instanceof VertexConsumerProvider.Immediate imm) {
imm.drawCurrentLayer();
}
EntityRenderTintEvent.overlayOverride = null;
}

@Inject(method = "render(Lnet/minecraft/client/render/entity/state/LivingEntityRenderState;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/math/MatrixStack;push()V"))
private void beforeRender(S livingEntityRenderState, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo ci) {
var tintState = EntityRenderTintEvent.HasTintRenderState.cast(livingEntityRenderState);
var overlayTexture = tintState.getOverlayTexture_firmament();
if (overlayTexture != null) {
EntityRenderTintEvent.overlayOverride = overlayTexture;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package moe.nea.firmament.mixins.render.entitytints;

import moe.nea.firmament.events.EntityRenderTintEvent;
import moe.nea.firmament.util.render.TintedOverlayTexture;
import net.minecraft.client.render.entity.state.EntityRenderState;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;

@Mixin(EntityRenderState.class)
public class EntityRenderStateTint implements EntityRenderTintEvent.HasTintRenderState {
@Unique
int tint = -1;
@Unique
TintedOverlayTexture overlayTexture;
@Unique
boolean hasTintOverride = false;

@Override
public int getTint_firmament() {
return tint;
}

@Override
public void setTint_firmament(int i) {
tint = i;
hasTintOverride = true;
}

@Override
public boolean getHasTintOverride_firmament() {
return hasTintOverride;
}

@Override
public void setHasTintOverride_firmament(boolean b) {
hasTintOverride = b;
}

@Override
public void reset_firmament() {
hasTintOverride = false;
overlayTexture = null;
}

@Override
public @Nullable TintedOverlayTexture getOverlayTexture_firmament() {
return overlayTexture;
}

@Override
public void setOverlayTexture_firmament(@Nullable TintedOverlayTexture tintedOverlayTexture) {
this.overlayTexture = tintedOverlayTexture;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package moe.nea.firmament.mixins.render.entitytints;

import moe.nea.firmament.events.EntityRenderTintEvent;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.entity.Entity;
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;

/**
* Dispatches {@link EntityRenderTintEvent} to collect additional render state used by {@link ChangeColorOfLivingEntities}
*/
@Mixin(EntityRenderer.class)
public class InjectIntoRenderState<T extends Entity, S extends EntityRenderState> {

@Inject(
method = "updateRenderState",
at = @At("RETURN"))
private void onUpdateRenderState(T entity, S state, float tickDelta, CallbackInfo ci) {
var renderState = EntityRenderTintEvent.HasTintRenderState.cast(state);
renderState.reset_firmament();
var tintEvent = new EntityRenderTintEvent(
entity,
renderState
);
EntityRenderTintEvent.Companion.publish(tintEvent);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package moe.nea.firmament.mixins.render.entitytints;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import moe.nea.firmament.events.EntityRenderTintEvent;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

/**
* Replaces the overlay texture used by rendering with the override specified in {@link EntityRenderTintEvent#overlayOverride}
*/
@Mixin(RenderLayer.Overlay.class)
public class ReplaceOverlayTexture {
@ModifyExpressionValue(
method = {"method_23555", "method_23556"},
expect = 2,
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;getOverlayTexture()Lnet/minecraft/client/render/OverlayTexture;"))
private static OverlayTexture replaceOverlayTexture(OverlayTexture original) {
if (EntityRenderTintEvent.overlayOverride != null)
return EntityRenderTintEvent.overlayOverride;
return original;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package moe.nea.firmament.mixins.render.entitytints;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import moe.nea.firmament.events.EntityRenderTintEvent;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.entity.equipment.EquipmentRenderer;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

/**
* Patch to make {@link EquipmentRenderer} use a {@link RenderLayer} that allows uses Minecraft's overlay texture, if a {@link EntityRenderTintEvent#overlayOverride} is specified.
*/
@Mixin(EquipmentRenderer.class)
public class UseOverlayableEquipmentRenderer {
@WrapOperation(method = "render(Lnet/minecraft/client/render/entity/equipment/EquipmentModel$LayerType;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/client/model/Model;Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/util/Identifier;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayer;getArmorCutoutNoCull(Lnet/minecraft/util/Identifier;)Lnet/minecraft/client/render/RenderLayer;"))
private RenderLayer replace(Identifier texture, Operation<RenderLayer> original) {
if (EntityRenderTintEvent.overlayOverride != null)
return RenderLayer.getEntityTranslucent(texture);
return original.call(texture);
}

@ModifyExpressionValue(method = "render(Lnet/minecraft/client/render/entity/equipment/EquipmentModel$LayerType;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/client/model/Model;Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/util/Identifier;)V",
at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/OverlayTexture;DEFAULT_UV:I"))
private int replaceUvIndex(int original) {
if (EntityRenderTintEvent.overlayOverride != null)
return OverlayTexture.packUv(15, 10); // TODO: store this info in a global alongside overlayOverride
return original;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package moe.nea.firmament.mixins.render.entitytints;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import moe.nea.firmament.events.EntityRenderTintEvent;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.entity.feature.HeadFeatureRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

/**
* Patch to make {@link HeadFeatureRenderer} use a {@link RenderLayer} that allows uses Minecraft's overlay texture, if a {@link EntityRenderTintEvent#overlayOverride} is specified.
* @see UseOverlayableItemRenderer
*/
@Mixin(HeadFeatureRenderer.class)
public class UseOverlayableHeadFeatureRenderer {

@ModifyExpressionValue(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/LivingEntityRenderState;FF)V",
at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/OverlayTexture;DEFAULT_UV:I"))
private int replaceUvIndex(int original) {
if (EntityRenderTintEvent.overlayOverride != null)
return OverlayTexture.packUv(15, 10); // TODO: store this info in a global alongside overlayOverride
return original;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package moe.nea.firmament.mixins.render.entitytints;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import moe.nea.firmament.events.EntityRenderTintEvent;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.RenderPhase;
import net.minecraft.client.render.item.ItemRenderState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

/**
* Patch to make {@link ItemRenderState} use a {@link RenderLayer} that allows uses Minecraft's overlay texture.
*
* @see UseOverlayableHeadFeatureRenderer
*/
@Mixin(ItemRenderState.LayerRenderState.class)
public class UseOverlayableItemRenderer {
@ModifyExpressionValue(method = "render", at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/item/ItemRenderState$LayerRenderState;renderLayer:Lnet/minecraft/client/render/RenderLayer;"))
private RenderLayer replace(RenderLayer original) {
if (EntityRenderTintEvent.overlayOverride != null && original instanceof RenderLayer.MultiPhase multiPhase && multiPhase.phases.texture instanceof RenderPhase.Texture texture && texture.getId().isPresent())
return RenderLayer.getEntityTranslucent(texture.getId().get());
return original;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package moe.nea.firmament.mixins.render.entitytints;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import moe.nea.firmament.events.EntityRenderTintEvent;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.block.entity.SkullBlockEntityRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

/**
* Patch to make {@link SkullBlockEntityRenderer} use a {@link RenderLayer} that allows uses Minecraft's overlay texture, if a {@link EntityRenderTintEvent#overlayOverride} is specified.
*/

@Mixin(SkullBlockEntityRenderer.class)
public class UseOverlayableSkullBlockEntityRenderer {
@ModifyExpressionValue(method = "renderSkull",
at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/OverlayTexture;DEFAULT_UV:I"))
private static int replaceUvIndex(int original) {
if (EntityRenderTintEvent.overlayOverride != null)
return OverlayTexture.packUv(15, 10); // TODO: store this info in a global alongside overlayOverride
return original;
}

}
Loading

0 comments on commit 89bceb6

Please sign in to comment.