Skip to content

Commit 3e7986f

Browse files
committed
Fixed capes
1 parent 2550fd1 commit 3e7986f

File tree

4 files changed

+46
-52
lines changed

4 files changed

+46
-52
lines changed

src/main/java/com/lambda/mixin/render/CapeFeatureRendererMixin.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@
3333
public class CapeFeatureRendererMixin {
3434
@ModifyExpressionValue(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/PlayerEntityRenderState;FF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/SkinTextures;capeTexture()Lnet/minecraft/util/Identifier;"))
3535
Identifier renderCape(Identifier original, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, PlayerEntityRenderState player, float f, float g) {
36-
var entity = Lambda.getMc().world.getEntityById(player.id);
37-
if (!Capes.INSTANCE.isEnabled() || !CapeManager.INSTANCE.containsKey(entity.getUuid())) return original;
36+
var entry = Lambda.getMc().getNetworkHandler().getPlayerListEntry(player.name);
37+
if (entry == null) return original;
3838

39-
return Identifier.of("lambda", CapeManager.INSTANCE.get(entity.getUuid()));
39+
var profile = entry.getProfile();
40+
if (!Capes.INSTANCE.isEnabled() || !CapeManager.INSTANCE.getCache().containsKey(profile.getId())) return original;
41+
42+
return Identifier.of("lambda", CapeManager.INSTANCE.getCache().get(profile.getId()));
4043
}
4144
}

src/main/java/com/lambda/mixin/render/ElytraFeatureRendererMixin.java

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,44 @@
1717

1818
package com.lambda.mixin.render;
1919

20+
import com.lambda.Lambda;
21+
import com.lambda.module.modules.client.Capes;
2022
import com.lambda.module.modules.render.NoRender;
21-
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
23+
import com.lambda.network.CapeManager;
24+
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
25+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
26+
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
2227
import net.minecraft.client.render.VertexConsumerProvider;
2328
import net.minecraft.client.render.entity.feature.ElytraFeatureRenderer;
2429
import net.minecraft.client.render.entity.state.BipedEntityRenderState;
30+
import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
2531
import net.minecraft.client.util.math.MatrixStack;
2632
import net.minecraft.entity.LivingEntity;
2733
import net.minecraft.util.Identifier;
2834
import org.spongepowered.asm.mixin.Mixin;
2935
import org.spongepowered.asm.mixin.injection.At;
30-
import org.spongepowered.asm.mixin.injection.Inject;
31-
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
3236

3337
@Mixin(ElytraFeatureRenderer.class)
3438
public class ElytraFeatureRendererMixin<T extends LivingEntity> {
35-
@ModifyReturnValue(method = "getTexture(Lnet/minecraft/client/render/entity/state/BipedEntityRenderState;)Lnet/minecraft/util/Identifier;", at = @At("TAIL"))
36-
private static Identifier getTexture(Identifier original, BipedEntityRenderState state) {
37-
// FixMe: fuck you mojang
38-
/*var entity = StreamSupport.stream(Lambda.getMc().world.getEntities().spliterator(), false)
39-
.filter(e -> e.getDisplayName() == state.displayName)
40-
.findFirst().get();
39+
@WrapOperation(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/BipedEntityRenderState;FF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/feature/ElytraFeatureRenderer;getTexture(Lnet/minecraft/client/render/entity/state/BipedEntityRenderState;)Lnet/minecraft/util/Identifier;"))
40+
Identifier injectElytra(BipedEntityRenderState state, Operation<Identifier> original) {
41+
if (!(state instanceof PlayerEntityRenderState))
42+
return original.call(state);
4143

42-
if (!Capes.INSTANCE.isEnabled() || !CapeManager.INSTANCE.containsKey(entity.getUuid())) return original;
44+
var entry = Lambda.getMc().getNetworkHandler().getPlayerListEntry(((PlayerEntityRenderState) state).name);
45+
if (entry == null) return original.call(state);
4346

44-
return Identifier.of("lambda", CapeManager.INSTANCE.get(entity.getUuid()));*/
47+
var profile = entry.getProfile();
4548

46-
return original;
49+
if (!Capes.INSTANCE.isEnabled() || !CapeManager.INSTANCE.getCache().containsKey(profile.getId()))
50+
return original.call(state);
51+
52+
return Identifier.of("lambda", CapeManager.INSTANCE.getCache().get(profile.getId()));
4753
}
4854

49-
@Inject(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/BipedEntityRenderState;FF)V", at = @At("HEAD"), cancellable = true)
50-
private void injectRender(MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, BipedEntityRenderState bipedEntityRenderState, float f, float g, CallbackInfo ci) {
51-
if (NoRender.INSTANCE.isEnabled() && NoRender.getNoElytra()) ci.cancel();
55+
@WrapMethod(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/BipedEntityRenderState;FF)V")
56+
private void injectRender(MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, BipedEntityRenderState bipedEntityRenderState, float f, float g, Operation<Void> original) {
57+
if (NoRender.INSTANCE.isDisabled() && !NoRender.getNoElytra())
58+
original.call(matrixStack, vertexConsumerProvider, i, bipedEntityRenderState, f, g);
5259
}
5360
}

src/main/kotlin/com/lambda/command/commands/CapeCommand.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ object CapeCommand : LambdaCommand(
3838
required(literal("set")) {
3939
required(string("id")) { id ->
4040
suggests { _, builder ->
41-
CapeManager.capeList
41+
CapeManager.availableCapes
4242
.forEach { builder.suggest(it) }
4343

4444
builder.buildFuture()

src/main/kotlin/com/lambda/network/CapeManager.kt

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@ package com.lambda.network
1919

2020
import com.lambda.Lambda.LOG
2121
import com.lambda.Lambda.mc
22-
import com.lambda.context.SafeContext
22+
import com.lambda.config.Configurable
23+
import com.lambda.config.configurations.SecretsConfig
2324
import com.lambda.core.Loadable
2425
import com.lambda.event.events.WorldEvent
2526
import com.lambda.event.listener.SafeListener.Companion.listen
2627
import com.lambda.network.api.v1.endpoints.getCape
2728
import com.lambda.network.api.v1.endpoints.getCapes
2829
import com.lambda.network.api.v1.endpoints.setCape
30+
import com.lambda.threading.runGameScheduled
2931
import com.lambda.threading.runIO
30-
import com.lambda.threading.runSafe
3132
import com.lambda.util.FileUtils.createIfNotExists
3233
import com.lambda.util.FileUtils.downloadCompare
3334
import com.lambda.util.FileUtils.downloadIfNotPresent
@@ -44,25 +45,19 @@ import org.lwjgl.BufferUtils
4445
import java.util.*
4546
import java.util.concurrent.ConcurrentHashMap
4647
import kotlin.concurrent.fixedRateTimer
47-
import kotlin.io.path.extension
48-
import kotlin.io.path.inputStream
49-
import kotlin.io.path.nameWithoutExtension
50-
import kotlin.io.path.walk
5148
import kotlin.time.Duration.Companion.hours
5249
import kotlin.time.Duration.Companion.seconds
5350

54-
@Suppress("JavaIoSerializableObjectMustHaveReadResolve")
55-
object CapeManager : ConcurrentHashMap<UUID, String>(), Loadable {
56-
// We want to cache images to reduce class B requests
57-
private val images = capes.walk()
58-
.filter { it.extension == "png" }
59-
.associate { it.nameWithoutExtension to NativeImageBackedTexture({ it.nameWithoutExtension }, read(it.inputStream())) }
60-
.onEach { (key, value) -> mc.textureManager.registerTexture(key.asIdentifier, value) }
51+
object CapeManager : Configurable(SecretsConfig), Loadable {
52+
override val name: String = "capes"
6153

54+
var currentCape by setting("cape", "")
55+
.onValueChangeUnsafe { _, to -> updateCape(to) }
56+
57+
val cache = ConcurrentHashMap<UUID, String>()
6258
private val fetchQueue = mutableListOf<UUID>()
6359

64-
// We want to cache the cape list to reduce class B requests
65-
val capeList = runBlocking {
60+
val availableCapes = runBlocking {
6661
capes.resolveFile("capes.txt")
6762
.isOlderThan(24.hours) {
6863
it.downloadIfNotPresent("${LambdaAPI.capes}.txt")
@@ -74,26 +69,15 @@ object CapeManager : ConcurrentHashMap<UUID, String>(), Loadable {
7469
}
7570
.createIfNotExists()
7671
.readText()
77-
.split("\n")
72+
.split(Regex("\\s+"))
7873
}
7974

80-
/**
81-
* Sets the current player's cape
82-
*
83-
* @param block Lambda called once the coroutine completes, it contains the throwable if any
84-
*/
8575
fun updateCape(cape: String, block: (Throwable?) -> Unit = {}) = runIO {
8676
setCape(cape).getOrThrow()
87-
88-
runSafe { fetchCape(player.uuid) }
77+
fetchCape(mc.gameProfile.id)
8978
}.invokeOnCompletion { block(it) }
9079

91-
/**
92-
* Fetches the cape of the given player id
93-
*
94-
* @param block Lambda called once the coroutine completes, it contains the throwable if any
95-
*/
96-
fun SafeContext.fetchCape(uuid: UUID, block: (Throwable?) -> Unit = {}) = runIO {
80+
fun fetchCape(uuid: UUID, block: (Throwable?) -> Unit = {}) = runIO {
9781
val cape = getCape(uuid).getOrNull() ?: return@runIO
9882

9983
val bytes = capes.resolveFile("${cape.id}.png")
@@ -107,12 +91,12 @@ object CapeManager : ConcurrentHashMap<UUID, String>(), Loadable {
10791

10892
val image = read(NativeImage.Format.RGBA, buffer)
10993

110-
mc.textureManager.registerTexture(cape.id.asIdentifier, NativeImageBackedTexture({ cape.id }, image))
94+
runGameScheduled { mc.textureManager.registerTexture(cape.id.asIdentifier, NativeImageBackedTexture({ cape.id }, image)) }
11195

112-
put(uuid, cape.id)
96+
cache[uuid] = cape.id
11397
}.invokeOnCompletion { block(it) }
11498

115-
override fun load() = "Loaded ${images.size} cached capes and ${capeList.size} remote capes"
99+
override fun load() = "Loaded ${availableCapes.size} capes"
116100

117101
init {
118102
fixedRateTimer(
@@ -124,7 +108,7 @@ object CapeManager : ConcurrentHashMap<UUID, String>(), Loadable {
124108

125109
runBlocking {
126110
getCapes(fetchQueue)
127-
.onSuccess { it.forEach { cape -> put(cape.uuid, cape.id) } }
111+
.onSuccess { it.forEach { cape -> cache[cape.uuid] = cape.id } }
128112

129113
fetchQueue.clear()
130114
}

0 commit comments

Comments
 (0)