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.guns.*
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.isRightClick
import de.moritzruth.spigot_ttt.utils.sendActionBarMessage
@ -16,7 +17,6 @@ import org.bukkit.Material
import org.bukkit.entity.Item
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.entity.EntityPickupItemEvent
import org.bukkit.event.entity.ItemDespawnEvent
@ -129,16 +129,32 @@ object ItemManager {
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
fun onTTTPlayerDeath(event: TTTPlayerDeathEvent) {
@EventHandler
fun onTTTPlayerDeathInPreparing(event: TTTPlayerDeathInPreparingEvent) {
val itemStackInHand = event.tttPlayer.player.inventory.itemInMainHand
if (itemStackInHand.type != Material.AIR) {
val instance = getInstanceByItemStack(itemStackInHand)
if (instance != null && instance.notDroppableReason == null)
GameManager.world.dropItem(event.location, instance.createItemStack())
event.tttPlayer.getOwningTTTItemInstances().forEach {
event.tttPlayer.removeItem(it.tttItem, false)
if (
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 shopInfo: ShopInfo? = null,
val spawnProbability: Probability? = null,
val disableDamage: Boolean = true
val disableDamage: Boolean = true,
val removeInstanceOnDeath: Boolean = true
) {
open val listener: Listener? = null
open val packetListener: PacketListener? = null
@ -34,7 +35,7 @@ open class TTTItem<InstanceT: TTTItem.Instance>(
itemStack.itemMeta?.persistentDataContainer?.get(ID_KEY, PersistentDataType.STRING)
?.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() {
instancesByUUID.values.forEach {
@ -69,7 +70,10 @@ open class TTTItem<InstanceT: TTTItem.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()!!
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) {
val player = event.player
if (player is Player) {
val tttPlayer = TTTPlayer.of(player) ?: return
val instance = tttItem.getInstance(tttPlayer) ?: return
handler(instance)
}
if (player is Player) handler(TTTPlayer.of(player)?.let { tttItem.getInstance(it) } ?: return)
}
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),
buyLimit = 1,
price = 2
)
),
removeInstanceOnDeath = false
) {
val ON_CORPSE = Resourcepack.Items.arrowDown
val ON_SPAWN = Resourcepack.Items.dot
private const val TIMEOUT = 10.0
override fun getInstance(tttPlayer: TTTPlayer) =
instancesByUUID.values.find { it.tttPlayer === tttPlayer }
class Instance: TTTItem.Instance(SecondChance, false) {
var preventRoundEnd = false; private set
var timeoutAction: TimeoutAction? = null
lateinit var tttPlayer: TTTPlayer
fun possiblyTrigger() {
if (Random.nextBoolean()) trigger()
if (true || Random.nextBoolean()) trigger()
}
private fun trigger() {
@ -59,6 +64,14 @@ object SecondChance: TTTItem<SecondChance.Instance>(
timeoutAction = TimeoutAction(this)
}
override fun reset() {
timeoutAction?.stop()
}
override fun onCarrierSet(carrier: TTTPlayer, isFirst: Boolean) {
tttPlayer = carrier
}
class TimeoutAction(private val instance: Instance) {
val deathLocation: Location = instance.requireCarrier().player.location
private val startedAt = Instant.now()!!
@ -66,7 +79,11 @@ object SecondChance: TTTItem<SecondChance.Instance>(
"${ChatColor.GREEN}${ChatColor.BOLD}Second Chance",
BarColor.GREEN,
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() {
val duration = Duration.between(startedAt, Instant.now()).toMillis().toDouble() / 1000
@ -79,18 +96,16 @@ object SecondChance: TTTItem<SecondChance.Instance>(
try {
PlayerManager.letRemainingRoleGroupWin()
} catch (e: IllegalStateException) {}
stop()
}
fun stop() {
val carrier = instance.requireCarrier()
task.cancel()
carrier.player.apply {
instance.tttPlayer.player.apply {
closeInventory()
bossBar.removePlayer(this)
}
carrier.removeItem(SecondChance)
instancesByUUID.remove(instance.uuid)
}
}
}
@ -127,8 +142,10 @@ object SecondChance: TTTItem<SecondChance.Instance>(
@EventHandler
fun onInventoryClose(event: InventoryCloseEvent) {
if (event.inventory == chooseSpawnInventory) {
nextTick {
handleWithInstance(event) { instance ->
nextTick { instance.carrier?.player?.openInventory(chooseSpawnInventory) }
instance.tttPlayer.player.openInventory(chooseSpawnInventory)
}
}
}
}
@ -147,7 +164,7 @@ object SecondChance: TTTItem<SecondChance.Instance>(
}
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) {
player.sendMessage("${TTTPlugin.prefix}${ChatColor.GRAY}${ChatColor.ITALIC}Du wirst nach der Vorbereitungsphase wiederbelebt")
val event = TTTPlayerDeathEvent(
val event = TTTPlayerDeathInPreparingEvent(
tttPlayer = this,
location = player.location,
killer = killer,
@ -98,19 +98,12 @@ class TTTPlayer(player: Player, role: Role, val tttClass: TTTClassCompanion = TT
val onlyRemainingRoleGroup = PlayerManager.getOnlyRemainingRoleGroup()
val firstEvent = TTTPlayerDeathEvent(
tttPlayer = this,
location = player.location,
killer = killer,
scream = reallyScream
).call()
val event = TTTPlayerTrueDeathEvent(
tttPlayer = this,
location = player.location,
tttCorpse = tttCorpse,
killer = killer,
scream = firstEvent.scream,
scream = reallyScream,
winnerRoleGroup = onlyRemainingRoleGroup
).call()
@ -118,6 +111,8 @@ class TTTPlayer(player: Player, role: Role, val tttClass: TTTClassCompanion = TT
event.winnerRoleGroup?.run { GameManager.letRoleWin(primaryRole) }
}
clearInventory(true)
if (reallyScream) GameManager.world.playSound(
player.location,
Resourcepack.Sounds.playerDeath,
@ -150,7 +145,7 @@ class TTTPlayer(player: Player, role: Role, val tttClass: TTTClassCompanion = TT
player.scoreboard = scoreboard.scoreboard
}
fun getOwningTTTItemInstances() = player.inventory.hotbarContents
private fun getOwningTTTItemInstances() = player.inventory.hotbarContents
.filterNotNull()
.mapNotNull { ItemManager.getInstanceByItemStack(it) }
@ -195,11 +190,21 @@ class TTTPlayer(player: Player, role: Role, val tttClass: TTTClassCompanion = TT
player.exp = 0F
player.allowFlight = player.gameMode == GameMode.CREATIVE
player.foodLevel = 20
player.inventory.clear()
clearInventory(false)
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<*>) {
val owningTTTItemInstances = getOwningTTTItemInstances()
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
}
fun removeItem(item: TTTItem<*>, removeInstance: Boolean = true) {
fun removeItem(item: TTTItem<*>, removeInstance: Boolean = true, becauseOfDeath: Boolean = false) {
item.getInstance(this)?.let {
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)

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.HandlerList
open class TTTPlayerDeathEvent(
class TTTPlayerTrueDeathEvent(
val tttPlayer: TTTPlayer,
val location: Location,
val killer: TTTPlayer?,
var scream: Boolean = true
val scream: Boolean = true,
val tttCorpse: TTTCorpse,
var winnerRoleGroup: RoleGroup? = null
): Event() {
override fun getHandlers(): HandlerList {
@Suppress("RedundantCompanionReference") // false positive
@ -23,29 +25,3 @@ open class TTTPlayerDeathEvent(
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
}
}