Update to 1.19

main
kalle 2023-04-08 23:51:19 +02:00
parent 10145032e2
commit 247159970c
10 changed files with 288 additions and 315 deletions

View File

@ -1,10 +1,10 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.5.31"
kotlin("jvm") version "1.7.0-RC"
id("com.github.johnrengelman.shadow") version "7.1.2"
id("xyz.jpenilla.run-paper") version "1.0.6" // Adds runServer and runMojangMappedServer tasks for testing
id("io.papermc.paperweight.userdev") version "1.3.4"
id("io.papermc.paperweight.userdev") version "1.3.7"
}
group = "nl.kallestruik"
@ -20,12 +20,13 @@ repositories {
}
dependencies {
paperDevBundle("1.19-R0.1-SNAPSHOT")
implementation("co.aikar:acf-paper:0.5.0-SNAPSHOT")
paperDevBundle("1.18.1-R0.1-SNAPSHOT")
compileOnly("com.comphenix.protocol:ProtocolLib:4.6.0")
compileOnly(kotlin("stdlib-jdk8"))
compileOnly("nl.kallestruik:DLib:1.3.6")
compileOnly("nl.kallestruik:DLib:1.4.4")
testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")

View File

@ -22,16 +22,4 @@ class CommandPlayer(
fun onKill(sender: Player, @Single playerName: String) {
fakePlayerManager.killFakePlayer(playerName)
}
@Subcommand("attack")
@CommandCompletion("@players")
fun onAttack(sender: Player, @Single playerName: String) {
fakePlayerManager.attack(playerName)
}
@Subcommand("use")
@CommandCompletion("@players")
fun onUse(sender: Player, @Single playerName: String) {
fakePlayerManager.use(playerName)
}
}

View File

@ -1,7 +1,7 @@
package nl.kallestruik.dtweaks.fakeplayer
import com.mojang.authlib.GameProfile
import net.minecraft.network.chat.TextComponent
import net.minecraft.network.chat.Component
import net.minecraft.network.protocol.PacketFlow
import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket
@ -10,18 +10,18 @@ import net.minecraft.server.TickTask
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.entity.Entity
import net.minecraft.world.food.FoodData
import net.minecraft.world.level.block.entity.SkullBlockEntity
import nl.kallestruik.dtweaks.fakeplayer.FakePlayerList.placeFakePlayer
import org.bukkit.Location
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld
import java.util.concurrent.atomic.AtomicReference
class FakePlayer(
server: MinecraftServer,
val serverLevel: ServerLevel,
private val serverLevel: ServerLevel,
gameProfile: GameProfile
): ServerPlayer(server, serverLevel, gameProfile) {
): ServerPlayer(server, serverLevel, gameProfile, null) {
val locale = "en_US"
companion object {
@ -43,7 +43,7 @@ class FakePlayer(
// Create a fake connection for our fake player.
val connection = FakeConnection(PacketFlow.SERVERBOUND)
FakePlayerList.placeNewPlayer(minecraftServer.playerList, minecraftServer, connection, instance)
minecraftServer.playerList.placeFakePlayer(connection, instance)
instance.respawn()
instance.teleportTo(serverLevel, location.x, location.y, location.z, location.yaw, location.pitch)
@ -119,7 +119,9 @@ class FakePlayer(
}
override fun kill() {
server.tell(TickTask(server.tickCount) {connection.onDisconnect(TextComponent("Killed"))})
server.tell(TickTask(server.tickCount) {
connection.onDisconnect(Component.literal("Killed"))
})
}
override fun die(source: DamageSource) {

View File

@ -3,7 +3,6 @@ package nl.kallestruik.dtweaks.fakeplayer
import io.netty.util.concurrent.Future
import io.netty.util.concurrent.GenericFutureListener
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.network.protocol.Packet
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerGamePacketListenerImpl
@ -18,11 +17,8 @@ class FakePlayerConnection(
override fun send(packet: Packet<*>, listener: GenericFutureListener<out Future<in Void>>?) {}
override fun disconnect(message: Component) {
if (message is TranslatableComponent && (message.key.equals("multiplayer.disconnect.idling") || message.equals("multiplayer.disconnect.duplicate_login")))
{
player.kill()
}
}
override fun tick() {
println("Tick for ${player.name}")

View File

@ -1,23 +1,29 @@
package nl.kallestruik.dtweaks.fakeplayer
import com.destroystokyo.paper.PaperConfig
import com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent
import com.mojang.authlib.GameProfile
import com.mojang.datafixers.util.Either
import com.mojang.serialization.Dynamic
import io.netty.buffer.Unpooled
import io.papermc.paper.configuration.GlobalConfiguration
import net.minecraft.core.RegistryAccess
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.NbtOps
import net.minecraft.nbt.Tag
import net.minecraft.network.Connection
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.protocol.game.*
import net.minecraft.resources.ResourceKey
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.*
import net.minecraft.server.level.ChunkHolder.ChunkLoadingFailure
import net.minecraft.server.level.DistanceManager
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.level.TicketType
import net.minecraft.server.network.ServerGamePacketListenerImpl
import net.minecraft.server.players.GameProfileCache
import net.minecraft.server.players.PlayerList
import net.minecraft.tags.TagNetworkSerialization
import net.minecraft.world.level.ChunkPos
import net.minecraft.world.level.GameRules
import net.minecraft.world.level.Level
@ -25,18 +31,185 @@ import net.minecraft.world.level.biome.BiomeManager
import net.minecraft.world.level.chunk.ChunkAccess
import net.minecraft.world.level.dimension.DimensionType
import nl.kallestruik.dlib.ReflectionUtil
import nl.kallestruik.dtweaks.DTweaks
import org.apache.logging.log4j.Logger
import org.bukkit.Bukkit
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld
import org.bukkit.craftbukkit.v1_19_R1.CraftServer
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld
import org.bukkit.entity.Player
import org.spigotmc.event.player.PlayerSpawnLocationEvent
import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.function.Consumer
object FakePlayerList {
fun PlayerList.placeFakePlayer(connection: Connection, player: ServerPlayer) {
player.isRealPlayer = true // Paper - Chunk priority
player.networkManager = connection // Paper
player.loginTime = System.currentTimeMillis() // Paper
val gameprofile = player.getGameProfile()
val usercache = server.profileCache
val optional = usercache[gameprofile.id]
var s: String? = optional.map { obj: GameProfile -> obj.name }.orElse(gameprofile.name)
usercache.add(gameprofile)
val nbttagcompound = load(player)
// CraftBukkit start - Better rename detection
// CraftBukkit start - Better rename detection
if (nbttagcompound != null && nbttagcompound.contains("bukkit")) {
val bukkit = nbttagcompound.getCompound("bukkit")
s = if (bukkit.contains("lastKnownName", 8)) bukkit.getString("lastKnownName") else s
}
val lastKnownName = s // Paper
// CraftBukkit end
// Paper start - move logic in Entity to here, to use bukkit supplied world UUID.
// CraftBukkit end
// Paper start - move logic in Entity to here, to use bukkit supplied world UUID.
val resourcekey =
if (nbttagcompound != null && nbttagcompound.contains("WorldUUIDMost") && nbttagcompound.contains("WorldUUIDLeast")) {
val uid = UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast"))
val bWorld = Bukkit.getServer().getWorld(uid)
if (bWorld != null) {
(bWorld as CraftWorld).handle.dimension()
} else {
Level.OVERWORLD
}
} else if (nbttagcompound != null) {
// Vanilla migration support
// Paper end
val dataresult = DimensionType.parseLegacy(
Dynamic(
NbtOps.INSTANCE,
nbttagcompound["Dimension"]
)
) // CraftBukkit - decompile error
dataresult.resultOrPartial { msg: String? ->
}.orElse(Level.OVERWORLD)
} else {
Level.OVERWORLD
}
val resourcekey1: ResourceKey<Level> = resourcekey
val worldserver = server.getLevel(resourcekey1)
var worldserver1: ServerLevel
worldserver1 = if (worldserver == null) {
server.overworld()
} else {
worldserver
}
if (nbttagcompound == null) player.fudgeSpawnLocation(worldserver1) // Paper - only move to spawn on first login, otherwise, stay where you are....
player.setLevel(worldserver1)
// Paper start - make s1 final
// Paper start - make s1 final
val s1: String
s1 = if (connection.remoteAddress != null) {
if (GlobalConfiguration.get().logging.logPlayerIpAddresses) connection.remoteAddress.toString() else "<ip address withheld>" // Paper
} else {
"local"
}
// Paper end
// Spigot start - spawn location event
// Paper end
// Spigot start - spawn location event
val spawnPlayer: Player = player.bukkitEntity
val ev: PlayerSpawnLocationEvent =
PlayerInitialSpawnEvent(spawnPlayer, spawnPlayer.location) // Paper use our duplicate event
val cserver = ReflectionUtil().getValueFromField(this, "cserver") as CraftServer
cserver.pluginManager.callEvent(ev)
val loc = ev.spawnLocation
worldserver1 = (loc.world as CraftWorld).handle
player.spawnIn(worldserver1)
player.gameMode.setLevel(player.level as ServerLevel)
player.setPosRaw(loc.x, loc.y, loc.z)
player.setRot(loc.yaw, loc.pitch)
val worlddata = worldserver1.getLevelData()
player.loadGameTypes(nbttagcompound)
val playerconnection = ServerGamePacketListenerImpl(server, connection, player)
val gamerules = worldserver1.gameRules
val flag = gamerules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN)
val flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO)
val registryHolder = ReflectionUtil().getValueFromField(this, "t" /* registryHolder -> t */) as RegistryAccess.Frozen
playerconnection.send(
ClientboundLoginPacket(
player.id,
worlddata.isHardcore,
player.gameMode.gameModeForPlayer,
player.gameMode.previousGameModeForPlayer,
server.levelKeys(),
registryHolder,
worldserver1.dimensionTypeId(),
worldserver1.dimension(),
BiomeManager.obfuscateSeed(worldserver1.seed),
maxPlayers,
worldserver1.getChunkSource().chunkMap.playerChunkManager.targetSendDistance,
worldserver1.getChunkSource().chunkMap.playerChunkManager.targetTickViewDistance,
flag1,
!flag,
worldserver1.isDebug,
worldserver1.isFlat,
player.lastDeathLocation
)
)
player.bukkitEntity.sendSupportedChannels() // CraftBukkit
playerconnection.send(
ClientboundCustomPayloadPacket(
ClientboundCustomPayloadPacket.BRAND, FriendlyByteBuf(Unpooled.buffer()).writeUtf(
server.serverModName
)
)
)
playerconnection.send(ClientboundChangeDifficultyPacket(worlddata.difficulty, worlddata.isDifficultyLocked))
playerconnection.send(ClientboundPlayerAbilitiesPacket(player.abilities))
playerconnection.send(ClientboundSetCarriedItemPacket(player.inventory.selected))
playerconnection.send(ClientboundUpdateRecipesPacket(server.recipeManager.getRecipes()))
playerconnection.send(ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(registryHolder)))
this.sendPlayerPermissionLevel(player)
player.stats.markAllDirty()
player.recipeBook.sendInitialRecipeBook(player)
updateEntireScoreboard(worldserver1.scoreboard, player)
server.invalidateStatus()
// Paper start - async load spawn in chunk
// Paper start - async load spawn in chunk
val finalWorldserver = worldserver1
val chunkX = loc.blockX shr 4
val chunkZ = loc.blockZ shr 4
val pos = ChunkPos(chunkX, chunkZ)
val playerChunkMap = worldserver1.getChunkSource().chunkMap
val distanceManager: DistanceManager = playerChunkMap.distanceManager
distanceManager.addTicket(TicketType.LOGIN, pos, 31, pos.toLong())
worldserver1.getChunkSource().markAreaHighPriority(pos, 28, 3) // Paper - Chunk priority
val postChunkLoadJoin = this::class.java.superclass.getDeclaredMethod("postChunkLoadJoin", ServerPlayer::class.java, ServerLevel::class.java, Connection::class.java, ServerGamePacketListenerImpl::class.java, CompoundTag::class.java, String::class.java, String::class.java)
postChunkLoadJoin.isAccessible = true
postChunkLoadJoin.invoke(this, player, finalWorldserver, connection, playerconnection,
nbttagcompound, "127.0.0.1", lastKnownName)
}
fun placeNewPlayer(playerList: PlayerList, server: MinecraftServer, connection: FakeConnection, player: FakePlayer) {
}
fun placeNewPlayerOld(playerList: PlayerList, server: MinecraftServer, connection: FakeConnection, player: FakePlayer) {
player.isRealPlayer = true // Paper - Chunk priority
player.networkManager = connection // Paper
@ -139,7 +312,7 @@ object FakePlayerList {
val pos = ChunkPos(chunkX, chunkZ)
val playerChunkMap = worldServer.getChunkSource().chunkMap
val distanceManager: DistanceManager = playerChunkMap.distanceManager
distanceManager.addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.toLong())
// distanceManager.addTicket(TicketType.LOGIN, pos, 31, pos.toLong())
worldServer.getChunkSource().markAreaHighPriority(pos, 28, 3) // Paper - Chunk priority
val postChunkLoadJoin = playerList::class.java.superclass.getDeclaredMethod("postChunkLoadJoin", ServerPlayer::class.java, ServerLevel::class.java, Connection::class.java, ServerGamePacketListenerImpl::class.java, CompoundTag::class.java, String::class.java, String::class.java)

View File

@ -1,20 +1,11 @@
package nl.kallestruik.dtweaks.managers
import net.minecraft.core.Direction
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.Entity
import net.minecraft.world.level.ClipContext
import net.minecraft.world.phys.*
import nl.kallestruik.dlib.ReflectionUtil
import nl.kallestruik.dtweaks.DTweaks
import nl.kallestruik.dtweaks.fakeplayer.FakePlayer
import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftEntity
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer
import org.bukkit.scheduler.BukkitRunnable
import org.bukkit.scheduler.BukkitTask
import java.util.function.Predicate
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftEntity
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer
/*
@ -24,12 +15,6 @@ import java.util.function.Predicate
class FakePlayerManager(
val plugin: DTweaks,
) {
init {
// Tick all fake players.
FakePlayerTickTask().runTaskTimer(plugin, 10, 10)
}
fun getPlayerByName(name: String): FakePlayer? {
val player = Bukkit.getPlayer(name)
if (player == null || !player.isOnline) return null
@ -57,166 +42,4 @@ class FakePlayerManager(
fakePlayer.kill()
}
}
private fun tickAll() {
for (player in Bukkit.getOnlinePlayers()) {
if (!player.isOnline) continue
val fakePlayer = (player as CraftPlayer).handle as? FakePlayer ?: continue
fakePlayer.doTick()
}
}
// fun attackInterval(name: String, interval: Int) {
//
//
// fakePlayer.swing()
// }
fun attack(name: String) {
val player = getPlayerByName(name) ?: return
val target = getTarget(player) ?: return
when (target.type) {
HitResult.Type.BLOCK -> {/*TODO: Not implemented*/}
HitResult.Type.ENTITY -> {
if (target !is EntityHitResult) return
player.attack(target.entity);
player.swing(InteractionHand.MAIN_HAND);
player.resetLastActionTime();
}
else -> return
}
}
fun use(name: String) {
val player = getPlayerByName(name) ?: return
val target = getTarget(player) ?: return
for (hand in InteractionHand.values()) {
when (target.type) {
HitResult.Type.BLOCK -> {
if (target !is BlockHitResult) return
player.resetLastActionTime()
val world = player.getLevel()
val pos = target.blockPos
val side = target.direction
if (pos.y < player.getLevel().maxBuildHeight - (if (side === Direction.UP) 1 else 0)
&& world.mayInteract(player, pos)) {
val result = player.gameMode.useItemOn(player, world, player.getItemInHand(hand), hand, target)
if (result.consumesAction()) {
if (result.shouldSwing()) player.swing(hand)
return
}
}
}
HitResult.Type.ENTITY -> {
if (target !is EntityHitResult) return
player.resetLastActionTime()
val entity = target.entity
val relativeHitPos: Vec3 = target.getLocation().subtract(entity.x, entity.y, entity.z)
entity.interactAt(player, relativeHitPos, hand).consumesAction()
// fix for SS itemframe always returns CONSUME even if no action is performed
player.interactOn(entity, hand).consumesAction()
}
}
player.gameMode.useItem(player, player.getLevel(), player.getItemInHand(hand), hand)
}
}
//
// Ray tracing code borrowed from carpet mod: https://github.com/gnembon/fabric-carpet/blob/master/src/main/java/carpet/helpers/Tracer.java
//
fun getTarget(player: FakePlayer): HitResult? {
val reach: Double = if (player.gameMode.isCreative) 5.0 else 4.5f.toDouble()
return rayTrace(player, 1F, reach, false)
}
fun rayTrace(source: FakePlayer, partialTicks: Float, reach: Double, fluids: Boolean): HitResult? {
val blockHit = rayTraceBlocks(source, partialTicks, reach, fluids)
var maxSqDist = reach * reach
if (blockHit != null) {
maxSqDist = blockHit.location.distanceToSqr(source.getEyePosition(partialTicks))
}
val entityHit = rayTraceEntities(source, partialTicks, reach, maxSqDist)
return entityHit ?: blockHit
}
fun rayTraceBlocks(source: FakePlayer, partialTicks: Float, reach: Double, fluids: Boolean): BlockHitResult? {
val pos: Vec3 = source.getEyePosition(partialTicks)
val rotation: Vec3 = source.getViewVector(partialTicks)
val reachEnd = pos.add(rotation.x * reach, rotation.y * reach, rotation.z * reach)
return source.level.clip(
ClipContext(
pos,
reachEnd,
ClipContext.Block.OUTLINE,
if (fluids) ClipContext.Fluid.ANY else ClipContext.Fluid.NONE,
source
)
)
}
fun rayTraceEntities(source: FakePlayer, partialTicks: Float, reach: Double, maxSqDist: Double): EntityHitResult? {
val pos = source.getEyePosition(partialTicks)
val reachVec = source.getViewVector(partialTicks).scale(reach)
val box = source.boundingBox.expandTowards(reachVec).inflate(1.0)
return rayTraceEntities(source, pos, pos.add(reachVec), box, maxSqDist) {
e -> !e.isSpectator && e.isPickable
}
}
fun rayTraceEntities(
source: FakePlayer,
start: Vec3,
end: Vec3,
box: AABB,
maxSqDistance: Double,
predicate: Predicate<Entity>,
): EntityHitResult? {
val world = source.level
var targetDistance = maxSqDistance
var target: Entity? = null
var targetHitPos: Vec3? = null
for (current in world.getEntities(source, box, predicate)) {
val currentBox = current.boundingBox.inflate(current.pickRadius.toDouble())
val currentHit = currentBox.clip(start, end)
if (currentBox.contains(start)) {
if (targetDistance >= 0) {
target = current
targetHitPos = currentHit.orElse(start)
targetDistance = 0.0
}
} else if (currentHit.isPresent) {
val currentHitPos: Vec3 = currentHit.get()
val currentDistance = start.distanceToSqr(currentHitPos)
if (currentDistance < targetDistance || targetDistance == 0.0) {
if (current.rootVehicle === source.rootVehicle) {
if (targetDistance == 0.0) {
target = current
targetHitPos = currentHitPos
}
} else {
target = current
targetHitPos = currentHitPos
targetDistance = currentDistance
}
}
}
}
return if (target == null) null else EntityHitResult(target, targetHitPos!!)
}
inner class FakePlayerTickTask: BukkitRunnable() {
override fun run() {
tickAll()
}
}
}

View File

@ -4,9 +4,7 @@ import nl.kallestruik.dtweaks.DTweaks
import nl.kallestruik.dtweaks.fakeplayer.FakePlayer
import nl.kallestruik.dtweaks.managers.FakePlayerManager
import nl.kallestruik.dtweaks.tweaks.ITweak
import org.bukkit.Material
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.HandlerList

View File

@ -1,20 +1,12 @@
package nl.kallestruik.dtweaks.tweaks.mobtweaks
import net.minecraft.core.GlobalPos
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.schedule.Activity
import nl.kallestruik.dtweaks.managers.NoSpawnZoneManager
import nl.kallestruik.dtweaks.tweaks.ITweak
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftVillager
import org.bukkit.entity.Villager
import org.bukkit.event.EventHandler
import org.bukkit.event.HandlerList
import org.bukkit.event.Listener
import org.bukkit.event.entity.CreatureSpawnEvent
import org.bukkit.event.entity.EntitySpawnEvent
import org.bukkit.event.player.PlayerInteractEntityEvent
import org.bukkit.plugin.java.JavaPlugin
import java.util.concurrent.atomic.AtomicReference
class NoSpawnZones(
private val plugin: JavaPlugin,

View File

@ -4,7 +4,7 @@ import net.minecraft.core.GlobalPos
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.schedule.Activity
import nl.kallestruik.dtweaks.tweaks.ITweak
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftVillager
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftVillager
import org.bukkit.entity.Villager
import org.bukkit.event.EventHandler
import org.bukkit.event.HandlerList