Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,23 @@ object GameProfileSerializer : JsonSerializer<GameProfile>, JsonDeserializer<Gam
src?.let {
JsonObject().apply {
addProperty("name", it.name)
addProperty("uuid", it.id.toString())
addProperty("id", it.id.toString())
}
} ?: JsonNull.INSTANCE

override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?,
): GameProfile =
GameProfile(
UUID.fromString(json?.asJsonObject?.get("uuid")?.asString),
): GameProfile {
val id = json?.asJsonObject?.get("id")?.asString
val parsedId =
if (id?.length == 32) id.replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})".toRegex(), "$1-$2-$3-$4-$5")
else id

return GameProfile(
UUID.fromString(parsedId),
json?.asJsonObject?.get("name")?.asString
)
}
}
5 changes: 0 additions & 5 deletions common/src/main/kotlin/com/lambda/http/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,3 @@ fun <T> tryOrDefault(default: T, block: () -> T): T = try {
} catch (e: Exception) {
default
}

/**
* Try-catch block wrapped with null
*/
fun <T> tryOrNull(block: () -> T): T? = tryOrDefault(null, block)
13 changes: 9 additions & 4 deletions common/src/main/kotlin/com/lambda/http/Request.kt
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,9 @@ data class Request(
connection.outputStream.use {
it.write(parameters.toJson().toByteArray())
}
} else {
connection.connect()
}
} else connection.connect()
}.onFailure {
println("Failed to execute HTTP request: $it")
return Response(
connection = connection,
data = null,
Expand All @@ -121,9 +120,15 @@ data class Request(
)
}

var error: Throwable? = null
val data = runCatching { Lambda.gson.fromJson(connection.inputStream.bufferedReader().readText(), Success::class.java) }
.onFailure { error = it }
.getOrNull()

return Response(
connection = connection,
data = tryOrNull { Lambda.gson.fromJson(connection.inputStream.bufferedReader().readText(), Success::class.java) },
data = data,
error = error,
)
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.lambda.module.modules.combat

import com.lambda.context.SafeContext
import com.lambda.http.Method
import com.lambda.http.request
import com.lambda.module.Module
import com.lambda.module.tag.ModuleTag
import com.lambda.threading.runSafeConcurrent
import com.mojang.authlib.GameProfile
import net.minecraft.client.network.OtherClientPlayerEntity
import net.minecraft.client.network.PlayerListEntry
import net.minecraft.entity.Entity
import java.util.*

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

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

init {
onEnable {
fakePlayer = OtherClientPlayerEntity(world, GameProfile(uuid, playerName))
.apply {
copyFrom(player)
// Avoid multiple api requests
if (fakePlayer?.gameProfile?.name == playerName)
return@onEnable spawnPlayer(fakePlayer!!.gameProfile)

id = -2024 - 4 - 20
runSafeConcurrent {
val uuid =
request("https://api.mojang.com/users/profiles/minecraft/$playerName") {
method(Method.GET)
}.json<GameProfile>().data?.id ?: UUID(0, 0)

val fetchedProperties = mc.sessionService.fetchProfile(uuid, true)?.profile?.properties

val profile = GameProfile(UUID(0, 0), playerName).apply {
fetchedProperties?.forEach { key, value -> properties.put(key, value) }
}

world.addEntity(fakePlayer)
// This is the cache that mc pulls profile data from when it fetches skins.
mc.networkHandler?.playerListEntries?.put(profile.id, PlayerListEntry(profile, false))
spawnPlayer(profile)
}
}

onDisable {
fakePlayer?.setRemoved(Entity.RemovalReason.DISCARDED)
deletePlayer()
}
}

private fun SafeContext.spawnPlayer(profile: GameProfile) {
fakePlayer = OtherClientPlayerEntity(world, profile)
.apply {
copyFrom(player)

playerListEntry = PlayerListEntry(profile, false)
id = -2024 - 4 - 20
}

world.addEntity(fakePlayer)
}

private fun deletePlayer() {
fakePlayer?.setRemoved(Entity.RemovalReason.DISCARDED)
}
}
2 changes: 2 additions & 0 deletions common/src/main/resources/lambda.accesswidener
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ accessible method net/minecraft/entity/passive/AbstractHorseEntity setHorseFlag
accessible method net/minecraft/entity/passive/AbstractHorseEntity updateSaddle ()V
accessible field net/minecraft/entity/LivingEntity lastAttackedTicks I
accessible method net/minecraft/entity/Entity setFlag (IZ)V
accessible field net/minecraft/client/network/AbstractClientPlayerEntity playerListEntry Lnet/minecraft/client/network/PlayerListEntry;

# Camera
accessible method net/minecraft/client/render/Camera setPos (DDD)V
Expand All @@ -47,6 +48,7 @@ accessible field net/minecraft/text/Style font Lnet/minecraft/util/Identifier;
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

# Network
accessible field net/minecraft/client/network/ClientPlayNetworkHandler playerListEntries Ljava/util/Map;
accessible field net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket entityId I
accessible field net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket type Lnet/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket$InteractTypeHandler;
accessible class net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket$InteractTypeHandler
Expand Down