Port to 1.20 and update CI/CD

kalle 2023-06-28 21:17:07 +02:00
parent 247159970c
commit 8dca36983c
22 changed files with 103 additions and 1337 deletions

View File

@ -0,0 +1,33 @@
name: "Build and publish releases"
on:
push:
tag: "v*"
jobs:
release:
if: github.repository_owner == 'mc'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: github.com/actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: "build"
run: |
./gradlew build
- name: "move releases"
run: |
mkdir release
mv build/libs/*.jar release
- name: "publish release"
uses: https://code.forgejo.org/actions/forgejo-release@v1
with:
direction: upload
release-dir: release
token: ${{ secrets.TOKEN }}

View File

@ -1,14 +1,14 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
kotlin("jvm") version "1.7.0-RC" kotlin("jvm") version "1.8.22"
id("com.github.johnrengelman.shadow") version "7.1.2" id("com.github.johnrengelman.shadow") version "8.1.1"
id("xyz.jpenilla.run-paper") version "1.0.6" // Adds runServer and runMojangMappedServer tasks for testing id("xyz.jpenilla.run-paper") version "2.1.0" // Adds runServer and runMojangMappedServer tasks for testing
id("io.papermc.paperweight.userdev") version "1.3.7" id("io.papermc.paperweight.userdev") version "1.5.5"
} }
group = "nl.kallestruik" group = "nl.kallestruik"
version = "1.0" version = "1.1"
repositories { repositories {
mavenCentral() mavenCentral()
@ -17,16 +17,16 @@ repositories {
maven("https://papermc.io/repo/repository/maven-public/") maven("https://papermc.io/repo/repository/maven-public/")
maven("https://repo.aikar.co/content/groups/aikar/") maven("https://repo.aikar.co/content/groups/aikar/")
maven("https://repo.dmulloy2.net/repository/public/") maven("https://repo.dmulloy2.net/repository/public/")
maven("https://git.kallestruik.nl/api/packages/mc/maven/")
} }
dependencies { dependencies {
paperDevBundle("1.19-R0.1-SNAPSHOT") paperweight.paperDevBundle("1.20-R0.1-SNAPSHOT")
implementation("co.aikar:acf-paper:0.5.0-SNAPSHOT") implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT")
compileOnly("com.comphenix.protocol:ProtocolLib:4.6.0") compileOnly("com.comphenix.protocol:ProtocolLib:5.0.0")
compileOnly(kotlin("stdlib-jdk8"))
compileOnly("nl.kallestruik:DLib:1.4.4") compileOnly("nl.kallestruik:DLib:1.5.1")
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")
@ -58,7 +58,7 @@ tasks {
kotlinOptions.javaParameters = true kotlinOptions.javaParameters = true
} }
withType<KotlinCompile> { withType<KotlinCompile> {
kotlinOptions.jvmTarget = "16" kotlinOptions.jvmTarget = "17"
} }
processResources { processResources {

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -1,25 +0,0 @@
package nl.kallestruik.dtweaks
import org.bukkit.Material
enum class BundleColor(
val modelData: Int,
val dye: Material,
) {
BLACK(0, Material.BLACK_DYE),
BLUE(1, Material.BLUE_DYE),
BROWN(2, Material.BROWN_DYE),
CYAN(3, Material.CYAN_DYE),
GRAY(4, Material.GRAY_DYE),
GREEN(5, Material.GREEN_DYE),
LIGHT_BLUE(6, Material.LIGHT_BLUE_DYE),
LIGHT_GRAY(7, Material.LIGHT_GRAY_DYE),
LIME(8, Material.LIME_DYE),
MAGENTA(9, Material.MAGENTA_DYE),
ORANGE(10, Material.ORANGE_DYE),
PINK(11, Material.PINK_DYE),
PURPLE(12, Material.PURPLE_DYE),
RED(13, Material.RED_DYE),
WHITE(14, Material.WHITE_DYE),
YELLOW(15, Material.YELLOW_DYE)
}

View File

@ -1,15 +0,0 @@
package nl.kallestruik.dtweaks
import org.bukkit.Material
enum class BundleVariant(
val modelDataStart: Int,
val maxWeight: Int,
val material: Material?,
) {
NORMAL(0, 1 * 64, null),
IRON(100, 2 * 64, Material.IRON_INGOT),
GOLD(200, 4 * 64, Material.GOLD_INGOT),
DIAMOND(300, 6 * 64, Material.DIAMOND),
NETHERITE(400, 8 * 64, Material.NETHERITE_INGOT)
}

View File

@ -5,7 +5,6 @@ import co.aikar.commands.PaperCommandManager
import nl.kallestruik.dlib.DUtil import nl.kallestruik.dlib.DUtil
import nl.kallestruik.dlib.MathHelper import nl.kallestruik.dlib.MathHelper
import nl.kallestruik.dlib.ReflectionUtil import nl.kallestruik.dlib.ReflectionUtil
import nl.kallestruik.dtweaks.commands.CommandBundle
import nl.kallestruik.dtweaks.commands.CommandPlayer import nl.kallestruik.dtweaks.commands.CommandPlayer
import nl.kallestruik.dtweaks.commands.CommandSpawnzones import nl.kallestruik.dtweaks.commands.CommandSpawnzones
import nl.kallestruik.dtweaks.commands.CommandToggletrample import nl.kallestruik.dtweaks.commands.CommandToggletrample
@ -25,6 +24,7 @@ import java.util.*
class DTweaks: JavaPlugin() { class DTweaks: JavaPlugin() {
companion object { companion object {
lateinit var plugin: DTweaks
private lateinit var random: Random private lateinit var random: Random
private lateinit var tweakManager: TweakManager private lateinit var tweakManager: TweakManager
private lateinit var util: DUtil private lateinit var util: DUtil
@ -34,13 +34,13 @@ class DTweaks: JavaPlugin() {
private lateinit var commandManager: PaperCommandManager private lateinit var commandManager: PaperCommandManager
private lateinit var fakePlayerManager: FakePlayerManager private lateinit var fakePlayerManager: FakePlayerManager
private lateinit var noSpawnZoneManager: NoSpawnZoneManager private lateinit var noSpawnZoneManager: NoSpawnZoneManager
// private lateinit var pocketDimensionManager: PocketDimensionManager
} }
override fun onEnable() { override fun onEnable() {
/* /*
* Initialize stuff * Initialize stuff
*/ */
plugin = this
random = Random() random = Random()
tweakManager = TweakManager(this) tweakManager = TweakManager(this)
util = DUtil(random) util = DUtil(random)
@ -50,23 +50,18 @@ class DTweaks: JavaPlugin() {
commandManager = PaperCommandManager(this) commandManager = PaperCommandManager(this)
fakePlayerManager = FakePlayerManager(this) fakePlayerManager = FakePlayerManager(this)
noSpawnZoneManager = NoSpawnZoneManager() noSpawnZoneManager = NoSpawnZoneManager()
// pocketDimensionManager = PocketDimensionManager(mathHelper)
// Enable brigadier support on ACF // Enable brigadier support on ACF
commandManager.enableUnstableAPI("brigadier") commandManager.enableUnstableAPI("brigadier")
registerCommandConditions() registerCommandConditions()
val betterBundles = BetterBundles(this)
/* /*
* Commands * Commands
*/ */
// commandManager.registerCommand(CommandMobcaps(reflectionUtil)) // commandManager.registerCommand(CommandMobcaps(reflectionUtil))
commandManager.registerCommand(CommandPlayer(fakePlayerManager)) commandManager.registerCommand(CommandPlayer(fakePlayerManager))
// commandManager.registerCommand(CommandPocketdim(pocketDimensionManager))
commandManager.registerCommand(CommandToggletrample(trampleManager)) commandManager.registerCommand(CommandToggletrample(trampleManager))
commandManager.registerCommand(CommandBundle(betterBundles))
commandManager.registerCommand(CommandSpawnzones(noSpawnZoneManager)) commandManager.registerCommand(CommandSpawnzones(noSpawnZoneManager))
/* /*
@ -75,7 +70,6 @@ class DTweaks: JavaPlugin() {
tweakManager.loadFromFile(File(dataFolder, Const.TWEAK_STATE_FILE_NAME)) tweakManager.loadFromFile(File(dataFolder, Const.TWEAK_STATE_FILE_NAME))
trampleManager.loadFromFile(File(dataFolder, Const.TRAMPLE_ENABLED_FILE_NAME)) trampleManager.loadFromFile(File(dataFolder, Const.TRAMPLE_ENABLED_FILE_NAME))
noSpawnZoneManager.loadFromFile(File(dataFolder, Const.NO_SPAWN_ZONE_FILE_NAME)) noSpawnZoneManager.loadFromFile(File(dataFolder, Const.NO_SPAWN_ZONE_FILE_NAME))
// pocketDimensionManager.loadData()
/* /*
* Crafting tweaks * Crafting tweaks
@ -113,12 +107,8 @@ class DTweaks: JavaPlugin() {
*/ */
tweakManager.registerTweak(ArmorStandArmorSwapping(this)) tweakManager.registerTweak(ArmorStandArmorSwapping(this))
// tweakManager.registerTweak(CarpetBlockPlacingProtocol(this, mathHelper)) // tweakManager.registerTweak(CarpetBlockPlacingProtocol(this, mathHelper))
tweakManager.registerTweak(betterBundles)
// tweakManager.registerTweak(DyeableNetherite(this))
tweakManager.registerTweak(FakePlayers(fakePlayerManager, this)) tweakManager.registerTweak(FakePlayers(fakePlayerManager, this))
tweakManager.registerTweak(Hammers(this))
tweakManager.registerTweak(NoMelting(this)) tweakManager.registerTweak(NoMelting(this))
// tweakManager.registerTweak(SpaceTimePockets(this, pocketDimensionManager))
/* /*
* Mob Tweaks * Mob Tweaks
@ -126,7 +116,6 @@ class DTweaks: JavaPlugin() {
tweakManager.registerTweak(NoCreeperGrief(this)) tweakManager.registerTweak(NoCreeperGrief(this))
tweakManager.registerTweak(NoDoorBreaking(this)) tweakManager.registerTweak(NoDoorBreaking(this))
tweakManager.registerTweak(NoEndermanGrief(this)) tweakManager.registerTweak(NoEndermanGrief(this))
tweakManager.registerTweak(VillagerInfo(this))
tweakManager.registerTweak(NoSpawnZones(this, noSpawnZoneManager)) tweakManager.registerTweak(NoSpawnZones(this, noSpawnZoneManager))
} }
@ -137,7 +126,6 @@ class DTweaks: JavaPlugin() {
tweakManager.saveToFile(File(dataFolder, Const.TWEAK_STATE_FILE_NAME)) tweakManager.saveToFile(File(dataFolder, Const.TWEAK_STATE_FILE_NAME))
trampleManager.saveToFile(File(dataFolder, Const.TRAMPLE_ENABLED_FILE_NAME)) trampleManager.saveToFile(File(dataFolder, Const.TRAMPLE_ENABLED_FILE_NAME))
noSpawnZoneManager.saveToFile() noSpawnZoneManager.saveToFile()
// pocketDimensionManager.saveData()
} }
private fun registerCommandConditions() { private fun registerCommandConditions() {

View File

@ -1,40 +0,0 @@
package nl.kallestruik.dtweaks.commands
import co.aikar.commands.BaseCommand
import co.aikar.commands.annotation.*
import nl.kallestruik.dtweaks.BundleColor
import nl.kallestruik.dtweaks.BundleVariant
import nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks.BetterBundles
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.persistence.PersistentDataType
@CommandAlias("bundle")
@Conditions("tweakEnabled:tweak=BetterBundles")
class CommandBundle(
private val betterBundles: BetterBundles,
): BaseCommand() {
@Subcommand("variant")
fun onVariant(sender: Player, variant: BundleVariant) {
val bundle = sender.inventory.itemInMainHand
if (bundle.type != Material.BUNDLE)
return
val bundleMeta = bundle.itemMeta
bundleMeta.persistentDataContainer.set(betterBundles.VARIANT_KEY, PersistentDataType.STRING, variant.toString())
bundle.itemMeta = bundleMeta
betterBundles.updateBundle(bundle)
}
@Subcommand("color")
fun onVariant(sender: Player, color: BundleColor) {
val bundle = sender.inventory.itemInMainHand
if (bundle.type != Material.BUNDLE)
return
val bundleMeta = bundle.itemMeta
bundleMeta.persistentDataContainer.set(betterBundles.COLOR_KEY, PersistentDataType.STRING, color.toString())
bundle.itemMeta = bundleMeta
betterBundles.updateBundle(bundle)
}
}

View File

@ -1,25 +0,0 @@
//package nl.kallestruik.dtweaks.commands
//
//import co.aikar.commands.BaseCommand
//import co.aikar.commands.annotation.CommandAlias
//import co.aikar.commands.annotation.Conditions
//import co.aikar.commands.annotation.Subcommand
//import nl.kallestruik.dtweaks.managers.PocketDimensionManager
//import org.bukkit.entity.Player
//
//@CommandAlias("pocketdim")
//@Conditions("tweakEnabled:tweak=SpaceTimePockets")
//class CommandPocketdim(
// private val pocketDimensionManager: PocketDimensionManager
//): BaseCommand() {
//
// @Subcommand("create")
// fun onCreate(sender: Player) {
// pocketDimensionManager.createPocketForPlayer(sender)
// }
//
// @Subcommand("tp")
// fun onTp(sender: Player) {
// pocketDimensionManager.teleportPlayerIntoPocket(sender, sender.uniqueId)
// }
//}

View File

@ -1,5 +1,8 @@
package nl.kallestruik.dtweaks.fakeplayer package nl.kallestruik.dtweaks.fakeplayer
import io.netty.channel.ChannelHandler
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelPipeline
import io.netty.channel.embedded.EmbeddedChannel import io.netty.channel.embedded.EmbeddedChannel
import net.minecraft.network.Connection import net.minecraft.network.Connection
import net.minecraft.network.protocol.PacketFlow import net.minecraft.network.protocol.PacketFlow
@ -10,10 +13,31 @@ class FakeConnection(
): Connection(packetFlow) { ): Connection(packetFlow) {
init { init {
this.channel = EmbeddedChannel() this.channel = FakeChannel()
} }
override fun setReadOnly() {} override fun setReadOnly() {}
override fun handleDisconnection() {} override fun handleDisconnection() {}
// We need protocol lib to not get very confused with our fake connection,
// so we need to create a fake netty pipeline.
class FakeChannel: EmbeddedChannel() {
override fun pipeline(): ChannelPipeline {
val pipeline = newChannelPipeline()
return pipeline
.addFirst("encoder", NoopChannelHandler())
.addFirst("decoder", NoopChannelHandler())
}
}
class NoopChannelHandler : ChannelHandler {
override fun handlerAdded(ctx: ChannelHandlerContext?) {}
override fun handlerRemoved(ctx: ChannelHandlerContext?) {}
@Deprecated("Deprecated in Java")
override fun exceptionCaught(ctx: ChannelHandlerContext?, cause: Throwable?) {}
}
} }

View File

@ -12,16 +12,17 @@ import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.damagesource.DamageSource import net.minecraft.world.damagesource.DamageSource
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 nl.kallestruik.dtweaks.DTweaks
import org.bukkit.Bukkit
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld import org.bukkit.craftbukkit.v1_20_R1.CraftWorld
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
class FakePlayer( class FakePlayer(
server: MinecraftServer, server: MinecraftServer,
private val serverLevel: ServerLevel, private val serverLevel: ServerLevel,
gameProfile: GameProfile gameProfile: GameProfile
): ServerPlayer(server, serverLevel, gameProfile, null) { ): ServerPlayer(server, serverLevel, gameProfile) {
val locale = "en_US" val locale = "en_US"
companion object { companion object {
@ -31,7 +32,7 @@ class FakePlayer(
// Get the world // Get the world
val serverLevel = (location.world as CraftWorld).handle val serverLevel = (location.world as CraftWorld).handle
// Get the game profile from the cache (or retrieve it if it is not cached) // Get the game profile from the cache (or retrieve it if it is not cached)
var gameProfile = minecraftServer.profileCache.get(name).takeIf { it.isPresent }?.get() ?: return null var gameProfile = minecraftServer.profileCache?.get(name).takeIf { it?.isPresent == true }?.get() ?: return null
if (gameProfile.properties.containsKey("textures")) { if (gameProfile.properties.containsKey("textures")) {
val result = AtomicReference<GameProfile>() val result = AtomicReference<GameProfile>()
SkullBlockEntity.updateGameprofile(gameProfile, result::set) SkullBlockEntity.updateGameprofile(gameProfile, result::set)
@ -43,14 +44,15 @@ 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)
minecraftServer.playerList.placeFakePlayer(connection, instance)
instance.respawn() val bukkitPlayer = instance.bukkitEntity
instance.teleportTo(serverLevel, location.x, location.y, location.z, location.yaw, location.pitch)
instance.dead = false Bukkit.getScheduler().runTaskLater(DTweaks.plugin, Runnable {
instance.heal(instance.maxHealth) bukkitPlayer.spigot().respawn()
instance.unsetRemoved() bukkitPlayer.teleport(location)
instance.maxUpStep = 0.6F }, 0)
minecraftServer.playerList.placeNewPlayer(connection, instance)
minecraftServer.playerList.broadcastAll( minecraftServer.playerList.broadcastAll(
ClientboundRotateHeadPacket( ClientboundRotateHeadPacket(
@ -62,59 +64,6 @@ class FakePlayer(
instance.entityData.set(DATA_PLAYER_MODE_CUSTOMISATION, 0x7f) instance.entityData.set(DATA_PLAYER_MODE_CUSTOMISATION, 0x7f)
return instance return instance
// (DTweaks.reflectionUtil.getValueFromField(
// serverConnection!!,
// "connectedChannels"
// ) as MutableList<NetworkManager?>).add(connection)
//
// // Connect the fake player to the server using the fake connection.
// FakePlayerList.a(minecraftServer.playerList, connection, instance)
//
// // Check if the fake player is not yet in the correct world.
// if (instance.world.dimensionKey != worldServer.dimensionKey) {
// // Store the old world of the fake player.
// val old_world = instance.world as WorldServer
// // Remove the fake player from the old world.
// old_world.removePlayer(instance)
// // Make the fake player not be dead.
// instance.dead = false
// // Create the fake player in the new world.
// worldServer.addEntity(instance)
// // Spawn the fake player in the new world.
// instance.spawnIn(worldServer)
// // Move the fake player to the new world for the server.
// minecraftServer.playerList.moveToWorld(instance, old_world, true, null, false)
// // requestTeleport(x, y, z, yaw, pitch)
// // Request the teleport from the fake player.
// instance.playerConnection.a(x, y, z, yaw.toFloat(), pitch.toFloat())
// // Set the fake player's world to the new world.
// instance.playerInteractManager.world = worldServer
// instance.teleportTo(worldServer, BlockPosition(x, y, z))
// }
//
// /// Set the fake players health to max.
// instance.health = 20.0f
// // Make the fake player not be dead.
// instance.dead = false
// // a == requestTeleport
// // Request the teleport from the fake player.
// instance.playerConnection.a(x, y, z, yaw.toFloat(), pitch.toFloat())
// // G == stepHeight
// // Set the fake players step height to 0.6 (The normal value).
// instance.G = 0.6f
// // Set the fake players gamemode to survival.
// playerInteractManager.gameMode = EnumGamemode.SURVIVAL
// // Tell everyone in the world about the fake player and where he is.
// minecraftServer.playerList.a(
// PacketPlayOutEntityHeadRotation(instance, (instance.yaw * 256 / 360).toByte()),
// instance.world.dimensionKey
// )
// minecraftServer.playerList.a(PacketPlayOutEntityTeleport(instance), instance.world.dimensionKey)
// // Move the fake player for the worlds chunk provider.
// instance.worldServer.getChunkProvider().movePlayer(instance)
// // bp == PLAYER_MODEL_PARTS
// instance.datawatcher.set<Byte>(bj, 0x7f.toByte()) // show all model layers (incl. capes)
} }
} }

View File

@ -2,6 +2,7 @@ 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.PacketSendListener
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.protocol.Packet import net.minecraft.network.protocol.Packet
import net.minecraft.server.MinecraftServer import net.minecraft.server.MinecraftServer
@ -13,15 +14,10 @@ class FakePlayerConnection(
connection: FakeConnection, connection: FakeConnection,
player: FakePlayer player: FakePlayer
): ServerGamePacketListenerImpl(minecraftServer, connection, player) { ): ServerGamePacketListenerImpl(minecraftServer, connection, player) {
override fun send(packetIn: Packet<*>?) {} override fun send(packetIn: Packet<*>) {}
override fun send(packet: Packet<*>, listener: GenericFutureListener<out Future<in Void>>?) {} override fun send(packet: Packet<*>, callbacks: PacketSendListener?) {}
override fun disconnect(message: Component) { override fun disconnect(message: Component) {
player.kill() player.kill()
} }
override fun tick() {
println("Tick for ${player.name}")
super.tick()
}
} }

View File

@ -1,338 +1,12 @@
package nl.kallestruik.dtweaks.fakeplayer package nl.kallestruik.dtweaks.fakeplayer
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.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.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.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.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
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 org.bukkit.Bukkit
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
object FakePlayerList { object FakePlayerList {
fun PlayerList.placeFakePlayer(connection: Connection, player: ServerPlayer) { 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
player.loginTime = System.currentTimeMillis() // Paper
val gameProfile: GameProfile = player.getGameProfile()
val userCache: GameProfileCache = server.getProfileCache()
val optional = userCache[gameProfile.id]
var s: String? = optional.map { obj: GameProfile -> obj.name }.orElse(gameProfile.name)
userCache.add(gameProfile)
val nbtTagCompound: CompoundTag? = playerList.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: ResourceKey<Level> = 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"]
)
)
dataResult.result().orElse(Level.OVERWORLD)
} else {
Level.OVERWORLD
}
var worldServer: ServerLevel = server.getLevel(resourceKey) ?: server.overworld()
if (nbtTagCompound == null) player.fudgeSpawnLocation(worldServer) // Paper - only move to spawn on first login, otherwise, stay where you are....
player.setLevel(worldServer)
// Spigot start - spawn location event
val spawnPlayer: Player = player.bukkitEntity
val ev: PlayerSpawnLocationEvent =
PlayerInitialSpawnEvent(spawnPlayer, spawnPlayer.location) // Paper use our duplicate event
Bukkit.getServer().pluginManager.callEvent(ev)
val loc = ev.spawnLocation
worldServer = (loc.world as CraftWorld).handle
player.spawnIn(worldServer)
player.gameMode.setLevel(player.level as ServerLevel)
// Paper start - set raw so we aren't fully joined to the world (not added to chunk or world)
// Paper start - set raw so we aren't fully joined to the world (not added to chunk or world)
player.setPosRaw(loc.x, loc.y, loc.z)
player.setRot(loc.yaw, loc.pitch)
// Paper end
// Spigot end
// CraftBukkit - Moved message to after join
// PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ());
// Paper end
// Spigot end
// CraftBukkit - Moved message to after join
// PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ());
val worlddata = worldServer.getLevelData()
player.loadGameTypes(nbtTagCompound)
val playerconnection = FakePlayerConnection(server, connection, player)
val gamerules = worldServer.gameRules
player.bukkitEntity.sendSupportedChannels() // CraftBukkit
player.stats.markAllDirty()
player.recipeBook.sendInitialRecipeBook(player)
playerList.updateEntireScoreboard(worldServer.scoreboard, player)
server.invalidateStatus()
// Paper start - async load spawn in chunk
// Paper start - async load spawn in chunk
val finalWorldserver = worldServer
val chunkX = loc.blockX shr 4
val chunkZ = loc.blockZ shr 4
val pos = ChunkPos(chunkX, chunkZ)
val playerChunkMap = worldServer.getChunkSource().chunkMap
val distanceManager: DistanceManager = playerChunkMap.distanceManager
// 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)
postChunkLoadJoin.isAccessible = true
postChunkLoadJoin.invoke(playerList, player, finalWorldserver, connection, playerconnection,
nbtTagCompound, "127.0.0.1", lastKnownName)
// worldServer.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, false)
// .thenApply { chunk: Either<ChunkAccess, ChunkLoadingFailure> -> // Paper - Chunk priority
// val updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong())
// if (updatingChunk != null) {
// return@thenApply updatingChunk.entityTickingChunkFuture
// } else {
// return@thenApply CompletableFuture.completedFuture(
// chunk
// )
// }
// }.thenAccept {
//
// }
} }
} }

View File

@ -4,8 +4,8 @@ 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_19_R1.entity.CraftEntity import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer
/* /*

View File

@ -1,108 +0,0 @@
//package nl.kallestruik.dtweaks.managers
//
//import nl.kallestruik.dlib.MathHelper
//import nl.kallestruik.dtweaks.spacetimepockets.SpaceTimePocketChunkGenerator
//import org.bukkit.*
//import org.bukkit.entity.Player
//import java.util.*
//
//class PocketDimensionManager(
// private val mathHelper: MathHelper
//) {
// val pocketDimension: World = WorldCreator.name("space-time-pockets").generator(SpaceTimePocketChunkGenerator()).createWorld()!!
// private val data = HashMap<UUID, PocketData>()
// private var lastCreatedPocket = -1
//
// fun loadData() {
// //TODO: Load data from data file on disk.
// }
//
// fun saveData() {
// //TODO: Save data to file on disk.
// }
//
// fun teleportPlayerIntoPocket(player: Player, pocketOwner: UUID) {
// var pocketData = data[pocketOwner]
// if (pocketData == null) pocketData = if (player.uniqueId == pocketOwner) {
// createPocketForPlayer(player)
// } else return
// player.teleport(
// Location(
// pocketDimension, (pocketData.startX + 9).toDouble(), 128.0,
// (pocketData.startZ + 9).toDouble()
// )
// )
// }
//
// fun createPocketForPlayer(player: Player): PocketData {
// // Find a spot
// val point = findNextFree()
//
// // Load the chunks
// for (x in 0..2) {
// for (y in 0..2) {
// pocketDimension.loadChunk(point.x / 16 + x, point.z / 16 + y)
// }
// }
//
// // Build the box
// for (x in 0..17) {
// for (z in 0..17) {
// for (y in 0..255) {
// if (x == 0 || y == 0 || z == 0 || x == 17 || y == 255 || z == 17) {
// pocketDimension.getBlockAt(point.x + x, y, point.z + z).type = Material.BLACK_CONCRETE
// }
// }
// }
// }
//
// // Create the spawning platform
// pocketDimension.getBlockAt(point.x + 8, 127, point.z + 8).type = Material.STONE
// pocketDimension.getBlockAt(point.x + 8, 127, point.z + 9).type = Material.STONE
// pocketDimension.getBlockAt(point.x + 9, 127, point.z + 8).type = Material.STONE
// pocketDimension.getBlockAt(point.x + 9, 127, point.z + 9).type = Material.STONE
//
// // Unload the chunks
// for (x in 0..2) {
// for (y in 0..2) {
// pocketDimension.unloadChunk(point.x / 16 + x, point.z / 16 + y)
// }
// }
// val pocketData = PocketData(player.uniqueId, point.x, point.z, ArrayList())
// data[player.uniqueId] = pocketData
// return pocketData
// }
//
// private fun findNextFree(): Point {
// while (true) {
// lastCreatedPocket++
// val toCheck = getXYForIndex(lastCreatedPocket)
// val chunk = pocketDimension.getChunkAt(
// Location(
// pocketDimension,
// toCheck.x.toDouble(), 0.0, toCheck.z.toDouble()
// )
// )
// val corner = chunk.getBlock(mathHelper.chunkAbs(toCheck.x % 16), 0, mathHelper.chunkAbs(toCheck.z % 16))
// if (corner.type == Material.AIR) {
// return toCheck
// }
// }
// }
//
// private fun getXYForIndex(index: Int): Point {
// // Space the pockets 256 blocks (16 chunks) from each other with each pocket being 16 blocks (and two for walls)
// // Also subtract 1 from each point so the interior is chunk aligned.
// val x = (256 + 16) * (index % 1000) - 1
// val z = (256 + 16) * (index / 1000) - 1
// return Point(x, z)
// }
//
// class PocketData(var owner: UUID, var startX: Int, var startZ: Int, var queuedGateways: ArrayList<GatewayData?>)
//
// class GatewayData
//
// class Point(var x: Int, var y: Int, var z: Int) {
// constructor(x: Int, z: Int) : this(x, 0, z) {}
// }
//}

View File

@ -1,27 +0,0 @@
//package nl.kallestruik.dtweaks.spacetimepockets
//
//import org.bukkit.World
//import org.bukkit.block.Biome
//import org.bukkit.craftbukkit.v1_18_R1.generator.CraftChunkData
//import org.bukkit.generator.ChunkGenerator
//import java.util.*
//
//class SpaceTimePocketChunkGenerator: ChunkGenerator() {
//
// override fun generateChunkData(
// world: World,
// random: Random,
// x: Int,
// z: Int,
// biome: BiomeGrid
// ): ChunkData {
// for (cx in 0..15) {
// for (cz in 0..15) {
// for (cy in 0..264) {
// biome.setBiome(cx, cy, cz, Biome.THE_VOID)
// }
// }
// }
// return CraftChunkData(world)
// }
//}

View File

@ -1,345 +0,0 @@
package nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks
import com.google.common.base.Preconditions
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.text.format.TextDecoration
import nl.kallestruik.dtweaks.BundleColor
import nl.kallestruik.dtweaks.BundleVariant
import nl.kallestruik.dtweaks.DTweaks
import nl.kallestruik.dtweaks.tweaks.ITweak
import org.bukkit.Bukkit
import org.bukkit.Keyed
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.event.EventHandler
import org.bukkit.event.HandlerList
import org.bukkit.event.Listener
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.PrepareItemCraftEvent
import org.bukkit.inventory.*
import org.bukkit.inventory.meta.BundleMeta
import org.bukkit.persistence.PersistentDataType
class BetterBundles(
private val plugin: DTweaks
): ITweak, Listener {
override fun getIdentifier(): String = "BetterBundles"
override fun getCategories(): List<String> = listOf("miscellaneous", "survival")
private val recipeKeys = mutableListOf<NamespacedKey>()
override fun onEnable() {
plugin.server.pluginManager.registerEvents(this, plugin)
for (color in BundleColor.values()) {
val result = ItemStack(Material.BUNDLE)
val resultMeta = result.itemMeta
resultMeta.setCustomModelData(BundleVariant.NORMAL.modelDataStart + color.modelData)
resultMeta.persistentDataContainer.set(COLOR_KEY, PersistentDataType.STRING, color.toString())
result.itemMeta = resultMeta
val key = NamespacedKey(plugin, "${color.name.lowercase()}_color_bundle")
recipeKeys.add(key)
addDyeRecipe(key, color.dye, result)
}
for (variant in BundleVariant.values()) {
if (variant.material == null)
continue
val result = ItemStack(Material.BUNDLE)
val resultMeta = result.itemMeta
resultMeta.setCustomModelData(variant.modelDataStart + BundleColor.BROWN.modelData)
resultMeta.persistentDataContainer.set(VARIANT_KEY, PersistentDataType.STRING, variant.toString())
result.itemMeta = resultMeta
val key = NamespacedKey(plugin, "${variant.name.lowercase()}_variant_bundle")
recipeKeys.add(key)
addUpgradeRecipe(key, variant.material, result)
}
}
override fun onDisable() {
HandlerList.unregisterAll(this)
for (key in recipeKeys) {
plugin.server.removeRecipe(key)
}
recipeKeys.clear()
}
val VARIANT_KEY = NamespacedKey(plugin, "variant")
val COLOR_KEY = NamespacedKey(plugin, "color")
private fun addDyeRecipe(key: NamespacedKey, dye: Material, result: ItemStack) {
val recipe = ShapelessRecipe(key, result)
recipe.addIngredient(dye)
recipe.addIngredient(Material.BUNDLE)
plugin.server.addRecipe(recipe)
}
private fun addUpgradeRecipe(key: NamespacedKey, material: Material, result: ItemStack) {
val recipe = ShapedRecipe(key, result)
recipe.shape("MMM", "MBM", "MMM")
recipe.setIngredient('M', material)
recipe.setIngredient('B', Material.BUNDLE)
plugin.server.addRecipe(recipe)
}
private fun isBundleRecipe(recipe: Recipe): Boolean {
return isDyeRecipe(recipe) || isVariantRecipe(recipe)
}
private fun isDyeRecipe(recipe: Recipe): Boolean {
if (recipe !is Keyed)
return false
val key = recipe.key
if (key.namespace != plugin.getNamespace())
return false
if (!key.key.endsWith("_color_bundle"))
return false
return true
}
private fun isVariantRecipe(recipe: Recipe): Boolean {
if (recipe !is Keyed)
return false
val key = recipe.key
if (key.namespace != plugin.getNamespace())
return false
if (!key.key.endsWith("_variant_bundle"))
return false
return true
}
@EventHandler
fun onCraft(event: PrepareItemCraftEvent) {
val recipe = event.recipe ?: return
if (!isBundleRecipe(recipe))
return
val inventory = event.inventory
Bukkit.getScheduler().runTask(
plugin,
Runnable {
inventory.result =
if (isDyeRecipe(recipe)) getDyeResult(recipe, inventory)
else if (isVariantRecipe(recipe)) getVariantResult(recipe, inventory)
else null
})
}
private fun getDyeResult(recipe: Recipe, inventory: CraftingInventory): ItemStack? {
val bundle = inventory.matrix?.filter { it?.type == Material.BUNDLE }?.get(0) ?: return null
val recipeResult = recipe.result
val result = bundle.clone()
val resultMeta = result.itemMeta
resultMeta.persistentDataContainer.set(
COLOR_KEY,
PersistentDataType.STRING,
recipeResult.itemMeta.persistentDataContainer.get(
COLOR_KEY,
PersistentDataType.STRING
) ?: BundleColor.BROWN.name
)
result.itemMeta = resultMeta
updateBundle(result)
return result
}
private fun getVariantResult(recipe: Recipe, inventory: CraftingInventory): ItemStack? {
val bundle = inventory.matrix?.filter { it?.type == Material.BUNDLE }?.get(0) ?: return null
val recipeResult = recipe.result
val result = bundle.clone()
val resultMeta = result.itemMeta
resultMeta.persistentDataContainer.set(
VARIANT_KEY,
PersistentDataType.STRING,
recipeResult.itemMeta.persistentDataContainer.get(
VARIANT_KEY,
PersistentDataType.STRING
) ?: BundleVariant.NORMAL.name
)
result.itemMeta = resultMeta
updateBundle(result)
return result
}
@EventHandler
fun onInventoryClick(event: InventoryClickEvent) {
if (!event.isRightClick)
return
val cursor = event.cursor ?: return
val clicked = event.currentItem ?: return
val bundle: ItemStack
val item: ItemStack
var itemIsCursor = true
if (cursor.type == Material.BUNDLE) {
bundle = cursor
item = clicked
itemIsCursor = false
} else if (clicked.type == Material.BUNDLE) {
bundle = clicked
item = cursor
} else
return
if (item.type.isAir || item.amount == 0) {
val itemStack = removeItemFromBundle(bundle) ?: return
if (itemIsCursor)
event.cursor = itemStack
else
event.currentItem = itemStack
} else
addItemToBundle(bundle, item)
event.isCancelled = true
}
private fun removeItemFromBundle(bundle: ItemStack): ItemStack? {
val meta = bundle.itemMeta as BundleMeta
if (!meta.hasItems())
return null
val itemsInBundle = mutableListOf<ItemStack>()
itemsInBundle.addAll(meta.items)
val toReturn = itemsInBundle.removeFirst()
meta.setItems(itemsInBundle)
bundle.itemMeta = meta
updateBundle(bundle)
return toReturn
}
private fun addItemToBundle(bundle: ItemStack, item: ItemStack) {
var meta = bundle.itemMeta as BundleMeta
val persistentContainer = bundle.itemMeta.persistentDataContainer
val variant = BundleVariant.valueOf(persistentContainer.get(VARIANT_KEY, PersistentDataType.STRING) ?: "NORMAL")
val currentWeight = computeWeight(meta.items)
val availableWeight = variant.maxWeight - currentWeight
val weightPerItem = getWeightPerItem(item)
val totalStackWeight = weightPerItem * item.amount
if (totalStackWeight > availableWeight) {
val toStoreAmount = availableWeight / weightPerItem
if (toStoreAmount <= 0)
return
meta = addItemToBundleProper(meta, item.asQuantity(toStoreAmount))
item.amount -= toStoreAmount
} else {
meta = addItemToBundleProper(meta, item.clone())
item.amount = 0
}
bundle.itemMeta = meta
updateBundle(bundle)
}
fun updateBundle(bundle: ItemStack) {
val meta = bundle.itemMeta as BundleMeta
val persistentContainer = meta.persistentDataContainer
val variant = BundleVariant.valueOf(persistentContainer.get(VARIANT_KEY, PersistentDataType.STRING) ?: "NORMAL")
val color = BundleColor.valueOf(persistentContainer.get(COLOR_KEY, PersistentDataType.STRING) ?: "BROWN")
val customModelData = variant.modelDataStart + color.modelData
meta.setCustomModelData(customModelData)
meta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS)
meta.lore(listOf(Component
.text("${computeWeight(meta.items)}/${variant.maxWeight}")
.color(NamedTextColor.GRAY)
.decoration(TextDecoration.ITALIC, false)))
bundle.itemMeta = meta
}
private fun computeWeight(items: List<ItemStack>): Int {
return items.sumOf { getWeight(it) }
}
private fun getWeight(item: ItemStack): Int {
return item.amount * getWeightPerItem(item)
}
private fun getWeightPerItem(item: ItemStack): Int {
// Special case for bundle nesting.
if (item.type == Material.BUNDLE) {
val meta = item.itemMeta as BundleMeta
return if (meta.hasItems())
64
else
4
}
// Calculate the right weight.
return (64 / item.maxStackSize)
}
private fun addItemToBundleProper(itemMeta: BundleMeta, itemStack: ItemStack): BundleMeta {
Preconditions.checkArgument(!itemStack.type.isAir, "item is null or air")
var leftOver = true
val items = mutableListOf<ItemStack>()
items.addAll(itemMeta.items)
for (item in itemMeta.items) {
if (item.isSimilar(itemStack)) {
if (item.amount >= item.maxStackSize)
continue
items.remove(item)
val spaceLeft = item.maxStackSize - item.amount
if (spaceLeft >= itemStack.amount) {
item.amount += itemStack.amount
itemStack.amount = 0
items.add(0, item)
leftOver = false
break
} else {
item.amount = item.maxStackSize
itemStack.amount -= spaceLeft
items.add(0, item)
}
}
}
if (leftOver)
items.add(0, itemStack)
itemMeta.setItems(items)
return itemMeta
}
}

View File

@ -4,7 +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.craftbukkit.v1_19_R1.entity.CraftPlayer import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer
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,134 +0,0 @@
package nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks
import nl.kallestruik.dtweaks.DTweaks
import nl.kallestruik.dtweaks.tweaks.ITweak
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.block.Block
import org.bukkit.block.BlockFace
import org.bukkit.event.EventHandler
import org.bukkit.event.HandlerList
import org.bukkit.event.Listener
import org.bukkit.event.block.BlockBreakEvent
import org.bukkit.inventory.*
import org.bukkit.inventory.meta.Damageable
import org.bukkit.persistence.PersistentDataType
class Hammers(
private val plugin: DTweaks
): ITweak, Listener {
override fun getIdentifier(): String = "Hammers"
override fun getCategories(): List<String> = listOf("miscellaneous", "survival")
val HAMMER_KEY = NamespacedKey(plugin, "hammer")
val diamondHammerRecipeKey = NamespacedKey(plugin, "diamond_hammer")
override fun onEnable() {
plugin.server.pluginManager.registerEvents(this, plugin)
val diamondHammer = ItemStack(Material.DIAMOND_PICKAXE)
val diamondHammerMeta = diamondHammer.itemMeta
diamondHammerMeta.persistentDataContainer.set(HAMMER_KEY, PersistentDataType.SHORT, 1)
diamondHammer.itemMeta = diamondHammerMeta
updateHammer(diamondHammer)
val recipe = ShapedRecipe(diamondHammerRecipeKey, diamondHammer)
recipe.shape(
" BD",
" SB",
"S ")
recipe.setIngredient('B', Material.DIAMOND_BLOCK)
recipe.setIngredient('D', Material.DIAMOND)
recipe.setIngredient('S', Material.STICK)
plugin.server.addRecipe(recipe)
}
override fun onDisable() {
HandlerList.unregisterAll(this)
plugin.server.removeRecipe(diamondHammerRecipeKey)
}
fun updateHammer(hammer: ItemStack) {
if (!isHammer(hammer))
return
val meta = hammer.itemMeta
meta.setCustomModelData(1)
hammer.itemMeta = meta
}
private fun isHammer(itemStack: ItemStack): Boolean {
val meta = itemStack.itemMeta ?: return false
val persistentContainer = meta.persistentDataContainer
return persistentContainer.get(HAMMER_KEY, PersistentDataType.SHORT) == 1.toShort()
}
@EventHandler
fun onBlockBreak(event: BlockBreakEvent) {
val hammer = event.player.inventory.itemInMainHand
if (!isHammer(hammer))
return
val player = event.player
val lastTwoTargetBlocks: List<Block> = player.getLastTwoTargetBlocks(null, 100)
if (lastTwoTargetBlocks.size != 2 || !lastTwoTargetBlocks[1].type.isOccluding) return
val targetBlock: Block = lastTwoTargetBlocks[1]
val adjacentBlock: Block = lastTwoTargetBlocks[0]
val targetFace = targetBlock.getFace(adjacentBlock)
val toBreak: MutableList<Block> = mutableListOf()
when (targetFace) {
BlockFace.NORTH, BlockFace.SOUTH -> {
toBreak.add(targetBlock.getRelative(1, 0, 0))
toBreak.add(targetBlock.getRelative(-1, 0, 0))
toBreak.add(targetBlock.getRelative(0, 1, 0))
toBreak.add(targetBlock.getRelative(0, -1, 0))
toBreak.add(targetBlock.getRelative(1, 1, 0))
toBreak.add(targetBlock.getRelative(-1, 1, 0))
toBreak.add(targetBlock.getRelative(1, -1, 0))
toBreak.add(targetBlock.getRelative(-1, -1, 0))
}
BlockFace.EAST, BlockFace.WEST -> {
toBreak.add(targetBlock.getRelative(0, 1, 0))
toBreak.add(targetBlock.getRelative(0, -1, 0))
toBreak.add(targetBlock.getRelative(0, 0, 1))
toBreak.add(targetBlock.getRelative(0, 0, -1))
toBreak.add(targetBlock.getRelative(0, 1, 1))
toBreak.add(targetBlock.getRelative(0, -1, 1))
toBreak.add(targetBlock.getRelative(0, 1, -1))
toBreak.add(targetBlock.getRelative(0, -1, -1))
}
BlockFace.UP, BlockFace.DOWN -> {
toBreak.add(targetBlock.getRelative(1, 0, 0))
toBreak.add(targetBlock.getRelative(-1, 0, 0))
toBreak.add(targetBlock.getRelative(0, 0, 1))
toBreak.add(targetBlock.getRelative(0, 0, -1))
toBreak.add(targetBlock.getRelative(1, 0, 1))
toBreak.add(targetBlock.getRelative(-1, 0, 1))
toBreak.add(targetBlock.getRelative(1, 0, -1))
toBreak.add(targetBlock.getRelative(-1, 0, -1))
}
else -> return
}
val maxHardness = targetBlock.type.hardness
for (block in toBreak) {
if (block.type.hardness > maxHardness)
continue
block.breakNaturally(hammer)
}
}
}

View File

@ -1,70 +0,0 @@
//package nl.kallestruik.dtweaks.tweaks.miscellaneoustweaks
//
//import nl.kallestruik.dtweaks.managers.PocketDimensionManager
//import nl.kallestruik.dtweaks.tweaks.ITweak
//import org.bukkit.entity.Player
//import org.bukkit.event.EventHandler
//import org.bukkit.event.HandlerList
//import org.bukkit.event.Listener
//import org.bukkit.event.block.BlockBreakEvent
//import org.bukkit.event.entity.CreatureSpawnEvent
//import org.bukkit.event.entity.EntityDamageEvent
//import org.bukkit.event.player.PlayerMoveEvent
//import org.bukkit.plugin.java.JavaPlugin
//
//class SpaceTimePockets(
// private val plugin: JavaPlugin,
// private val pocketDimensionManager: PocketDimensionManager
//): ITweak, Listener {
// override fun getIdentifier(): String = "SpaceTimePockets"
// override fun getCategories(): List<String> = listOf("miscellaneous", "survival")
//
// override fun onRegister() {
// plugin.server.pluginManager.registerEvents(this, plugin)
// }
//
// override fun onUnRegister() {
// HandlerList.unregisterAll(this)
// }
//
//
// @EventHandler
// fun onBlockBreak(event: BlockBreakEvent) {
// if (event.player.world != pocketDimensionManager.pocketDimension) {
// return
// }
// if (event.block.location.chunk == event.player.location.chunk && event.block.y != 0 && event.block.y != 255) return
// event.isCancelled = true
// event.player.sendMessage("It seems like a bad idea to break the only thing keeping you from getting lost into the endlessness around you.")
// }
//
// @EventHandler
// fun onMobSpawn(event: CreatureSpawnEvent) {
// if (pocketDimensionManager.pocketDimension != event.location.world) return
// event.isCancelled = true
// }
//
// @EventHandler
// fun onPlayerDamage(event: EntityDamageEvent) {
// if (event.entity !is Player) return
// if (pocketDimensionManager.pocketDimension != event.entity.world) return
// event.isCancelled = true
// }
//
// @EventHandler
// fun onPlayerFall(event: PlayerMoveEvent) {
// if (pocketDimensionManager.pocketDimension != event.from.world
// || pocketDimensionManager.pocketDimension != event.to.world
// ) return
// if (event.from.chunk != event.to.chunk) {
// event.player.sendMessage("Something pulls you back from the darkness.")
// event.isCancelled = true
// }
// if (event.to.blockY < 0 || event.to.blockY > 256) {
// event.player.sendMessage("Something pulls you back from the darkness.")
// val safeLocation = event.player.location
// safeLocation.y = 128.0
// event.player.teleport(safeLocation)
// }
// }
//}

View File

@ -1,111 +0,0 @@
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.tweaks.ITweak
import org.bukkit.craftbukkit.v1_19_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.player.PlayerInteractEntityEvent
import org.bukkit.plugin.java.JavaPlugin
import java.util.concurrent.atomic.AtomicReference
class VillagerInfo(
private val plugin: JavaPlugin
): ITweak, Listener {
override fun getIdentifier(): String = "VillagerInfo"
override fun getCategories(): List<String> = listOf("mobs")
override fun onEnable() {
plugin.server.pluginManager.registerEvents(this, plugin)
}
override fun onDisable() {
HandlerList.unregisterAll(this)
}
@EventHandler
fun onInteractEvent(event: PlayerInteractEntityEvent) {
if (!event.player.isSneaking) return
val clicked = event.rightClicked as? Villager ?: return
val eVillager: net.minecraft.world.entity.npc.Villager = (clicked as CraftVillager).handle
val homePos: AtomicReference<GlobalPos?> = AtomicReference(null)
eVillager.brain.getMemory(MemoryModuleType.HOME)
.ifPresent { newValue -> homePos.set(newValue) }
val workPos: AtomicReference<GlobalPos?> = AtomicReference(null)
eVillager.brain.getMemory(MemoryModuleType.JOB_SITE).ifPresent { newValue ->
workPos.set(
newValue
)
}
val meetingPos: AtomicReference<GlobalPos?> = AtomicReference(null)
eVillager.brain.getMemory(MemoryModuleType.MEETING_POINT).ifPresent { newValue ->
meetingPos.set(
newValue
)
}
val lastWork: AtomicReference<Long?> = AtomicReference(null)
eVillager.brain.getMemory(MemoryModuleType.LAST_WORKED_AT_POI).ifPresent { newValue ->
lastWork.set(
newValue
)
}
val lastSleep: AtomicReference<Long?> = AtomicReference(null)
eVillager.brain.getMemory(MemoryModuleType.LAST_SLEPT).ifPresent { newValue ->
lastSleep.set(
newValue
)
}
val seenIGRecently: AtomicReference<Boolean?> = AtomicReference(null)
eVillager.brain.getMemory(MemoryModuleType.GOLEM_DETECTED_RECENTLY).ifPresent { newValue ->
seenIGRecently.set(
newValue
)
}
val isPanicking: Boolean = eVillager.brain.isActive(Activity.PANIC)
val player = event.player
player.sendMessage("=====Villager Info=====")
player.sendMessage("Type: " + clicked.villagerType)
player.sendMessage("Profession: " + clicked.profession)
player.sendMessage("Level: " + clicked.villagerLevel + "(" + clicked.villagerExperience + " xp)")
player.sendMessage("Panic: $isPanicking")
if (homePos.get() != null) player.sendMessage(
java.lang.String.format(
"Home: %s, %s, %s",
homePos.get()?.pos()?.x,
homePos.get()?.pos()?.y,
homePos.get()?.pos()?.z
)
)
if (workPos.get() != null) player.sendMessage(
java.lang.String.format(
"Work: %s, %s, %s",
workPos.get()?.pos()?.x,
workPos.get()?.pos()?.y,
workPos.get()?.pos()?.z
)
)
if (homePos.get() != null) player.sendMessage(
java.lang.String.format(
"Meeting point: %s, %s, %s",
meetingPos.get()?.pos()?.x,
meetingPos.get()?.pos()?.y,
meetingPos.get()?.pos()?.z
)
)
if (lastSleep.get() != null)
player.sendMessage("Last slept: ${lastSleep.get()}")
if (seenIGRecently.get() != null)
player.sendMessage("Seen iron golem Recently: ${seenIGRecently.get()}")
}
}

View File

@ -1,22 +1,25 @@
name: DTweaks name: DTweaks
version: ${version} version: ${version}
main: nl.kallestruik.dtweaks.DTweaks main: nl.kallestruik.dtweaks.DTweaks
api-version: 1.16 api-version: "1.20"
depend: dependencies:
- "ProtocolLib" - name: "ProtocolLib"
- "DLib" required: true
- name: "DLib"
required: true
bootstrap: true
has-open-classloader: true
load-after:
- name: "DLib"
bootstrap: true
commands: commands:
toggletrample: toggletrample:
description: "Toggles whether you can trample crops." description: "Toggles whether you can trample crops."
player: player:
description: "Interact with fake players." description: "Interact with fake players."
permission: op permission: op
bundle:
description: "Admin command for managing custom bundles."
permission: op
mobcaps: mobcaps:
description: "Display mobcap information from your current dimension." description: "Display mobcap information from your current dimension."
pocketdim:
description: "Interact with pocket dimensions. Testing command."
spawnzones: spawnzones:
description: "Manage no spawn zones" description: "Manage no spawn zones"

View File

@ -20,7 +20,6 @@ NoDoorBreaking: true
NoCreeperGrief: false NoCreeperGrief: false
NoEndermanGrief: true NoEndermanGrief: true
SugarcaneBonemealing: true SugarcaneBonemealing: true
SpaceTimePockets: true
VillagerInfo: true VillagerInfo: true
BetterBundles: true BetterBundles: true
RedyeTerracotta: true RedyeTerracotta: true