diff --git a/build.gradle.kts b/build.gradle.kts index ad7f8bf13..071424f32 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -41,8 +41,8 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2") // Custom dependencies - implementation("com.github.shynixn.mcutils:common:2024.19") - implementation("com.github.shynixn.mcutils:packet:2024.32") + implementation("com.github.shynixn.mcutils:common:2024.20") + implementation("com.github.shynixn.mcutils:packet:2024.33") implementation("com.github.shynixn.mcutils:database:2024.2") implementation("com.github.shynixn.mcutils:sign:2024.3") implementation("com.github.shynixn.mcutils:guice:2024.2") diff --git a/src/main/java/com/github/shynixn/blockball/BlockBallDependencyInjectionModule.kt b/src/main/java/com/github/shynixn/blockball/BlockBallDependencyInjectionModule.kt index 0d0c31e30..c3aaa24a9 100644 --- a/src/main/java/com/github/shynixn/blockball/BlockBallDependencyInjectionModule.kt +++ b/src/main/java/com/github/shynixn/blockball/BlockBallDependencyInjectionModule.kt @@ -4,8 +4,10 @@ import com.fasterxml.jackson.core.type.TypeReference import com.github.shynixn.blockball.contract.* import com.github.shynixn.blockball.entity.SoccerArena import com.github.shynixn.blockball.entity.PlayerInformation +import com.github.shynixn.blockball.enumeration.Permission import com.github.shynixn.blockball.impl.service.* import com.github.shynixn.mccoroutine.bukkit.launch +import com.github.shynixn.mccoroutine.bukkit.minecraftDispatcher import com.github.shynixn.mcutils.common.ConfigurationService import com.github.shynixn.mcutils.common.ConfigurationServiceImpl import com.github.shynixn.mcutils.common.CoroutineExecutor @@ -15,6 +17,7 @@ import com.github.shynixn.mcutils.common.repository.CacheRepository import com.github.shynixn.mcutils.common.repository.CachedRepositoryImpl import com.github.shynixn.mcutils.common.repository.Repository import com.github.shynixn.mcutils.common.repository.YamlFileRepositoryImpl +import com.github.shynixn.mcutils.common.selection.AreaSelectionService import com.github.shynixn.mcutils.common.sound.SoundService import com.github.shynixn.mcutils.common.sound.SoundServiceImpl import com.github.shynixn.mcutils.database.api.CachePlayerRepository @@ -23,14 +26,17 @@ import com.github.shynixn.mcutils.database.impl.AutoSavePlayerDataRepositoryImpl import com.github.shynixn.mcutils.database.impl.CachePlayerDataRepositoryImpl import com.github.shynixn.mcutils.database.impl.ConfigSelectedRepositoryImpl import com.github.shynixn.mcutils.guice.DependencyInjectionModule +import com.github.shynixn.mcutils.packet.api.Packet import com.github.shynixn.mcutils.packet.api.PacketService import com.github.shynixn.mcutils.packet.api.RayTracingService import com.github.shynixn.mcutils.packet.impl.service.ChatMessageServiceImpl import com.github.shynixn.mcutils.packet.impl.service.ItemServiceImpl import com.github.shynixn.mcutils.packet.impl.service.PacketServiceImpl import com.github.shynixn.mcutils.packet.impl.service.RayTracingServiceImpl +import com.github.shynixn.mcutils.packet.nms.v1_21_R1.AreaSelectionServiceImpl import com.github.shynixn.mcutils.sign.SignService import com.github.shynixn.mcutils.sign.SignServiceImpl +import kotlinx.coroutines.CoroutineDispatcher import org.bukkit.Bukkit import org.bukkit.plugin.Plugin import java.util.logging.Level @@ -101,7 +107,25 @@ class BlockBallDependencyInjectionModule( addService(ChatMessageServiceImpl(plugin)) addService() addService() - addService() + addService { + AreaSelectionServiceImpl( + Permission.EDIT_GAME.permission, + plugin, + getService(), + getService(), + object : CoroutineExecutor { + override fun execute(f: suspend () -> Unit) { + plugin.launch { f.invoke() } + } + }, + plugin.minecraftDispatcher as CoroutineDispatcher, + object : CoroutineExecutor { + override fun execute(f: suspend () -> Unit) { + plugin.launch { f.invoke() } + } + } + ) + } addService() if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { diff --git a/src/main/java/com/github/shynixn/blockball/BlockBallLanguageImpl.kt b/src/main/java/com/github/shynixn/blockball/BlockBallLanguageImpl.kt index 1fa14d4d9..f3fadc90c 100644 --- a/src/main/java/com/github/shynixn/blockball/BlockBallLanguageImpl.kt +++ b/src/main/java/com/github/shynixn/blockball/BlockBallLanguageImpl.kt @@ -21,6 +21,9 @@ object BlockBallLanguageImpl : BlockBallLanguage { /** &0&l[&f&lBlockBall&0&l]&c Team %1$1s does not exist. **/ override var teamDoesNotExistMessage : String = "&0&l[&f&lBlockBall&0&l]&c Team %1$1s does not exist." + /** &0&l[&f&lBlockBall&0&l]&c This selection type is not known. **/ + override var selectionTypeDoesNotExistMessage : String = "&0&l[&f&lBlockBall&0&l]&c This selection type is not known. " + /** &0&l[&f&lBlockBall&0&l]&7 Reloaded game %1$1s. **/ override var reloadedGameMessage : String = "&0&l[&f&lBlockBall&0&l]&7 Reloaded game %1$1s." @@ -75,6 +78,9 @@ object BlockBallLanguageImpl : BlockBallLanguage { /** 60 **/ override var winBlueStay : String = "60" + /** Updates a location selection of a part of the arena. **/ + override var commandSelectionToolTip : String = "Updates a location selection of a part of the arena." + /** &0&l[&f&lBlockBall&0&l]&7 Created game %1$1s. **/ override var gameCreatedMessage : String = "&0&l[&f&lBlockBall&0&l]&7 Created game %1$1s." @@ -114,9 +120,6 @@ object BlockBallLanguageImpl : BlockBallLanguage { /** All commands for the BlockBall plugin. **/ override var commandDescription : String = "All commands for the BlockBall plugin." - /** &0&l[&f&lBlockBall&0&l]&c This location type is not known. For more locations, open the arena.yml. **/ - override var locationTypeDoesNotExistMessage : String = "&0&l[&f&lBlockBall&0&l]&c This location type is not known. For more locations, open the arena.yml." - /** &0&l[&f&lBlockBall&0&l]&c You do not have permission. **/ override var noPermissionMessage : String = "&0&l[&f&lBlockBall&0&l]&c You do not have permission." @@ -144,6 +147,9 @@ object BlockBallLanguageImpl : BlockBallLanguage { /** &aJoin **/ override var gameStatusJoinAble : String = "&aJoin" + /** Gives you the BlockBall selection axe. **/ + override var commandAxeToolTip : String = "Gives you the BlockBall selection axe." + /** Lets the player executing the command join the game. The optional team argument allows to directly join a specific team. If the team is full, the other team will be chosen. If no team is specified, a random team will be selected. **/ override var commandJoinToolTip : String = "Lets the player executing the command join the game. The optional team argument allows to directly join a specific team. If the team is full, the other team will be chosen. If no team is specified, a random team will be selected." @@ -159,12 +165,18 @@ object BlockBallLanguageImpl : BlockBallLanguage { /** &9[Team Blue] **/ override var hubGameJoinBlue : String = "&9[Team Blue]" - /** Updates the location of a part of the arena. **/ - override var commandLocationToolTip : String = "Updates the location of a part of the arena." - /** &9Team Blue **/ override var winBlueTitle : String = "&9Team Blue" + /** Toggles highlighting the important areas of your arena. **/ + override var commandHighlightToolTip : String = "Toggles highlighting the important areas of your arena." + + /** Sets a selected location for your arena. **/ + override var commandSelectToolTip : String = "Sets a selected location for your arena." + + /** &0&l[&f&lBlockBall&0&l]&7 Selection %1$1s was set. **/ + override var selectionSetMessage : String = "&0&l[&f&lBlockBall&0&l]&7 Selection %1$1s was set." + /** 60 **/ override var winDrawStay : String = "60" @@ -174,11 +186,14 @@ object BlockBallLanguageImpl : BlockBallLanguage { /** &4Disabled **/ override var gameStatusDisabled : String = "&4Disabled" + /** &0&l[&f&lBlockBall&0&l]&c You need to select a location using the BlockBall axe with left click. **/ + override var noLeftClickSelectionMessage : String = "&0&l[&f&lBlockBall&0&l]&c You need to select a location using the BlockBall axe with left click." + /** &0&l[&f&lBlockBall&0&l]&7 Updated inventory of game. **/ override var updatedInventoryMessage : String = "&0&l[&f&lBlockBall&0&l]&7 Updated inventory of game." - /** &0&l[&f&lBlockBall&0&l]&7 Location %1$1s was set on %2$1s. **/ - override var spawnPointSetMessage : String = "&0&l[&f&lBlockBall&0&l]&7 Location %1$1s was set on %2$1s." + /** &0&l[&f&lBlockBall&0&l]&c You need to select a location using the BlockBall axe with right click. **/ + override var noRightClickSelectionMessage : String = "&0&l[&f&lBlockBall&0&l]&c You need to select a location using the BlockBall axe with right click." /** 20 **/ override var scoreBlueFadeIn : String = "20" diff --git a/src/main/java/com/github/shynixn/blockball/BlockBallPlugin.kt b/src/main/java/com/github/shynixn/blockball/BlockBallPlugin.kt index 547c248b4..fe3ebda7b 100644 --- a/src/main/java/com/github/shynixn/blockball/BlockBallPlugin.kt +++ b/src/main/java/com/github/shynixn/blockball/BlockBallPlugin.kt @@ -13,6 +13,7 @@ import com.github.shynixn.mcutils.common.ConfigurationService import com.github.shynixn.mcutils.common.Version import com.github.shynixn.mcutils.common.reloadTranslation import com.github.shynixn.mcutils.common.repository.Repository +import com.github.shynixn.mcutils.common.selection.AreaSelectionService import com.github.shynixn.mcutils.database.api.CachePlayerRepository import com.github.shynixn.mcutils.database.api.PlayerDataRepository import com.github.shynixn.mcutils.guice.DependencyInjectionModule @@ -24,11 +25,9 @@ import org.bstats.bukkit.Metrics import org.bukkit.Bukkit import org.bukkit.plugin.ServicePriority import org.bukkit.plugin.java.JavaPlugin -import java.io.File import java.nio.file.Files -import java.nio.file.Paths import java.nio.file.StandardCopyOption -import java.util.UUID +import java.util.* import java.util.logging.Level /** @@ -105,7 +104,6 @@ class BlockBallPlugin : JavaPlugin() { Bukkit.getPluginManager().registerEvents(module.getService(), this) Bukkit.getPluginManager().registerEvents(module.getService(), this) Bukkit.getPluginManager().registerEvents(module.getService(), this) - Bukkit.getPluginManager().registerEvents(module.getService(), this) // Register CommandExecutor module.getService() @@ -229,6 +227,7 @@ class BlockBallPlugin : JavaPlugin() { } module.getService().close() + module.getService().close() val playerDataRepository = module.getService>() runBlocking { diff --git a/src/main/java/com/github/shynixn/blockball/contract/BlockBallLanguage.kt b/src/main/java/com/github/shynixn/blockball/contract/BlockBallLanguage.kt index 8afe05a9c..5c24d308b 100644 --- a/src/main/java/com/github/shynixn/blockball/contract/BlockBallLanguage.kt +++ b/src/main/java/com/github/shynixn/blockball/contract/BlockBallLanguage.kt @@ -19,6 +19,9 @@ interface BlockBallLanguage { /** &0&l[&f&lBlockBall&0&l]&c Team %1$1s does not exist. **/ var teamDoesNotExistMessage : String + /** &0&l[&f&lBlockBall&0&l]&c This selection type is not known. **/ + var selectionTypeDoesNotExistMessage : String + /** &0&l[&f&lBlockBall&0&l]&7 Reloaded game %1$1s. **/ var reloadedGameMessage : String @@ -73,6 +76,9 @@ interface BlockBallLanguage { /** 60 **/ var winBlueStay : String + /** Updates a location selection of a part of the arena. **/ + var commandSelectionToolTip : String + /** &0&l[&f&lBlockBall&0&l]&7 Created game %1$1s. **/ var gameCreatedMessage : String @@ -112,9 +118,6 @@ interface BlockBallLanguage { /** All commands for the BlockBall plugin. **/ var commandDescription : String - /** &0&l[&f&lBlockBall&0&l]&c This location type is not known. For more locations, open the arena.yml. **/ - var locationTypeDoesNotExistMessage : String - /** &0&l[&f&lBlockBall&0&l]&c You do not have permission. **/ var noPermissionMessage : String @@ -142,6 +145,9 @@ interface BlockBallLanguage { /** &aJoin **/ var gameStatusJoinAble : String + /** Gives you the BlockBall selection axe. **/ + var commandAxeToolTip : String + /** Lets the player executing the command join the game. The optional team argument allows to directly join a specific team. If the team is full, the other team will be chosen. If no team is specified, a random team will be selected. **/ var commandJoinToolTip : String @@ -157,12 +163,18 @@ interface BlockBallLanguage { /** &9[Team Blue] **/ var hubGameJoinBlue : String - /** Updates the location of a part of the arena. **/ - var commandLocationToolTip : String - /** &9Team Blue **/ var winBlueTitle : String + /** Toggles highlighting the important areas of your arena. **/ + var commandHighlightToolTip : String + + /** Sets a selected location for your arena. **/ + var commandSelectToolTip : String + + /** &0&l[&f&lBlockBall&0&l]&7 Selection %1$1s was set. **/ + var selectionSetMessage : String + /** 60 **/ var winDrawStay : String @@ -172,11 +184,14 @@ interface BlockBallLanguage { /** &4Disabled **/ var gameStatusDisabled : String + /** &0&l[&f&lBlockBall&0&l]&c You need to select a location using the BlockBall axe with left click. **/ + var noLeftClickSelectionMessage : String + /** &0&l[&f&lBlockBall&0&l]&7 Updated inventory of game. **/ var updatedInventoryMessage : String - /** &0&l[&f&lBlockBall&0&l]&7 Location %1$1s was set on %2$1s. **/ - var spawnPointSetMessage : String + /** &0&l[&f&lBlockBall&0&l]&c You need to select a location using the BlockBall axe with right click. **/ + var noRightClickSelectionMessage : String /** 20 **/ var scoreBlueFadeIn : String diff --git a/src/main/java/com/github/shynixn/blockball/entity/Selection.kt b/src/main/java/com/github/shynixn/blockball/entity/Selection.kt index c4631e227..867b13330 100644 --- a/src/main/java/com/github/shynixn/blockball/entity/Selection.kt +++ b/src/main/java/com/github/shynixn/blockball/entity/Selection.kt @@ -10,38 +10,38 @@ open class Selection { /** [upperCorner] of the selected square soccerArena. */ @JsonProperty("corner1") - final var upperCorner: Vector3d = Vector3d() + var upperCorner: Vector3d? = null /** [lowerCorner] of the selected square soccerArena. */ @JsonProperty("corner2") - final var lowerCorner: Vector3d = Vector3d() + var lowerCorner: Vector3d? = null /** [center] of the soccerArena */ val center: Vector3d get() { return Vector3d( - this.lowerCorner.world!!, - (this.lowerCorner.blockX + this.offsetX / 2).toDouble(), - (this.lowerCorner.blockY + offsetX / 2).toDouble(), (this.lowerCorner.blockZ + offsetZ / 2).toDouble() + this.lowerCorner!!.world!!, + (this.lowerCorner!!.blockX + this.offsetX / 2).toDouble(), + (this.lowerCorner!!.blockY + offsetX / 2).toDouble(), (this.lowerCorner!!.blockZ + offsetZ / 2).toDouble() ) } /** Length of the x axe. */ val offsetX: Int get() { - return this.upperCorner.blockX - this.lowerCorner.blockX + 1 + return this.upperCorner!!.blockX - this.lowerCorner!!.blockX + 1 } /** Length of the y axe. */ val offsetY: Int get() { - return this.upperCorner.blockY - this.lowerCorner.blockY + 1 + return this.upperCorner!!.blockY - this.lowerCorner!!.blockY + 1 } /** Length of the z axe. */ val offsetZ: Int get() { - return this.upperCorner.blockZ - this.lowerCorner.blockZ + return this.upperCorner!!.blockZ - this.lowerCorner!!.blockZ } @@ -55,10 +55,10 @@ open class Selection { * Is location inside of this selection. */ fun isLocationInSelection(location: Vector3d): Boolean { - if (location.world != null && location.world == this.upperCorner.world) { - if (this.upperCorner.x >= location.x && this.lowerCorner.x <= location.x) { - if (this.upperCorner.y >= location.y + 1 && this.lowerCorner.y <= location.y + 1) { - if (this.upperCorner.z >= location.z && this.lowerCorner.z <= location.z) { + if (location.world != null && location.world == this.upperCorner!!.world) { + if (this.upperCorner!!.x >= location.x && this.lowerCorner!!.x <= location.x) { + if (this.upperCorner!!.y >= location.y + 1 && this.lowerCorner!!.y <= location.y + 1) { + if (this.upperCorner!!.z >= location.z && this.lowerCorner!!.z <= location.z) { return true } } @@ -72,19 +72,19 @@ open class Selection { * in which the soccerArena can be reached. */ fun getRelativeBlockDirectionToLocation(location: Vector3d): BlockDirection { - if (location.blockX >= upperCorner.blockX && this.upperCorner.z >= location.z && this.lowerCorner.z <= location.z) { + if (location.blockX >= upperCorner!!.blockX && this.upperCorner!!.z >= location.z && this.lowerCorner!!.z <= location.z) { return BlockDirection.WEST } - if (location.blockX <= lowerCorner.blockX && this.upperCorner.z >= location.z && this.lowerCorner.z <= location.z) { + if (location.blockX <= lowerCorner!!.blockX && this.upperCorner!!.z >= location.z && this.lowerCorner!!.z <= location.z) { return BlockDirection.EAST } - if (location.blockZ >= upperCorner.blockZ && this.upperCorner.x >= location.x && this.lowerCorner.x <= location.x) { + if (location.blockZ >= upperCorner!!.blockZ && this.upperCorner!!.x >= location.x && this.lowerCorner!!.x <= location.x) { return BlockDirection.NORTH } - if (location.blockZ <= lowerCorner.blockZ && this.upperCorner.x >= location.x && this.lowerCorner.x <= location.x) { + if (location.blockZ <= lowerCorner!!.blockZ && this.upperCorner!!.x >= location.x && this.lowerCorner!!.x <= location.x) { return BlockDirection.SOUTH } diff --git a/src/main/java/com/github/shynixn/blockball/enumeration/LocationType.kt b/src/main/java/com/github/shynixn/blockball/enumeration/LocationType.kt deleted file mode 100644 index 6fd6fb56d..000000000 --- a/src/main/java/com/github/shynixn/blockball/enumeration/LocationType.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.github.shynixn.blockball.enumeration - -enum class LocationType(val id: String) { - LOBBY_RED("lobbyRed"), - LOBBY_BLUE("lobbyBlue"), - LEAVE("leave"), - SPAWN_RED_1("spawnRed1"), - SPAWN_BLUE_1("spawnBlue1"), - CORNER_RED_1("cornerRed1"), - CORNER_RED_2("cornerRed2"), - CORNER_BLUE_1("cornerBlue1"), - CORNER_BLUE_2("cornerBlue2"), -} diff --git a/src/main/java/com/github/shynixn/blockball/enumeration/SelectionType.kt b/src/main/java/com/github/shynixn/blockball/enumeration/SelectionType.kt new file mode 100644 index 000000000..f0191f5f6 --- /dev/null +++ b/src/main/java/com/github/shynixn/blockball/enumeration/SelectionType.kt @@ -0,0 +1,8 @@ +package com.github.shynixn.blockball.enumeration + +enum class SelectionType { + FIELD, + BALL, + RED_GOAL, + BLUE_GOAL +} diff --git a/src/main/java/com/github/shynixn/blockball/impl/commandexecutor/BlockBallCommandExecutor.kt b/src/main/java/com/github/shynixn/blockball/impl/commandexecutor/BlockBallCommandExecutor.kt index f1a168cb7..cb8b35465 100644 --- a/src/main/java/com/github/shynixn/blockball/impl/commandexecutor/BlockBallCommandExecutor.kt +++ b/src/main/java/com/github/shynixn/blockball/impl/commandexecutor/BlockBallCommandExecutor.kt @@ -15,14 +15,18 @@ import com.github.shynixn.mcutils.common.command.CommandMeta import com.github.shynixn.mcutils.common.command.CommandType import com.github.shynixn.mcutils.common.command.Validator import com.github.shynixn.mcutils.common.repository.CacheRepository +import com.github.shynixn.mcutils.common.selection.AreaHighlight +import com.github.shynixn.mcutils.common.selection.AreaSelectionService import com.github.shynixn.mcutils.sign.SignService import com.google.inject.Inject import org.bukkit.command.CommandSender import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.entity.Player import org.bukkit.plugin.Plugin +import java.awt.Color import java.util.* import java.util.logging.Level +import kotlin.collections.ArrayList class BlockBallCommandExecutor @Inject constructor( private val arenaRepository: CacheRepository, @@ -31,6 +35,7 @@ class BlockBallCommandExecutor @Inject constructor( private val configurationService: ConfigurationService, private val language: BlockBallLanguage, private val signService: SignService, + private val selectionService: AreaSelectionService, chatMessageService: ChatMessageService ) { private val arenaTabs: suspend (s: CommandSender) -> List = { @@ -129,15 +134,15 @@ class BlockBallCommandExecutor @Inject constructor( } } - private val locationTypeValidator = object : Validator { + private val selectionTypeValidator = object : Validator { override suspend fun transform( sender: CommandSender, prevArgs: List, openArgs: List - ): LocationType? { - return LocationType.values().firstOrNull { e -> e.id.equals(openArgs[0], true) } + ): SelectionType? { + return SelectionType.values().firstOrNull { e -> e.name.equals(openArgs[0], true) } } override suspend fun message(sender: CommandSender, prevArgs: List, openArgs: List): String { - return language.locationTypeDoesNotExistMessage + return language.selectionTypeDoesNotExistMessage } } private val signTypeValidator = object : Validator { @@ -203,13 +208,34 @@ class BlockBallCommandExecutor @Inject constructor( builder().executePlayer({ language.commandSenderHasToBePlayer }) { sender -> leaveGame(sender) } } helpCommand() - subCommand("location") { + subCommand("axe") { permission(Permission.EDIT_GAME) - toolTip { language.commandLocationToolTip } + toolTip { language.commandAxeToolTip } + builder().executePlayer({ language.commandSenderHasToBePlayer }) { player -> + selectionService.addSelectionItemToInventory(player) + } + } + subCommand("select") { + permission(Permission.EDIT_GAME) + toolTip { language.commandSelectToolTip } builder().argument("name").validator(gameMustExistValidator).tabs(arenaTabs) - .argument("type").validator(locationTypeValidator).tabs { LocationType.values().map { e -> e.id } } + .argument("type").validator(selectionTypeValidator).tabs { + SelectionType.values().map { e -> + e.name.lowercase( + Locale.ENGLISH + ) + } + } .executePlayer({ language.commandSenderHasToBePlayer }) { player, arena, locationType -> - setLocation(player, arena, locationType) + setSelection(player, arena, locationType) + } + } + subCommand("highlight") { + permission(Permission.EDIT_GAME) + toolTip { language.commandHighlightToolTip } + builder().argument("name").validator(gameMustExistValidator).tabs(arenaTabs) + .executePlayer({ language.commandSenderHasToBePlayer }) { player, arena -> + } } subCommand("inventory") { @@ -423,14 +449,46 @@ class BlockBallCommandExecutor @Inject constructor( } } - private suspend fun setLocation(player: Player, arena: SoccerArena, locationType: LocationType) { - if (locationType == LocationType.LOBBY_RED) { - arena.meta.redTeamMeta.lobbySpawnpoint = player.location.toVector3d() + private suspend fun setSelection(player: Player, arena: SoccerArena, selectionType: SelectionType) { + val selectionLeft = selectionService.getLeftClickLocation(player) + val selectionRight = selectionService.getRightClickLocation(player) + + if (selectionType == SelectionType.FIELD || selectionType == SelectionType.RED_GOAL || selectionType == SelectionType.BLUE_GOAL) { + if (selectionLeft == null) { + player.sendMessage(language.noLeftClickSelectionMessage) + return + } + if (selectionRight == null) { + player.sendMessage(language.noRightClickSelectionMessage) + return + } + + if (selectionType == SelectionType.FIELD) { + arena.lowerCorner = selectionLeft.toVector3d() + arena.upperCorner = selectionRight.toVector3d() + } else if (selectionType == SelectionType.RED_GOAL) { + arena.meta.redTeamMeta.goal.lowerCorner = selectionLeft.toVector3d() + arena.meta.redTeamMeta.goal.upperCorner = selectionRight.toVector3d() + } else if (selectionType == SelectionType.BLUE_GOAL) { + arena.meta.blueTeamMeta.goal.lowerCorner = selectionLeft.toVector3d() + arena.meta.blueTeamMeta.goal.upperCorner = selectionRight.toVector3d() + } + } else { + if (selectionLeft == null) { + player.sendMessage(language.noLeftClickSelectionMessage) + return + } + + if (selectionType == SelectionType.BALL) { + arena.meta.ballMeta.spawnpoint = selectionLeft.toVector3d() + } } + arenaRepository.save(arena) - player.sendMessage(language.spawnPointSetMessage.format(locationType.name.uppercase(), player.location)) + player.sendMessage(language.selectionSetMessage.format(selectionType.name.uppercase())) } + private suspend fun setSign(sender: Player, arena: SoccerArena, signType: SignType) { if (signType == SignType.JOIN) { sender.sendMessage(language.rightClickOnSignMessage) @@ -527,4 +585,57 @@ class BlockBallCommandExecutor @Inject constructor( sender.sendMessage(language.reloadedGameMessage.format(arena.name)) return } + + private fun setHighlights(player: Player, arena: SoccerArena) { + if (selectionService.isHighlighting(player)) { + selectionService.removePlayer(player) + } else { + selectionService.setPlayer(player) { + val highLights = ArrayList() + if (arena.lowerCorner != null && arena.upperCorner != null) { + highLights.add( + AreaHighlight( + arena.lowerCorner!!, + arena.upperCorner!!, + Color.BLACK.rgb, + "Field", + true + ) + ) + } + if (arena.meta.redTeamMeta.goal.lowerCorner != null && arena.meta.redTeamMeta.goal.upperCorner != null) { + highLights.add( + AreaHighlight( + arena.meta.redTeamMeta.goal.lowerCorner!!, + arena.meta.redTeamMeta.goal.upperCorner!!, + Color.RED.rgb, + "Red" + ) + ) + } + if (arena.meta.blueTeamMeta.goal.lowerCorner != null && arena.meta.blueTeamMeta.goal.upperCorner != null) { + highLights.add( + AreaHighlight( + arena.meta.blueTeamMeta.goal.lowerCorner!!, + arena.meta.blueTeamMeta.goal.upperCorner!!, + Color.BLUE.rgb, + "Blue" + ) + ) + } + if (arena.meta.ballMeta.spawnpoint != null) { + highLights.add( + AreaHighlight( + arena.meta.ballMeta.spawnpoint!!, + null, + Color.pink.rgb, + "Ball" + ) + ) + } + + highLights + } + } + } } diff --git a/src/main/java/com/github/shynixn/blockball/impl/listener/BlockSelectionListener.kt b/src/main/java/com/github/shynixn/blockball/impl/listener/BlockSelectionListener.kt deleted file mode 100644 index f66813c24..000000000 --- a/src/main/java/com/github/shynixn/blockball/impl/listener/BlockSelectionListener.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.github.shynixn.blockball.impl.listener - -import com.github.shynixn.blockball.contract.BlockSelectionService -import com.google.inject.Inject -import org.bukkit.event.EventHandler -import org.bukkit.event.Listener -import org.bukkit.event.block.Action -import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.event.player.PlayerQuitEvent - -class BlockSelectionListener @Inject constructor(private val blockSelectionService: BlockSelectionService) : Listener { - /** - * Gets called when the player interacts with a block. - */ - @EventHandler - fun onPlayerInteractEvent(event: PlayerInteractEvent) { - if (event.action == Action.LEFT_CLICK_BLOCK) { - val shouldBeCancelled = - blockSelectionService.selectLeftLocation(event.player, event.clickedBlock!!.location) - - @Suppress("DEPRECATION") - if (!event.isCancelled) { - event.isCancelled = shouldBeCancelled - } - } else if (event.action == Action.RIGHT_CLICK_BLOCK) { - val shouldBeCancelled = - blockSelectionService.selectRightLocation(event.player, event.clickedBlock!!.location) - - @Suppress("DEPRECATION") - if (!event.isCancelled) { - event.isCancelled = shouldBeCancelled - } - } - } - - /** - * Gets called when a player leaves the server. - */ - @EventHandler - fun onPlayerQuitEvent(event: PlayerQuitEvent) { - blockSelectionService.cleanResources(event.player) - } -} diff --git a/src/main/java/com/github/shynixn/blockball/impl/service/BlockSelectionServiceImpl.kt b/src/main/java/com/github/shynixn/blockball/impl/service/BlockSelectionServiceImpl.kt deleted file mode 100644 index 2bed5e7ea..000000000 --- a/src/main/java/com/github/shynixn/blockball/impl/service/BlockSelectionServiceImpl.kt +++ /dev/null @@ -1,195 +0,0 @@ -@file:Suppress("UNCHECKED_CAST") - -package com.github.shynixn.blockball.impl.service - -import com.github.shynixn.blockball.contract.BlockSelectionService -import com.github.shynixn.blockball.enumeration.Permission -import com.github.shynixn.mccoroutine.bukkit.launch -import com.github.shynixn.mccoroutine.bukkit.ticks -import com.github.shynixn.mcutils.common.ChatColor -import com.github.shynixn.mcutils.common.item.Item -import com.github.shynixn.mcutils.common.item.ItemService -import com.github.shynixn.mcutils.common.translateChatColors -import com.github.shynixn.mcutils.packet.api.PacketService -import com.github.shynixn.mcutils.packet.api.packet.PacketOutDebugMarker -import com.google.inject.Inject -import kotlinx.coroutines.delay -import org.bukkit.Location -import org.bukkit.entity.Player -import org.bukkit.plugin.Plugin -import java.awt.Color -import java.util.* - -@Suppress("DEPRECATION", "SENSELESS_COMPARISON") -class BlockSelectionServiceImpl @Inject constructor( - private val plugin: Plugin, - private val itemService: ItemService, - private val packetService: PacketService -) : BlockSelectionService { - private val axeName = - ChatColor.WHITE.toString() + ChatColor.BOLD + ">>" + ChatColor.YELLOW + "BlockBall" + ChatColor.WHITE + ChatColor.BOLD + "<<" - private val playerSelection = HashMap>() - private val rightClickSelectionCahe = HashSet() - - init { - plugin.launch { - while (true) { - for (player in playerSelection.keys.toTypedArray()) { - updateSelection(player, playerSelection[player]!!) - } - delay(2000) - } - } - } - - - /** - * Selects the left location internally. - */ - override fun selectLeftLocation(player: Player, location: Location): Boolean { - if (selectLocation(player, location, 0)) { - player.sendMessage(ChatColor.YELLOW.toString() + "Leftclick: " + location.blockX + " " + location.blockY + " " + location.blockZ) - return true - } - - return false - } - - /** - * Selects the right location internally. - */ - override fun selectRightLocation(player: Player, location: Location): Boolean { - if (!rightClickSelectionCahe.contains(player) && selectLocation(player, location, 1)) { - player.sendMessage(ChatColor.YELLOW.toString() + "Rightclick: " + location.blockX + " " + location.blockY + " " + location.blockZ) - - rightClickSelectionCahe.add(player) - plugin.launch { - delay(10.ticks) - rightClickSelectionCahe.remove(player) - } - - return true - } - - return false - } - - /** - * Returns the leftclick internal or worledit selection of the given [player]. - */ - override fun getLeftClickLocation(player: Player): Optional { - return getCompatibilitySelection(player, 0) - } - - /** - * Returns the rightclick internal or worledit selection of the given [player]. - */ - override fun getRightClickLocation(player: Player): Optional { - return getCompatibilitySelection(player, 1) - } - - /** - * Cleans open resources. - */ - override fun cleanResources(player: Player) { - if (playerSelection.containsKey(player)) { - playerSelection.remove(player) - } - } - - /** - * Select location and returns if success. - */ - private fun selectLocation(player: Player, location: Location, index: Int): Boolean { - if (!player.hasPermission(Permission.EDIT_GAME.permission)) { - return false - } - - @Suppress("DEPRECATION") - if (player.itemInHand == null) { - return false - } - - val itemStack = player.itemInHand - val itemMeta = itemStack.itemMeta - - if (itemMeta == null) { - return false - } - - - if (itemMeta.displayName == null) { - return false - } - - if (org.bukkit.ChatColor.stripColor(itemMeta.displayName) != org.bukkit.ChatColor.stripColor(this.axeName)) { - return false - } - - if (!playerSelection.containsKey(player)) { - playerSelection[player] = arrayOfNulls(2) - } - - playerSelection[player]!![index] = location - updateSelection(player, playerSelection[player]!!) - - return true - } - - /** - * Gives the given [player] the selection tool if he does not - * already have it. - */ - override fun setSelectionToolForPlayer(player: Player) { - for (i in 0..player.inventory.contents.size) { - if (player.inventory.contents[0] != null) { - val item = player.inventory.contents[0] - val itemMeta = item.itemMeta - - if (itemMeta != null) { - if (itemMeta.displayName != null - && org.bukkit.ChatColor.stripColor(itemMeta.displayName) == org.bukkit.ChatColor.stripColor(this.axeName) - ) { - return - } - } - } - } - - val item = Item().also { - it.typeName = "minecraft:golden_axe,286" - it.displayName = axeName.translateChatColors() - } - player.inventory.addItem(itemService.toItemStack(item)) - player.sendMessage("Take a look into your inventory. Use this golden axe for selection.") - } - - private fun updateSelection(player: Player, locations: Array) { - for (i in 0 until locations.size) { - if (i == 0 && locations[i] != null) { - packetService.sendPacketOutDebugMarker( - player, - PacketOutDebugMarker(locations[i]!!, 2200, Color.YELLOW.rgb, "BlockBall [LEFT]") - ) - } - - if (i == 1 && locations[i] != null) { - packetService.sendPacketOutDebugMarker( - player, - PacketOutDebugMarker(locations[i]!!, 2200, Color.YELLOW.rgb, "BlockBall [RIGHT]") - ) - } - } - } - - /** - * Returns the compaitiblity selection. - */ - private fun getCompatibilitySelection(player: Player, index: Int): Optional { - if (playerSelection.containsKey(player) && playerSelection[player]!![index] != null) { - return Optional.of(playerSelection[player]!![index]!!) - } - - return Optional.empty() - } -} diff --git a/src/main/java/com/github/shynixn/blockball/impl/service/GameServiceImpl.kt b/src/main/java/com/github/shynixn/blockball/impl/service/GameServiceImpl.kt index de9392d18..08087e845 100644 --- a/src/main/java/com/github/shynixn/blockball/impl/service/GameServiceImpl.kt +++ b/src/main/java/com/github/shynixn/blockball/impl/service/GameServiceImpl.kt @@ -1,27 +1,28 @@ package com.github.shynixn.blockball.impl.service import com.github.shynixn.blockball.contract.* -import com.github.shynixn.blockball.entity.* +import com.github.shynixn.blockball.entity.PlayerInformation +import com.github.shynixn.blockball.entity.SoccerArena import com.github.shynixn.blockball.enumeration.GameType import com.github.shynixn.blockball.impl.SoccerHubGameImpl import com.github.shynixn.blockball.impl.SoccerMiniGameImpl import com.github.shynixn.blockball.impl.exception.SoccerGameException import com.github.shynixn.mcutils.common.ConfigurationService +import com.github.shynixn.mcutils.common.Vector3d import com.github.shynixn.mcutils.common.chat.ChatMessageService import com.github.shynixn.mcutils.common.command.CommandService import com.github.shynixn.mcutils.common.repository.Repository import com.github.shynixn.mcutils.common.sound.SoundService -import com.github.shynixn.mcutils.common.toVector3d import com.github.shynixn.mcutils.database.api.PlayerDataRepository import com.github.shynixn.mcutils.packet.api.PacketService import com.github.shynixn.mcutils.sign.SignService import com.google.inject.Inject import kotlinx.coroutines.runBlocking -import org.bukkit.Location import org.bukkit.entity.Player import org.bukkit.plugin.Plugin -import java.util.* import java.util.logging.Level +import kotlin.math.max +import kotlin.math.min class GameServiceImpl @Inject constructor( private val arenaRepository: Repository, @@ -209,7 +210,53 @@ class GameServiceImpl @Inject constructor( private fun validateGame(arena: SoccerArena) { if (arena.meta.ballMeta.spawnpoint == null) { arena.enabled = false - throw SoccerGameException(arena, "Set the leave spawnpoint values in arena ${arena.name}!") + throw SoccerGameException(arena, "Set the ball spawnpoint for arena ${arena.name}!") } + if (arena.lowerCorner == null || arena.upperCorner == null) { + arena.enabled = false + throw SoccerGameException(arena, "Set the playing field for arena ${arena.name}!") + } + if (arena.meta.redTeamMeta.goal.lowerCorner == null || arena.meta.redTeamMeta.goal.upperCorner == null) { + arena.enabled = false + throw SoccerGameException(arena, "Set the red goal for arena ${arena.name}!") + } + if (arena.meta.blueTeamMeta.goal.lowerCorner == null || arena.meta.blueTeamMeta.goal.upperCorner == null) { + arena.enabled = false + throw SoccerGameException(arena, "Set the blue goal for arena ${arena.name}!") + } + + if (arena.gameType == GameType.MINIGAME) { + if (arena.meta.lobbyMeta.leaveSpawnpoint == null) { + arena.enabled = false + throw SoccerGameException(arena, "Set the leave spawnpoint for arena ${arena.name}!") + } + if (arena.meta.redTeamMeta.lobbySpawnpoint == null) { + arena.enabled = false + throw SoccerGameException(arena, "Set the red lobby spawnpoint for arena ${arena.name}!") + } + if (arena.meta.blueTeamMeta.lobbySpawnpoint == null) { + arena.enabled = false + throw SoccerGameException(arena, "Set the blue lobby spawnpoint for arena ${arena.name}!") + } + } + + fixCorners(arena.lowerCorner!!, arena.upperCorner!!) + fixCorners(arena.meta.redTeamMeta.goal.lowerCorner!!, arena.meta.redTeamMeta.goal.upperCorner!!) + fixCorners(arena.meta.blueTeamMeta.goal.lowerCorner!!, arena.meta.blueTeamMeta.goal.upperCorner!!) + } + + /** + * Corrects the corner values. + */ + private fun fixCorners(corner1: Vector3d, corner2: Vector3d) { + val copyCorner1 = corner1.copy() + val copyCorner2 = corner2.copy() + + corner1.x = min(copyCorner1.x, copyCorner2.x) + corner1.y = min(copyCorner1.y, copyCorner2.y) + corner1.z = min(copyCorner1.z, copyCorner2.z) + corner2.x = max(copyCorner1.x, copyCorner2.x) + corner2.y = max(copyCorner1.y, copyCorner2.y) + corner2.z = max(copyCorner1.z, copyCorner2.z) } } diff --git a/src/main/resources/lang/en_us.properties b/src/main/resources/lang/en_us.properties index 5d8a17ad4..6dd8e8e8e 100644 --- a/src/main/resources/lang/en_us.properties +++ b/src/main/resources/lang/en_us.properties @@ -4,7 +4,7 @@ gameAlreadyExistsMessage=&0&l[&f&lBlockBall&0&l]&c Game %1$1s already exists. maxLength20Characters=&0&l[&f&lBlockBall&0&l]&c The text length has to be less than 20 characters. gameDoesNotExistMessage=&0&l[&f&lBlockBall&0&l]&c Game %1$1s does not exist. teamDoesNotExistMessage=&0&l[&f&lBlockBall&0&l]&c Team %1$1s does not exist. -locationTypeDoesNotExistMessage=&0&l[&f&lBlockBall&0&l]&c This location type is not known. For more locations, open the arena.yml. +selectionTypeDoesNotExistMessage=&0&l[&f&lBlockBall&0&l]&c This selection type is not known. signTypeDoesNotExistMessage=&0&l[&f&lBlockBall&0&l]&c This sign type is not known. noPermissionForGameMessage=&0&l[&f&lBlockBall&0&l]&c You do not have permission to join game %1$1s. noPermissionMessage=&0&l[&f&lBlockBall&0&l]&c You do not have permission. @@ -15,7 +15,7 @@ gameIsFullMessage=&0&l[&f&lBlockBall&0&l]&c Game is already full. joinTeamRedMessage=&0&l[&f&lBlockBall&0&l]&7 Successfully joined team red. joinTeamBlueMessage=&0&l[&f&lBlockBall&0&l]&7 Successfully joined team blue. leftGameMessage=&0&l[&f&lBlockBall&0&l]&7 Left the game. -spawnPointSetMessage=&0&l[&f&lBlockBall&0&l]&7 Location %1$1s was set on %2$1s. +selectionSetMessage=&0&l[&f&lBlockBall&0&l]&7 Selection %1$1s was set. enabledArenaMessage=&0&l[&f&lBlockBall&0&l]&7 Game enable state was set to %1$1s. reloadedAllGamesMessage=&0&l[&f&lBlockBall&0&l]&7 Reloaded all games. reloadedGameMessage=&0&l[&f&lBlockBall&0&l]&7 Reloaded game %1$1s. @@ -23,6 +23,8 @@ updatedInventoryMessage=&0&l[&f&lBlockBall&0&l]&7 Updated inventory of game. updatedArmorMessage=&0&l[&f&lBlockBall&0&l]&7 Updated armor of game. rightClickOnSignMessage=&0&l[&f&lBlockBall&0&l]&7 RightClick on a sign to convert it into a game sign. addedSignMessage=&0&l[&f&lBlockBall&0&l]&7 A sign was added to the game. +noLeftClickSelectionMessage=&0&l[&f&lBlockBall&0&l]&c You need to select a location using the BlockBall axe with left click. +noRightClickSelectionMessage=&0&l[&f&lBlockBall&0&l]&c You need to select a location using the BlockBall axe with right click. scoreRedTitle=&c&l%1$1s scoreRedSubTitle=%2$1s scored for &cTeam Red. scoreRedFadeIn=20 @@ -60,9 +62,11 @@ commandListToolTip=Lists all games you have created. commandToggleToolTip=Enables or disables your game. If a game is disabled, nobody can join. commandJoinToolTip=Lets the player executing the command join the game. The optional team argument allows to directly join a specific team. If the team is full, the other team will be chosen. If no team is specified, a random team will be selected. commandLeaveToolTip=Lets the player executing the command leave the game. -commandLocationToolTip=Updates the location of a part of the arena. +commandSelectionToolTip=Updates a location selection of a part of the arena. commandInventoryToolTip=Copies the inventory of the player executing the command. This copy will be applied to players when they join a game. commandArmorToolTip=Copies the armor inventory of the player executing the command. This copy will be applied to players when they join a game. commandSignToolTip=Enables the player to add a specific sign by right-clicking any sign. You can remove signs by simply breaking the block. commandReloadToolTip=Allows to reload all games or a specific single one. - +commandAxeToolTip=Gives you the BlockBall selection axe. +commandHighlightToolTip=Toggles highlighting the important areas of your arena. +commandSelectToolTip=Sets a selected location for your arena.