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
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
javaVersion=25
mcVersion=26.1.2
group=dev.slne.surf.api
version=3.20.0
version=3.21.0
relocationPrefix=dev.slne.surf.api.libs
snapshot=false
4 changes: 4 additions & 0 deletions surf-api-core/surf-api-core/api/surf-api-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -11035,6 +11035,10 @@ public abstract interface class dev/slne/surf/api/core/util/ToByteFunction {
public abstract fun applyAsByte (Ljava/lang/Object;)B
}

public final class dev/slne/surf/api/core/util/Var_handle_utilKt {
public static final fun setIfGreater (Ljava/lang/invoke/VarHandle;Ljava/lang/Object;I)Z
}

public abstract interface class dev/slne/surf/api/core/util/blockstate/BlockStateFactory {
public static final field Companion Ldev/slne/surf/api/core/util/blockstate/BlockStateFactory$Companion;
public static fun builder (Lcom/github/retrooper/packetevents/protocol/world/states/WrappedBlockState;)Ldev/slne/surf/api/core/util/blockstate/BlockStateFactory$Builder;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dev.slne.surf.api.core.util

import java.lang.invoke.VarHandle

/**
* Sets the value at the specified variable handle to the new value if the new value is greater than the current value.
*
* This method ensures that the value is updated only when the provided `newValue` is strictly greater
* than the current value stored at the variable handle. The operation is performed atomically.
*
* @param receiver the object on which the variable handle operates
* @param newValue the new value to set if greater than the current value
* @return `true` if the value was updated to `newValue`, `false` if `newValue` was not greater and no update occurred
*/
fun VarHandle.setIfGreater(receiver: Any, newValue: Int): Boolean {
while (true) {
val current = getVolatile(receiver) as Int

if (newValue <= current) {
return false
}

if (compareAndSet(receiver, current, newValue)) {
return true
}
}
}
Comment on lines +15 to +27
2 changes: 1 addition & 1 deletion surf-api-gradle-plugin/surf-api-processor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ plugins {

group = groupId
version = buildString {
append("1.0.0")
append("1.0.1")
if (snapshot) append("-SNAPSHOT")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
import com.google.devtools.ksp.symbol.*
import com.google.devtools.ksp.validate
import com.palantir.javapoet.ClassName
import com.palantir.javapoet.ParameterizedTypeName
import com.palantir.javapoet.TypeName
import com.palantir.javapoet.WildcardTypeName
import com.palantir.javapoet.*
import dev.slne.surf.api.processor.ClassNames
import dev.slne.surf.api.processor.ShortClassNames
import dev.slne.surf.api.processor.ShortClassNames.CONSTANT_BOOLEAN_ARGUMENT
Expand Down Expand Up @@ -412,6 +409,79 @@ class ReflectionSymbolProcessor(environment: SymbolProcessorEnvironment) : Symbo
"kotlin.Double" -> if (isNullable) boxed("java.lang.Double", javaNullability) else JavaType.Double
"kotlin.Char" -> if (isNullable) boxed("java.lang.Character", javaNullability) else JavaType.Char

"kotlin.Array" -> {
val componentType = arguments.firstOrNull()
?.type
?.resolve()
?.toJavaType()
?: JavaType.Object

val arrayType = ArrayTypeName.of(componentType.className.box())

JavaType(
sourceName = "${componentType.sourceName}[]",
className = arrayType,
erasedClassName = ArrayTypeName.of(componentType.erasedClassName.box()),
nullability = javaNullability,
)
Comment on lines +419 to +426
}

"kotlin.BooleanArray" -> JavaType(
sourceName = "boolean[]",
className = ArrayTypeName.of(TypeName.BOOLEAN),
erasedClassName = ArrayTypeName.of(TypeName.BOOLEAN),
nullability = javaNullability,
)

"kotlin.ByteArray" -> JavaType(
sourceName = "byte[]",
className = ArrayTypeName.of(TypeName.BYTE),
erasedClassName = ArrayTypeName.of(TypeName.BYTE),
nullability = javaNullability,
)

"kotlin.ShortArray" -> JavaType(
sourceName = "short[]",
className = ArrayTypeName.of(TypeName.SHORT),
erasedClassName = ArrayTypeName.of(TypeName.SHORT),
nullability = javaNullability,
)

"kotlin.IntArray" -> JavaType(
sourceName = "int[]",
className = ArrayTypeName.of(TypeName.INT),
erasedClassName = ArrayTypeName.of(TypeName.INT),
nullability = javaNullability,
)

"kotlin.LongArray" -> JavaType(
sourceName = "long[]",
className = ArrayTypeName.of(TypeName.LONG),
erasedClassName = ArrayTypeName.of(TypeName.LONG),
nullability = javaNullability,
)

"kotlin.FloatArray" -> JavaType(
sourceName = "float[]",
className = ArrayTypeName.of(TypeName.FLOAT),
erasedClassName = ArrayTypeName.of(TypeName.FLOAT),
nullability = javaNullability,
)

"kotlin.DoubleArray" -> JavaType(
sourceName = "double[]",
className = ArrayTypeName.of(TypeName.DOUBLE),
erasedClassName = ArrayTypeName.of(TypeName.DOUBLE),
nullability = javaNullability,
)

"kotlin.CharArray" -> JavaType(
sourceName = "char[]",
className = ArrayTypeName.of(TypeName.CHAR),
erasedClassName = ArrayTypeName.of(TypeName.CHAR),
nullability = javaNullability,
)

else -> {
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(FqNameUnsafe(qualifiedName))
val javaFqName = javaClassId?.asSingleFqName()?.asString() ?: qualifiedName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import net.minecraft.world.entity.EntityEquipment
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.npc.InventoryCarrier
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.ProfilePublicKey
import net.minecraft.world.level.storage.*
import org.bukkit.craftbukkit.CraftEquipmentSlot
import org.bukkit.craftbukkit.inventory.CraftItemStack
Expand Down Expand Up @@ -63,6 +64,35 @@ class V1_21_11SurfPaperNmsPlayerBridgeImpl : SurfPaperNmsPlayerBridge {
)
}

@Suppress("USELESS_ELVIS")
override fun resetPlayerChatState(player: Player, chatSession: RemoteChatSessionData) {
val nmsPlayer = player.toNms()
val connection = nmsPlayer.connection ?: return

val newChatSessionData = RemoteChatSession.Data(
chatSession.sessionId,
ProfilePublicKey.Data(
chatSession.expiresAt,
chatSession.key,
chatSession.keySignature
)
)


val signatureValidator = MinecraftServer.getServer().services().profileKeySignatureValidator()
if (signatureValidator == null) {
CHAT_LOGGER.warn("Ignoring chat session from {} due to missing Services public key", player.name)
return
}

val newChatSession = newChatSessionData.validate(
nmsPlayer.gameProfile,
signatureValidator
)

V1_21_11NmsReflections.resetPlayerChatState(connection, newChatSession)
}

override fun runOnChatMessageChain(player: Player, scope: CoroutineScope, block: suspend () -> Unit) {
val nmsPlayer = player.toNms()
val connection = nmsPlayer.connection
Expand Down Expand Up @@ -347,5 +377,6 @@ class V1_21_11SurfPaperNmsPlayerBridgeImpl : SurfPaperNmsPlayerBridge {

companion object {
private val OFFLINE_INVENTORY_EDIT_LOGGER = ComponentLogger.logger("OfflinePlayer Inventory Edit")
private val CHAT_LOGGER = ComponentLogger.logger("SurfPaperNmsPlayerBridge Chat")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import com.google.gson.JsonElement
import dev.slne.surf.api.shared.api.reflection.*
import io.netty.channel.ChannelFuture
import io.papermc.paper.adventure.ChatProcessor
import net.minecraft.network.chat.ChatType
import net.minecraft.network.chat.FilterMask
import net.minecraft.network.chat.LastSeenMessagesValidator
import net.minecraft.network.chat.MessageSignatureCache
import net.minecraft.network.chat.*
import net.minecraft.network.syncher.EntityDataAccessor
import net.minecraft.resources.ResourceKey
import net.minecraft.server.network.ServerConnectionListener
Expand Down Expand Up @@ -86,5 +83,11 @@ interface V1_21_11NmsReflections {
)
fun getServerStatsCounterGson(): Gson

@ReflectedMethod("resetPlayerChatState")
fun resetPlayerChatState(
instance: ServerGamePacketListenerImpl,
chatSession: RemoteChatSession
)

companion object : V1_21_11NmsReflections by generatedReflectionAccessor()
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import dev.slne.surf.api.paper.extensions.server
import dev.slne.surf.api.paper.nms.NmsUseWithCaution
import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsPlayerBridge
import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsPlayerBridge.PlayerInventoryEdit
import dev.slne.surf.api.paper.nms.bridges.data.chat.PlayerChatMessageMirror
import dev.slne.surf.api.paper.nms.bridges.data.chat.RemoteChatSessionData
import dev.slne.surf.api.paper.nms.bridges.data.chat.*
import dev.slne.surf.api.paper.nms.common.dummy.DummyEntityEquipment
import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms
import dev.slne.surf.api.paper.server.nms.v26_1.reflection.V26_1NmsReflections
Expand Down Expand Up @@ -36,6 +35,7 @@ import net.minecraft.world.entity.EntityEquipment
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.npc.InventoryCarrier
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.ProfilePublicKey
import net.minecraft.world.level.storage.*
import org.bukkit.craftbukkit.CraftEquipmentSlot
import org.bukkit.craftbukkit.inventory.CraftItemStack
Expand All @@ -44,24 +44,57 @@ import org.bukkit.inventory.EquipmentSlot
import org.bukkit.inventory.ItemStack
import java.io.File
import java.nio.file.Path
import java.util.*
import java.util.concurrent.CompletableFuture
import kotlin.io.path.createTempFile
import kotlin.jvm.optionals.getOrNull

@NmsUseWithCaution
@Suppress("ClassName")
class V26_1SurfPaperNmsPlayerBridgeImpl : SurfPaperNmsPlayerBridge {

@Suppress("USELESS_ELVIS")
override fun getRemoteChatSessionData(player: Player): RemoteChatSessionData? {
val session = player.toNms().chatSession?.asData() ?: return null
val connection = player.toNms().connection ?: return null
val session = V26_1NmsReflections.getRemoteChatSession(connection) ?: return null
val profilePublicKey = session.profilePublicKey()

return RemoteChatSessionData(
sessionId = session.sessionId(),
expiresAt = profilePublicKey.expiresAt(),
key = profilePublicKey.key(),
keySignature = profilePublicKey.keySignature()
expiresAt = profilePublicKey.data().expiresAt(),
key = profilePublicKey.data().key(),
keySignature = profilePublicKey.data().keySignature()
)
}

@Suppress("USELESS_ELVIS")
override fun resetPlayerChatState(player: Player, chatSession: RemoteChatSessionData) {
val nmsPlayer = player.toNms()
val connection = nmsPlayer.connection ?: return

val newChatSessionData = RemoteChatSession.Data(
chatSession.sessionId,
ProfilePublicKey.Data(
chatSession.expiresAt,
chatSession.key,
chatSession.keySignature
)
)

val signatureValidator = MinecraftServer.getServer().services().profileKeySignatureValidator()
if (signatureValidator == null) {
CHAT_LOGGER.warn("Ignoring chat session from {} due to missing Services public key", player.name)
return
}

val newChatSession = newChatSessionData.validate(
nmsPlayer.gameProfile,
signatureValidator
)

V26_1NmsReflections.resetPlayerChatState(connection, newChatSession,)
}

override fun runOnChatMessageChain(player: Player, scope: CoroutineScope, block: suspend () -> Unit) {
val nmsPlayer = player.toNms()
val connection = nmsPlayer.connection
Expand Down Expand Up @@ -346,5 +379,6 @@ class V26_1SurfPaperNmsPlayerBridgeImpl : SurfPaperNmsPlayerBridge {

companion object {
private val OFFLINE_INVENTORY_EDIT_LOGGER = ComponentLogger.logger("OfflinePlayer Inventory Edit")
private val CHAT_LOGGER = ComponentLogger.logger("SurfPaperNmsPlayerBridge Chat")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import com.google.gson.JsonElement
import dev.slne.surf.api.shared.api.reflection.*
import io.netty.channel.ChannelFuture
import io.papermc.paper.adventure.ChatProcessor
import net.minecraft.network.chat.ChatType
import net.minecraft.network.chat.FilterMask
import net.minecraft.network.chat.LastSeenMessagesValidator
import net.minecraft.network.chat.MessageSignatureCache
import net.minecraft.network.chat.*
import net.minecraft.network.syncher.EntityDataAccessor
import net.minecraft.resources.ResourceKey
import net.minecraft.server.network.ServerConnectionListener
Expand Down Expand Up @@ -85,5 +82,14 @@ interface V26_1NmsReflections {
)
fun getServerStatsCounterGson(): Gson

@ReflectedMethod("resetPlayerChatState")
fun resetPlayerChatState(
instance: ServerGamePacketListenerImpl,
chatSession: RemoteChatSession
)

@ReflectedField("chatSession")
fun getRemoteChatSession(instance: ServerGamePacketListenerImpl): RemoteChatSession?

companion object : V26_1NmsReflections by generatedReflectionAccessor()
}
2 changes: 2 additions & 0 deletions surf-api-paper/surf-api-paper/api/surf-api-paper.api
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,7 @@ public abstract interface class dev/slne/surf/api/paper/nms/bridges/SurfPaperNms
public abstract fun getRemoteChatSessionData (Lorg/bukkit/entity/Player;)Ldev/slne/surf/api/paper/nms/bridges/data/chat/RemoteChatSessionData;
public abstract fun getStatsDataPath ()Ljava/nio/file/Path;
public abstract fun increaseNextChatIndex (Lorg/bukkit/entity/Player;)Ljava/lang/Integer;
public abstract fun resetPlayerChatState (Lorg/bukkit/entity/Player;Ldev/slne/surf/api/paper/nms/bridges/data/chat/RemoteChatSessionData;)V
public abstract fun runOnChatMessageChain (Lorg/bukkit/entity/Player;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function1;)V
public abstract fun sendPlayerChatMessage (Lorg/bukkit/entity/Player;Lnet/kyori/adventure/chat/SignedMessage;Lnet/kyori/adventure/chat/ChatType$Bound;)V
public abstract fun sendSignedMessageWithChangedContent (Lorg/bukkit/entity/Player;Lnet/kyori/adventure/chat/SignedMessage;Lnet/kyori/adventure/chat/ChatType$Bound;Lnet/kyori/adventure/text/Component;)V
Expand All @@ -1750,6 +1751,7 @@ public final class dev/slne/surf/api/paper/nms/bridges/SurfPaperNmsPlayerBridge$
public fun getRemoteChatSessionData (Lorg/bukkit/entity/Player;)Ldev/slne/surf/api/paper/nms/bridges/data/chat/RemoteChatSessionData;
public fun getStatsDataPath ()Ljava/nio/file/Path;
public fun increaseNextChatIndex (Lorg/bukkit/entity/Player;)Ljava/lang/Integer;
public fun resetPlayerChatState (Lorg/bukkit/entity/Player;Ldev/slne/surf/api/paper/nms/bridges/data/chat/RemoteChatSessionData;)V
public fun runOnChatMessageChain (Lorg/bukkit/entity/Player;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function1;)V
public fun sendPlayerChatMessage (Lorg/bukkit/entity/Player;Lnet/kyori/adventure/chat/SignedMessage;Lnet/kyori/adventure/chat/ChatType$Bound;)V
public fun sendSignedMessageWithChangedContent (Lorg/bukkit/entity/Player;Lnet/kyori/adventure/chat/SignedMessage;Lnet/kyori/adventure/chat/ChatType$Bound;Lnet/kyori/adventure/text/Component;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ interface SurfPaperNmsPlayerBridge {

fun getRemoteChatSessionData(player: Player): RemoteChatSessionData?

fun resetPlayerChatState(player: Player, chatSession: RemoteChatSessionData)

fun runOnChatMessageChain(player: Player, scope: CoroutineScope, block: suspend () -> Unit)

fun sendSignedMessageWithChangedContent(
Expand Down