diff --git a/build.gradle.kts b/build.gradle.kts index 2ba1eae..c285526 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ plugins { kotlin("jvm") version "2.1.20-Beta1" id("com.github.johnrengelman.shadow") version "8.1.1" + id("io.papermc.paperweight.userdev") version "2.0.0-beta.11" // id("de.nilsdruyen.gradle-ftp-upload-plugin") version "0.5.0" } @@ -24,13 +25,13 @@ repositories { } dependencies { - compileOnly("io.papermc.paper:paper-api:1.21.3-R0.1-SNAPSHOT") +// compileOnly("io.papermc.paper:paper-api:1.21.3-R0.1-SNAPSHOT") // compileOnly("com.comphenix.protocol:ProtocolLib:5.3.0") compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit") compileOnly(files("libs/ProtocolLib.jar")) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation(platform("com.intellectualsites.bom:bom-newest:1.51")) // Ref: https://github.com/IntellectualSites/bom -// implementation("de.nilsdruyen.gradle-ftp-upload-plugin:de.nilsdruyen.gradle-ftp-upload-plugin.gradle.plugin:0.5.0") + paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT") } val targetJavaVersion = 21 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a441313..cea7a79 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/kotlin/com/pobnellion/aoe/Aoe.kt b/src/main/kotlin/com/pobnellion/aoe/Aoe.kt index 816cd98..2cdde48 100644 --- a/src/main/kotlin/com/pobnellion/aoe/Aoe.kt +++ b/src/main/kotlin/com/pobnellion/aoe/Aoe.kt @@ -1,15 +1,22 @@ package com.pobnellion.aoe import com.pobnellion.aoe.command.TestCommand +import com.pobnellion.aoe.team.Team import com.pobnellion.aoe.ui.PlaceHint import com.pobnellion.aoe.ui.PlaceItem import org.bukkit.Bukkit +import org.bukkit.entity.Player import org.bukkit.plugin.java.JavaPlugin import java.io.File class Aoe : JavaPlugin() { companion object { private var instance: Aoe? = null + val teams: MutableList = mutableListOf() + + fun getTeam(player: Player): Team? { + return teams.singleOrNull() { team -> team.players.contains(player) } + } fun getSchematicsFolder(): File = File(instance!!.dataFolder, "schematics") } @@ -18,8 +25,8 @@ class Aoe : JavaPlugin() { instance = this // Events - Bukkit.getPluginManager().registerEvents(PlaceHint, this) Bukkit.getPluginManager().registerEvents(PlaceItem(), this) + Bukkit.getPluginManager().registerEvents(PlaceHint, this) // Commands this.getCommand("debug")!!.setExecutor(TestCommand()) diff --git a/src/main/kotlin/com/pobnellion/aoe/building/Blacksmith.kt b/src/main/kotlin/com/pobnellion/aoe/building/Blacksmith.kt index 241d704..a06d229 100644 --- a/src/main/kotlin/com/pobnellion/aoe/building/Blacksmith.kt +++ b/src/main/kotlin/com/pobnellion/aoe/building/Blacksmith.kt @@ -6,12 +6,8 @@ import org.bukkit.Location import org.bukkit.Material import org.bukkit.entity.Player -class Blacksmith: Building { - override fun showPlaceHint(player: Player) { - PlaceHint.add(player, "house2", ::place, PlaceHintValidators::allReplaceable) - } - - fun place(location: Location, sizeX: Float, sizeY: Float, sizeZ: Float) { +class Blacksmith(location: Location, variant: Int): Building(location, variant) { + fun place(location: Location, sizeX: Float, sizeY: Float, sizeZ: Float, offsetY: Int) { for (x in 0.. + fun validate(location: Location): Boolean + fun create(location: Location, variant: Int): Building } \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/building/BuildingType.kt b/src/main/kotlin/com/pobnellion/aoe/building/BuildingType.kt new file mode 100644 index 0000000..30cb223 --- /dev/null +++ b/src/main/kotlin/com/pobnellion/aoe/building/BuildingType.kt @@ -0,0 +1,12 @@ +package com.pobnellion.aoe.building + +enum class BuildingType { + BARRACKS, + FARM, + HOUSE, + MILL, + TOWN_CENTER, + UNIQUE, + WALL, + WATCH_TOWER, +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/building/House.kt b/src/main/kotlin/com/pobnellion/aoe/building/House.kt index 493a1a6..363bc62 100644 --- a/src/main/kotlin/com/pobnellion/aoe/building/House.kt +++ b/src/main/kotlin/com/pobnellion/aoe/building/House.kt @@ -1,17 +1,22 @@ package com.pobnellion.aoe.building -import com.pobnellion.aoe.ui.PlaceHint import com.pobnellion.aoe.ui.PlaceHintValidators import org.bukkit.Location import org.bukkit.Material -import org.bukkit.entity.Player -class House: Building { - override fun showPlaceHint(player: Player) { - PlaceHint.add(player, "house1", ::place, PlaceHintValidators::allReplaceable) +class House(location: Location, variant: Int): Building(location, variant) { + companion object Info: BuildingInfo { + override val buildingType: BuildingType = BuildingType.HOUSE + override val schematicNames: List = listOf("house1") + + override fun validate(location: Location): Boolean { + return PlaceHintValidators.allReplaceable(location, 5f, 5f, 5f, -1) + } + + override fun create(location: Location, variant: Int): Building = House(location, variant) } - fun place(location: Location, sizeX: Float, sizeY: Float, sizeZ: Float) { + fun place(location: Location, sizeX: Float, sizeY: Float, sizeZ: Float, int: Int) { for (x in 0..?): Boolean { + override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array): Boolean { if (sender !is Player) { sender.sendMessage("Command can only be executed by players") return true diff --git a/src/main/kotlin/com/pobnellion/aoe/entity/Villager.kt b/src/main/kotlin/com/pobnellion/aoe/entity/Villager.kt new file mode 100644 index 0000000..1bf9edd --- /dev/null +++ b/src/main/kotlin/com/pobnellion/aoe/entity/Villager.kt @@ -0,0 +1,21 @@ +package com.pobnellion.aoe.entity + +import com.pobnellion.aoe.building.Building +import com.pobnellion.aoe.entity.goals.GoToBuildingGoal +import net.minecraft.world.entity.EntityType +import net.minecraft.world.entity.npc.Villager +import org.bukkit.Location +import org.bukkit.craftbukkit.CraftWorld + +class AoeVillager(location: Location) : Villager(EntityType.VILLAGER, (location.world as CraftWorld).handle) { + init { + setPos(location.x, location.y, location.z) + level().addFreshEntity(this) + + targetSelector.removeAllGoals { true } + } + + fun goToBuilding(building: Building) { + targetSelector.addGoal(0, GoToBuildingGoal(this, building, 1.0)) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/entity/goals/GoToBuildingGoal.kt b/src/main/kotlin/com/pobnellion/aoe/entity/goals/GoToBuildingGoal.kt new file mode 100644 index 0000000..bbf1eb4 --- /dev/null +++ b/src/main/kotlin/com/pobnellion/aoe/entity/goals/GoToBuildingGoal.kt @@ -0,0 +1,35 @@ +package com.pobnellion.aoe.entity.goals + +import com.pobnellion.aoe.building.Building +import net.minecraft.world.entity.PathfinderMob +import net.minecraft.world.entity.ai.goal.Goal +import java.util.* + +class GoToBuildingGoal( + private val mob: PathfinderMob, + private val building: Building, + private var speedModifier: Double +): Goal() { + private var recalculateTicks = 0 + + init { + this.setFlags(EnumSet.of(Flag.MOVE, Flag.JUMP)) + } + + override fun canUse(): Boolean { + return true + } + + override fun start() { + mob.navigation.moveTo(building.location.x, building.location.y, building.location.z, speedModifier) + } + + override fun tick() { + recalculateTicks++ + + if (recalculateTicks % 40 == 0) + mob.navigation.moveTo(building.location.x, building.location.y, building.location.z, speedModifier) + } + + override fun requiresUpdateEveryTick(): Boolean = true +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/team/Plains.kt b/src/main/kotlin/com/pobnellion/aoe/team/Plains.kt new file mode 100644 index 0000000..31e2dda --- /dev/null +++ b/src/main/kotlin/com/pobnellion/aoe/team/Plains.kt @@ -0,0 +1,23 @@ +package com.pobnellion.aoe.team + +import com.pobnellion.aoe.building.BuildingInfo +import com.pobnellion.aoe.building.BuildingType +import com.pobnellion.aoe.building.House +import org.bukkit.entity.Player + +class Plains(players: List) : Team(players) { + + override fun getBuildingInfo(type: BuildingType): BuildingInfo { + return when (type) { + BuildingType.BARRACKS -> TODO() + BuildingType.FARM -> TODO() + BuildingType.HOUSE -> House.Info + BuildingType.MILL -> TODO() + BuildingType.TOWN_CENTER -> TODO() + BuildingType.UNIQUE -> TODO() + BuildingType.WALL -> TODO() + BuildingType.WATCH_TOWER -> TODO() + } + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/team/Team.kt b/src/main/kotlin/com/pobnellion/aoe/team/Team.kt index 1a5c2ab..e61b675 100644 --- a/src/main/kotlin/com/pobnellion/aoe/team/Team.kt +++ b/src/main/kotlin/com/pobnellion/aoe/team/Team.kt @@ -1,7 +1,25 @@ package com.pobnellion.aoe.team import com.pobnellion.aoe.building.Building +import com.pobnellion.aoe.building.BuildingInfo +import com.pobnellion.aoe.building.BuildingType +import com.pobnellion.aoe.ui.BuildingPlaceHint +import org.bukkit.Location +import org.bukkit.entity.Player +import kotlin.random.Random -class Team { - public val Buildings: List = listOf() +abstract class Team(val players: List) { + val buildings: MutableList = mutableListOf() + + protected abstract fun getBuildingInfo(type: BuildingType): BuildingInfo + + fun addBuilding(location: Location, building: BuildingInfo, variant: Int) { + buildings.add(building.create(location, variant)) + } + + fun showBuildingPlaceHint(type: BuildingType, player: Player) { + val info = getBuildingInfo(type) + val variant = Random.nextInt(info.schematicNames.size) + BuildingPlaceHint.add(player, info, ::addBuilding, variant) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/ui/AreaPlaceHint.kt b/src/main/kotlin/com/pobnellion/aoe/ui/AreaPlaceHint.kt new file mode 100644 index 0000000..111aa35 --- /dev/null +++ b/src/main/kotlin/com/pobnellion/aoe/ui/AreaPlaceHint.kt @@ -0,0 +1,80 @@ +package com.pobnellion.aoe.ui + +import com.comphenix.protocol.PacketType +import com.comphenix.protocol.ProtocolLibrary +import com.comphenix.protocol.events.PacketContainer +import com.comphenix.protocol.wrappers.BukkitConverters +import com.comphenix.protocol.wrappers.Pair +import com.comphenix.protocol.wrappers.WrappedBlockData +import com.comphenix.protocol.wrappers.WrappedDataValue +import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry +import org.bukkit.Location +import org.bukkit.Material +import org.bukkit.entity.Player +import org.bukkit.util.Vector +import org.joml.Math +import org.joml.Vector3f +import java.util.* + +class AreaPlaceHint( + override val player: Player, + private val sizeX: Float, + private val sizeY: Float, + private val sizeZ: Float, + private val onConfirm: (Location, Float, Float, Float) -> Unit, + private val validate: (Location, Float, Float, Float) -> Boolean +) : PlaceHint() { + companion object { + fun add( + player: Player, + sizeX: Float, + sizeY: Float, + sizeZ: Float, + onConfirm: (Location, Float, Float, Float) -> Unit, + validate: (Location, Float, Float, Float) -> Boolean, + ) { + remove(player) + createOutlineTeam(player) + + playerHints[player.uniqueId] = AreaPlaceHint(player, sizeX, sizeY, sizeZ, onConfirm, validate) + val block = player.getTargetBlockExact(MAX_TARGET_DISTANCE) + playerHints[player.uniqueId]!!.moveTo(block?.location) + } + } + + private var base: Pair = Pair((Math.random() * Int.MAX_VALUE).toInt(), UUID.randomUUID()) + + init { + this.offset = Vector(sizeX / 2.0, 0.0, sizeZ / 2.0) + } + + override fun validate(location: Location) = validate(location, sizeX, sizeY, sizeZ) + + override fun confirm() = onConfirm(currentLocation!!, sizeX, sizeY, sizeZ) + + override fun addDisplays(initialLocation: Location) { + base = spawnBlockDisplay(initialLocation, Material.GRAY_STAINED_GLASS.createBlockData(), + scale = Vector3f(sizeX + 0.1f, 0.2f, sizeZ + 0.1f), offset = Vector3f(-0.05f, -0.05f, -0.05f)) + + } + + override fun updateColour() { + super.updateColour() + + // base + val dataPacket = PacketContainer(PacketType.Play.Server.ENTITY_METADATA) + dataPacket.integers.write(0, base.first) + + val material = if (isValid) Material.LIME_STAINED_GLASS else Material.RED_STAINED_GLASS + val blockData = BukkitConverters + .getWrappedBlockDataConverter() + .getGeneric(WrappedBlockData.createData(material)) + + val metadata = listOf( + WrappedDataValue(23, Registry.getBlockDataSerializer(false), blockData) + ) + + dataPacket.dataValueCollectionModifier.write(0, metadata) + ProtocolLibrary.getProtocolManager().sendServerPacket(player, dataPacket) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/ui/BuildingPlaceHint.kt b/src/main/kotlin/com/pobnellion/aoe/ui/BuildingPlaceHint.kt new file mode 100644 index 0000000..690c832 --- /dev/null +++ b/src/main/kotlin/com/pobnellion/aoe/ui/BuildingPlaceHint.kt @@ -0,0 +1,75 @@ +package com.pobnellion.aoe.ui + +import com.pobnellion.aoe.Aoe +import com.pobnellion.aoe.building.BuildingInfo +import com.sk89q.worldedit.bukkit.BukkitAdapter +import com.sk89q.worldedit.extent.clipboard.Clipboard +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats +import com.sk89q.worldedit.math.BlockVector3 +import org.bukkit.Location +import org.bukkit.entity.Player +import org.bukkit.util.Vector +import org.joml.Vector3f +import java.io.File +import java.io.FileInputStream +import kotlin.math.floor + +class BuildingPlaceHint( + override val player: Player, + private val buildingInfo: BuildingInfo, + private val onConfirm: (Location, BuildingInfo, Int) -> Unit, + private val buildingVariant: Int = 0 +) : PlaceHint() { + companion object { + fun add( + player: Player, + buildingInfo: BuildingInfo, + onConfirm: (Location, BuildingInfo, Int) -> Unit, + buildingVariant: Int = 0 + ) { + remove(player) + createOutlineTeam(player) + + playerHints[player.uniqueId] = BuildingPlaceHint(player, buildingInfo, onConfirm, buildingVariant) + val block = player.getTargetBlockExact(MAX_TARGET_DISTANCE) + playerHints[player.uniqueId]!!.moveTo(block?.location) + } + } + + private val schematic: Clipboard + + init { + val schematicName = buildingInfo.schematicNames[buildingVariant] + val file = File(Aoe.getSchematicsFolder(), + if (schematicName.endsWith(".schem")) schematicName else "$schematicName.schem") + + val format = ClipboardFormats.findByFile(file) + val reader = format?.getReader(FileInputStream(file)) + val clipboard = reader?.read() ?: throw NullPointerException("Could not load schematic ${file.path}. Is it present?") + clipboard.origin = BlockVector3.ZERO + this.schematic = clipboard + + this.offset = Vector( + -floor(clipboard.dimensions.x() / 2.0), + clipboard.minY.toDouble(), + -floor(clipboard.dimensions.z() / 2.0)) + } + + override fun validate(location: Location) = buildingInfo.validate(location) + + override fun confirm() = onConfirm(currentLocation!!, buildingInfo, buildingVariant) + + override fun addDisplays(initialLocation: Location) { + schematic.iterator().forEach { blockPosition -> + val block = BukkitAdapter.adapt(schematic.getBlock(blockPosition)) + + if (!block.material.isAir && !block.material.isEmpty) { + val x = (blockPosition.x() - schematic.minimumPoint.x()).toFloat() + val y = blockPosition.y().toFloat() + val z = (blockPosition.z() - schematic.minimumPoint.z()).toFloat() + + displayIds.add(spawnBlockDisplay(initialLocation, block, offset = Vector3f(x, y, z), options = 0b01000000)) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/ui/PlaceHint.kt b/src/main/kotlin/com/pobnellion/aoe/ui/PlaceHint.kt index d414ef8..fc5f35d 100644 --- a/src/main/kotlin/com/pobnellion/aoe/ui/PlaceHint.kt +++ b/src/main/kotlin/com/pobnellion/aoe/ui/PlaceHint.kt @@ -6,12 +6,7 @@ import com.comphenix.protocol.events.PacketContainer import com.comphenix.protocol.wrappers.* import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry import com.destroystokyo.paper.MaterialSetTag -import com.pobnellion.aoe.Aoe -import com.sk89q.worldedit.bukkit.BukkitAdapter -import com.sk89q.worldedit.extent.clipboard.Clipboard -import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats import org.bukkit.Location -import org.bukkit.Material import org.bukkit.block.data.BlockData import org.bukkit.entity.EntityType import org.bukkit.entity.Player @@ -20,47 +15,16 @@ import org.bukkit.event.Listener import org.bukkit.event.block.Action import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.player.PlayerMoveEvent +import org.bukkit.util.Vector import org.joml.Math import org.joml.Vector3f -import java.io.File -import java.io.FileInputStream import java.util.* -import kotlin.math.floor -class PlaceHint { +abstract class PlaceHint { companion object : Listener { - private const val MAX_TARGET_DISTANCE = 64 - private val playerHints = HashMap() - - fun add( - player: Player, - sizeX: Float, - sizeY: Float, - sizeZ: Float, - onConfirm: (Location, Float, Float, Float) -> Unit, - validate: (Location, Float, Float, Float) -> Boolean, - ) { - remove(player) - createOutlineTeam(player) - - playerHints[player.uniqueId] = PlaceHint(player, sizeX, sizeY, sizeZ, onConfirm, validate) - val block = player.getTargetBlockExact(MAX_TARGET_DISTANCE) - playerHints[player.uniqueId]!!.moveTo(block?.location) - } - - fun add( - player: Player, - schematicName: String, - onConfirm: (Location, Float, Float, Float) -> Unit, - validate: (Location, Float, Float, Float) -> Boolean, - ) { - remove(player) - createOutlineTeam(player) - - playerHints[player.uniqueId] = PlaceHint(player, schematicName, onConfirm, validate) - val block = player.getTargetBlockExact(MAX_TARGET_DISTANCE) - playerHints[player.uniqueId]!!.moveTo(block?.location) - } + const val MAX_TARGET_DISTANCE = 64 + @JvmStatic + protected val playerHints = HashMap() fun remove(player: Player) { if (!playerHints.containsKey(player.uniqueId)) @@ -79,7 +43,8 @@ class PlaceHint { return playerHints.containsKey(player.uniqueId) } - private fun createOutlineTeam(player: Player) { + @JvmStatic + protected fun createOutlineTeam(player: Player) { val packet = PacketContainer(PacketType.Play.Server.SCOREBOARD_TEAM) packet.strings.write(0, "placeValid") packet.integers.write(0, 0) @@ -105,13 +70,12 @@ class PlaceHint { event.isCancelled = true - // left click - place + // left click - confirm if (event.action == Action.LEFT_CLICK_BLOCK || event.action == Action.LEFT_CLICK_AIR) { if (!playerHints[event.player.uniqueId]!!.isValid) return - val marker = playerHints[event.player.uniqueId]!! - marker.onConfirm(marker.currentLocation!!, marker.sizeX, marker.sizeY, marker.sizeZ) + playerHints[event.player.uniqueId]!!.confirm() remove(event.player) } @@ -132,53 +96,19 @@ class PlaceHint { .build() } - private val player: Player - private val sizeX: Float - private val sizeY: Float - private val sizeZ: Float - val onConfirm: (Location, Float, Float, Float) -> Unit - val validate: (Location, Float, Float, Float) -> Boolean - private val schematic: Clipboard? + protected abstract val player: Player + protected lateinit var offset: Vector private var marker: Pair = Pair((Math.random() * Int.MAX_VALUE).toInt(), UUID.randomUUID()) - private var base: Pair = Pair((Math.random() * Int.MAX_VALUE).toInt(), UUID.randomUUID()) - private val displayIds: MutableList> = mutableListOf() + protected val displayIds: MutableList> = mutableListOf() var currentLocation: Location? = null var isValid = false - constructor(player: Player, sizeX: Float, sizeY: Float, sizeZ: Float, - onConfirm: (Location, Float, Float, Float) -> Unit, - validate: (Location, Float, Float, Float) -> Boolean) { - this.player = player - this.sizeX = sizeX - this.sizeY = sizeY - this.sizeZ = sizeZ - this.onConfirm = onConfirm - this.validate = validate - this.schematic = null - } + protected abstract fun addDisplays(initialLocation: Location) + protected abstract fun confirm() + protected abstract fun validate(location: Location): Boolean - constructor(player: Player, schematicName: String, - onConfirm: (Location, Float, Float, Float) -> Unit, - validate: (Location, Float, Float, Float) -> Boolean) { - this.player = player - this.onConfirm = onConfirm - this.validate = validate - - val file = File(Aoe.getSchematicsFolder(), - if (schematicName.endsWith(".schem")) schematicName else "$schematicName.schem") - - val format = ClipboardFormats.findByFile(file) - val reader = format?.getReader(FileInputStream(file)) - val clipboard = reader?.read() ?: throw NullPointerException("Could not load schematic ${file.path}. Is it present?") - - this.schematic = clipboard - this.sizeX = clipboard.dimensions.x().toFloat() - this.sizeY = clipboard.dimensions.y().toFloat() - this.sizeZ = clipboard.dimensions.z().toFloat() - } - - private fun show(initialLocation: Location) { - initialLocation.add(-floor(sizeX / 2.0), 1.0, -floor(sizeZ / 2.0)) + protected fun show(initialLocation: Location) { + initialLocation.add(this.offset) currentLocation = initialLocation val spawnMarkerPacket = PacketContainer(PacketType.Play.Server.SPAWN_ENTITY) @@ -190,20 +120,7 @@ class PlaceHint { .write(1, initialLocation.y) .write(2, initialLocation.z) - base = spawnBlockDisplay(initialLocation, Material.GRAY_STAINED_GLASS.createBlockData(), - scale = Vector3f(sizeX + 0.1f, 0.2f, sizeZ + 0.1f), offset = Vector3f(-0.05f, -0.05f, -0.05f)) - - schematic?.iterator()?.forEach { blockPosition -> - val block = BukkitAdapter.adapt(schematic.getBlock(blockPosition)) - - if (!block.material.isAir && !block.material.isEmpty) { - val x = (blockPosition.x() - schematic.minimumPoint.x()).toFloat() - val y = (blockPosition.y() - schematic.minimumPoint.y()).toFloat() - val z = (blockPosition.z() - schematic.minimumPoint.z()).toFloat() - - displayIds.add(spawnBlockDisplay(initialLocation, block, offset = Vector3f(x, y, z), options = 0b01000000)) - } - } + addDisplays(initialLocation) val outlineTeamPacket = PacketContainer(PacketType.Play.Server.SCOREBOARD_TEAM) outlineTeamPacket.strings.write(0, "placeValid") @@ -211,7 +128,6 @@ class PlaceHint { outlineTeamPacket.getSpecificModifier(Collection::class.java).write(0, displayIds.map { it.second.toString() }) val ids = displayIds.map { it.first }.toMutableList() - ids.add(base.first) val passengerPacket = PacketContainer(PacketType.Play.Server.MOUNT) passengerPacket.integers.write(0, marker.first) @@ -221,7 +137,7 @@ class PlaceHint { ProtocolLibrary.getProtocolManager().sendServerPacket(player, outlineTeamPacket) ProtocolLibrary.getProtocolManager().sendServerPacket(player, passengerPacket) - isValid = validate(initialLocation, sizeX, sizeY, sizeZ) + isValid = validate(initialLocation) updateColour() } @@ -229,7 +145,6 @@ class PlaceHint { val packet = PacketContainer(PacketType.Play.Server.ENTITY_DESTROY) val ids = displayIds.map { it.first }.toMutableList() ids.add(marker.first) - ids.add(base.first) packet.intLists.write(0, ids) ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet) @@ -245,11 +160,11 @@ class PlaceHint { } if (currentLocation == null) { - show(newLocation) + addDisplays(newLocation) return } - newLocation.add(-floor(sizeX / 2.0), 1.0, -floor(sizeZ / 2.0)) + newLocation.add(this.offset) val basePacket = PacketContainer(PacketType.Play.Server.ENTITY_POSITION_SYNC) basePacket.integers.write(0, marker.first) @@ -266,7 +181,7 @@ class PlaceHint { currentLocation = newLocation // Update material - val valid = validate(newLocation, sizeX, sizeY, sizeZ) + val valid = validate(newLocation) if (valid != isValid) { isValid = valid @@ -276,7 +191,7 @@ class PlaceHint { // region helper functions - private fun spawnBlockDisplay( + protected fun spawnBlockDisplay( location: Location, block: BlockData, scale: Vector3f = Vector3f(1f, 1f, 1f), @@ -318,23 +233,7 @@ class PlaceHint { return Pair(id, uuid) } - private fun updateColour() { - // base - val dataPacket = PacketContainer(PacketType.Play.Server.ENTITY_METADATA) - dataPacket.integers.write(0, base.first) - - val material = if (isValid) Material.LIME_STAINED_GLASS else Material.RED_STAINED_GLASS - val blockData = BukkitConverters - .getWrappedBlockDataConverter() - .getGeneric(WrappedBlockData.createData(material)) - - val metadata = listOf( - WrappedDataValue(23, Registry.getBlockDataSerializer(false), blockData) - ) - - dataPacket.dataValueCollectionModifier.write(0, metadata) - ProtocolLibrary.getProtocolManager().sendServerPacket(player, dataPacket) - + protected open fun updateColour() { // outline val outlineTeamPacket = PacketContainer(PacketType.Play.Server.SCOREBOARD_TEAM) outlineTeamPacket.strings.write(0, "placeValid") diff --git a/src/main/kotlin/com/pobnellion/aoe/ui/PlaceHintValidators.kt b/src/main/kotlin/com/pobnellion/aoe/ui/PlaceHintValidators.kt index f23ef08..2f9cb91 100644 --- a/src/main/kotlin/com/pobnellion/aoe/ui/PlaceHintValidators.kt +++ b/src/main/kotlin/com/pobnellion/aoe/ui/PlaceHintValidators.kt @@ -5,13 +5,13 @@ import org.bukkit.Location class PlaceHintValidators { companion object { - fun alwaysTrue(location: Location, sizeX: Float, sizeY: Float, sizeZ: Float): Boolean { + fun alwaysTrue(location: Location, sizeX: Float, sizeY: Float, sizeZ: Float, offsetY: Int): Boolean { return true } - fun allAir(location: Location, sizeX: Float, sizeY: Float, sizeZ: Float): Boolean { + fun allAir(location: Location, sizeX: Float, sizeY: Float, sizeZ: Float, offsetY: Int): Boolean { for (x in 0.. House().showPlaceHint(event.whoClicked as Player) - Material.ANVIL -> Blacksmith().showPlaceHint(event.whoClicked as Player) + Material.OAK_LOG -> team.showBuildingPlaceHint(BuildingType.HOUSE, player) + Material.BELL -> team.showBuildingPlaceHint(BuildingType.TOWN_CENTER, player) + Material.EMERALD -> {} else -> validClick = false }