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 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
kotlin("jvm") version "1.5.31" kotlin("jvm") version "1.7.0-RC"
id("com.github.johnrengelman.shadow") version "7.1.2" 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("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" group = "nl.kallestruik"
@ -20,12 +20,13 @@ repositories {
} }
dependencies { dependencies {
paperDevBundle("1.19-R0.1-SNAPSHOT")
implementation("co.aikar:acf-paper:0.5.0-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("com.comphenix.protocol:ProtocolLib:4.6.0")
compileOnly(kotlin("stdlib-jdk8")) compileOnly(kotlin("stdlib-jdk8"))
compileOnly("nl.kallestruik:DLib:1.3.6") compileOnly("nl.kallestruik:DLib:1.4.4")
testImplementation(kotlin("test-junit5")) testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0") testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")

178
gradlew.bat vendored
View File

@ -1,89 +1,89 @@
@rem @rem
@rem Copyright 2015 the original author or authors. @rem Copyright 2015 the original author or authors.
@rem @rem
@rem Licensed under the Apache License, Version 2.0 (the "License"); @rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License. @rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at @rem You may obtain a copy of the License at
@rem @rem
@rem https://www.apache.org/licenses/LICENSE-2.0 @rem https://www.apache.org/licenses/LICENSE-2.0
@rem @rem
@rem Unless required by applicable law or agreed to in writing, software @rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS, @rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and @rem See the License for the specific language governing permissions and
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@if "%DEBUG%" == "" @echo off @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@rem Gradle startup script for Windows @rem Gradle startup script for Windows
@rem @rem
@rem ########################################################################## @rem ##########################################################################
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=. if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter. @rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute if "%ERRORLEVEL%" == "0" goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo. echo.
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. echo location of your Java installation.
goto fail goto fail
:findJavaFromJavaHome :findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto execute
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo. echo.
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. echo location of your Java installation.
goto fail goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if "%ERRORLEVEL%"=="0" goto mainEnd
:fail :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1 exit /b 1
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal
:omega :omega

View File

@ -22,16 +22,4 @@ class CommandPlayer(
fun onKill(sender: Player, @Single playerName: String) { fun onKill(sender: Player, @Single playerName: String) {
fakePlayerManager.killFakePlayer(playerName) 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 package nl.kallestruik.dtweaks.fakeplayer
import com.mojang.authlib.GameProfile 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.PacketFlow
import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket 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.ServerLevel
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.damagesource.DamageSource import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.entity.Entity
import net.minecraft.world.food.FoodData import net.minecraft.world.food.FoodData
import net.minecraft.world.level.block.entity.SkullBlockEntity import net.minecraft.world.level.block.entity.SkullBlockEntity
import nl.kallestruik.dtweaks.fakeplayer.FakePlayerList.placeFakePlayer
import org.bukkit.Location 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 import java.util.concurrent.atomic.AtomicReference
class FakePlayer( class FakePlayer(
server: MinecraftServer, server: MinecraftServer,
val serverLevel: ServerLevel, private val serverLevel: ServerLevel,
gameProfile: GameProfile gameProfile: GameProfile
): ServerPlayer(server, serverLevel, gameProfile) { ): ServerPlayer(server, serverLevel, gameProfile, null) {
val locale = "en_US" val locale = "en_US"
companion object { companion object {
@ -43,7 +43,7 @@ class FakePlayer(
// Create a fake connection for our fake player. // Create a fake connection for our fake player.
val connection = FakeConnection(PacketFlow.SERVERBOUND) val connection = FakeConnection(PacketFlow.SERVERBOUND)
FakePlayerList.placeNewPlayer(minecraftServer.playerList, minecraftServer, connection, instance) minecraftServer.playerList.placeFakePlayer(connection, instance)
instance.respawn() instance.respawn()
instance.teleportTo(serverLevel, location.x, location.y, location.z, location.yaw, location.pitch) instance.teleportTo(serverLevel, location.x, location.y, location.z, location.yaw, location.pitch)
@ -119,7 +119,9 @@ class FakePlayer(
} }
override fun kill() { 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) { 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.Future
import io.netty.util.concurrent.GenericFutureListener import io.netty.util.concurrent.GenericFutureListener
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.network.protocol.Packet import net.minecraft.network.protocol.Packet
import net.minecraft.server.MinecraftServer import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerGamePacketListenerImpl import net.minecraft.server.network.ServerGamePacketListenerImpl
@ -18,10 +17,7 @@ class FakePlayerConnection(
override fun send(packet: Packet<*>, listener: GenericFutureListener<out Future<in Void>>?) {} override fun send(packet: Packet<*>, listener: GenericFutureListener<out Future<in Void>>?) {}
override fun disconnect(message: Component) { override fun disconnect(message: Component) {
if (message is TranslatableComponent && (message.key.equals("multiplayer.disconnect.idling") || message.equals("multiplayer.disconnect.duplicate_login"))) player.kill()
{
player.kill()
}
} }
override fun tick() { override fun tick() {

View File

@ -1,23 +1,29 @@
package nl.kallestruik.dtweaks.fakeplayer package nl.kallestruik.dtweaks.fakeplayer
import com.destroystokyo.paper.PaperConfig
import com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent import com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent
import com.mojang.authlib.GameProfile import com.mojang.authlib.GameProfile
import com.mojang.datafixers.util.Either import com.mojang.datafixers.util.Either
import com.mojang.serialization.Dynamic import com.mojang.serialization.Dynamic
import io.netty.buffer.Unpooled 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.CompoundTag
import net.minecraft.nbt.NbtOps import net.minecraft.nbt.NbtOps
import net.minecraft.nbt.Tag
import net.minecraft.network.Connection import net.minecraft.network.Connection
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.protocol.game.* import net.minecraft.network.protocol.game.*
import net.minecraft.resources.ResourceKey import net.minecraft.resources.ResourceKey
import net.minecraft.server.MinecraftServer import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.*
import net.minecraft.server.level.ChunkHolder.ChunkLoadingFailure 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.network.ServerGamePacketListenerImpl
import net.minecraft.server.players.GameProfileCache import net.minecraft.server.players.GameProfileCache
import net.minecraft.server.players.PlayerList import net.minecraft.server.players.PlayerList
import net.minecraft.tags.TagNetworkSerialization
import net.minecraft.world.level.ChunkPos import net.minecraft.world.level.ChunkPos
import net.minecraft.world.level.GameRules import net.minecraft.world.level.GameRules
import net.minecraft.world.level.Level 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.chunk.ChunkAccess
import net.minecraft.world.level.dimension.DimensionType import net.minecraft.world.level.dimension.DimensionType
import nl.kallestruik.dlib.ReflectionUtil import nl.kallestruik.dlib.ReflectionUtil
import nl.kallestruik.dtweaks.DTweaks
import org.apache.logging.log4j.Logger
import org.bukkit.Bukkit 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.bukkit.entity.Player
import org.spigotmc.event.player.PlayerSpawnLocationEvent import org.spigotmc.event.player.PlayerSpawnLocationEvent
import java.util.* import java.util.*
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.function.Consumer
object FakePlayerList { 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 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.isRealPlayer = true // Paper - Chunk priority
player.networkManager = connection // Paper player.networkManager = connection // Paper
@ -139,7 +312,7 @@ object FakePlayerList {
val pos = ChunkPos(chunkX, chunkZ) val pos = ChunkPos(chunkX, chunkZ)
val playerChunkMap = worldServer.getChunkSource().chunkMap val playerChunkMap = worldServer.getChunkSource().chunkMap
val distanceManager: DistanceManager = playerChunkMap.distanceManager 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 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) 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 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.DTweaks
import nl.kallestruik.dtweaks.fakeplayer.FakePlayer import nl.kallestruik.dtweaks.fakeplayer.FakePlayer
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftEntity import org.bukkit.craftbukkit.v1_19_R1.entity.CraftEntity
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer
import org.bukkit.scheduler.BukkitRunnable
import org.bukkit.scheduler.BukkitTask
import java.util.function.Predicate
/* /*
@ -24,12 +15,6 @@ import java.util.function.Predicate
class FakePlayerManager( class FakePlayerManager(
val plugin: DTweaks, val plugin: DTweaks,
) { ) {
init {
// Tick all fake players.
FakePlayerTickTask().runTaskTimer(plugin, 10, 10)
}
fun getPlayerByName(name: String): FakePlayer? { fun getPlayerByName(name: String): FakePlayer? {
val player = Bukkit.getPlayer(name) val player = Bukkit.getPlayer(name)
if (player == null || !player.isOnline) return null if (player == null || !player.isOnline) return null
@ -57,166 +42,4 @@ class FakePlayerManager(
fakePlayer.kill() 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.fakeplayer.FakePlayer
import nl.kallestruik.dtweaks.managers.FakePlayerManager import nl.kallestruik.dtweaks.managers.FakePlayerManager
import nl.kallestruik.dtweaks.tweaks.ITweak import nl.kallestruik.dtweaks.tweaks.ITweak
import org.bukkit.Material import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.HandlerList import org.bukkit.event.HandlerList

View File

@ -1,20 +1,12 @@
package nl.kallestruik.dtweaks.tweaks.mobtweaks 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.managers.NoSpawnZoneManager
import nl.kallestruik.dtweaks.tweaks.ITweak 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.EventHandler
import org.bukkit.event.HandlerList import org.bukkit.event.HandlerList
import org.bukkit.event.Listener import org.bukkit.event.Listener
import org.bukkit.event.entity.CreatureSpawnEvent 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 org.bukkit.plugin.java.JavaPlugin
import java.util.concurrent.atomic.AtomicReference
class NoSpawnZones( class NoSpawnZones(
private val plugin: JavaPlugin, 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.ai.memory.MemoryModuleType
import net.minecraft.world.entity.schedule.Activity import net.minecraft.world.entity.schedule.Activity
import nl.kallestruik.dtweaks.tweaks.ITweak 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.entity.Villager
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.HandlerList import org.bukkit.event.HandlerList