Skip to content

Commit 4cacf41

Browse files
[1.20.x] [All] Bug: FakePlayer not showing skin (#64)
Closes #62 as fixed # Description Fixes a bug where the fake player would get assigned one of the default skins instead of the player's skin --------- Co-authored-by: pothemagicdragon <pothemagicdragon1@gmail.com>
1 parent 87e0095 commit 4cacf41

File tree

5 files changed

+60
-20
lines changed

5 files changed

+60
-20
lines changed

common/src/main/kotlin/com/lambda/config/serializer/GameProfileSerializer.kt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,23 @@ object GameProfileSerializer : JsonSerializer<GameProfile>, JsonDeserializer<Gam
1818
src?.let {
1919
JsonObject().apply {
2020
addProperty("name", it.name)
21-
addProperty("uuid", it.id.toString())
21+
addProperty("id", it.id.toString())
2222
}
2323
} ?: JsonNull.INSTANCE
2424

2525
override fun deserialize(
2626
json: JsonElement?,
2727
typeOfT: Type?,
2828
context: JsonDeserializationContext?,
29-
): GameProfile =
30-
GameProfile(
31-
UUID.fromString(json?.asJsonObject?.get("uuid")?.asString),
29+
): GameProfile {
30+
val id = json?.asJsonObject?.get("id")?.asString
31+
val parsedId =
32+
if (id?.length == 32) id.replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})".toRegex(), "$1-$2-$3-$4-$5")
33+
else id
34+
35+
return GameProfile(
36+
UUID.fromString(parsedId),
3237
json?.asJsonObject?.get("name")?.asString
3338
)
39+
}
3440
}

common/src/main/kotlin/com/lambda/http/Extensions.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,3 @@ fun <T> tryOrDefault(default: T, block: () -> T): T = try {
2727
} catch (e: Exception) {
2828
default
2929
}
30-
31-
/**
32-
* Try-catch block wrapped with null
33-
*/
34-
fun <T> tryOrNull(block: () -> T): T? = tryOrDefault(null, block)

common/src/main/kotlin/com/lambda/http/Request.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,9 @@ data class Request(
9292
connection.outputStream.use {
9393
it.write(parameters.toJson().toByteArray())
9494
}
95-
} else {
96-
connection.connect()
97-
}
95+
} else connection.connect()
9896
}.onFailure {
97+
println("Failed to execute HTTP request: $it")
9998
return Response(
10099
connection = connection,
101100
data = null,
@@ -121,9 +120,15 @@ data class Request(
121120
)
122121
}
123122

123+
var error: Throwable? = null
124+
val data = runCatching { Lambda.gson.fromJson(connection.inputStream.bufferedReader().readText(), Success::class.java) }
125+
.onFailure { error = it }
126+
.getOrNull()
127+
124128
return Response(
125129
connection = connection,
126-
data = tryOrNull { Lambda.gson.fromJson(connection.inputStream.bufferedReader().readText(), Success::class.java) },
130+
data = data,
131+
error = error,
127132
)
128133
}
129134
}
Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.lambda.module.modules.combat
22

3+
import com.lambda.context.SafeContext
4+
import com.lambda.http.Method
5+
import com.lambda.http.request
36
import com.lambda.module.Module
47
import com.lambda.module.tag.ModuleTag
8+
import com.lambda.threading.runSafeConcurrent
59
import com.mojang.authlib.GameProfile
610
import net.minecraft.client.network.OtherClientPlayerEntity
11+
import net.minecraft.client.network.PlayerListEntry
712
import net.minecraft.entity.Entity
813
import java.util.*
914

@@ -14,23 +19,50 @@ object FakePlayer : Module(
1419
) {
1520
private val playerName by setting("Name", "Steve")
1621

17-
private val uuid = UUID.fromString("41C82C87-7AfB-4024-BA57-13D2C99CAE77")
1822
private var fakePlayer: OtherClientPlayerEntity? = null
1923

2024
init {
2125
onEnable {
22-
fakePlayer = OtherClientPlayerEntity(world, GameProfile(uuid, playerName))
23-
.apply {
24-
copyFrom(player)
26+
// Avoid multiple api requests
27+
if (fakePlayer?.gameProfile?.name == playerName)
28+
return@onEnable spawnPlayer(fakePlayer!!.gameProfile)
2529

26-
id = -2024 - 4 - 20
30+
runSafeConcurrent {
31+
val uuid =
32+
request("https://api.mojang.com/users/profiles/minecraft/$playerName") {
33+
method(Method.GET)
34+
}.json<GameProfile>().data?.id ?: UUID(0, 0)
35+
36+
val fetchedProperties = mc.sessionService.fetchProfile(uuid, true)?.profile?.properties
37+
38+
val profile = GameProfile(UUID(0, 0), playerName).apply {
39+
fetchedProperties?.forEach { key, value -> properties.put(key, value) }
2740
}
2841

29-
world.addEntity(fakePlayer)
42+
// This is the cache that mc pulls profile data from when it fetches skins.
43+
mc.networkHandler?.playerListEntries?.put(profile.id, PlayerListEntry(profile, false))
44+
spawnPlayer(profile)
45+
}
3046
}
3147

3248
onDisable {
33-
fakePlayer?.setRemoved(Entity.RemovalReason.DISCARDED)
49+
deletePlayer()
3450
}
3551
}
52+
53+
private fun SafeContext.spawnPlayer(profile: GameProfile) {
54+
fakePlayer = OtherClientPlayerEntity(world, profile)
55+
.apply {
56+
copyFrom(player)
57+
58+
playerListEntry = PlayerListEntry(profile, false)
59+
id = -2024 - 4 - 20
60+
}
61+
62+
world.addEntity(fakePlayer)
63+
}
64+
65+
private fun deletePlayer() {
66+
fakePlayer?.setRemoved(Entity.RemovalReason.DISCARDED)
67+
}
3668
}

common/src/main/resources/lambda.accesswidener

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ accessible method net/minecraft/entity/passive/AbstractHorseEntity setHorseFlag
2323
accessible method net/minecraft/entity/passive/AbstractHorseEntity updateSaddle ()V
2424
accessible field net/minecraft/entity/LivingEntity lastAttackedTicks I
2525
accessible method net/minecraft/entity/Entity setFlag (IZ)V
26+
accessible field net/minecraft/client/network/AbstractClientPlayerEntity playerListEntry Lnet/minecraft/client/network/PlayerListEntry;
2627

2728
# Camera
2829
accessible method net/minecraft/client/render/Camera setPos (DDD)V
@@ -47,6 +48,7 @@ accessible field net/minecraft/text/Style font Lnet/minecraft/util/Identifier;
4748
accessible method net/minecraft/text/Style <init> (Lnet/minecraft/text/TextColor;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Lnet/minecraft/text/ClickEvent;Lnet/minecraft/text/HoverEvent;Ljava/lang/String;Lnet/minecraft/util/Identifier;)V
4849

4950
# Network
51+
accessible field net/minecraft/client/network/ClientPlayNetworkHandler playerListEntries Ljava/util/Map;
5052
accessible field net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket entityId I
5153
accessible field net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket type Lnet/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket$InteractTypeHandler;
5254
accessible class net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket$InteractTypeHandler

0 commit comments

Comments
 (0)