diff --git a/src/main/kotlin/com/pobnellion/aoe/Aoe.kt b/src/main/kotlin/com/pobnellion/aoe/Aoe.kt index f0f7972..e9f633b 100644 --- a/src/main/kotlin/com/pobnellion/aoe/Aoe.kt +++ b/src/main/kotlin/com/pobnellion/aoe/Aoe.kt @@ -6,8 +6,9 @@ import com.pobnellion.aoe.civilisation.Civilisation import com.pobnellion.aoe.civilisation.CivilisationType import com.pobnellion.aoe.map.AoeMap import com.pobnellion.aoe.ui.PlaceHint -import com.pobnellion.aoe.ui.PlaceItem +import com.pobnellion.aoe.ui.InventoryManager import org.bukkit.Bukkit +import org.bukkit.GameMode import org.bukkit.entity.Player import org.bukkit.plugin.java.JavaPlugin import java.io.File @@ -19,6 +20,10 @@ class Aoe : JavaPlugin() { private var instance: Aoe? = null val civilisations: MutableMap = mutableMapOf() val map: AoeMap = AoeMap() + val players: MutableMap = mutableMapOf() + val inventoryManager: InventoryManager = InventoryManager() + + fun isPlaying(player: Player) = players.containsKey(player) fun getTeam(player: Player): Civilisation? { return civilisations.values.singleOrNull { team -> team.players.contains(player) } @@ -28,8 +33,18 @@ class Aoe : JavaPlugin() { Paths.get(instance!!.dataFolder.path, "schematics", "$schematicName.schem").toFile() fun startGame() { - if (!gameInProgress) - civilisations.values.forEach { civ -> civ.initSetup() } + if (gameInProgress) + return + + for (player in Bukkit.getOnlinePlayers()) { + if (isPlaying(player)) + player.gameMode = GameMode.CREATIVE + else + player.gameMode = GameMode.SPECTATOR + } + + civilisations.values.forEach { civ -> civ.initSetup() } + inventoryManager.initHotbars() gameInProgress = true } @@ -39,7 +54,7 @@ class Aoe : JavaPlugin() { instance = this // Events - Bukkit.getPluginManager().registerEvents(PlaceItem(), this) + Bukkit.getPluginManager().registerEvents(InventoryManager(), this) Bukkit.getPluginManager().registerEvents(PlaceHint, this) // Commands diff --git a/src/main/kotlin/com/pobnellion/aoe/Extensions.kt b/src/main/kotlin/com/pobnellion/aoe/Extensions.kt new file mode 100644 index 0000000..3b67259 --- /dev/null +++ b/src/main/kotlin/com/pobnellion/aoe/Extensions.kt @@ -0,0 +1,8 @@ +package com.pobnellion.aoe + +import com.pobnellion.aoe.civilisation.Civilisation +import org.bukkit.entity.Player + +fun Player.getCivilisation(): Civilisation? { + return Aoe.civilisations[Aoe.players[this]] +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/building/Building.kt b/src/main/kotlin/com/pobnellion/aoe/building/Building.kt index df0b3cf..9a6682d 100644 --- a/src/main/kotlin/com/pobnellion/aoe/building/Building.kt +++ b/src/main/kotlin/com/pobnellion/aoe/building/Building.kt @@ -11,6 +11,7 @@ import com.sk89q.worldedit.function.operation.Operations import com.sk89q.worldedit.math.BlockVector3 import com.sk89q.worldedit.session.ClipboardHolder import org.bukkit.Location +import org.bukkit.util.Vector import java.io.File import java.io.FileInputStream @@ -22,19 +23,26 @@ abstract class Building(val location: Location, val variant: Int): EntityWorkTar override fun removeProgress(amount: Float) {} override fun onComplete() {} + var sizeX: Int + var sizeZ: Int + fun center(): Location = location.clone().add(sizeX / 2.0, 0.0, sizeZ / 2.0) + private val clipboard: Clipboard abstract var populationCapacity: Int abstract fun getSchematicName(variant: Int): String - fun placeFull() { - currentProgressPercent = 1f - var clipboard: Clipboard - - val file: File = Aoe.getSchematicFile(getSchematicName(variant)) + init { + val file: File = Aoe.getSchematicFile(this.getSchematicName(variant)) val format = ClipboardFormats.findByFile(file) format!!.getReader(FileInputStream(file)).use { reader -> clipboard = reader.read() } + sizeX = clipboard.maximumPoint.x() - clipboard.minimumPoint.x() + sizeZ = clipboard.maximumPoint.z() - clipboard.minimumPoint.z() + } + + fun placeFull() { + currentProgressPercent = 1f val offset = clipboard.region.minimumPoint.subtract(clipboard.origin) WorldEdit.getInstance().newEditSession(BukkitAdapter.adapt(location.world)).use { editSession -> @@ -50,6 +58,7 @@ abstract class Building(val location: Location, val variant: Int): EntityWorkTar interface BuildingInfo { val buildingType: BuildingType val schematicNames: List + fun getSize(variant: Int): Vector 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/civilisation/Civilisation.kt b/src/main/kotlin/com/pobnellion/aoe/civilisation/Civilisation.kt index 2e9e343..64f2095 100644 --- a/src/main/kotlin/com/pobnellion/aoe/civilisation/Civilisation.kt +++ b/src/main/kotlin/com/pobnellion/aoe/civilisation/Civilisation.kt @@ -1,13 +1,17 @@ package com.pobnellion.aoe.civilisation +import com.pobnellion.aoe.Aoe import com.pobnellion.aoe.Constants import com.pobnellion.aoe.building.Building import com.pobnellion.aoe.building.BuildingInfo import com.pobnellion.aoe.building.BuildingType import com.pobnellion.aoe.building.TownCenter import com.pobnellion.aoe.entity.AoeVillager +import com.pobnellion.aoe.ui.AoeInventory import com.pobnellion.aoe.ui.BuildingPlaceHint +import net.minecraft.world.phys.AABB import org.bukkit.Location +import org.bukkit.craftbukkit.CraftWorld import org.bukkit.entity.Player import kotlin.math.min import kotlin.random.Random @@ -17,15 +21,17 @@ abstract class Civilisation( ) { private val buildings: MutableList = mutableListOf() private val villagers: MutableList = mutableListOf() - val players: MutableList = mutableListOf() - fun addPlayer(player: Player) { - players.add(player) - player.sendMessage("Joined team ${name()}") - } + val players get() = Aoe.players.filter { player -> player.value == this.type }.keys + val buildingInventory = AoeInventory("Buildings", BuildingType.entries.size) protected abstract fun getBuildingInfo(type: BuildingType): BuildingInfo - protected abstract fun name(): String + protected abstract val name: String + protected abstract val type: CivilisationType + + init { + buildingInventory.addItem() + } fun addBuilding(location: Location, buildingInfo: BuildingInfo, variant: Int): Building { val building = buildingInfo.create(location, variant) @@ -47,9 +53,31 @@ abstract class Civilisation( townCenter.placeFull() // Spawn initial villagers - for (i in 0..Constants.STARTING_VILLAGER_COUNT) - villagers.add(AoeVillager(townCenter.villagerSpawnLocation)) + for (i in 0..< Constants.STARTING_VILLAGER_COUNT) { + val villager = AoeVillager(townCenter.villagerSpawnLocation, type) + villager.leaveBuilding(townCenter) + villagers.add(villager) + } + + // tp players above town center + for (player in players) { + player.teleport(townCenter.location + .clone() + .add(townCenterInfo.getSize(variant).x / 2, 0.0, townCenterInfo.getSize(variant).z / 2) + .toHighestLocation() + .add(0.0, 10.0, 0.0)) + + player.isFlying = true + } } fun populationCap() = min(Constants.MAX_POP_CAP, buildings.sumOf { building -> building.populationCapacity }) + + fun selectVillagers(location: Location, sizeX: Float, sizeY: Float, sizeZ: Float) { + (location.world as CraftWorld).handle.getEntitiesOfClass( + AoeVillager::class.java, + AABB(location.x, location.y, location.z, location.x + sizeX, location.y + sizeY, location.z + sizeZ) + ) + { villager -> villager.civilisationType == type } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/civilisation/Plains.kt b/src/main/kotlin/com/pobnellion/aoe/civilisation/Plains.kt index 9db774a..a1a6656 100644 --- a/src/main/kotlin/com/pobnellion/aoe/civilisation/Plains.kt +++ b/src/main/kotlin/com/pobnellion/aoe/civilisation/Plains.kt @@ -7,7 +7,8 @@ import com.pobnellion.aoe.building.plains.PlainsTownCenter import org.bukkit.Location class Plains(setupLocation: Location) : Civilisation(setupLocation) { - override fun name(): String = "Plains" + override val name: String = "Plains" + override val type: CivilisationType = CivilisationType.PLAINS override fun getBuildingInfo(type: BuildingType): BuildingInfo { return when (type) { diff --git a/src/main/kotlin/com/pobnellion/aoe/command/TestCommand.kt b/src/main/kotlin/com/pobnellion/aoe/command/TestCommand.kt index f81b067..02a6243 100644 --- a/src/main/kotlin/com/pobnellion/aoe/command/TestCommand.kt +++ b/src/main/kotlin/com/pobnellion/aoe/command/TestCommand.kt @@ -48,7 +48,7 @@ class TestCommand : CommandExecutor { CivilisationType.PLAINS -> Aoe.civilisations[CivilisationType.PLAINS] = Plains(Aoe.map.getStartingLocations()[0]) } - Aoe.civilisations[civilisationType]!!.addPlayer(player) + Aoe.players[player] = civilisationType } } diff --git a/src/main/kotlin/com/pobnellion/aoe/entity/Villager.kt b/src/main/kotlin/com/pobnellion/aoe/entity/AoeVillager.kt similarity index 59% rename from src/main/kotlin/com/pobnellion/aoe/entity/Villager.kt rename to src/main/kotlin/com/pobnellion/aoe/entity/AoeVillager.kt index 1bf9edd..e578137 100644 --- a/src/main/kotlin/com/pobnellion/aoe/entity/Villager.kt +++ b/src/main/kotlin/com/pobnellion/aoe/entity/AoeVillager.kt @@ -1,13 +1,16 @@ package com.pobnellion.aoe.entity import com.pobnellion.aoe.building.Building +import com.pobnellion.aoe.civilisation.CivilisationType import com.pobnellion.aoe.entity.goals.GoToBuildingGoal +import com.pobnellion.aoe.entity.goals.LeaveBuildingGoal 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) { +class AoeVillager(location: Location, var civilisationType: CivilisationType) + : Villager(EntityType.VILLAGER, (location.world as CraftWorld).handle) { init { setPos(location.x, location.y, location.z) level().addFreshEntity(this) @@ -15,6 +18,10 @@ class AoeVillager(location: Location) : Villager(EntityType.VILLAGER, (location. targetSelector.removeAllGoals { true } } + fun leaveBuilding(building: Building) { + targetSelector.addGoal(0, LeaveBuildingGoal(this, building, 1.0)) + } + fun goToBuilding(building: Building) { targetSelector.addGoal(0, GoToBuildingGoal(this, building, 1.0)) } diff --git a/src/main/kotlin/com/pobnellion/aoe/entity/goals/LeaveBuildingGoal.kt b/src/main/kotlin/com/pobnellion/aoe/entity/goals/LeaveBuildingGoal.kt new file mode 100644 index 0000000..379cc6f --- /dev/null +++ b/src/main/kotlin/com/pobnellion/aoe/entity/goals/LeaveBuildingGoal.kt @@ -0,0 +1,52 @@ +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 net.minecraft.world.entity.ai.util.DefaultRandomPos +import net.minecraft.world.level.pathfinder.Path +import net.minecraft.world.phys.Vec3 +import java.util.* +import kotlin.math.sqrt +import kotlin.math.pow + +class LeaveBuildingGoal( + private val mob: PathfinderMob, + private val building: Building, + private var speedModifier: Double +): Goal() { + private var path: Path? = null + + init { + this.setFlags(EnumSet.of(Flag.MOVE)) + } + + override fun canUse(): Boolean { + val buildingCornerDistance = sqrt((building.sizeX.toFloat().pow(2) + building.sizeZ.toFloat().pow(2))) + val buildingCenter = building.center() + val fromPosition = Vec3(buildingCenter.x, buildingCenter.y, buildingCenter.z) + val posAway = DefaultRandomPos.getPosAway(mob, (buildingCornerDistance / 2).toInt(), 2, fromPosition) + + if (posAway == null) + return false + + if (fromPosition.distanceToSqr(posAway.x, posAway.y, posAway.z) < fromPosition.distanceToSqr(mob.position())) + return false + + path = mob.navigation.createPath(posAway.x, posAway.y, posAway.z, 0) + return path != null + } + + override fun start() { + mob.navigation.moveTo(path, speedModifier) + } + + override fun tick() { + if (!canContinueToUse()) + mob.targetSelector.removeGoal(this) + } + + override fun canContinueToUse(): Boolean { + return !mob.navigation.isDone + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/aoe/ui/AoeInventory.kt b/src/main/kotlin/com/pobnellion/aoe/ui/AoeInventory.kt new file mode 100644 index 0000000..2e9c159 --- /dev/null +++ b/src/main/kotlin/com/pobnellion/aoe/ui/AoeInventory.kt @@ -0,0 +1,13 @@ +package com.pobnellion.aoe.ui + +import net.kyori.adventure.text.Component +import org.bukkit.Bukkit +import org.bukkit.inventory.Inventory + +class AoeInventory(name: String, size: Int) { + val inventory: Inventory = Bukkit.createInventory(null, size + size % 9, Component.text(name)) + + fun addItem() { + + } +} \ 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 index 111aa35..01e6306 100644 --- a/src/main/kotlin/com/pobnellion/aoe/ui/AreaPlaceHint.kt +++ b/src/main/kotlin/com/pobnellion/aoe/ui/AreaPlaceHint.kt @@ -1,13 +1,6 @@ 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 @@ -22,7 +15,7 @@ class AreaPlaceHint( private val sizeY: Float, private val sizeZ: Float, private val onConfirm: (Location, Float, Float, Float) -> Unit, - private val validate: (Location, Float, Float, Float) -> Boolean + private val onTick: (Location, Float, Float, Float) -> Unit, ) : PlaceHint() { companion object { fun add( @@ -31,12 +24,12 @@ class AreaPlaceHint( sizeY: Float, sizeZ: Float, onConfirm: (Location, Float, Float, Float) -> Unit, - validate: (Location, Float, Float, Float) -> Boolean, + onTick: (Location, Float, Float, Float) -> Unit, ) { remove(player) createOutlineTeam(player) - playerHints[player.uniqueId] = AreaPlaceHint(player, sizeX, sizeY, sizeZ, onConfirm, validate) + playerHints[player.uniqueId] = AreaPlaceHint(player, sizeX, sizeY, sizeZ, onConfirm, onTick) val block = player.getTargetBlockExact(MAX_TARGET_DISTANCE) playerHints[player.uniqueId]!!.moveTo(block?.location) } @@ -48,9 +41,14 @@ class AreaPlaceHint( this.offset = Vector(sizeX / 2.0, 0.0, sizeZ / 2.0) } - override fun validate(location: Location) = validate(location, sizeX, sizeY, sizeZ) + override fun tick() { + currentLocation?.let { onTick(it, sizeX, sizeY, sizeZ) } + } - override fun confirm() = onConfirm(currentLocation!!, sizeX, sizeY, sizeZ) + override fun confirm(): Boolean { + currentLocation?.let { onConfirm(it, sizeX, sizeY, sizeZ) } + return true + } override fun addDisplays(initialLocation: Location) { base = spawnBlockDisplay(initialLocation, Material.GRAY_STAINED_GLASS.createBlockData(), @@ -58,23 +56,23 @@ class AreaPlaceHint( } - 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) - } +// override fun updateGlowColour(colour: ChatFormatting) { +// super.updateGlowColour(colour) +// +// // 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 index 5c32c19..4a3e8fb 100644 --- a/src/main/kotlin/com/pobnellion/aoe/ui/BuildingPlaceHint.kt +++ b/src/main/kotlin/com/pobnellion/aoe/ui/BuildingPlaceHint.kt @@ -1,5 +1,6 @@ package com.pobnellion.aoe.ui +import com.comphenix.protocol.wrappers.EnumWrappers import com.pobnellion.aoe.Aoe import com.pobnellion.aoe.building.BuildingInfo import com.sk89q.worldedit.bukkit.BukkitAdapter @@ -36,6 +37,7 @@ class BuildingPlaceHint( } private val schematic: Clipboard + private var isValid = false init { val schematicName = buildingInfo.schematicNames[buildingVariant] @@ -53,9 +55,23 @@ class BuildingPlaceHint( -floor(clipboard.dimensions.z() / 2.0)) } - override fun validate(location: Location) = buildingInfo.validate(location) + override fun tick() { + // Update material + val valid = currentLocation?.let { buildingInfo.validate(it) } ?: false - override fun confirm() = onConfirm(currentLocation!!, buildingInfo, buildingVariant) + if (valid != isValid) { + isValid = valid + updateGlowColour(if (isValid) EnumWrappers.ChatFormatting.GREEN else EnumWrappers.ChatFormatting.RED) + } + } + + override fun confirm(): Boolean { + if (!isValid || currentLocation == null) + return false + + onConfirm(currentLocation!!, buildingInfo, buildingVariant) + return true + } override fun addDisplays(initialLocation: Location) { schematic.iterator().forEach { blockPosition -> diff --git a/src/main/kotlin/com/pobnellion/aoe/ui/PlaceItem.kt b/src/main/kotlin/com/pobnellion/aoe/ui/InventoryManager.kt similarity index 64% rename from src/main/kotlin/com/pobnellion/aoe/ui/PlaceItem.kt rename to src/main/kotlin/com/pobnellion/aoe/ui/InventoryManager.kt index 7806fdf..986bf21 100644 --- a/src/main/kotlin/com/pobnellion/aoe/ui/PlaceItem.kt +++ b/src/main/kotlin/com/pobnellion/aoe/ui/InventoryManager.kt @@ -2,8 +2,8 @@ package com.pobnellion.aoe.ui import com.pobnellion.aoe.Aoe import com.pobnellion.aoe.building.BuildingType +import com.pobnellion.aoe.getCivilisation import net.kyori.adventure.text.Component -import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.entity.Player import org.bukkit.event.EventHandler @@ -16,8 +16,8 @@ import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack -class PlaceItem : Listener { - private val buildingInventory = Bukkit.createInventory(null, 9, Component.text("Buildings")) +class InventoryManager : Listener { + private val buildingInventory = init { buildingInventory.addItem(createGuiItem(Material.BELL, "Town center", "middle of the town :D")) @@ -25,6 +25,25 @@ class PlaceItem : Listener { buildingInventory.addItem(createGuiItem(Material.EMERALD, "Villager", "willager")) } + fun initHotbars() { + for (player in Aoe.players.keys) { + player.inventory.clear() + player.inventory.setItem(0, createGuiItem(Material.BRICKS, "Buildings")) + + // TODO: double click select selects all of looking at type + player.inventory.setItem(6, createGuiItem(Material.WOODEN_HOE, "Select inactive villagers")) + player.inventory.setItem(7, createGuiItem(Material.IRON_HOE, "Select villagers")) + player.inventory.setItem(8, createGuiItem(Material.IRON_SWORD, "Select army")) + } + } + + fun showBuildingInventory(player: Player) { + if (Aoe.isPlaying(player)) + player.openInventory(player.getCivilisation()!!.buildingInventory.inventory) + } + + // region events + @EventHandler fun onRightClickItem(event: PlayerInteractEvent) { if (event.action != Action.RIGHT_CLICK_AIR && event.action != Action.RIGHT_CLICK_BLOCK) @@ -40,18 +59,20 @@ class PlaceItem : Listener { return event.isCancelled = true - event.player.openInventory(buildingInventory) + showBuildingInventory(event.player) } @EventHandler fun onInventoryClick(event: InventoryClickEvent) { + if (Aoe.players.containsKey(event.whoClicked as Player)) + event.isCancelled = true + val player = event.whoClicked as Player val team = Aoe.getTeam(player) ?: return if (event.inventory != buildingInventory) return - event.isCancelled = true var validClick = true when (event.currentItem?.type) { @@ -67,14 +88,19 @@ class PlaceItem : Listener { @EventHandler fun onInventoryClick(event: InventoryDragEvent) { - if (event.inventory == buildingInventory) + if (Aoe.players.containsKey(event.whoClicked as Player)) event.isCancelled = true } - private fun createGuiItem(material: Material, name: String, lore: String): ItemStack { + // endregion + + private fun createGuiItem(material: Material, name: String, lore: String? = null): ItemStack { val item = ItemStack(material, 1) item.itemMeta.displayName(Component.text(name)) - item.itemMeta.lore(mutableListOf(Component.text(lore))) + + if (lore != null) + item.itemMeta.lore(mutableListOf(Component.text(lore))) + return item } } \ 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 ae530c3..199c8a8 100644 --- a/src/main/kotlin/com/pobnellion/aoe/ui/PlaceHint.kt +++ b/src/main/kotlin/com/pobnellion/aoe/ui/PlaceHint.kt @@ -4,6 +4,7 @@ import com.comphenix.protocol.PacketType import com.comphenix.protocol.ProtocolLibrary import com.comphenix.protocol.events.PacketContainer import com.comphenix.protocol.wrappers.* +import com.comphenix.protocol.wrappers.EnumWrappers.ChatFormatting import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry import com.destroystokyo.paper.MaterialSetTag import org.bukkit.Location @@ -73,11 +74,8 @@ abstract class PlaceHint { // left click - confirm if (event.action == Action.LEFT_CLICK_BLOCK || event.action == Action.LEFT_CLICK_AIR) { - if (!playerHints[event.player.uniqueId]!!.isValid) - return - - playerHints[event.player.uniqueId]!!.confirm() - remove(event.player) + if (playerHints[event.player.uniqueId]!!.confirm()) + remove(event.player) } // right click - cancel @@ -91,7 +89,7 @@ abstract class PlaceHint { .collisionRule("never") .nametagVisibility("never") .options(0) - .color(EnumWrappers.ChatFormatting.RED) + .color(ChatFormatting.RED) .prefix(WrappedChatComponent.fromText("")) .suffix(WrappedChatComponent.fromText("")) .build() @@ -102,11 +100,10 @@ abstract class PlaceHint { private var marker: Pair = Pair((Math.random() * Int.MAX_VALUE).toInt(), UUID.randomUUID()) protected val displayIds: MutableList> = mutableListOf() var currentLocation: Location? = null - var isValid = false protected abstract fun addDisplays(initialLocation: Location) - protected abstract fun confirm() - protected abstract fun validate(location: Location): Boolean + protected abstract fun confirm(): Boolean + protected abstract fun tick() private fun show(initialLocation: Location) { initialLocation.add(this.offset) @@ -138,8 +135,7 @@ abstract class PlaceHint { ProtocolLibrary.getProtocolManager().sendServerPacket(player, outlineTeamPacket) ProtocolLibrary.getProtocolManager().sendServerPacket(player, passengerPacket) - isValid = validate(initialLocation) - updateColour() + tick() } private fun hide() { @@ -181,13 +177,7 @@ abstract class PlaceHint { currentLocation = newLocation - // Update material - val valid = validate(newLocation) - - if (valid != isValid) { - isValid = valid - updateColour() - } + this.tick() } // region helper functions @@ -234,13 +224,13 @@ abstract class PlaceHint { return Pair(id, uuid) } - protected open fun updateColour() { + protected open fun updateGlowColour(colour: ChatFormatting) { // outline glow val outlineTeamPacket = PacketContainer(PacketType.Play.Server.SCOREBOARD_TEAM) outlineTeamPacket.strings.write(0, "placeValid") outlineTeamPacket.integers.write(0, 2) val params = WrappedTeamParameters.newBuilder(teamParamsTemplate) - .color(if (isValid) EnumWrappers.ChatFormatting.GREEN else EnumWrappers.ChatFormatting.RED) + .color(colour) .build() outlineTeamPacket.optionalTeamParameters.write(0, Optional.of(params))