Add new game states and update

This commit is contained in:
TDSTOS
2025-12-08 21:59:40 +01:00
parent 590318772f
commit fef0072007
10 changed files with 440 additions and 52 deletions

View File

@@ -16,6 +16,7 @@ import club.mcscrims.spigot.chat.ChatFormatter
import club.mcscrims.spigot.chat.ChatManager import club.mcscrims.spigot.chat.ChatManager
import club.mcscrims.spigot.network.SpigotNetworkManager import club.mcscrims.spigot.network.SpigotNetworkManager
import club.mcscrims.spigot.scheduler.SchedulerManager import club.mcscrims.spigot.scheduler.SchedulerManager
import club.mcscrims.spigot.util.WorldEditUtils
import com.mongodb.client.model.Indexes import com.mongodb.client.model.Indexes
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.luckperms.api.LuckPerms import net.luckperms.api.LuckPerms
@@ -44,6 +45,8 @@ class SpeedHG : JavaPlugin() {
internal lateinit var gameManager: GameManager internal lateinit var gameManager: GameManager
internal lateinit var worldManager: WorldManager internal lateinit var worldManager: WorldManager
internal lateinit var worldEditUtils: WorldEditUtils
internal lateinit var luckPerms: LuckPerms internal lateinit var luckPerms: LuckPerms
internal var isReady: Boolean = false internal var isReady: Boolean = false
@@ -74,6 +77,8 @@ class SpeedHG : JavaPlugin() {
schedulerManager = SchedulerManager( this ) schedulerManager = SchedulerManager( this )
worldEditUtils = WorldEditUtils( this )
gameManager = GameManager( this ) gameManager = GameManager( this )
gameManager.initialize() gameManager.initialize()

View File

@@ -2,6 +2,8 @@ package club.mcscrims.speedhg.game
import club.mcscrims.speedhg.SpeedHG import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.game.impl.BattleState import club.mcscrims.speedhg.game.impl.BattleState
import club.mcscrims.speedhg.game.impl.DeathmatchState
import club.mcscrims.speedhg.game.impl.EndState
import club.mcscrims.speedhg.game.impl.FeastState import club.mcscrims.speedhg.game.impl.FeastState
import club.mcscrims.speedhg.game.impl.ImmunityState import club.mcscrims.speedhg.game.impl.ImmunityState
import club.mcscrims.speedhg.game.impl.PreStartState import club.mcscrims.speedhg.game.impl.PreStartState
@@ -16,7 +18,7 @@ class GameManager(
) { ) {
private var currentState: GameState? = null private var currentState: GameState? = null
private val gameStateTypes = ConcurrentHashMap<GameStateTypes, GameState>() internal val gameStateTypes = ConcurrentHashMap<GameStateTypes, GameState>()
private val winners = ArrayList<Player>() private val winners = ArrayList<Player>()
@@ -33,20 +35,20 @@ class GameManager(
plugin.pluginConfig.data.getDuration( "waiting" ).seconds plugin.pluginConfig.data.getDuration( "waiting" ).seconds
) )
gameStateTypes[ GameStateTypes.WAITING ] = currentState!!
gameStateTypes[ GameStateTypes.PRE_START ] = PreStartState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "pre_start" ).seconds )
gameStateTypes[ GameStateTypes.IMMUNITY ] = ImmunityState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "immunity" ).seconds )
gameStateTypes[ GameStateTypes.BATTLE ] = BattleState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "battle" ).seconds )
gameStateTypes[ GameStateTypes.FEAST ] = FeastState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "feast" ).seconds )
gameStateTypes[ GameStateTypes.DEATHMATCH ] = DeathmatchState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "deathmatch" ).seconds )
gameStateTypes[ GameStateTypes.END ] = EndState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "end" ).seconds )
try { try {
currentState?.onEnter( null ) currentState?.onEnter( null )
} catch ( e: Exception ) { } catch ( e: Exception ) {
plugin.logger.severe("Error during onEnter for state ${currentState?.name}: ${e.message}") plugin.logger.severe("Error during onEnter for state ${currentState?.name}: ${e.message}")
e.printStackTrace() e.printStackTrace()
} }
gameStateTypes[ GameStateTypes.WAITING ] = currentState!!
gameStateTypes[ GameStateTypes.PRE_START ] = PreStartState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "pre_start" ).seconds )
gameStateTypes[ GameStateTypes.IMMUNITY ] = ImmunityState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "immunity" ).seconds )
gameStateTypes[ GameStateTypes.BATTLE ] = BattleState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "battle" ).seconds )
gameStateTypes[ GameStateTypes.FEAST ] = FeastState( this, plugin, plugin.schedulerManager, plugin.pluginConfig.data.getDuration( "feast" ).seconds )
gameStateTypes[ GameStateTypes.DEATHMATCH ] = TODO()
gameStateTypes[ GameStateTypes.END ] = TODO()
} }
fun transitionTo( fun transitionTo(
@@ -85,6 +87,8 @@ class GameManager(
winners.forEach { this.winners.add( it ) } winners.forEach { this.winners.add( it ) }
} }
fun getWinners(): List<Player> = winners.toList()
fun getCurrentState(): GameState? = currentState fun getCurrentState(): GameState? = currentState
fun getCurrentStateType(): GameStateTypes? = gameStateTypes.filter { it.value.name == currentState?.name }.keys.firstOrNull() fun getCurrentStateType(): GameStateTypes? = gameStateTypes.filter { it.value.name == currentState?.name }.keys.firstOrNull()

View File

@@ -6,8 +6,6 @@ import club.mcscrims.spigot.scheduler.SchedulerManager
import club.mcscrims.spigot.scheduler.TaskRegistration import club.mcscrims.spigot.scheduler.TaskRegistration
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.HandlerList
import org.bukkit.event.Listener
abstract class GameState( abstract class GameState(
val name: String, val name: String,
@@ -17,7 +15,6 @@ abstract class GameState(
protected val durationSeconds: Int? = null protected val durationSeconds: Int? = null
) { ) {
private val listeners = mutableListOf<Listener>()
private var tickTask: TaskRegistration? = null private var tickTask: TaskRegistration? = null
var remainingSeconds: Int = durationSeconds ?: 0 var remainingSeconds: Int = durationSeconds ?: 0
private var isActive: Boolean = false private var isActive: Boolean = false
@@ -41,7 +38,6 @@ abstract class GameState(
) { ) {
isActive = false isActive = false
stopTicking() stopTicking()
unregisterAllListeners()
} }
private fun startTicking() private fun startTicking()
@@ -63,7 +59,7 @@ abstract class GameState(
if ( durationSeconds != null && remainingSeconds > 0 ) if ( durationSeconds != null && remainingSeconds > 0 )
{ {
if (plugin.pluginConfig.data.getDuration( name ).type == DurationType.INCREASING) if (plugin.pluginConfig.data.getDuration( name ).type == DurationType.INCREASING )
{ {
remainingSeconds++ remainingSeconds++
return@runRepeating return@runRepeating
@@ -87,25 +83,6 @@ abstract class GameState(
tickTask = null tickTask = null
} }
protected fun registerListener(
listener: Listener
) {
listeners.add( listener )
Bukkit.getPluginManager().registerEvents( listener, plugin )
}
private fun unregisterAllListeners()
{
listeners.forEach { listener -> HandlerList.unregisterAll( listener ) }
listeners.clear()
}
protected fun transitionTo(
next: GameState
) {
gameManager.transitionTo( next )
}
protected fun broadcast( protected fun broadcast(
messageKey: String, messageKey: String,
vararg placeholders: Pair<String, String> vararg placeholders: Pair<String, String>

View File

@@ -32,6 +32,7 @@ class BattleState(
{ {
300 -> 300 ->
{ {
gameManager.gameStateTypes[ GameStateTypes.BATTLE ] = this
gameManager.transitionTo( GameStateTypes.FEAST ) gameManager.transitionTo( GameStateTypes.FEAST )
afterFeast = true afterFeast = true
} }
@@ -51,7 +52,7 @@ class BattleState(
private fun checkForWinners(): Boolean private fun checkForWinners(): Boolean
{ {
val players = Bukkit.getOnlinePlayers() val players = Bukkit.getOnlinePlayers().filter { !it.isDead }
if ( players.size > 1 ) if ( players.size > 1 )
return false return false

View File

@@ -0,0 +1,113 @@
package club.mcscrims.speedhg.game.impl
import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.game.GameManager
import club.mcscrims.speedhg.game.GameState
import club.mcscrims.speedhg.game.GameStateTypes
import club.mcscrims.speedhg.game.impl.PreStartState.AnnouncementType
import club.mcscrims.spigot.scheduler.SchedulerManager
import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.Statistic
import org.bukkit.potion.PotionEffect
import org.bukkit.potion.PotionEffectType
class DeathmatchState(
gameManager: GameManager,
plugin: SpeedHG,
schedulerManager: SchedulerManager,
durationSeconds: Int? = null
) : GameState( "deathmatch", gameManager, plugin, schedulerManager, durationSeconds ) {
private val world = plugin.worldManager.getWorld()
private val pitLocation = Location( world, 0.0, 1.0, 0.0 )
override fun onTick()
{
checkForWinners()
when( remainingSeconds )
{
0 ->
{
plugin.chatManager.broadcast( "gameStates.deathmatch.started" )
circle()
schedulerManager.runLater( 10L ) { randomTeleport() }
}
600 -> announce( AnnouncementType.MINUTES, 5 )
660 -> announce( AnnouncementType.MINUTES, 4 )
720 -> announce( AnnouncementType.MINUTES, 3 )
780 -> announce( AnnouncementType.MINUTES, 2 )
840 -> announce( AnnouncementType.MINUTES, 1 )
870 -> announce( AnnouncementType.SECONDS, 30 )
885 -> announce( AnnouncementType.SECONDS, 15 )
890 -> announce( AnnouncementType.SECONDS, 10 )
895 -> announce( AnnouncementType.SECONDS, 5 )
896 -> announce( AnnouncementType.SECONDS, 4 )
897 -> announce( AnnouncementType.SECONDS, 3 )
898 -> announce( AnnouncementType.SECONDS, 2 )
899 -> announce( AnnouncementType.SECONDS, 1 )
900 -> try {
onEndOfDuration()
} catch ( e: Exception ) {
plugin.logger.severe("Error during onEndOfDuration for state $name: ${e.message}")
e.printStackTrace()
}
}
}
override fun onEndOfDuration()
{
val winner = Bukkit.getOnlinePlayers().stream()
.filter { !it.isDead }
.map { it.getStatistic( Statistic.PLAYER_KILLS ) to it }
.max(compareBy { it.first })
.get().second
gameManager.addWinners( winner )
gameManager.transitionTo( GameStateTypes.END )
}
private fun checkForWinners(): Boolean
{
val players = Bukkit.getOnlinePlayers().filter { !it.isDead }
if ( players.size > 1 )
return false
gameManager.addWinners( players.first() )
gameManager.transitionTo( GameStateTypes.END )
return true
}
private fun announce(
type: AnnouncementType,
time: Int
) {
val arg = if ( type == AnnouncementType.MINUTES ) "M" else "S"
broadcast( "gameStates.deathmatch.ending$arg", "{time}" to time.toString() )
}
private fun randomTeleport()
{
forAlivePlayers { player ->
player.addPotionEffect(PotionEffect( PotionEffectType.RESISTANCE, 40, 20 ))
val loc = pitLocation.clone()
loc.x = (( pitLocation.blockX - 15 )..( pitLocation.blockX + 15 )).random().toDouble()
loc.z = (( pitLocation.blockZ - 15 )..( pitLocation.blockZ + 15 )).random().toDouble()
loc.y = world!!.getHighestBlockYAt( loc.blockX, loc.blockZ ).toDouble()
player.teleport( loc )
}
}
private fun circle()
{
val highestLocation = plugin.worldManager.highestLocationWithRadius( pitLocation, 30 )
plugin.worldEditUtils.createCylinder( world!!, pitLocation, 30.0, highestLocation.blockY, Material.AIR, true )
}
}

View File

@@ -0,0 +1,43 @@
package club.mcscrims.speedhg.game.impl
import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.game.GameManager
import club.mcscrims.speedhg.game.GameState
import club.mcscrims.spigot.chat.getDisplayName
import club.mcscrims.spigot.scheduler.SchedulerManager
import kotlinx.coroutines.runBlocking
import org.bukkit.Bukkit
class EndState(
gameManager: GameManager,
plugin: SpeedHG,
schedulerManager: SchedulerManager,
durationSeconds: Int? = null
) : GameState( "end", gameManager, plugin, schedulerManager, durationSeconds ) {
override fun onEnter(
previous: GameState?
) {
super.onEnter( previous )
val winners = gameManager.getWinners()
if ( winners.size > 1 )
plugin.chatManager.broadcast( "gameStates.end.multipleWinners", "{winners}" to winners.joinToString { it.getDisplayName } )
else if ( winners.size == 1 )
plugin.chatManager.broadcast( "gameStates.end.oneWinner", "{winner}" to winners.first().getDisplayName )
else
plugin.chatManager.broadcast( "gameStates.end.noWinners" )
runBlocking { winners.forEach {
plugin.statsRepository.addWins( it.uniqueId, 1 )
} }
}
override fun onTick() {}
override fun onEndOfDuration()
{
Bukkit.shutdown()
}
}

View File

@@ -3,10 +3,21 @@ package club.mcscrims.speedhg.game.impl
import club.mcscrims.speedhg.SpeedHG import club.mcscrims.speedhg.SpeedHG
import club.mcscrims.speedhg.game.GameManager import club.mcscrims.speedhg.game.GameManager
import club.mcscrims.speedhg.game.GameState import club.mcscrims.speedhg.game.GameState
import club.mcscrims.speedhg.game.GameStateTypes
import club.mcscrims.speedhg.game.impl.PreStartState.AnnouncementType
import club.mcscrims.speedhg.util.RandomCollection
import club.mcscrims.spigot.item.ItemBuilder
import club.mcscrims.spigot.scheduler.SchedulerManager import club.mcscrims.spigot.scheduler.SchedulerManager
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.block.Chest
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.PotionMeta
import org.bukkit.potion.PotionEffect
import org.bukkit.potion.PotionEffectType
import org.bukkit.util.BoundingBox import org.bukkit.util.BoundingBox
import java.util.Random import java.util.*
class FeastState( class FeastState(
gameManager: GameManager, gameManager: GameManager,
@@ -18,18 +29,181 @@ class FeastState(
private val world = plugin.worldManager.getWorld() private val world = plugin.worldManager.getWorld()
private val random = Random() private val random = Random()
internal lateinit var feastLocation: Location internal var feastLocation: Location
internal lateinit var feastBox: BoundingBox internal lateinit var feastBox: BoundingBox
internal var feastHeight: Int = 1 internal var feastHeight: Int = 1
init
{
this.feastLocation = getLocation()
this.feastHeight = plugin.worldManager.highestLocationWithRadius( feastLocation, 11 ).blockY + 3
this.feastBox = BoundingBox.of( feastLocation, 11.0, feastHeight.toDouble(), 11.0 )
}
override fun onEnter(
previous: GameState?
) {
super.onEnter( previous )
circle()
}
override fun onTick() override fun onTick()
{ {
TODO("Not yet implemented") when( remainingSeconds )
{
300 -> announce( AnnouncementType.MINUTES, 5 )
240 -> announce( AnnouncementType.MINUTES, 4 )
180 -> announce( AnnouncementType.MINUTES, 3 )
120 -> announce( AnnouncementType.MINUTES, 2 )
60 -> announce( AnnouncementType.MINUTES, 1 )
30 -> announce( AnnouncementType.SECONDS, 30 )
15 -> announce( AnnouncementType.SECONDS, 15 )
10 -> announce( AnnouncementType.SECONDS, 10 )
5 -> announce( AnnouncementType.SECONDS, 5 )
4 -> announce( AnnouncementType.SECONDS, 4 )
3 -> announce( AnnouncementType.SECONDS, 3 )
2 -> announce( AnnouncementType.SECONDS, 2 )
1 -> announce( AnnouncementType.SECONDS, 1 )
}
} }
override fun onEndOfDuration() override fun onEndOfDuration()
{ {
TODO("Not yet implemented") plugin.chatManager.broadcast( "feast.started",
"{x}" to feastLocation.blockX.toString(),
"{y}" to feastLocation.blockY.toString(),
"{z}" to feastLocation.blockZ.toString()
)
chests()
gameManager.transitionTo( GameStateTypes.BATTLE )
}
private fun chests()
{
feastLocation.clone().block.type = Material.ENCHANTING_TABLE
val chestLocations = arrayOfNulls<Location>( 12 )
chestLocations[0] = feastLocation.clone().add( 1.0, 0.0, 1.0 )
chestLocations[1] = feastLocation.clone().add( -1.0, 0.0, 1.0 )
chestLocations[2] = feastLocation.clone().add( -1.0, 0.0, -1.0 )
chestLocations[3] = feastLocation.clone().add( 1.0, 0.0, -1.0 )
chestLocations[4] = feastLocation.clone().add( 2.0, 0.0, 2.0 )
chestLocations[5] = feastLocation.clone().add( 0.0, 0.0, 2.0 )
chestLocations[6] = feastLocation.clone().add( -2.0, 0.0, 2.0 )
chestLocations[7] = feastLocation.clone().add( 2.0, 0.0, 0.0 )
chestLocations[8] = feastLocation.clone().add( -2.0, 0.0, 0.0 )
chestLocations[9] = feastLocation.clone().add( 2.0, 0.0, -2.0 )
chestLocations[10] = feastLocation.clone().add( 0.0, 0.0, -2.0 )
chestLocations[11] = feastLocation.clone().add( -2.0, 0.0, -2.0 )
Arrays.stream( chestLocations ).forEach { it!!.block.type = Material.CHEST }
val diamondItems = RandomCollection<ItemStack>()
diamondItems.add( 1.0, ItemStack( Material.DIAMOND_BOOTS ))
diamondItems.add( 1.0, ItemStack( Material.DIAMOND_CHESTPLATE ))
diamondItems.add( 1.0, ItemStack( Material.DIAMOND_SWORD ))
val ironItems = RandomCollection<ItemStack>()
ironItems.add( 1.0, ItemStack( Material.IRON_BOOTS ))
ironItems.add( 1.0, ItemStack( Material.IRON_LEGGINGS ))
ironItems.add( 1.0, ItemStack( Material.IRON_CHESTPLATE ))
ironItems.add( 1.0, ItemStack( Material.IRON_HELMET ))
ironItems.add( 1.0, ItemStack( Material.IRON_SWORD ))
val netheriteItems = RandomCollection<ItemStack>()
netheriteItems.add( 1.0, ItemStack( Material.NETHERITE_INGOT ))
netheriteItems.add( 1.0, ItemStack( Material.SMITHING_TABLE ))
val sizeableItems = RandomCollection<ItemStack>()
sizeableItems.add( 1.0, ItemStack( Material.RED_MUSHROOM ))
sizeableItems.add( 1.0, ItemStack( Material.BROWN_MUSHROOM ))
sizeableItems.add( 1.0, ItemStack( Material.BOWL ))
sizeableItems.add( 1.0, ItemStack( Material.CACTUS ))
sizeableItems.add( 1.0, ItemStack( Material.COCOA_BEANS ))
sizeableItems.add( 1.0, ItemStack( Material.MUSHROOM_STEW ))
sizeableItems.add( 1.0, ItemStack( Material.LAPIS_LAZULI ))
sizeableItems.add( 1.0, ItemStack( Material.ARROW ))
sizeableItems.add( 1.0, ItemStack( Material.COOKED_BEEF ))
sizeableItems.add( 1.0, ItemStack( Material.COOKED_PORKCHOP ))
sizeableItems.add( 1.0, ItemStack( Material.COOKED_CHICKEN ))
val singleItems = RandomCollection<ItemStack>()
singleItems.add( 1.0, ItemStack( Material.BOW ))
singleItems.add( 1.0, ItemStack( Material.COBWEB ))
singleItems.add( 1.0, ItemStack( Material.FLINT_AND_STEEL ))
singleItems.add( 1.0, ItemStack( Material.TNT ))
singleItems.add( 1.0, ItemStack( Material.ENDER_PEARL ))
singleItems.add( 1.0, ItemStack( Material.LAVA_BUCKET ))
singleItems.add( 1.0, ItemStack( Material.WATER_BUCKET ))
val strengthPotion = ItemStack( Material.SPLASH_POTION )
val effect = PotionEffect( PotionEffectType.STRENGTH, (60..240).random(), 0 )
strengthPotion.editMeta { ( it as PotionMeta ).addCustomEffect( effect, true ) }
singleItems.add( 1.0, strengthPotion )
val cleanser = ItemBuilder( plugin, Material.SUGAR )
.name(LegacyComponentSerializer.legacySection().serialize(plugin.chatFormatter.format( "feast.cleanser.name" )))
.unbreakable( true )
.hideAttributes()
.build()
singleItems.add( 1.0, cleanser )
val lootPool = RandomCollection<RandomCollection<ItemStack>>()
lootPool.add( 17.5, ironItems )
lootPool.add( 6.8, diamondItems )
lootPool.add( 33.0, sizeableItems )
lootPool.add( 33.0, singleItems )
lootPool.add( 1.5, netheriteItems )
for ( location in chestLocations )
{
val chest = location!!.block.state as Chest
for ( i in 0..( 6..12 ).random() )
{
val randomItemCollection = lootPool.getRandom()
val itemList = randomItemCollection.random().getRandom()
for ( item in itemList )
{
if ( randomItemCollection == sizeableItems )
item.amount = ( 1..16 ).random()
chest.inventory.setItem(random.nextInt( 26 - 1 ) + 1, item)
}
}
}
}
private fun announce(
type: AnnouncementType,
time: Int
) {
val arg = if ( type == AnnouncementType.MINUTES ) "M" else "S"
broadcast( "gameStates.feast.starting$arg", "{time}" to time.toString() )
}
private fun circle()
{
plugin.worldEditUtils.createCylinder( world!!, feastLocation, 11.0, feastHeight, Material.GRASS_BLOCK, false )
plugin.worldEditUtils.createCylinder( world, feastLocation.add( 0.0, 1.0, 0.0 ), 11.0, feastHeight, Material.AIR, false)
}
private fun getLocation(): Location
{
val x = ( -100..100 ).random()
val z = ( -100..100 ).random()
val highestY = world!!.getHighestBlockYAt( x, z )
if ( highestY >= 70 )
return getLocation()
return Location( world, x.toDouble(), highestY.toDouble() + 5.0, z.toDouble() )
} }
} }

View File

@@ -62,15 +62,14 @@ class ImmunityState(
3 -> announce( AnnouncementType.SECONDS, 3 ) 3 -> announce( AnnouncementType.SECONDS, 3 )
2 -> announce( AnnouncementType.SECONDS, 2 ) 2 -> announce( AnnouncementType.SECONDS, 2 )
1 -> announce( AnnouncementType.SECONDS, 1 ) 1 -> announce( AnnouncementType.SECONDS, 1 )
0 ->
{
broadcast( "gameStates.immunity.ended" )
gameManager.transitionTo( GameStateTypes.BATTLE )
}
} }
} }
override fun onEndOfDuration() {} override fun onEndOfDuration()
{
broadcast( "gameStates.immunity.ended" )
gameManager.transitionTo( GameStateTypes.BATTLE )
}
private fun announce( private fun announce(
type: AnnouncementType, type: AnnouncementType,

View File

@@ -60,15 +60,16 @@ class PreStartState(
3 -> announce( AnnouncementType.SECONDS, 3 ) 3 -> announce( AnnouncementType.SECONDS, 3 )
2 -> announce( AnnouncementType.SECONDS, 2 ) 2 -> announce( AnnouncementType.SECONDS, 2 )
1 -> announce( AnnouncementType.SECONDS, 1 ) 1 -> announce( AnnouncementType.SECONDS, 1 )
0 ->
{
broadcast( "gameStates.preStart.started" )
isStarting = false
gameManager.transitionTo( GameStateTypes.IMMUNITY )
}
} }
} }
override fun onEndOfDuration()
{
broadcast( "gameStates.preStart.started" )
isStarting = false
gameManager.transitionTo( GameStateTypes.IMMUNITY )
}
override fun onExit( override fun onExit(
next: GameState? next: GameState?
) { ) {
@@ -76,8 +77,6 @@ class PreStartState(
Bukkit.getOnlinePlayers().forEach { it.inventory.clear() } Bukkit.getOnlinePlayers().forEach { it.inventory.clear() }
} }
override fun onEndOfDuration() {}
private fun announce( private fun announce(
type: AnnouncementType, type: AnnouncementType,
time: Int time: Int

View File

@@ -0,0 +1,73 @@
package club.mcscrims.speedhg.util
import java.util.*
class RandomCollection<E> {
private val map = TreeMap<Double, List<E>>()
private val names = hashMapOf<List<E>, String>()
private val random = Random()
private var total = 0.0
fun add(
weight: Double,
result: E
) {
if ( weight <= 0 ) return
total += weight
map[ total ] = listOf( result )
}
fun add(
name: String,
weight: Double,
result: E
) {
if ( weight <= 0 ) return
total += weight
map[ total ] = listOf( result )
names[listOf( result )] = name
}
fun add(
weight: Double,
result: List<E>
) {
if ( weight <= 0 ) return
total += weight
map[ total ] = result
}
fun add(
name: String,
weight: Double,
result: List<E>
) {
if ( weight <= 0 ) return
total += weight
map[ total ] = result
names[ result ] = name
}
fun getName(
key: E
): String
{
return names.getOrDefault(listOf( key ), "" )
}
fun getName(
key: List<E>
): String
{
return names.getOrDefault( key, "" )
}
fun getRandom(): List<E>
{
val value = random.nextDouble() * total
return map.higherEntry( value ).value
}
}