1
0
Fork 0

Fix Second Chance

This commit is contained in:
Moritz Ruth 2020-06-19 16:02:40 +02:00
parent 87d0e6c43c
commit 4f7058d892
No known key found for this signature in database
GPG key ID: AFD57E23E753841B
7 changed files with 108 additions and 67 deletions

View file

@ -7,7 +7,8 @@ import de.moritzruth.spigot_ttt.game.items.impl.weapons.BaseballBat
import de.moritzruth.spigot_ttt.game.items.impl.weapons.Knife import de.moritzruth.spigot_ttt.game.items.impl.weapons.Knife
import de.moritzruth.spigot_ttt.game.items.impl.weapons.guns.* import de.moritzruth.spigot_ttt.game.items.impl.weapons.guns.*
import de.moritzruth.spigot_ttt.game.players.TTTPlayer import de.moritzruth.spigot_ttt.game.players.TTTPlayer
import de.moritzruth.spigot_ttt.game.players.TTTPlayerDeathEvent import de.moritzruth.spigot_ttt.game.players.TTTPlayerDeathInPreparingEvent
import de.moritzruth.spigot_ttt.game.players.TTTPlayerTrueDeathEvent
import de.moritzruth.spigot_ttt.utils.isLeftClick import de.moritzruth.spigot_ttt.utils.isLeftClick
import de.moritzruth.spigot_ttt.utils.isRightClick import de.moritzruth.spigot_ttt.utils.isRightClick
import de.moritzruth.spigot_ttt.utils.sendActionBarMessage import de.moritzruth.spigot_ttt.utils.sendActionBarMessage
@ -16,7 +17,6 @@ import org.bukkit.Material
import org.bukkit.entity.Item import org.bukkit.entity.Item
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.entity.EntityDamageByEntityEvent import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.entity.EntityPickupItemEvent import org.bukkit.event.entity.EntityPickupItemEvent
import org.bukkit.event.entity.ItemDespawnEvent import org.bukkit.event.entity.ItemDespawnEvent
@ -129,16 +129,32 @@ object ItemManager {
} }
} }
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) @EventHandler
fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) { fun onTTTPlayerDeathInPreparing(event: TTTPlayerDeathInPreparingEvent) {
val itemStackInHand = event.tttPlayer.player.inventory.itemInMainHand val itemStackInHand = event.tttPlayer.player.inventory.itemInMainHand
if (itemStackInHand.type != Material.AIR) { if (itemStackInHand.type != Material.AIR) {
val instance = getInstanceByItemStack(itemStackInHand) val instance = getInstanceByItemStack(itemStackInHand)
if (instance != null && instance.notDroppableReason == null)
GameManager.world.dropItem(event.location, instance.createItemStack())
event.tttPlayer.getOwningTTTItemInstances().forEach { if (
event.tttPlayer.removeItem(it.tttItem, false) instance != null &&
!event.tttPlayer.tttClass.defaultItems.contains(instance.tttItem) &&
instance.notDroppableReason == null
) {
event.tttPlayer.removeItem(instance.tttItem, removeInstance = false, becauseOfDeath = true)
GameManager.world.dropItem(event.location, instance.createItemStack())
}
}
}
@EventHandler
fun onTTTPlayerTrueDeath(event: TTTPlayerTrueDeathEvent) {
val itemStackInHand = event.tttPlayer.player.inventory.itemInMainHand
if (itemStackInHand.type != Material.AIR) {
val instance = getInstanceByItemStack(itemStackInHand)
if (instance != null && instance.notDroppableReason == null) {
event.tttPlayer.removeItem(instance.tttItem, removeInstance = false, becauseOfDeath = true)
GameManager.world.dropItem(event.location, instance.createItemStack())
} }
} }
} }

View file

