From 6c3b9defd27f656ac2b62f698ebbbc6204c850f6 Mon Sep 17 00:00:00 2001 From: joshbker <43449531+joshbker@users.noreply.github.com> Date: Sun, 17 Dec 2023 03:34:57 +0000 Subject: [PATCH] feat: add spleef, progress pass the parcel, start board --- .../kotlin/gg/flyte/event/game/GameType.kt | 18 ++++ .../gg/flyte/event/game/main/MainGame.kt | 3 +- .../event/game/main/type/PassTheParcelGame.kt | 102 ++++++++++++++++-- .../flyte/event/game/main/type/SpleefGame.kt | 91 ++++++++++++++++ .../event/listener/ConnectionListener.kt | 18 +++- .../kotlin/gg/flyte/event/util/Message.kt | 5 +- .../kotlin/gg/flyte/event/util/Scoreboard.kt | 70 ++++++++++++ .../kotlin/gg/flyte/event/visual/Board.kt | 18 ++++ 8 files changed, 310 insertions(+), 15 deletions(-) create mode 100644 src/main/kotlin/gg/flyte/event/game/main/type/SpleefGame.kt create mode 100644 src/main/kotlin/gg/flyte/event/util/Scoreboard.kt create mode 100644 src/main/kotlin/gg/flyte/event/visual/Board.kt diff --git a/src/main/kotlin/gg/flyte/event/game/GameType.kt b/src/main/kotlin/gg/flyte/event/game/GameType.kt index aece6ec..ac473b8 100644 --- a/src/main/kotlin/gg/flyte/event/game/GameType.kt +++ b/src/main/kotlin/gg/flyte/event/game/GameType.kt @@ -104,6 +104,24 @@ enum class GameType( MapLocation(635, 112, 828, 145, 0) ), + SPLEEF( + GameCategory.MAIN, + Component.text("Spleef"), + Component.text("test game"), + GameMode.ADVENTURE, + SpleefGame::class.java, + BoundingBox.of( + MapLocation(633, 110, 783), + MapLocation(599, 110, 817) + ), + listOf( + listOf( + MapLocation(616, 111, 800) + ) + ), + MapLocation(635, 112, 828, 145, 0) + ), + PRESENT_SNATCH( GameCategory.MAIN, Component.text("Present Snatch"), diff --git a/src/main/kotlin/gg/flyte/event/game/main/MainGame.kt b/src/main/kotlin/gg/flyte/event/game/main/MainGame.kt index 0b7b3f2..5b098d8 100644 --- a/src/main/kotlin/gg/flyte/event/game/main/MainGame.kt +++ b/src/main/kotlin/gg/flyte/event/game/main/MainGame.kt @@ -5,9 +5,8 @@ import gg.flyte.event.game.GameType import org.bukkit.entity.Player import java.util.* -abstract class MainGame(type: GameType) : Game() { +abstract class MainGame(val type: GameType) : Game() { - lateinit var type: GameType var state = MainGameState.COUNTDOWN val alive = mutableListOf() diff --git a/src/main/kotlin/gg/flyte/event/game/main/type/PassTheParcelGame.kt b/src/main/kotlin/gg/flyte/event/game/main/type/PassTheParcelGame.kt index 59a776f..e634555 100644 --- a/src/main/kotlin/gg/flyte/event/game/main/type/PassTheParcelGame.kt +++ b/src/main/kotlin/gg/flyte/event/game/main/type/PassTheParcelGame.kt @@ -1,27 +1,115 @@ package gg.flyte.event.game.main.type +import com.xxmicloxx.NoteBlockAPI.model.RepeatMode +import com.xxmicloxx.NoteBlockAPI.songplayer.RadioSongPlayer import gg.flyte.event.game.GameType import gg.flyte.event.game.main.MainGame +import gg.flyte.event.game.main.MainGameEngine +import gg.flyte.event.util.NBSSongType +import gg.flyte.twilight.event.event +import gg.flyte.twilight.scheduler.delay +import gg.flyte.twilight.time.TimeUnit +import net.kyori.adventure.text.Component.newline +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.Bukkit import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryOpenEvent +import kotlin.random.Random class PassTheParcelGame : MainGame(GameType.PASS_THE_PARCEL) { - override fun onPlayerJoin(player: Player) { - TODO("Not yet implemented") - } + private lateinit var music: RadioSongPlayer override fun events() { - TODO("Not yet implemented") + events += event { + if (inventory != player.inventory) return@event + isCancelled = true + handleParcelLand() + } } override fun start() { - TODO("Not yet implemented") + val song = NBSSongType.entries.random() + music = RadioSongPlayer(song.song) + music.repeatMode = RepeatMode.ALL + Bukkit.getOnlinePlayers().forEach(music::addPlayer) + + Bukkit.broadcast( + text().append( + newline(), + text("♫ ").color(NamedTextColor.RED), text("Now playing ${song.title}..."), + newline(), + ).build() + ) + + music.isPlaying = true + + // Give to first player + nextPlayer() + } + + private var parcelHolder: Player? = null + + private fun nextPlayer() { + parcelHolder = parcelHolder?.let { + alive.elementAtOrElse(alive.indexOf(it) + 1) { alive.first() } + } ?: alive.first() + + val player = parcelHolder ?: throw IllegalStateException() + + Bukkit.broadcast(text("${player.name} HAS THE PARCEL")) + + // If haven't opened after 3 seconds, trigger opening parcel automatically + tasks += delay(3, TimeUnit.SECONDS) { + if (parcelHolder == null) return@delay + if (player.uniqueId == parcelHolder!!.uniqueId) handleParcelLand() + } + } + + private fun handleParcelLand() { + val parcelHolder = parcelHolder ?: return nextPlayer() + + // 40% chance of music stopping + if (Random.nextInt(100) >= 60) { + music.isPlaying = false + Bukkit.broadcast(text("THE PARCEL LANDED ON ${parcelHolder.name}")) + tasks += delay(2, TimeUnit.SECONDS) { openParcel() } + } + + // Pass to next player + tasks += delay(3, TimeUnit.SECONDS) { + nextPlayer() + music.isPlaying = true + } + } + + private fun openParcel() { + val parcelHolder = parcelHolder ?: return nextPlayer() + + // 30% chance of blowing up + if (Random.nextInt(100) >= 70) { + handleElimination(parcelHolder) + Bukkit.broadcast(text("${parcelHolder.name} went BOOM")) + } else { + points += parcelHolder.uniqueId to points.getOrDefault(parcelHolder.uniqueId, 0) + 1 + Bukkit.broadcast(text("${parcelHolder.name} didn't die!")) + } + } + + private fun handleElimination(player: Player) { + alive -= player + if (alive.size <= 1) MainGameEngine.stop() } override fun stop() { - TODO("Not yet implemented") + music.destroy() + } + + override fun onPlayerJoin(player: Player) { + } override fun onPlayerQuit(player: Player) { - TODO("Not yet implemented") + } } \ No newline at end of file diff --git a/src/main/kotlin/gg/flyte/event/game/main/type/SpleefGame.kt b/src/main/kotlin/gg/flyte/event/game/main/type/SpleefGame.kt new file mode 100644 index 0000000..3c161e0 --- /dev/null +++ b/src/main/kotlin/gg/flyte/event/game/main/type/SpleefGame.kt @@ -0,0 +1,91 @@ +package gg.flyte.event.game.main.type + +import gg.flyte.event.ChristmasEvent +import gg.flyte.event.game.GameType +import gg.flyte.event.game.main.MainGame +import gg.flyte.event.game.main.MainGameEngine +import gg.flyte.event.game.main.MainGameState +import gg.flyte.twilight.event.event +import gg.flyte.twilight.extension.* +import net.kyori.adventure.text.Component.text +import org.bukkit.* +import org.bukkit.block.data.type.Snow +import org.bukkit.entity.Player +import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.entity.EntityDamageByBlockEvent +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.event.player.PlayerMoveEvent +import org.bukkit.inventory.ItemStack + +class SpleefGame : MainGame(GameType.SPLEEF) { + + private val shovel = ItemStack(Material.DIAMOND_SHOVEL).apply { name("${ChatColor.RED}Scooper") } + private val snowball = ItemStack(Material.SNOWBALL) + + override fun events() { + events += event(ignoreCancelled = true) { + if (state != MainGameState.ACTIVE) return@event + if (block.type != Material.SNOW) return@event + + isCancelled = true + isDropItems = false + + var clear = false + + (block.blockData as Snow).apply { + if (layers == 1) { + clear = true + return@apply + } + layers -= 1 + }.also { block.blockData = it } + + if (clear) block.type = Material.AIR + if (player.inventory.itemInMainHand == shovel) player.inventory.addItem(snowball) + } + + events += event(ignoreCancelled = true) { + if (player.isOnFire()) handleElimination(player) + } + } + + // Setup arena + init { + type.region.getBlocks(ChristmasEvent.WORLD).applyForEach { + type = Material.SNOW + (blockData as Snow).apply { layers = maximumLayers }.also { blockData = it } + } + } + + override fun start() { + alive.applyForEach { + inventory.addItem(shovel) + gameMode = GameMode.SURVIVAL + } + } + + private fun handleElimination(player: Player) { + player.apply { + alive -= this + playSound(Sound.ENTITY_PLAYER_DEATH) + teleport(this@SpleefGame.type.spectatorSpawn!!) + fireTicks = 0 + Bukkit.broadcast(text("$name was eliminated")) + } + if (alive.size <= 1) MainGameEngine.stop() + } + + override fun stop() { + type.region.getBlocks(ChristmasEvent.WORLD).applyForEach { + type = Material.SPRUCE_PLANKS + } + } + + override fun onPlayerJoin(player: Player) { + + } + + override fun onPlayerQuit(player: Player) { + + } +} \ No newline at end of file diff --git a/src/main/kotlin/gg/flyte/event/listener/ConnectionListener.kt b/src/main/kotlin/gg/flyte/event/listener/ConnectionListener.kt index e4cb471..6cbde5c 100644 --- a/src/main/kotlin/gg/flyte/event/listener/ConnectionListener.kt +++ b/src/main/kotlin/gg/flyte/event/listener/ConnectionListener.kt @@ -4,11 +4,14 @@ import gg.flyte.event.ChristmasEvent import gg.flyte.event.ChristmasEvent.Companion.LOBBY_SPAWN import gg.flyte.event.game.main.MainGameEngine import gg.flyte.event.util.CHRISTMAS_RED +import gg.flyte.event.util.Scoreboard import gg.flyte.event.util.npc.NPC import gg.flyte.event.visual.TablistManager import gg.flyte.event.visual.hud.impl.ActionBarImpl import gg.flyte.twilight.event.event import gg.flyte.twilight.extension.RemoteFile +import gg.flyte.twilight.extension.applyForEach +import gg.flyte.twilight.extension.removeActivePotionEffects import gg.flyte.twilight.scheduler.delay import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text @@ -75,13 +78,19 @@ object ConnectionListener { } MainGameEngine.onPlayerJoin(this) - ActionBarImpl.register(this) + Scoreboard.onPlayerJoin(this) + // ActionBarImpl.register(this) - gameMode = GameMode.ADVENTURE - foodLevel = 20 teleport(LOBBY_SPAWN) + getAttribute(Attribute.GENERIC_MAX_HEALTH)!!.baseValue = 20.0 health = 20.0 + foodLevel = 20 + fireTicks = 0 + + gameMode = GameMode.ADVENTURE + + removeActivePotionEffects() inventory.clear() inventory.helmet = RED_CHRISTMAS_HAT @@ -106,8 +115,9 @@ object ConnectionListener { player.apply { MainGameEngine.onPlayerQuit(this) - ActionBarImpl.unregister(this) + //ActionBarImpl.unregister(this) TablistManager.remove(this) + Scoreboard.onPlayerQuit(this) } } diff --git a/src/main/kotlin/gg/flyte/event/util/Message.kt b/src/main/kotlin/gg/flyte/event/util/Message.kt index 4e196cf..dc6b858 100644 --- a/src/main/kotlin/gg/flyte/event/util/Message.kt +++ b/src/main/kotlin/gg/flyte/event/util/Message.kt @@ -1,6 +1,7 @@ package gg.flyte.event.util import net.kyori.adventure.text.Component +import net.kyori.adventure.text.ComponentLike import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.minimessage.MiniMessage import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer @@ -10,5 +11,5 @@ val CHRISTMAS_RED = TextColor.color(0xF85555) val String.miniMessage: Component get() = MiniMessage.miniMessage().deserialize(this) -val Component.plainText: String - get() = PlainTextComponentSerializer.plainText().serialize(this) \ No newline at end of file +val ComponentLike.plainText: String + get() = PlainTextComponentSerializer.plainText().serialize(asComponent()) \ No newline at end of file diff --git a/src/main/kotlin/gg/flyte/event/util/Scoreboard.kt b/src/main/kotlin/gg/flyte/event/util/Scoreboard.kt new file mode 100644 index 0000000..71ac6d8 --- /dev/null +++ b/src/main/kotlin/gg/flyte/event/util/Scoreboard.kt @@ -0,0 +1,70 @@ +package gg.flyte.event.util + +import gg.flyte.event.visual.Board +import gg.flyte.twilight.scheduler.delay +import gg.flyte.twilight.scheduler.repeat +import net.kyori.adventure.text.TextComponent +import org.bukkit.Bukkit +import org.bukkit.ChatColor +import org.bukkit.entity.Player +import org.bukkit.event.Listener +import org.bukkit.scoreboard.* +import org.bukkit.scoreboard.Scoreboard + +abstract class Scoreboard(open val player: Player) : Listener { + val scoreboard: Scoreboard = Bukkit.getScoreboardManager().newScoreboard + val objective: Objective = scoreboard.registerNewObjective("board", Criteria.DUMMY, title()) + val team: Team = scoreboard.getTeam("no_collide") ?: scoreboard.registerNewTeam("no_collide") + + init { + delay { + objective.displaySlot = DisplaySlot.SIDEBAR + objective.displayName = title().plainText + + lines(player).reversedArray().forEachIndexed { index, line -> + scoreboard.registerNewTeam((index + 1).toString()).apply { + val value = ChatColor.entries[index].toString() + addEntry(value) + prefix = line.plainText + objective.getScore(value).score = index + 1 + } + } + + player.scoreboard = scoreboard + } + + repeat(2) { update() } + } + + private fun update() { + lines(player).reversedArray().forEachIndexed { index, line -> + val lineString = line.plainText + scoreboard.getTeam((index + 1).toString())?.let { if (it.hasLineChanged(lineString)) it.prefix = lineString } + } + } + + private fun Team.hasLineChanged(line: String): Boolean = ChatColor.stripColor(prefix) != line + + abstract fun title(): TextComponent + abstract fun lines(player: Player): Array + + fun enableCollisions() { + if (team.hasEntry(player.name)) team.removeEntry(player.name) + } + + fun disableCollisions() { + if (!team.hasEntry(player.name)) team.addEntry(player.name) + } + + companion object { + private val boards = mutableMapOf() + + fun onPlayerJoin(player: Player) { + boards += player to Board(player) + } + + fun onPlayerQuit(player: Player) { + boards -= player + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/gg/flyte/event/visual/Board.kt b/src/main/kotlin/gg/flyte/event/visual/Board.kt new file mode 100644 index 0000000..51ce570 --- /dev/null +++ b/src/main/kotlin/gg/flyte/event/visual/Board.kt @@ -0,0 +1,18 @@ +package gg.flyte.event.visual + +import gg.flyte.event.util.CHRISTMAS_RED +import gg.flyte.event.util.Scoreboard +import net.kyori.adventure.text.Component.empty +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.TextComponent +import org.bukkit.entity.Player + +class Board(player: Player) : Scoreboard(player) { + override fun title() = text("Christmas Event", CHRISTMAS_RED) + + override fun lines(player: Player): Array = arrayOf( + text("Test", CHRISTMAS_RED), + empty(), + text("flyte.gg"), + ) +} \ No newline at end of file