Skip to content

Commit

Permalink
feat: add spleef, progress pass the parcel, start board
Browse files Browse the repository at this point in the history
  • Loading branch information
joshbker committed Dec 17, 2023
1 parent 3c3fd69 commit 6c3b9de
Show file tree
Hide file tree
Showing 8 changed files with 310 additions and 15 deletions.
18 changes: 18 additions & 0 deletions src/main/kotlin/gg/flyte/event/game/GameType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
3 changes: 1 addition & 2 deletions src/main/kotlin/gg/flyte/event/game/main/MainGame.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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<Player>()
Expand Down
102 changes: 95 additions & 7 deletions src/main/kotlin/gg/flyte/event/game/main/type/PassTheParcelGame.kt
Original file line number Diff line number Diff line change
@@ -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<InventoryOpenEvent> {
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")

}
}
91 changes: 91 additions & 0 deletions src/main/kotlin/gg/flyte/event/game/main/type/SpleefGame.kt
Original file line number Diff line number Diff line change
@@ -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<BlockBreakEvent>(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<PlayerMoveEvent>(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) {

}
}
18 changes: 14 additions & 4 deletions src/main/kotlin/gg/flyte/event/listener/ConnectionListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -106,8 +115,9 @@ object ConnectionListener {

player.apply {
MainGameEngine.onPlayerQuit(this)
ActionBarImpl.unregister(this)
//ActionBarImpl.unregister(this)
TablistManager.remove(this)
Scoreboard.onPlayerQuit(this)
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/main/kotlin/gg/flyte/event/util/Message.kt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)
val ComponentLike.plainText: String
get() = PlainTextComponentSerializer.plainText().serialize(asComponent())
70 changes: 70 additions & 0 deletions src/main/kotlin/gg/flyte/event/util/Scoreboard.kt
Original file line number Diff line number Diff line change
@@ -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<TextComponent>

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<Player, gg.flyte.event.util.Scoreboard>()

fun onPlayerJoin(player: Player) {
boards += player to Board(player)
}

fun onPlayerQuit(player: Player) {
boards -= player
}
}
}
Loading

0 comments on commit 6c3b9de

Please sign in to comment.