@ -22,7 +22,8 @@ open class TTTItem<InstanceT: TTTItem.Instance>(
val instanceType: KClass<out InstanceT>, val instanceType: KClass<out InstanceT>,
val shopInfo: ShopInfo? = null, val shopInfo: ShopInfo? = null,
val spawnProbability: Probability? = null, val spawnProbability: Probability? = null,
val disableDamage: Boolean = true val disableDamage: Boolean = true,
val removeInstanceOnDeath: Boolean = true
) { ) {
open val listener: Listener? = null open val listener: Listener? = null
open val packetListener: PacketListener? = null open val packetListener: PacketListener? = null
@ -34,7 +35,7 @@ open class TTTItem<InstanceT: TTTItem.Instance>(
itemStack.itemMeta?.persistentDataContainer?.get(ID_KEY, PersistentDataType.STRING) itemStack.itemMeta?.persistentDataContainer?.get(ID_KEY, PersistentDataType.STRING)
?.let { instancesByUUID[UUID.fromString(it)] } ?.let { instancesByUUID[UUID.fromString(it)] }
fun getInstance(tttPlayer: TTTPlayer) = instancesByUUID.values.find { it.carrier === tttPlayer } open fun getInstance(tttPlayer: TTTPlayer) = instancesByUUID.values.find { it.carrier === tttPlayer }
fun reset() { fun reset() {
instancesByUUID.values.forEach { instancesByUUID.values.forEach {
@ -69,7 +70,10 @@ open class TTTItem<InstanceT: TTTItem.Instance>(
val ID_KEY = NamespacedKey(plugin, "instance") val ID_KEY = NamespacedKey(plugin, "instance")
} }
abstract class Instance(val tttItem: TTTItem<*>, droppable: Boolean = true) { abstract class Instance(
val tttItem: TTTItem<*>,
droppable: Boolean = true
) {
val uuid = UUID.randomUUID()!! val uuid = UUID.randomUUID()!!
fun createItemStack() = tttItem.templateItemStack.clone().applyMeta { fun createItemStack() = tttItem.templateItemStack.clone().applyMeta {

View file

@ -37,11 +37,7 @@ open class TTTItemListener<InstanceT: TTTItem.Instance>(private val tttItem: TTT
protected fun handleWithInstance(event: InventoryCloseEvent, handler: (instance: InstanceT) -> Unit) { protected fun handleWithInstance(event: InventoryCloseEvent, handler: (instance: InstanceT) -> Unit) {
val player = event.player val player = event.player
if (player is Player) { if (player is Player) handler(TTTPlayer.of(player)?.let { tttItem.getInstance(it) } ?: return)
val tttPlayer = TTTPlayer.of(player) ?: return
val instance = tttItem.getInstance(tttPlayer) ?: return
handler(instance)
}
} }
protected fun handleWithInstance(event: InventoryClickEvent, handler: (instance: InstanceT) -> Unit) { protected fun handleWithInstance(event: InventoryClickEvent, handler: (instance: InstanceT) -> Unit) {

View file

@ -40,18 +40,23 @@ object SecondChance: TTTItem<SecondChance.Instance>(
buyableBy = roles(Role.TRAITOR, Role.JACKAL), buyableBy = roles(Role.TRAITOR, Role.JACKAL),
buyLimit = 1, buyLimit = 1,
price = 2 price = 2
) ),
removeInstanceOnDeath = false
) { ) {
val ON_CORPSE = Resourcepack.Items.arrowDown val ON_CORPSE = Resourcepack.Items.arrowDown
val ON_SPAWN = Resourcepack.Items.dot val ON_SPAWN = Resourcepack.Items.dot
private const val TIMEOUT = 10.0 private const val TIMEOUT = 10.0
override fun getInstance(tttPlayer: TTTPlayer) =
instancesByUUID.values.find { it.tttPlayer === tttPlayer }
class Instance: TTTItem.Instance(SecondChance, false) { class Instance: TTTItem.Instance(SecondChance, false) {
var preventRoundEnd = false; private set var preventRoundEnd = false; private set
var timeoutAction: TimeoutAction? = null var timeoutAction: TimeoutAction? = null
lateinit var tttPlayer: TTTPlayer
fun possiblyTrigger() { fun possiblyTrigger() {
if (Random.nextBoolean()) trigger() if (true || Random.nextBoolean()) trigger()
} }
private fun trigger() { private fun trigger() {
@ -59,6 +64,14 @@ object SecondChance: TTTItem<SecondChance.Instance>(
timeoutAction = TimeoutAction(this) timeoutAction = TimeoutAction(this)
} }
override fun reset() {
timeoutAction?.stop()
}
override fun onCarrierSet(carrier: TTTPlayer, isFirst: Boolean) {
tttPlayer = carrier
}
class TimeoutAction(private val instance: Instance) { class TimeoutAction(private val instance: Instance) {
val deathLocation: Location = instance.requireCarrier().player.location val deathLocation: Location = instance.requireCarrier().player.location
private val startedAt = Instant.now()!! private val startedAt = Instant.now()!!
@ -66,7 +79,11 @@ object SecondChance: TTTItem<SecondChance.Instance>(
"${ChatColor.GREEN}${ChatColor.BOLD}Second Chance", "${ChatColor.GREEN}${ChatColor.BOLD}Second Chance",
BarColor.GREEN, BarColor.GREEN,
BarStyle.SOLID BarStyle.SOLID
).also { it.addPlayer(instance.requireCarrier().player) } ).also { it.addPlayer(instance.tttPlayer.player) }
init {
instance.tttPlayer.player.openInventory(chooseSpawnInventory)
}
private var task: BukkitTask = plugin.server.scheduler.runTaskTimer(plugin, fun() { private var task: BukkitTask = plugin.server.scheduler.runTaskTimer(plugin, fun() {
val duration = Duration.between(startedAt, Instant.now()).toMillis().toDouble() / 1000 val duration = Duration.between(startedAt, Instant.now()).toMillis().toDouble() / 1000
@ -79,18 +96,16 @@ object SecondChance: TTTItem<SecondChance.Instance>(
try { try {
PlayerManager.letRemainingRoleGroupWin() PlayerManager.letRemainingRoleGroupWin()
} catch (e: IllegalStateException) {} } catch (e: IllegalStateException) {}
stop() stop()
} }
fun stop() { fun stop() {
val carrier = instance.requireCarrier()
task.cancel() task.cancel()
carrier.player.apply { instance.tttPlayer.player.apply {
closeInventory() closeInventory()
bossBar.removePlayer(this) bossBar.removePlayer(this)
} }
carrier.removeItem(SecondChance) instancesByUUID.remove(instance.uuid)
} }
} }
} }
@ -127,8 +142,10 @@ object SecondChance: TTTItem<SecondChance.Instance>(
@EventHandler @EventHandler
fun onInventoryClose(event: InventoryCloseEvent) { fun onInventoryClose(event: InventoryCloseEvent) {
if (event.inventory == chooseSpawnInventory) { if (event.inventory == chooseSpawnInventory) {
handleWithInstance(event) { instance -> nextTick {
nextTick { instance.carrier?.player?.openInventory(chooseSpawnInventory) } handleWithInstance(event) { instance ->
instance.tttPlayer.player.openInventory(chooseSpawnInventory)
}
} }
} }
} }
@ -147,7 +164,7 @@ object SecondChance: TTTItem<SecondChance.Instance>(
} }
timeoutAction.stop() timeoutAction.stop()
instance.carrier!!.revive(location) instance.tttPlayer.revive(location)
} }
} }

View file

@ -84,7 +84,7 @@ class TTTPlayer(player: Player, role: Role, val tttClass: TTTClassCompanion = TT
if (GameManager.phase == GamePhase.PREPARING) { if (GameManager.phase == GamePhase.PREPARING) {
player.sendMessage("${TTTPlugin.prefix}${ChatColor.GRAY}${ChatColor.ITALIC}Du wirst nach der Vorbereitungsphase wiederbelebt") player.sendMessage("${TTTPlugin.prefix}${ChatColor.GRAY}${ChatColor.ITALIC}Du wirst nach der Vorbereitungsphase wiederbelebt")
val event = TTTPlayerDeathEvent( val event = TTTPlayerDeathInPreparingEvent(
tttPlayer = this, tttPlayer = this,
location = player.location, location = player.location,
killer = killer, killer = killer,
@ -98,19 +98,12 @@ class TTTPlayer(player: Player, role: Role, val tttClass: TTTClassCompanion = TT
val onlyRemainingRoleGroup = PlayerManager.getOnlyRemainingRoleGroup() val onlyRemainingRoleGroup = PlayerManager.getOnlyRemainingRoleGroup()
val firstEvent = TTTPlayerDeathEvent(
tttPlayer = this,
location = player.location,
killer = killer,
scream = reallyScream
).call()
val event = TTTPlayerTrueDeathEvent( val event = TTTPlayerTrueDeathEvent(
tttPlayer = this, tttPlayer = this,
location = player.location, location = player.location,
tttCorpse = tttCorpse, tttCorpse = tttCorpse,
killer = killer, killer = killer,
scream = firstEvent.scream, scream = reallyScream,
winnerRoleGroup = onlyRemainingRoleGroup winnerRoleGroup = onlyRemainingRoleGroup
).call() ).call()
@ -118,6 +111,8 @@ class TTTPlayer(player: Player, role: Role, val tttClass: TTTClassCompanion = TT
event.winnerRoleGroup?.run { GameManager.letRoleWin(primaryRole) } event.winnerRoleGroup?.run { GameManager.letRoleWin(primaryRole) }
} }
clearInventory(true)
if (reallyScream) GameManager.world.playSound( if (reallyScream) GameManager.world.playSound(
player.location, player.location,
Resourcepack.Sounds.playerDeath, Resourcepack.Sounds.playerDeath,
@ -150,7 +145,7 @@ class TTTPlayer(player: Player, role: Role, val tttClass: TTTClassCompanion = TT
player.scoreboard = scoreboard.scoreboard player.scoreboard = scoreboard.scoreboard
} }
fun getOwningTTTItemInstances() = player.inventory.hotbarContents private fun getOwningTTTItemInstances() = player.inventory.hotbarContents
.filterNotNull() .filterNotNull()
.mapNotNull { ItemManager.getInstanceByItemStack(it) } .mapNotNull { ItemManager.getInstanceByItemStack(it) }
@ -195,11 +190,21 @@ class TTTPlayer(player: Player, role: Role, val tttClass: TTTClassCompanion = TT
player.exp = 0F player.exp = 0F
player.allowFlight = player.gameMode == GameMode.CREATIVE player.allowFlight = player.gameMode == GameMode.CREATIVE
player.foodLevel = 20 player.foodLevel = 20
player.inventory.clear()
clearInventory(false)
tttClassInstance.reset() tttClassInstance.reset()
} }
private fun clearInventory(becauseOfDeath: Boolean) {
val owningTTTItemInstances = getOwningTTTItemInstances()
owningTTTItemInstances.forEach {
if (!(tttClass.defaultItems.contains(it.tttItem) && GameManager.phase == GamePhase.PREPARING)) {
removeItem(it.tttItem, becauseOfDeath = becauseOfDeath)
}
}
}
fun checkAddItemPreconditions(tttItem: TTTItem<*>) { fun checkAddItemPreconditions(tttItem: TTTItem<*>) {
val owningTTTItemInstances = getOwningTTTItemInstances() val owningTTTItemInstances = getOwningTTTItemInstances()
if (owningTTTItemInstances.find { it.tttItem === tttItem } != null) throw AlreadyHasItemException() if (owningTTTItemInstances.find { it.tttItem === tttItem } != null) throw AlreadyHasItemException()
@ -221,10 +226,13 @@ class TTTPlayer(player: Player, role: Role, val tttClass: TTTClassCompanion = TT
instance.carrier = this instance.carrier = this
} }
fun removeItem(item: TTTItem<*>, removeInstance: Boolean = true) { fun removeItem(item: TTTItem<*>, removeInstance: Boolean = true, becauseOfDeath: Boolean = false) {
item.getInstance(this)?.let { item.getInstance(this)?.let {
it.carrier = null it.carrier = null
if (removeInstance) item.instancesByUUID.remove(it.uuid) if (removeInstance && (!becauseOfDeath || it.tttItem.removeInstanceOnDeath)) {
item.instancesByUUID.remove(it.uuid)
it.reset()
}
} }
player.inventory.removeTTTItem(item) player.inventory.removeTTTItem(item)

View file

@ -0,0 +1,24 @@
package de.moritzruth.spigot_ttt.game.players
import org.bukkit.Location
import org.bukkit.event.Event
import org.bukkit.event.HandlerList
open class TTTPlayerDeathInPreparingEvent(
val tttPlayer: TTTPlayer,
val location: Location,
val killer: TTTPlayer?,
var scream: Boolean = true
): Event() {
override fun getHandlers(): HandlerList {
@Suppress("RedundantCompanionReference") // false positive
return Companion.handlers
}
companion object {
private val handlers = HandlerList()
@JvmStatic
fun getHandlerList() = handlers
}
}

View file

@ -5,11 +5,13 @@ import org.bukkit.Location
import org.bukkit.event.Event import org.bukkit.event.Event
import org.bukkit.event.HandlerList import org.bukkit.event.HandlerList
open class TTTPlayerDeathEvent( class TTTPlayerTrueDeathEvent(
val tttPlayer: TTTPlayer, val tttPlayer: TTTPlayer,
val location: Location, val location: Location,
val killer: TTTPlayer?, val killer: TTTPlayer?,
var scream: Boolean = true val scream: Boolean = true,
val tttCorpse: TTTCorpse,
var winnerRoleGroup: RoleGroup? = null
): Event() { ): Event() {
override fun getHandlers(): HandlerList { override fun getHandlers(): HandlerList {
@Suppress("RedundantCompanionReference") // false positive @Suppress("RedundantCompanionReference") // false positive
@ -23,29 +25,3 @@ open class TTTPlayerDeathEvent(
fun getHandlerList() = handlers fun getHandlerList() = handlers
} }
} }
class TTTPlayerTrueDeathEvent(
tttPlayer: TTTPlayer,
location: Location,
killer: TTTPlayer?,
scream: Boolean = true,
val tttCorpse: TTTCorpse,
var winnerRoleGroup: RoleGroup? = null
): TTTPlayerDeathEvent(
tttPlayer,
location,
killer,
scream
) {
override fun getHandlers(): HandlerList {
@Suppress("RedundantCompanionReference") // false positive
return Companion.handlers
}
companion object {
private val handlers = HandlerList()
@JvmStatic
fun getHandlerList() = handlers
}
}