Compare commits
2 Commits
ca15b3deeb
...
25804f76e0
| Author | SHA1 | Date | |
|---|---|---|---|
| 25804f76e0 | |||
| fa5a54c8b9 |
@@ -3,16 +3,18 @@ plugins {
|
||||
id("com.gradleup.shadow") version "9.2.2"
|
||||
id("xyz.jpenilla.run-paper") version "3.0.2"
|
||||
id("io.papermc.paperweight.userdev") version "2.0.0-beta.19"
|
||||
id("org.jlleitschuh.gradle.ktlint") version "14.0.1"
|
||||
}
|
||||
|
||||
group = "fr.azur"
|
||||
version = "1.1-SNAPSHOT"
|
||||
|
||||
val version: String by project
|
||||
val minecraftVersion: String by project
|
||||
val paperVersion: String by project
|
||||
val skinRestorerVersion: String by project
|
||||
val voiceChatVersion: String by project
|
||||
val voiceChatApiVersion: String by project
|
||||
val luckPermsVersion: String by project
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
@@ -34,11 +36,11 @@ repositories {
|
||||
dependencies {
|
||||
paperweight.paperDevBundle("$minecraftVersion-$paperVersion")
|
||||
|
||||
|
||||
implementation("net.skinsrestorer:skinsrestorer-api:$skinRestorerVersion")
|
||||
implementation("de.maxhenkel.voicechat:voicechat-api:$voiceChatApiVersion")
|
||||
compileOnly("net.skinsrestorer:skinsrestorer-api:$skinRestorerVersion")
|
||||
compileOnly("de.maxhenkel.voicechat:voicechat-api:$voiceChatApiVersion")
|
||||
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
implementation(kotlin("reflect"))
|
||||
}
|
||||
|
||||
val targetJavaVersion = 21
|
||||
@@ -49,8 +51,9 @@ kotlin {
|
||||
tasks {
|
||||
runServer {
|
||||
downloadPlugins {
|
||||
modrinth("plasmo-voice", "bukkit-$voiceChatVersion")
|
||||
modrinth("skinsrestorer", skinRestorerVersion)
|
||||
modrinth("luckperms", luckPermsVersion)
|
||||
modrinth("simple-voice-chat", voiceChatVersion)
|
||||
}
|
||||
minecraftVersion(minecraftVersion)
|
||||
}
|
||||
@@ -69,8 +72,5 @@ tasks {
|
||||
archiveBaseName.set("tcoww")
|
||||
|
||||
minimize()
|
||||
|
||||
// exclude("META-INF/*.kotlin_module")
|
||||
// exclude("META-INF/*.version")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
version=1.2.0
|
||||
paperVersion=R0.1-SNAPSHOT
|
||||
minecraftVersion=1.21.8
|
||||
skinRestorerVersion=15.8.2
|
||||
minecraftVersion=1.21.10
|
||||
skinRestorerVersion=15.9.0
|
||||
voiceChatApiVersion=2.6.0
|
||||
voiceChatVersion=2.6.6
|
||||
voiceChatVersion=2.6.6
|
||||
luckPermsVersion=5.5.17
|
||||
@@ -1,50 +1,64 @@
|
||||
package fr.azur.tcoww
|
||||
|
||||
import de.maxhenkel.voicechat.api.BukkitVoicechatService
|
||||
import fr.azur.tcoww.events.GameEvent
|
||||
import fr.azur.tcoww.events.GameEvents
|
||||
import fr.azur.tcoww.events.PowerEvents
|
||||
import fr.azur.tcoww.events.ToolsEvents
|
||||
import fr.azur.tcoww.roles.*
|
||||
import fr.azur.tcoww.utils.Skin
|
||||
import fr.azur.tcoww.voicechat.VoiceChatPlugin
|
||||
import net.skinsrestorer.api.SkinsRestorer
|
||||
import net.skinsrestorer.api.SkinsRestorerProvider
|
||||
import fr.azur.tcoww.events.UIEvents
|
||||
import fr.azur.tcoww.roles.Child
|
||||
import fr.azur.tcoww.roles.FortuneTeller
|
||||
import fr.azur.tcoww.roles.Hunter
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import fr.azur.tcoww.roles.Villager
|
||||
import fr.azur.tcoww.roles.Werewolf
|
||||
import fr.azur.tcoww.roles.Witch
|
||||
import fr.azur.tcoww.utils.VoiceChatPlugin
|
||||
import fr.azur.tcoww.utils.skins.Manager
|
||||
import fr.azur.tcoww.utils.skins.WerewolfSkin
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerialization
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
import org.bukkit.scoreboard.Team
|
||||
|
||||
class Tcoww : JavaPlugin() {
|
||||
private lateinit var skinsRestorer: SkinsRestorer
|
||||
private lateinit var skinManager: Skin
|
||||
|
||||
object Tcoww : JavaPlugin() {
|
||||
override fun onEnable() {
|
||||
saveResource("config.yml", false)
|
||||
ConfigurationSerialization.registerClass(WerewolfSkin::class.java)
|
||||
|
||||
saveDefaultConfig()
|
||||
|
||||
skinsRestorer = SkinsRestorerProvider.get()
|
||||
skinManager = Skin(this, skinsRestorer)
|
||||
Manager.handle()
|
||||
|
||||
server.pluginManager.registerEvents(ToolsEvents(this), this)
|
||||
server.pluginManager.registerEvents(GameEvent(this, skinManager), this)
|
||||
server.pluginManager.apply {
|
||||
registerEvents(UIEvents, this@Tcoww)
|
||||
registerEvents(GameEvents, this@Tcoww)
|
||||
registerEvents(PowerEvents, this@Tcoww)
|
||||
registerEvents(ToolsEvents, this@Tcoww)
|
||||
}
|
||||
|
||||
val vcservice = server.servicesManager.load(BukkitVoicechatService::class.java)
|
||||
vcservice?.registerPlugin(VoiceChatPlugin())
|
||||
val service = server.servicesManager.load(BukkitVoicechatService::class.java)
|
||||
service?.registerPlugin(VoiceChatPlugin)
|
||||
|
||||
registerRoles()
|
||||
|
||||
val mainScoreboard = server.scoreboardManager.mainScoreboard
|
||||
if (mainScoreboard.getTeam("NoCollide") == null) {
|
||||
val team = server.scoreboardManager.mainScoreboard.registerNewTeam("NoCollision")
|
||||
team.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDisable() {
|
||||
|
||||
}
|
||||
|
||||
fun reload() {
|
||||
this.reloadConfig()
|
||||
skinManager.reloadSkin()
|
||||
}
|
||||
|
||||
private fun registerRoles() {
|
||||
Role.registerRole(Villager())
|
||||
Role.registerRole(Werewolf())
|
||||
Role.registerRole(Child())
|
||||
Role.registerRole(FortuneTeller())
|
||||
Role.registerRole(Hunter())
|
||||
Role.registerRole(Witch())
|
||||
Role.registerRole(Villager)
|
||||
Role.registerRole(Werewolf)
|
||||
Role.registerRole(Child)
|
||||
Role.registerRole(FortuneTeller)
|
||||
Role.registerRole(Hunter)
|
||||
Role.registerRole(Witch)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
package fr.azur.tcoww
|
||||
|
||||
import fr.azur.tcoww.commands.Exclude
|
||||
import fr.azur.tcoww.commands.Power
|
||||
import fr.azur.tcoww.commands.GameCommand
|
||||
import fr.azur.tcoww.commands.ReloadCommands
|
||||
import fr.azur.tcoww.commands.TimeGest
|
||||
import fr.azur.tcoww.commands.Tools
|
||||
import fr.azur.tcoww.commands.Vote
|
||||
import io.papermc.paper.plugin.bootstrap.BootstrapContext
|
||||
import io.papermc.paper.plugin.bootstrap.PluginBootstrap
|
||||
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents
|
||||
|
||||
class TcowwBootstrap : PluginBootstrap {
|
||||
object TcowwBootstrap : PluginBootstrap {
|
||||
override fun bootstrap(context: BootstrapContext) {
|
||||
context.lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS) { commands ->
|
||||
commands.registrar().register(Tools().root.build())
|
||||
commands.registrar().register(TimeGest().root.build())
|
||||
commands.registrar().register(Power().root.build())
|
||||
commands.registrar().register(GameCommand().root.build())
|
||||
commands.registrar().register(Vote().root.build())
|
||||
commands.registrar().register(ReloadCommands().root.build())
|
||||
commands.registrar().register(Exclude().root.build())
|
||||
context.lifecycleManager.apply {
|
||||
registerEventHandler(LifecycleEvents.COMMANDS) { commands ->
|
||||
commands.registrar().apply {
|
||||
register(Tools.root)
|
||||
register(GameCommand.root)
|
||||
commands.registrar().register(Vote.root)
|
||||
register(ReloadCommands.root)
|
||||
commands.registrar().register(Exclude.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,32 @@
|
||||
package fr.azur.tcoww.commands
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
import fr.azur.tcoww.game.Game
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
||||
import fr.azur.tcoww.utils.Players.kill
|
||||
import io.papermc.paper.command.brigadier.Commands
|
||||
import io.papermc.paper.command.brigadier.argument.ArgumentTypes
|
||||
import io.papermc.paper.command.brigadier.argument.resolvers.PlayerProfileListResolver
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.GameMode
|
||||
|
||||
class Exclude {
|
||||
val root: LiteralArgumentBuilder<CommandSourceStack> = Commands.literal("exclude")
|
||||
.requires { sender ->
|
||||
sender.sender.isOp
|
||||
}.then(
|
||||
Commands.literal("start")
|
||||
.then(
|
||||
Commands.argument("players", ArgumentTypes.playerProfiles()).executes { ctx ->
|
||||
val targetResolver = ctx.getArgument("players", PlayerProfileListResolver::class.java)
|
||||
val target = targetResolver.resolve(ctx.source).first()
|
||||
val uuid = target.id
|
||||
if (uuid != null) {
|
||||
val player = Bukkit.getPlayer(uuid)
|
||||
if (player != null) {
|
||||
val game = Game.current ?: return@executes Command.SINGLE_SUCCESS
|
||||
player.gameMode = GameMode.SPECTATOR
|
||||
player.isInvulnerable = false
|
||||
game.playersMutable.remove(player)
|
||||
}
|
||||
|
||||
object Exclude {
|
||||
val root =
|
||||
Commands
|
||||
.literal("exclude")
|
||||
.requires { sender ->
|
||||
sender.sender.isOp
|
||||
}.then(
|
||||
Commands.argument("players", ArgumentTypes.playerProfiles()).executes { ctx ->
|
||||
val targetResolver = ctx.getArgument("players", PlayerProfileListResolver::class.java)
|
||||
val target = targetResolver.resolve(ctx.source).first()
|
||||
val uuid = target.id
|
||||
if (uuid != null) {
|
||||
val player = Bukkit.getPlayer(uuid)
|
||||
if (player != null) {
|
||||
val game = Game.current ?: return@executes Command.SINGLE_SUCCESS
|
||||
player.kill()
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
},
|
||||
).build()
|
||||
}
|
||||
|
||||
@@ -1,67 +1,90 @@
|
||||
package fr.azur.tcoww.commands
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.arguments.StringArgumentType
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import fr.azur.tcoww.game.Game
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import fr.azur.tcoww.roles.Villager
|
||||
import fr.azur.tcoww.roles.Werewolf
|
||||
import fr.azur.tcoww.ui.GameConfig
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
||||
import io.papermc.paper.command.brigadier.Commands
|
||||
import io.papermc.paper.command.brigadier.argument.ArgumentTypes
|
||||
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver
|
||||
import io.papermc.paper.dialog.Dialog
|
||||
import io.papermc.paper.registry.data.dialog.ActionButton
|
||||
import io.papermc.paper.registry.data.dialog.DialogBase
|
||||
import io.papermc.paper.registry.data.dialog.action.DialogAction
|
||||
import io.papermc.paper.registry.data.dialog.type.DialogType
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.event.ClickEvent
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.World
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.plugin.Plugin
|
||||
|
||||
|
||||
class GameCommand {
|
||||
val root: LiteralArgumentBuilder<CommandSourceStack> = Commands.literal("game")
|
||||
.requires { sender ->
|
||||
sender.sender.isOp
|
||||
}.then(
|
||||
Commands.literal("start")
|
||||
.then(
|
||||
Commands.argument("players", ArgumentTypes.players()).then(
|
||||
Commands.argument("roles", StringArgumentType.greedyString()).suggests { ctx, builder ->
|
||||
val roleswithoutauto =
|
||||
Role.registerRoles.filter { role -> role.value !is Villager && role.value !is Werewolf }
|
||||
val rolessplit = builder.remaining.split(" ")
|
||||
val startstr = rolessplit.dropLast(1).joinToString(separator = " ")
|
||||
|
||||
roleswithoutauto.forEach { role ->
|
||||
if (role.key.toString().startsWith(rolessplit.last())) {
|
||||
builder.suggest("$startstr${if (startstr.isEmpty()) "" else " "}${role.key}")
|
||||
}
|
||||
}
|
||||
if (builder.remaining != "" && !builder.remaining.endsWith(" ")) {
|
||||
roleswithoutauto.forEach { role ->
|
||||
builder.suggest("${builder.remaining} ${role.key}")
|
||||
}
|
||||
}
|
||||
builder.buildFuture()
|
||||
}.executes { ctx ->
|
||||
val plugin = Bukkit.getPluginManager().getPlugin("tcoww")!!
|
||||
val targetResolver = ctx.getArgument("players", PlayerSelectorArgumentResolver::class.java)
|
||||
val targets = targetResolver.resolve(ctx.source)
|
||||
|
||||
val rolesstr = StringArgumentType.getString(ctx, "roles")
|
||||
val rolessplit = rolesstr.split(" ")
|
||||
|
||||
val roles = rolessplit.map { str ->
|
||||
Role.registerRoles[NamespacedKey.fromString(str)]
|
||||
}
|
||||
val correctrole = roles.filterNotNull()
|
||||
|
||||
Game(plugin, ctx.source.location.world, targets, correctrole)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
object GameCommand {
|
||||
private fun createDialog(
|
||||
plugin: Plugin,
|
||||
world: World,
|
||||
players: Iterable<Player>,
|
||||
roles: Map<NamespacedKey, Int>,
|
||||
): Dialog =
|
||||
Dialog.create { builder ->
|
||||
builder
|
||||
.empty()
|
||||
.base(
|
||||
DialogBase
|
||||
.builder(Component.text("Start the Game", NamedTextColor.GREEN))
|
||||
.canCloseWithEscape(true)
|
||||
.build(),
|
||||
).type(
|
||||
DialogType.confirmation(
|
||||
ActionButton
|
||||
.builder(Component.text("Start", NamedTextColor.GREEN))
|
||||
.action(
|
||||
DialogAction.staticAction(
|
||||
ClickEvent.callback {
|
||||
Game(plugin, world, players, roles)
|
||||
it.closeDialog()
|
||||
},
|
||||
),
|
||||
).build(),
|
||||
ActionButton
|
||||
.builder(Component.text("Cancel", NamedTextColor.RED))
|
||||
.action(DialogAction.staticAction(ClickEvent.callback { it.closeDialog() }))
|
||||
.build(),
|
||||
),
|
||||
)
|
||||
).then(
|
||||
Commands.literal("stop").executes { ctx ->
|
||||
Game.current?.stopGame(true)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val root: LiteralCommandNode<CommandSourceStack> =
|
||||
Commands
|
||||
.literal("game")
|
||||
.requires { sender ->
|
||||
sender.sender.isOp
|
||||
}.then(
|
||||
Commands
|
||||
.literal("start")
|
||||
.executes { ctx ->
|
||||
val executor = ctx.source.executor ?: ctx.source.sender
|
||||
if (executor is Player) {
|
||||
val players =
|
||||
Bukkit
|
||||
.getOnlinePlayers()
|
||||
.filter { it.gameMode == GameMode.ADVENTURE || it.gameMode == GameMode.SURVIVAL }
|
||||
val menu = GameConfig(players.size)
|
||||
executor.openInventory(menu.inventory)
|
||||
menu.future.thenAccept {
|
||||
val dialog = createDialog(Tcoww, executor.world, players, it)
|
||||
executor.showDialog(dialog)
|
||||
}
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
},
|
||||
).then(
|
||||
Commands.literal("stop").executes { ctx ->
|
||||
Game.current?.stopGame(true)
|
||||
Command.SINGLE_SUCCESS
|
||||
},
|
||||
).build()
|
||||
}
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
package fr.azur.tcoww.commands
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
import fr.azur.tcoww.game.Game
|
||||
import fr.azur.tcoww.roles.FortuneTeller
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import fr.azur.tcoww.roles.Witch
|
||||
import fr.azur.tcoww.utils.Stockage
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
||||
import io.papermc.paper.command.brigadier.Commands
|
||||
import io.papermc.paper.command.brigadier.argument.ArgumentTypes
|
||||
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.event.HoverEvent
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
import org.bukkit.potion.PotionEffect
|
||||
import org.bukkit.potion.PotionEffectType
|
||||
|
||||
class Power {
|
||||
val root: LiteralArgumentBuilder<CommandSourceStack> = Commands.literal("power")
|
||||
.requires { ctx -> ctx.sender as? Player != null && Role.getRole(ctx.sender as Player)?.hasPowerCommand == true }
|
||||
.then(
|
||||
Commands.literal("kill")
|
||||
.requires { ctx ->
|
||||
val player = ctx.executor as? Player ?: return@requires false
|
||||
val role = Role.getRole(player)
|
||||
(role is Witch && player.hasPowerItem(1))
|
||||
}
|
||||
.then(
|
||||
Commands.argument("target", ArgumentTypes.player())
|
||||
.suggests { _, builder ->
|
||||
Game.current?.playersMutable?.forEach { builder.suggest(it.name) }
|
||||
builder.buildFuture()
|
||||
}
|
||||
.executes { ctx ->
|
||||
val target = ctx.getTargetPlayer("target") ?: return@executes 0
|
||||
val player = ctx.source.getPlayer() ?: return@executes 0
|
||||
if (Game.current?.playersMutable?.contains(target) == true) {
|
||||
target.addPotionEffect(PotionEffect(PotionEffectType.WITHER, 600, 4))
|
||||
player.removePowerItem(1)
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
)
|
||||
.then(
|
||||
Commands.literal("save")
|
||||
.requires { ctx ->
|
||||
val player = ctx.executor as? Player ?: return@requires false
|
||||
val role = Role.getRole(player)
|
||||
role is Witch && player.hasPowerItem(2)
|
||||
}
|
||||
.then(
|
||||
Commands.argument("target", ArgumentTypes.player())
|
||||
.executes { ctx ->
|
||||
val target = ctx.getTargetPlayer("target") ?: return@executes 0
|
||||
val player = ctx.source.getPlayer() ?: return@executes 0
|
||||
if (Game.current?.playersMutable?.contains(target) == true &&
|
||||
target.persistentDataContainer.get(
|
||||
NamespacedKey("tcoww", "dead"),
|
||||
PersistentDataType.BOOLEAN
|
||||
) == true
|
||||
) {
|
||||
target.persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "dead"),
|
||||
PersistentDataType.BOOLEAN,
|
||||
false
|
||||
)
|
||||
Stockage.backLocation[target.uniqueId]?.let { target.teleport(it) }
|
||||
target.isInvulnerable = false
|
||||
target.sendMessage(Component.text("Vous avez été résucité.").color(NamedTextColor.AQUA))
|
||||
player.sendMessage(
|
||||
Component.text("Vous avez résuciter ").color(NamedTextColor.AQUA)
|
||||
.append(player.displayName())
|
||||
)
|
||||
player.removePowerItem(2)
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
)
|
||||
.then(
|
||||
Commands.literal("view")
|
||||
.requires { ctx ->
|
||||
val player = ctx.executor as? Player ?: return@requires false
|
||||
val role = Role.getRole(player)
|
||||
role is FortuneTeller && player.hasPowerItem(4)
|
||||
}
|
||||
.then(
|
||||
Commands.argument("target", ArgumentTypes.player())
|
||||
.suggests { _, builder ->
|
||||
Game.current?.playersMutable?.forEach { builder.suggest(it.name) }
|
||||
builder.buildFuture()
|
||||
}
|
||||
.executes { ctx ->
|
||||
val target = ctx.getTargetPlayer("target") ?: return@executes 0
|
||||
val player = ctx.source.getPlayer() ?: return@executes 0
|
||||
val plugin = Bukkit.getPluginManager().getPlugin("tcoww") ?: return@executes 0
|
||||
if (Game.current?.playersMutable?.contains(target) == true) {
|
||||
val item = player.getPowerItem(4) ?: return@executes 0
|
||||
|
||||
val timeGestion = Game.current!!.timeGestion
|
||||
val cooldown =
|
||||
((timeGestion.dayDuration + timeGestion.voteDuration + timeGestion.nightDuration + timeGestion.crepuscularDuration - 30) * 2) * 20
|
||||
|
||||
val cloneditem = item.clone()
|
||||
|
||||
player.inventory.remove(item)
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(plugin, Runnable {
|
||||
player.inventory.addItem(cloneditem)
|
||||
}, cooldown.toLong())
|
||||
|
||||
val targetrole = Role.getRole(target)
|
||||
|
||||
player.sendMessage(
|
||||
target.displayName().append(Component.text(" est "))
|
||||
.append(
|
||||
(targetrole?.displayName ?: Component.text("Inconnu").hoverEvent(
|
||||
HoverEvent.showText(
|
||||
targetrole?.description ?: Component.empty()
|
||||
)
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
private fun CommandSourceStack.getPlayer(): Player? = (this.executor ?: this.sender) as? Player
|
||||
|
||||
private fun Player.hasPowerItem(id: Int): Boolean = this.inventory.any {
|
||||
it?.persistentDataContainer?.get(NamespacedKey("tcoww", "power"), PersistentDataType.INTEGER) == id
|
||||
}
|
||||
|
||||
private fun Player.getPowerItem(id: Int) = this.inventory.firstOrNull {
|
||||
it?.persistentDataContainer?.get(NamespacedKey("tcoww", "power"), PersistentDataType.INTEGER) == id
|
||||
}
|
||||
|
||||
private fun Player.removePowerItem(id: Int) {
|
||||
val item = getPowerItem(id) ?: return
|
||||
this.inventory.remove(item)
|
||||
}
|
||||
|
||||
private fun com.mojang.brigadier.context.CommandContext<CommandSourceStack>.getTargetPlayer(name: String): Player? {
|
||||
val resolver = this.getArgument(name, PlayerSelectorArgumentResolver::class.java)
|
||||
return resolver.resolve(this.source).firstOrNull()
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,21 @@
|
||||
package fr.azur.tcoww.commands
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
||||
import io.papermc.paper.command.brigadier.Commands
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class ReloadCommands {
|
||||
val root: LiteralArgumentBuilder<CommandSourceStack> = Commands.literal("reloadcommands").executes { ctx ->
|
||||
val sender = ctx.source.sender as? Player
|
||||
sender?.updateCommands()
|
||||
sender?.sendMessage(Component.text("Commands rechargés !").color(NamedTextColor.GOLD))
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
object ReloadCommands {
|
||||
val root: LiteralCommandNode<CommandSourceStack> =
|
||||
Commands
|
||||
.literal("reload-commands")
|
||||
.executes { ctx ->
|
||||
val sender = ctx.source.sender as? Player
|
||||
sender?.updateCommands()
|
||||
sender?.sendMessage(Component.text("Commands rechargés !", NamedTextColor.GOLD))
|
||||
Command.SINGLE_SUCCESS
|
||||
}.build()
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package fr.azur.tcoww.commands
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
import fr.azur.tcoww.game.TimeGestion
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
||||
import io.papermc.paper.command.brigadier.Commands
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.plugin.Plugin
|
||||
import org.bukkit.scheduler.BukkitTask
|
||||
|
||||
class TimeGest {
|
||||
var timeGestion: TimeGestion? = null
|
||||
var sheduler: BukkitTask? = null
|
||||
var plugin: Plugin? = null
|
||||
|
||||
private fun kill() {
|
||||
sheduler?.cancel()
|
||||
sheduler = null
|
||||
timeGestion = null
|
||||
}
|
||||
|
||||
val root: LiteralArgumentBuilder<CommandSourceStack> = Commands.literal("timegest")
|
||||
.requires { sender ->
|
||||
sender.sender.isOp
|
||||
}.then(
|
||||
Commands.literal("start").executes { ctx ->
|
||||
if (plugin == null) plugin = Bukkit.getPluginManager().getPlugin("tcoww")!!
|
||||
val executor = ctx.source.executor
|
||||
if (executor == null) throw Error("No executor !")
|
||||
if (timeGestion != null || sheduler != null) kill()
|
||||
timeGestion = TimeGestion(plugin!!, executor.world)
|
||||
sheduler = Bukkit.getScheduler().runTaskTimer(plugin!!, Runnable {
|
||||
timeGestion!!.tick()
|
||||
}, 0L, 1L)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
).then(
|
||||
Commands.literal("kill").executes {
|
||||
kill()
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package fr.azur.tcoww.commands
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType
|
||||
import com.mojang.brigadier.arguments.StringArgumentType
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import fr.azur.tcoww.items.CustomItems
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
||||
@@ -16,131 +16,139 @@ import org.bukkit.Bukkit
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class Tools {
|
||||
val root: LiteralArgumentBuilder<CommandSourceStack> = Commands.literal("tools")
|
||||
.requires { sender ->
|
||||
sender.sender.isOp
|
||||
}.then(
|
||||
Commands.literal("location")
|
||||
.then(
|
||||
Commands.literal("bed").executes { ctx ->
|
||||
val player = ctx.source.executor as Player
|
||||
player.inventory.addItem(CustomItems.BedLocTool.item)
|
||||
Command.SINGLE_SUCCESS
|
||||
}.then(
|
||||
Commands.literal("get").executes { ctx ->
|
||||
ctx.source.sender.sendMessage(sendBed())
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
).then(
|
||||
Commands.literal("remove").then(
|
||||
Commands.argument("index", IntegerArgumentType.integer(0))
|
||||
.executes { ctx ->
|
||||
val plugin = Bukkit.getPluginManager().getPlugin("tcoww") ?: return@executes 0
|
||||
val index = IntegerArgumentType.getInteger(ctx, "index")
|
||||
val list = plugin.config.getMapList("bedLocation")
|
||||
|
||||
plugin.config.set("bedLocation", list.minus(list[index]))
|
||||
plugin.saveConfig()
|
||||
|
||||
object Tools {
|
||||
val root: LiteralCommandNode<CommandSourceStack> =
|
||||
Commands
|
||||
.literal("tools")
|
||||
.requires { sender ->
|
||||
sender.sender.isOp
|
||||
}.then(
|
||||
Commands
|
||||
.literal("location")
|
||||
.then(
|
||||
Commands
|
||||
.literal("bed")
|
||||
.executes { ctx ->
|
||||
val player = ctx.source.executor as Player
|
||||
player.inventory.addItem(CustomItems.BedLocTool.item)
|
||||
Command.SINGLE_SUCCESS
|
||||
}.then(
|
||||
Commands.literal("get").executes { ctx ->
|
||||
ctx.source.sender.sendMessage(sendBed())
|
||||
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
))
|
||||
).then(
|
||||
Commands.literal("spawn").executes { ctx ->
|
||||
val player = ctx.source.executor as Player
|
||||
player.inventory.addItem(CustomItems.SpawnLocTool.item)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
).then(
|
||||
Commands.literal("lobby").executes { ctx ->
|
||||
val player = ctx.source.executor as Player
|
||||
player.inventory.addItem(CustomItems.LobbyLocTool.item)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
).then(
|
||||
Commands.literal("reload").executes {
|
||||
val plugin = Bukkit.getPluginManager().getPlugin("tcoww") as Tcoww
|
||||
plugin.reload()
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
).then(
|
||||
Commands.literal("customitem").then(
|
||||
Commands.argument("item", StringArgumentType.greedyString())
|
||||
.suggests { _, builder ->
|
||||
CustomItems.entries.forEach {
|
||||
builder.suggest(it.name)
|
||||
}
|
||||
builder.buildFuture()
|
||||
}
|
||||
.executes { ctx ->
|
||||
val itemName = StringArgumentType.getString(ctx, "item")
|
||||
val item = CustomItems.valueOf(itemName).item
|
||||
val exe = ctx.source.executor
|
||||
if (exe is Player) {
|
||||
exe.inventory.addItem(item)
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
)
|
||||
},
|
||||
).then(
|
||||
Commands.literal("remove").then(
|
||||
Commands
|
||||
.argument("index", IntegerArgumentType.integer(0))
|
||||
.executes { ctx ->
|
||||
val plugin = Bukkit.getPluginManager().getPlugin("tcoww") ?: return@executes 0
|
||||
val index = IntegerArgumentType.getInteger(ctx, "index")
|
||||
val list =
|
||||
plugin.config
|
||||
.getList("bed-locations")
|
||||
.orEmpty()
|
||||
.mapNotNull { it as? Location }
|
||||
|
||||
plugin.config.set("bed-locations", list.drop(index))
|
||||
plugin.saveConfig()
|
||||
|
||||
ctx.source.sender.sendMessage(sendBed())
|
||||
|
||||
Command.SINGLE_SUCCESS
|
||||
},
|
||||
),
|
||||
),
|
||||
).then(
|
||||
Commands.literal("spawn").executes { ctx ->
|
||||
val player = ctx.source.executor as Player
|
||||
player.inventory.addItem(CustomItems.SpawnLocTool.item)
|
||||
Command.SINGLE_SUCCESS
|
||||
},
|
||||
).then(
|
||||
Commands.literal("lobby").executes { ctx ->
|
||||
val player = ctx.source.executor as Player
|
||||
player.inventory.addItem(CustomItems.LobbyLocTool.item)
|
||||
Command.SINGLE_SUCCESS
|
||||
},
|
||||
),
|
||||
).then(
|
||||
Commands.literal("reload").executes {
|
||||
val plugin = Bukkit.getPluginManager().getPlugin("tcoww") as Tcoww
|
||||
plugin.reload()
|
||||
Command.SINGLE_SUCCESS
|
||||
},
|
||||
).then(
|
||||
Commands.literal("customitem").then(
|
||||
Commands
|
||||
.argument("item", StringArgumentType.greedyString())
|
||||
.suggests { _, builder ->
|
||||
CustomItems.entries.forEach {
|
||||
builder.suggest(it.name)
|
||||
}
|
||||
builder.buildFuture()
|
||||
}.executes { ctx ->
|
||||
val itemName = StringArgumentType.getString(ctx, "item")
|
||||
val item = CustomItems.valueOf(itemName).item
|
||||
val exe = ctx.source.executor
|
||||
if (exe is Player) {
|
||||
exe.inventory.addItem(item)
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
},
|
||||
),
|
||||
).build()
|
||||
|
||||
fun sendBed(): Component {
|
||||
val plugin = Bukkit.getPluginManager().getPlugin("tcoww") ?: return Component.empty()
|
||||
val bedlist = plugin.config.getMapList("bedLocation")
|
||||
val bedLocationComponent = bedlist.map {
|
||||
if (it as? Map<String, Object> != null) {
|
||||
val loc = Location.deserialize(it as Map<String, Object>)
|
||||
Component.text("[${loc.x}, ${loc.y}, ${loc.z}] ")
|
||||
.color(NamedTextColor.LIGHT_PURPLE)
|
||||
.append(
|
||||
Component.text("teleport")
|
||||
.clickEvent(
|
||||
ClickEvent.runCommand("/minecraft:tp ${loc.x.toInt()} ${loc.y.toInt()} ${loc.z.toInt()}")
|
||||
)
|
||||
.color(NamedTextColor.LIGHT_PURPLE)
|
||||
.decorate(TextDecoration.UNDERLINED)
|
||||
)
|
||||
.appendSpace()
|
||||
.append(
|
||||
Component.text("remove")
|
||||
.clickEvent(
|
||||
ClickEvent.runCommand(
|
||||
"/tcoww:tools location bed remove ${
|
||||
bedlist.indexOf(
|
||||
it
|
||||
)
|
||||
}"
|
||||
)
|
||||
)
|
||||
.color(NamedTextColor.LIGHT_PURPLE)
|
||||
.decorate(TextDecoration.UNDERLINED)
|
||||
)
|
||||
.appendNewline()
|
||||
} else Component.text("[unkown location] ")
|
||||
.color(NamedTextColor.LIGHT_PURPLE)
|
||||
.append(
|
||||
Component.text("remove")
|
||||
.clickEvent(
|
||||
ClickEvent.runCommand(
|
||||
"/tcoww:tools location bed remove ${
|
||||
bedlist.indexOf(
|
||||
it
|
||||
)
|
||||
}"
|
||||
)
|
||||
)
|
||||
val bedList =
|
||||
plugin.config
|
||||
.getList("bed-locations")
|
||||
.orEmpty()
|
||||
val bedLocationComponent =
|
||||
bedList.mapIndexed { index, element ->
|
||||
if (element is Location) {
|
||||
Component
|
||||
.text("[${element.x}, ${element.y}, ${element.z}] ")
|
||||
.color(NamedTextColor.LIGHT_PURPLE)
|
||||
.decorate(TextDecoration.UNDERLINED)
|
||||
)
|
||||
.appendNewline()
|
||||
}
|
||||
return Component.text("Current bed locations :")
|
||||
.append(
|
||||
Component
|
||||
.text("teleport")
|
||||
.clickEvent(
|
||||
ClickEvent.runCommand("/minecraft:tp ${element.x} ${element.y} ${element.z}"),
|
||||
).color(NamedTextColor.LIGHT_PURPLE)
|
||||
.decorate(TextDecoration.UNDERLINED),
|
||||
).appendSpace()
|
||||
.append(
|
||||
Component
|
||||
.text("remove")
|
||||
.clickEvent(
|
||||
ClickEvent.runCommand(
|
||||
"/tcoww:tools location bed remove $index",
|
||||
),
|
||||
).color(NamedTextColor.LIGHT_PURPLE)
|
||||
.decorate(TextDecoration.UNDERLINED),
|
||||
).appendNewline()
|
||||
} else {
|
||||
Component
|
||||
.text("[unkown location] ")
|
||||
.color(NamedTextColor.LIGHT_PURPLE)
|
||||
.append(
|
||||
Component
|
||||
.text("remove")
|
||||
.clickEvent(
|
||||
ClickEvent.runCommand(
|
||||
"/tcoww:tools location bed remove $index",
|
||||
),
|
||||
).color(NamedTextColor.LIGHT_PURPLE)
|
||||
.decorate(TextDecoration.UNDERLINED),
|
||||
).appendNewline()
|
||||
}
|
||||
}
|
||||
return Component
|
||||
.text("Current bed locations :")
|
||||
.color(NamedTextColor.DARK_PURPLE)
|
||||
.appendNewline()
|
||||
.append(bedLocationComponent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,53 @@
|
||||
package fr.azur.tcoww.commands
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode
|
||||
import fr.azur.tcoww.game.Game
|
||||
import fr.azur.tcoww.game.Phase
|
||||
import fr.azur.tcoww.utils.Stockage
|
||||
import fr.azur.tcoww.game.NightLightCycle
|
||||
import fr.azur.tcoww.ui.PlayerSelectMenu
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack
|
||||
import io.papermc.paper.command.brigadier.Commands
|
||||
import io.papermc.paper.command.brigadier.argument.ArgumentTypes
|
||||
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
|
||||
class Vote {
|
||||
val root: LiteralArgumentBuilder<CommandSourceStack> = Commands.literal("vote").then(
|
||||
Commands.argument("target", ArgumentTypes.player())
|
||||
.requires { ctx ->
|
||||
Game.current?.timeGestion?.phase == Phase.VOTE && Game.current!!.playersMutable.contains(ctx.sender)
|
||||
}.suggests { ctx, builder ->
|
||||
Game.current?.playersMutable?.forEach { player -> builder.suggest(player.name) }
|
||||
builder.buildFuture()
|
||||
}.executes { ctx ->
|
||||
val targetResolver = ctx.getArgument("target", PlayerSelectorArgumentResolver::class.java)
|
||||
val target = targetResolver.resolve(ctx.source).first()
|
||||
object Vote {
|
||||
var vote = mutableMapOf<UUID, UUID>()
|
||||
|
||||
val root: LiteralCommandNode<CommandSourceStack> =
|
||||
Commands
|
||||
.literal("vote")
|
||||
.then(
|
||||
Commands
|
||||
.argument("target", ArgumentTypes.player())
|
||||
.requires { ctx ->
|
||||
Game.current?.timeGestion?.phase == NightLightCycle.Phase.VOTE &&
|
||||
Game.current!!.remainingPlayer.contains(ctx.sender)
|
||||
}.suggests { _, builder ->
|
||||
Game.current?.remainingPlayer?.forEach { player -> builder.suggest(player.name) }
|
||||
builder.buildFuture()
|
||||
}.executes { ctx ->
|
||||
val targetResolver = ctx.getArgument("target", PlayerSelectorArgumentResolver::class.java)
|
||||
val target = targetResolver.resolve(ctx.source).first()
|
||||
val player = (ctx.source.executor ?: ctx.source.sender as Player) as Player
|
||||
if (Game.current?.remainingPlayer?.contains(target) ?: false) {
|
||||
vote[player.uniqueId] = target.uniqueId
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
},
|
||||
).executes { ctx ->
|
||||
val current = Game.current ?: return@executes Command.SINGLE_SUCCESS
|
||||
val player = (ctx.source.executor ?: ctx.source.sender as Player) as Player
|
||||
if (Game.current?.playersMutable?.contains(target) ?: false) {
|
||||
Stockage.vote[player.uniqueId] = target.uniqueId
|
||||
|
||||
val menu = PlayerSelectMenu(current.remainingPlayer)
|
||||
player.openInventory(menu.inventory)
|
||||
|
||||
menu.future.whenComplete { selectedPlayer, _ ->
|
||||
val target = selectedPlayer ?: return@whenComplete
|
||||
vote[player.uniqueId] = target.uniqueId
|
||||
}
|
||||
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
}
|
||||
}.build()
|
||||
}
|
||||
|
||||
@@ -1,421 +0,0 @@
|
||||
package fr.azur.tcoww.events
|
||||
|
||||
import fr.azur.tcoww.game.Game
|
||||
import fr.azur.tcoww.game.Phase
|
||||
import fr.azur.tcoww.items.CustomItems
|
||||
import fr.azur.tcoww.roles.Child
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import fr.azur.tcoww.roles.Witch
|
||||
import fr.azur.tcoww.utils.BedGestion
|
||||
import fr.azur.tcoww.utils.Skin
|
||||
import fr.azur.tcoww.utils.Stockage
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.event.ClickEvent
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import net.kyori.adventure.text.format.TextDecoration
|
||||
import net.kyori.adventure.title.Title
|
||||
import org.bukkit.*
|
||||
import org.bukkit.attribute.Attribute
|
||||
import org.bukkit.attribute.AttributeModifier
|
||||
import org.bukkit.entity.EntityType
|
||||
import org.bukkit.entity.ItemDisplay
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.EventPriority
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent
|
||||
import org.bukkit.event.entity.PlayerDeathEvent
|
||||
import org.bukkit.event.inventory.InventoryMoveItemEvent
|
||||
import org.bukkit.event.player.*
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.SkullMeta
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
import org.bukkit.plugin.Plugin
|
||||
import org.bukkit.potion.PotionEffect
|
||||
import org.bukkit.potion.PotionEffectType
|
||||
import java.time.Duration
|
||||
|
||||
class GameEvent(val plugin: Plugin, val skinUtils: Skin) : Listener {
|
||||
@EventHandler
|
||||
fun phaseChange(event: TimePhaseChangeEvent) {
|
||||
Game.current?.playersMutable?.forEach { it.updateCommands() }
|
||||
when (event.newPhase) {
|
||||
Phase.DAY -> {
|
||||
event.world.players.forEach { player ->
|
||||
player.sendMessage(Component.text("Le jour se lève.").color(NamedTextColor.GOLD))
|
||||
player.clearActivePotionEffects()
|
||||
player.persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "insomie"),
|
||||
PersistentDataType.BOOLEAN,
|
||||
false
|
||||
)
|
||||
if (player.role?.lg == true) {
|
||||
player.inventory.forEach {
|
||||
if (it != null && it.persistentDataContainer.get(
|
||||
NamespacedKey("tcoww", "power"),
|
||||
PersistentDataType.INTEGER
|
||||
) == 3
|
||||
) {
|
||||
player.inventory.remove(it)
|
||||
}
|
||||
|
||||
if (player.isTransformed()) {
|
||||
player.tfHuman()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Phase.VOTE -> {
|
||||
event.world.players.forEach { player ->
|
||||
player.sendMessage(
|
||||
Component.text("Le jour se couche, ce soir un vote est organisé.")
|
||||
.color(NamedTextColor.DARK_AQUA)
|
||||
.appendNewline()
|
||||
.append(
|
||||
Component.text("Faite /vote <pseudo> pour voter.")
|
||||
.color(NamedTextColor.AQUA)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Phase.NIGHT -> {
|
||||
if (Stockage.vote.isNotEmpty()) {
|
||||
val voteMap = Stockage.vote.values.groupingBy { it }.eachCount()
|
||||
val mostVoted = voteMap.maxByOrNull { it.value }?.key
|
||||
mostVoted?.let { uuid ->
|
||||
Bukkit.getPlayer(uuid)?.let { votedPlayer ->
|
||||
votedPlayer.fireTicks = 1200
|
||||
Bukkit.getScheduler().runTaskLater(plugin, Runnable {
|
||||
votedPlayer.health = 0.0
|
||||
}, 60)
|
||||
Game.current?.playersMutable?.forEach {
|
||||
it.sendMessage(
|
||||
Component.text("${votedPlayer.name} a reçu le plus de vote.")
|
||||
.color(NamedTextColor.RED)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Stockage.vote.clear()
|
||||
}
|
||||
|
||||
Game.current?.wwcankill = true
|
||||
event.world.players.forEach { player ->
|
||||
player.sendMessage(
|
||||
Component.text("La lune se léve et les loups sont de sortie. Vous devriez dormir.")
|
||||
.color(NamedTextColor.DARK_PURPLE)
|
||||
)
|
||||
|
||||
if (player.role?.lg ?: false) {
|
||||
player.sendMessage(
|
||||
Component.text("Vous pouvez vous transformer.").color(NamedTextColor.DARK_PURPLE)
|
||||
)
|
||||
player.inventory.addItem(CustomItems.WereWolfTransformItem.item)
|
||||
}
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(plugin, Runnable {
|
||||
val openBed = plugin.config.getMapList("bedLocation").mapNotNull {
|
||||
if (it as? Map<String, Object> != null) Location.deserialize(it as Map<String, Object>) else null
|
||||
}.filter { !BedGestion.isOcupied(it.block) }.toMutableList()
|
||||
Game.current?.playersMutable?.forEach { player ->
|
||||
if (!player.isSleeping && !player.persistentDataContainer.getOrDefault(
|
||||
NamespacedKey("tcoww", "dead"),
|
||||
PersistentDataType.BOOLEAN,
|
||||
false
|
||||
) && !player.isTransformed()
|
||||
) {
|
||||
val loc = openBed.removeFirst()
|
||||
player.sleep(loc, true)
|
||||
|
||||
val role = player.role
|
||||
if (role is Child || role?.lg == true) {
|
||||
player.sendMessage(
|
||||
Component.text(
|
||||
"Tout le monde est couché. Vous pouvez vous lever.",
|
||||
NamedTextColor.AQUA
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, plugin.config.getLong("playerSleep"))
|
||||
}
|
||||
|
||||
Phase.CREPUSCULAR -> {
|
||||
val current = Game.current ?: return
|
||||
val deadPlayers = current.playersMutable.filter {
|
||||
it.persistentDataContainer.get(NamespacedKey("tcoww", "dead"), PersistentDataType.BOOLEAN) == true
|
||||
}
|
||||
|
||||
deadPlayers.forEach { player ->
|
||||
player.gameMode = GameMode.SPECTATOR
|
||||
Stockage.backLocation[player.uniqueId]?.let { player.teleport(it) }
|
||||
player.kill(current)
|
||||
}
|
||||
|
||||
current.playersMutable.removeAll(deadPlayers)
|
||||
if (current.gameEnded()) {
|
||||
current.playersMutable.forEach {
|
||||
if (it.isTransformed()) it.tfHuman()
|
||||
}
|
||||
current.stopGame()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun powerItemDrop(event: PlayerDropItemEvent) {
|
||||
val item = event.itemDrop.itemStack
|
||||
if (event.player.gameMode != GameMode.CREATIVE &&
|
||||
item.itemMeta.persistentDataContainer.has(NamespacedKey("tcoww", "power"), PersistentDataType.INTEGER)
|
||||
) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun powerItemTransfer(event: InventoryMoveItemEvent) {
|
||||
val item = event.item
|
||||
if (event.source != event.destination &&
|
||||
item.itemMeta.persistentDataContainer.has(NamespacedKey("tcoww", "power"), PersistentDataType.INTEGER)
|
||||
) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun sleepLeaveEvent(event: PlayerBedLeaveEvent) {
|
||||
val role = event.player.role
|
||||
if (Game.current?.timeGestion?.phase == Phase.NIGHT &&
|
||||
role !is Child && role?.lg != true &&
|
||||
!event.player.persistentDataContainer.getOrDefault(
|
||||
NamespacedKey("tcoww", "insomie"),
|
||||
PersistentDataType.BOOLEAN,
|
||||
false
|
||||
)
|
||||
) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun clickEvent(event: PlayerInteractEvent) {
|
||||
val item = event.item ?: return
|
||||
if (item.persistentDataContainer.get(NamespacedKey("tcoww", "power"), PersistentDataType.INTEGER) == 3) {
|
||||
val player = event.player
|
||||
|
||||
player.inventory.remove(item)
|
||||
|
||||
if (player.isTransformed()) {
|
||||
player.tfHuman()
|
||||
} else {
|
||||
player.tfWerewolf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onDeath(event: PlayerDeathEvent) {
|
||||
val current = Game.current ?: return
|
||||
val player = event.player
|
||||
if (!current.playersMutable.contains(player)) return
|
||||
|
||||
event.isCancelled = true
|
||||
|
||||
if (current.timeGestion.phase == Phase.NIGHT) {
|
||||
Stockage.backLocation[player.uniqueId] = player.location
|
||||
Bukkit.getScheduler().runTaskLater(plugin, Runnable {
|
||||
player.teleport(plugin.config.getLocation("lobbyLocation")!!)
|
||||
player.clearActivePotionEffects()
|
||||
player.fireTicks = 0
|
||||
}, 1)
|
||||
player.isInvulnerable = true
|
||||
player.persistentDataContainer.set(NamespacedKey("tcoww", "dead"), PersistentDataType.BOOLEAN, true)
|
||||
player.sendMessage(
|
||||
Component.text("Vous étes mort... Mais vous pouvez être encore résucité.").color(
|
||||
NamedTextColor.RED
|
||||
)
|
||||
)
|
||||
|
||||
current.playersMutable.forEach { p ->
|
||||
if (p.role is Witch && p.inventory.any {
|
||||
it != null && it.persistentDataContainer.get(
|
||||
NamespacedKey("tcoww", "power"),
|
||||
PersistentDataType.INTEGER
|
||||
) == 2
|
||||
}) {
|
||||
p.sendMessage(
|
||||
Component.text("Cette nuit, ${player.name} est mort dans d'atroces souffrances. Vous avez le pouvoir de le/la sauver.\n")
|
||||
.color(NamedTextColor.DARK_PURPLE)
|
||||
.append(
|
||||
Component.text("Cliquez ici pour le/la ressusciter.")
|
||||
.color(NamedTextColor.DARK_PURPLE)
|
||||
.decorate(TextDecoration.UNDERLINED)
|
||||
.clickEvent(ClickEvent.suggestCommand("/power save ${player.name}"))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.kill(current)
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onHit(event: EntityDamageByEntityEvent) {
|
||||
val current = Game.current ?: return
|
||||
if (current.timeGestion.phase != Phase.NIGHT) return
|
||||
|
||||
val damager = event.damager
|
||||
val target = event.entity
|
||||
if (damager is Player && target is Player &&
|
||||
current.playersMutable.contains(damager) &&
|
||||
current.playersMutable.contains(target) &&
|
||||
damager.role?.lg == true &&
|
||||
damager.isTransformed() &&
|
||||
target.role?.lg != true &&
|
||||
current.wwcankill
|
||||
) {
|
||||
current.wwcankill = false
|
||||
target.health = 0.0
|
||||
target.persistentDataContainer.set(NamespacedKey("tcoww", "insomie"), PersistentDataType.BOOLEAN, true)
|
||||
if (target.isSleeping) target.wakeup(false)
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(
|
||||
priority = EventPriority.MONITOR,
|
||||
ignoreCancelled = true
|
||||
)
|
||||
fun startSleep(event: PlayerBedEnterEvent) {
|
||||
event.player.addPotionEffect(
|
||||
PotionEffect(
|
||||
PotionEffectType.REGENERATION,
|
||||
PotionEffect.INFINITE_DURATION,
|
||||
1,
|
||||
false,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@EventHandler(
|
||||
priority = EventPriority.MONITOR,
|
||||
ignoreCancelled = true
|
||||
)
|
||||
fun endSleep(event: PlayerBedLeaveEvent) {
|
||||
event.player.removePotionEffect(PotionEffectType.REGENERATION)
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun disconnect(event: PlayerQuitEvent) {
|
||||
val current = Game.current ?: return
|
||||
val player = event.player
|
||||
if (!current.playersMutable.contains(player)) return
|
||||
Bukkit.getScheduler().runTaskLater(plugin, Runnable {
|
||||
if (!player.isConnected) {
|
||||
player.kill(current)
|
||||
}
|
||||
}, 2_400)
|
||||
}
|
||||
|
||||
fun Player.kill(current: Game) {
|
||||
if (isTransformed()) tfHuman()
|
||||
val item = ItemStack.of(Material.PLAYER_HEAD)
|
||||
val skullmeta = item.itemMeta as SkullMeta
|
||||
skullmeta.owningPlayer = player
|
||||
item.itemMeta = skullmeta
|
||||
|
||||
val loc = this.location.add(0.0, 1.5, 0.0)
|
||||
val entity = this.world.spawnEntity(loc, EntityType.ITEM_DISPLAY) as ItemDisplay
|
||||
entity.setItemStack(item)
|
||||
Bukkit.getScheduler().runTaskLater(
|
||||
plugin,
|
||||
Runnable {
|
||||
entity.remove()
|
||||
},
|
||||
2400L
|
||||
)
|
||||
|
||||
|
||||
this.gameMode = GameMode.SPECTATOR
|
||||
this.isInvulnerable = false
|
||||
current.playersMutable.remove(player)
|
||||
|
||||
this.showTitle(
|
||||
Title.title(
|
||||
Component.text("Vous êtes mort.").color(NamedTextColor.DARK_RED),
|
||||
Component.empty(),
|
||||
Title.Times.times(Duration.ZERO, Duration.ofSeconds(2), Duration.ofMillis(500))
|
||||
)
|
||||
)
|
||||
|
||||
if (current.gameEnded()) current.stopGame()
|
||||
}
|
||||
|
||||
fun Player.tfWerewolf() {
|
||||
if (isTransformed()) return
|
||||
|
||||
skinUtils.applyWerewolfFur(this)
|
||||
persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "wwtranform"),
|
||||
PersistentDataType.BOOLEAN,
|
||||
true
|
||||
)
|
||||
|
||||
val speedatr = getAttribute(Attribute.MOVEMENT_SPEED)!!
|
||||
val scaleatr = getAttribute(Attribute.SCALE)!!
|
||||
|
||||
speedatr.addModifier(
|
||||
AttributeModifier(
|
||||
NamespacedKey("tcoww", "wwtranform"),
|
||||
0.05,
|
||||
AttributeModifier.Operation.ADD_NUMBER
|
||||
)
|
||||
)
|
||||
scaleatr.addModifier(
|
||||
AttributeModifier(
|
||||
NamespacedKey("tcoww", "wwtranform"),
|
||||
0.1,
|
||||
AttributeModifier.Operation.ADD_NUMBER
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun Player.tfHuman() {
|
||||
if (!isTransformed()) return
|
||||
|
||||
skinUtils.unApplySkin(this)
|
||||
persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "wwtranform"),
|
||||
PersistentDataType.BOOLEAN,
|
||||
false
|
||||
)
|
||||
|
||||
val speedatr = getAttribute(Attribute.MOVEMENT_SPEED)!!
|
||||
val scaleatr = getAttribute(Attribute.SCALE)!!
|
||||
speedatr.removeModifier(
|
||||
NamespacedKey("tcoww", "wwtranform")
|
||||
)
|
||||
scaleatr.removeModifier(
|
||||
NamespacedKey("tcoww", "wwtranform")
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
fun Player.isTransformed(): Boolean {
|
||||
return persistentDataContainer.getOrDefault(
|
||||
NamespacedKey("tcoww", "wwtranform"),
|
||||
PersistentDataType.BOOLEAN,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
val Player.role
|
||||
get() = Role.getRole(this)
|
||||
}
|
||||
247
src/main/kotlin/fr/azur/tcoww/events/GameEvents.kt
Normal file
247
src/main/kotlin/fr/azur/tcoww/events/GameEvents.kt
Normal file
@@ -0,0 +1,247 @@
|
||||
package fr.azur.tcoww.events
|
||||
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import fr.azur.tcoww.events.PowerEvents.backLocation
|
||||
import fr.azur.tcoww.game.Game
|
||||
import fr.azur.tcoww.game.NightLightCycle
|
||||
import fr.azur.tcoww.roles.Child
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import fr.azur.tcoww.roles.Role.Companion.werewolfRole
|
||||
import fr.azur.tcoww.roles.Witch
|
||||
import fr.azur.tcoww.utils.DataKeys.Insomnia
|
||||
import fr.azur.tcoww.utils.DataKeys.PlayerDead
|
||||
import fr.azur.tcoww.utils.DataKeys.PowerItems
|
||||
import fr.azur.tcoww.utils.Players
|
||||
import fr.azur.tcoww.utils.Players.isTransformed
|
||||
import fr.azur.tcoww.utils.Players.kill
|
||||
import fr.azur.tcoww.utils.VoiceChatPlugin
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.event.ClickEvent
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import net.kyori.adventure.text.format.TextDecoration
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Mannequin
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.EventPriority
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent
|
||||
import org.bukkit.event.entity.PlayerDeathEvent
|
||||
import org.bukkit.event.player.PlayerBedEnterEvent
|
||||
import org.bukkit.event.player.PlayerBedLeaveEvent
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent
|
||||
import org.bukkit.inventory.meta.Damageable
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
import org.bukkit.potion.PotionEffect
|
||||
import org.bukkit.potion.PotionEffectType
|
||||
|
||||
object GameEvents : Listener {
|
||||
@EventHandler
|
||||
fun onDeath(event: PlayerDeathEvent) {
|
||||
val current = Game.current ?: return
|
||||
val player = event.player
|
||||
if (!current.remainingPlayer.contains(player)) return
|
||||
|
||||
event.isCancelled = true
|
||||
|
||||
if (current.timeGestion.phase == NightLightCycle.Phase.NIGHT) {
|
||||
backLocation[player.uniqueId] = player.location
|
||||
val lobby = Tcoww.config.getLocation("lobby-location")
|
||||
Bukkit.getScheduler().runTaskLater(
|
||||
Tcoww,
|
||||
Runnable {
|
||||
if (lobby != null) {
|
||||
player.teleport(lobby)
|
||||
} else {
|
||||
player.gameMode = GameMode.SPECTATOR
|
||||
}
|
||||
player.clearActivePotionEffects()
|
||||
player.fireTicks = 0
|
||||
},
|
||||
1,
|
||||
)
|
||||
player.isInvulnerable = true
|
||||
player.persistentDataContainer.set(PlayerDead, PersistentDataType.BOOLEAN, true)
|
||||
player.sendMessage(
|
||||
Component.text(
|
||||
"Vous étes mort... Mais vous pouvez être encore résucité.",
|
||||
NamedTextColor.RED,
|
||||
),
|
||||
)
|
||||
|
||||
current.remainingPlayer.forEach { p ->
|
||||
if (p.werewolfRole is Witch &&
|
||||
p.inventory.any {
|
||||
it != null &&
|
||||
it.persistentDataContainer.get(
|
||||
PowerItems,
|
||||
PersistentDataType.INTEGER,
|
||||
) == 2 &&
|
||||
(it.itemMeta as Damageable).damage != 1
|
||||
}
|
||||
) {
|
||||
p.sendMessage(
|
||||
Component
|
||||
.text(
|
||||
"Cette nuit, ${player.name} est mort dans d'atroces souffrances. Vous avez le pouvoir de le/la sauver.\n",
|
||||
NamedTextColor.DARK_PURPLE,
|
||||
).append(
|
||||
Component
|
||||
.text("Cliquez ici pour le/la ressusciter.", NamedTextColor.DARK_PURPLE)
|
||||
.decorate(TextDecoration.UNDERLINED)
|
||||
.clickEvent(
|
||||
ClickEvent.callback {
|
||||
val item =
|
||||
p.inventory.find {
|
||||
it != null &&
|
||||
it.persistentDataContainer.get(
|
||||
PowerItems,
|
||||
PersistentDataType.INTEGER,
|
||||
) == 2 &&
|
||||
(it.itemMeta as Damageable).damage != 1
|
||||
}
|
||||
|
||||
if (player.persistentDataContainer.get(
|
||||
PlayerDead,
|
||||
PersistentDataType.BOOLEAN,
|
||||
) == true
|
||||
) {
|
||||
return@callback
|
||||
}
|
||||
if (item == null) return@callback
|
||||
|
||||
(item.itemMeta as Damageable).damage = 1
|
||||
|
||||
player.persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "dead"),
|
||||
PersistentDataType.BOOLEAN,
|
||||
false,
|
||||
)
|
||||
backLocation[player.uniqueId]?.let { player.teleport(it) }
|
||||
player.isInvulnerable = false
|
||||
player.sendMessage(
|
||||
Component.text("Vous avez été résucité.", NamedTextColor.AQUA),
|
||||
)
|
||||
player.sendMessage(
|
||||
Component
|
||||
.text("Vous avez résuciter ")
|
||||
.color(NamedTextColor.AQUA)
|
||||
.append(player.displayName()),
|
||||
)
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.kill()
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onHit(event: EntityDamageByEntityEvent) {
|
||||
val current = Game.current ?: return
|
||||
if (current.timeGestion.phase != NightLightCycle.Phase.NIGHT) return
|
||||
|
||||
val damager = event.damager
|
||||
val target = event.entity
|
||||
if (damager is Player &&
|
||||
target is Player &&
|
||||
current.remainingPlayer.contains(damager) &&
|
||||
current.remainingPlayer.contains(target) &&
|
||||
damager.werewolfRole.team == Role.Team.LG &&
|
||||
damager.isTransformed() &&
|
||||
target.werewolfRole.team != Role.Team.LG
|
||||
) {
|
||||
target.health = 0.0
|
||||
target.persistentDataContainer.set(Insomnia, PersistentDataType.BOOLEAN, true)
|
||||
if (target.isSleeping) target.wakeup(false)
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun sleepLeaveEvent(event: PlayerBedLeaveEvent) {
|
||||
val role = event.player.werewolfRole
|
||||
if (Game.current?.timeGestion?.phase == NightLightCycle.Phase.NIGHT &&
|
||||
role !is Child &&
|
||||
role.team != Role.Team.LG &&
|
||||
!event.player.persistentDataContainer.getOrDefault(
|
||||
Insomnia,
|
||||
PersistentDataType.BOOLEAN,
|
||||
false,
|
||||
)
|
||||
) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(
|
||||
priority = EventPriority.MONITOR,
|
||||
ignoreCancelled = true,
|
||||
)
|
||||
fun startSleep(event: PlayerBedEnterEvent) {
|
||||
if (event.player.werewolfRole.team == Role.Team.LG) {
|
||||
VoiceChatPlugin.addWerewolf(event.player)
|
||||
} else {
|
||||
VoiceChatPlugin.createSoloGroup(event.player)
|
||||
}
|
||||
event.player.addPotionEffect(
|
||||
PotionEffect(
|
||||
PotionEffectType.REGENERATION,
|
||||
PotionEffect.INFINITE_DURATION,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
)
|
||||
event.player.addPotionEffect(
|
||||
PotionEffect(
|
||||
PotionEffectType.BLINDNESS,
|
||||
PotionEffect.INFINITE_DURATION,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@EventHandler(
|
||||
priority = EventPriority.MONITOR,
|
||||
)
|
||||
fun endSleep(event: PlayerBedLeaveEvent) {
|
||||
event.player.removePotionEffect(PotionEffectType.REGENERATION)
|
||||
event.player.removePotionEffect(PotionEffectType.BLINDNESS)
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun clickOnCorpse(event: PlayerInteractEntityEvent) {
|
||||
val corpse = event.rightClicked
|
||||
if (corpse is Mannequin &&
|
||||
corpse.persistentDataContainer.getOrDefault(Players.corpseKey, PersistentDataType.BOOLEAN, false)
|
||||
) {
|
||||
val deadPlayer = Bukkit.getPlayer(corpse.profile.uuid()!!)!!
|
||||
val playerRole =
|
||||
Role.registerRoles.getValue(
|
||||
NamespacedKey.fromString(
|
||||
corpse.persistentDataContainer.get(
|
||||
Players.corpseRoleKey,
|
||||
PersistentDataType.STRING,
|
||||
)!!,
|
||||
)!!,
|
||||
)
|
||||
event.player.sendMessage {
|
||||
Component
|
||||
.text("Ceci est le cadavre de ", NamedTextColor.DARK_RED)
|
||||
.append(deadPlayer.displayName())
|
||||
.append(Component.text(".", NamedTextColor.DARK_RED))
|
||||
.appendNewline()
|
||||
.append(Component.text("Il était ", NamedTextColor.DARK_RED))
|
||||
.append(playerRole.displayName)
|
||||
.append(Component.text(".", NamedTextColor.DARK_RED))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
178
src/main/kotlin/fr/azur/tcoww/events/PhaseEvents.kt
Normal file
178
src/main/kotlin/fr/azur/tcoww/events/PhaseEvents.kt
Normal file
@@ -0,0 +1,178 @@
|
||||
package fr.azur.tcoww.events
|
||||
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import fr.azur.tcoww.commands.Vote
|
||||
import fr.azur.tcoww.game.Game
|
||||
import fr.azur.tcoww.game.NightLightCycle
|
||||
import fr.azur.tcoww.roles.Child
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import fr.azur.tcoww.roles.Role.Companion.werewolfRole
|
||||
import fr.azur.tcoww.utils.BedGestion.isOccupied
|
||||
import fr.azur.tcoww.utils.DataKeys.Insomnia
|
||||
import fr.azur.tcoww.utils.DataKeys.PlayerDead
|
||||
import fr.azur.tcoww.utils.DataKeys.PowerItems
|
||||
import fr.azur.tcoww.utils.Players.isTransformed
|
||||
import fr.azur.tcoww.utils.Players.kill
|
||||
import fr.azur.tcoww.utils.Players.tfHuman
|
||||
import fr.azur.tcoww.utils.VoiceChatPlugin
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
|
||||
object PhaseEvents : Listener {
|
||||
@EventHandler
|
||||
fun phaseChange(event: NightLightCycle.NightLightCyclePhaseChangeEvent) {
|
||||
val current = Game.current ?: return
|
||||
current.remainingPlayer.forEach { it.updateCommands() }
|
||||
when (event.newPhase) {
|
||||
NightLightCycle.Phase.DAY -> {
|
||||
event.world.players.forEach { player ->
|
||||
VoiceChatPlugin.degroupPlayer(player)
|
||||
player.sendMessage(Component.text("Le jour se lève.", NamedTextColor.GOLD))
|
||||
player.clearActivePotionEffects()
|
||||
player.persistentDataContainer.set(
|
||||
Insomnia,
|
||||
PersistentDataType.BOOLEAN,
|
||||
false,
|
||||
)
|
||||
if (player.werewolfRole.team == Role.Team.LG) {
|
||||
player.inventory.forEach {
|
||||
if (it != null &&
|
||||
it.persistentDataContainer.get(
|
||||
PowerItems,
|
||||
PersistentDataType.INTEGER,
|
||||
) == 3
|
||||
) {
|
||||
player.setCooldown(it, ((event.duration.day + event.duration.vote) * 20))
|
||||
}
|
||||
|
||||
if (player.isTransformed()) {
|
||||
player.tfHuman()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NightLightCycle.Phase.VOTE -> {
|
||||
event.world.players.forEach { player ->
|
||||
player.sendMessage(
|
||||
Component
|
||||
.text("Le jour se couche, ce soir un vote est organisé.")
|
||||
.color(NamedTextColor.DARK_AQUA)
|
||||
.appendNewline()
|
||||
.append(
|
||||
Component
|
||||
.text("Faite /vote <pseudo> pour voter.")
|
||||
.color(NamedTextColor.AQUA),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
NightLightCycle.Phase.NIGHT -> {
|
||||
if (Vote.vote.isNotEmpty()) {
|
||||
val voteMap =
|
||||
Vote.vote.values
|
||||
.groupingBy { it }
|
||||
.eachCount()
|
||||
val mostVoted = voteMap.maxByOrNull { it.value }?.key
|
||||
mostVoted?.let { uuid ->
|
||||
Bukkit.getPlayer(uuid)?.let { votedPlayer ->
|
||||
votedPlayer.fireTicks = 1200
|
||||
Bukkit.getScheduler().runTaskLater(
|
||||
Tcoww,
|
||||
Runnable {
|
||||
votedPlayer.health = 0.0
|
||||
},
|
||||
60,
|
||||
)
|
||||
current.remainingPlayer.forEach {
|
||||
it.sendMessage(
|
||||
Component
|
||||
.text("${votedPlayer.name} a reçu le plus de vote.")
|
||||
.color(NamedTextColor.RED),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Vote.vote.clear()
|
||||
}
|
||||
|
||||
event.world.players.forEach { player ->
|
||||
player.sendMessage(
|
||||
Component
|
||||
.text("La lune se léve et les loups sont de sortie. Vous devriez dormir.")
|
||||
.color(NamedTextColor.DARK_PURPLE),
|
||||
)
|
||||
|
||||
if (player.werewolfRole.team == Role.Team.LG) {
|
||||
player.sendMessage(
|
||||
Component.text("Vous pouvez vous transformer.", NamedTextColor.DARK_PURPLE),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(
|
||||
Tcoww,
|
||||
Runnable {
|
||||
val openBed =
|
||||
current.beds
|
||||
.filter { !it.block.isOccupied() }
|
||||
.toMutableList()
|
||||
current.remainingPlayer.forEach { player ->
|
||||
if (!player.isSleeping &&
|
||||
!player.persistentDataContainer.getOrDefault(
|
||||
PlayerDead,
|
||||
PersistentDataType.BOOLEAN,
|
||||
false,
|
||||
) &&
|
||||
!player.isTransformed()
|
||||
) {
|
||||
val loc = openBed.removeFirst()
|
||||
player.sleep(loc, true)
|
||||
|
||||
val role = player.werewolfRole
|
||||
if (role is Child || role.team == Role.Team.LG) {
|
||||
player.sendMessage(
|
||||
Component.text(
|
||||
"Tout le monde est couché. Vous pouvez vous lever.",
|
||||
NamedTextColor.AQUA,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Tcoww.config.getLong("player-sleep"),
|
||||
)
|
||||
}
|
||||
|
||||
NightLightCycle.Phase.CREPUSCULAR -> {
|
||||
val current = Game.current ?: return
|
||||
val deadPlayers =
|
||||
current.remainingPlayer.filter {
|
||||
it.persistentDataContainer.get(PlayerDead, PersistentDataType.BOOLEAN) == true
|
||||
}
|
||||
|
||||
deadPlayers.forEach { player ->
|
||||
player.gameMode = GameMode.SPECTATOR
|
||||
PowerEvents.backLocation[player.uniqueId]?.let { player.teleport(it) }
|
||||
player.kill()
|
||||
}
|
||||
|
||||
current.remainingPlayer.removeAll(deadPlayers)
|
||||
// if (current.gameEnded()) {
|
||||
// current.remainingPlayer.forEach {
|
||||
// if (it.isTransformed()) it.tfHuman()
|
||||
// }
|
||||
// current.stopGame()
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
157
src/main/kotlin/fr/azur/tcoww/events/PowerEvents.kt
Normal file
157
src/main/kotlin/fr/azur/tcoww/events/PowerEvents.kt
Normal file
@@ -0,0 +1,157 @@
|
||||
package fr.azur.tcoww.events
|
||||
|
||||
import fr.azur.tcoww.game.Game
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import fr.azur.tcoww.ui.PlayerSelectMenu
|
||||
import fr.azur.tcoww.utils.DataKeys
|
||||
import fr.azur.tcoww.utils.Players.isTransformed
|
||||
import fr.azur.tcoww.utils.Players.tfHuman
|
||||
import fr.azur.tcoww.utils.Players.tfWerewolf
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.event.HoverEvent
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.InventoryMoveItemEvent
|
||||
import org.bukkit.event.player.PlayerDropItemEvent
|
||||
import org.bukkit.event.player.PlayerInteractEvent
|
||||
import org.bukkit.inventory.meta.Damageable
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
import org.bukkit.potion.PotionEffect
|
||||
import org.bukkit.potion.PotionEffectType
|
||||
import java.util.UUID
|
||||
|
||||
object PowerEvents : Listener {
|
||||
var backLocation = mutableMapOf<UUID, Location>()
|
||||
|
||||
@EventHandler
|
||||
fun powerItemDrop(event: PlayerDropItemEvent) {
|
||||
val item = event.itemDrop.itemStack
|
||||
if (event.player.gameMode != GameMode.CREATIVE &&
|
||||
item.itemMeta.persistentDataContainer.has(DataKeys.PowerItems, PersistentDataType.INTEGER)
|
||||
) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun powerItemTransfer(event: InventoryMoveItemEvent) {
|
||||
val item = event.item
|
||||
if (event.source != event.destination &&
|
||||
item.itemMeta.persistentDataContainer.has(DataKeys.PowerItems, PersistentDataType.INTEGER)
|
||||
) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun clickEvent(event: PlayerInteractEvent) {
|
||||
val item = event.item ?: return
|
||||
val player = event.player
|
||||
if (player.hasCooldown(item)) return
|
||||
when (item.persistentDataContainer.get(NamespacedKey("tcoww", "power"), PersistentDataType.INTEGER)) {
|
||||
1 -> {
|
||||
if ((item.itemMeta as Damageable).damage == 1) return
|
||||
val current = Game.current ?: return
|
||||
|
||||
val menu = PlayerSelectMenu(current.remainingPlayer)
|
||||
player.openInventory(menu.inventory)
|
||||
|
||||
menu.future.whenComplete { selectedPlayer, _ ->
|
||||
val target = selectedPlayer ?: return@whenComplete
|
||||
(item.itemMeta as Damageable).damage = 1
|
||||
target.addPotionEffect(PotionEffect(PotionEffectType.WITHER, 600, 4))
|
||||
}
|
||||
}
|
||||
|
||||
2 -> {
|
||||
if ((item.itemMeta as Damageable).damage == 1) return
|
||||
val current = Game.current ?: return
|
||||
|
||||
val menu =
|
||||
PlayerSelectMenu(
|
||||
current.remainingPlayer.filter {
|
||||
it.persistentDataContainer.get(
|
||||
NamespacedKey("tcoww", "dead"),
|
||||
PersistentDataType.BOOLEAN,
|
||||
) == true
|
||||
},
|
||||
)
|
||||
|
||||
player.openInventory(menu.inventory)
|
||||
|
||||
menu.future.whenComplete { selectedPlayer, _ ->
|
||||
val target = selectedPlayer ?: return@whenComplete
|
||||
(item.itemMeta as Damageable).damage = 1
|
||||
target.persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "dead"),
|
||||
PersistentDataType.BOOLEAN,
|
||||
false,
|
||||
)
|
||||
backLocation[target.uniqueId]?.let { target.teleport(it) }
|
||||
target.isInvulnerable = false
|
||||
target.sendMessage(Component.text("Vous avez été résucité.", NamedTextColor.AQUA))
|
||||
player.sendMessage(
|
||||
Component
|
||||
.text("Vous avez résuciter ")
|
||||
.color(NamedTextColor.AQUA)
|
||||
.append(player.displayName()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
3 -> {
|
||||
player.setCooldown(item, 600)
|
||||
|
||||
if (player.isTransformed()) {
|
||||
player.tfHuman()
|
||||
} else {
|
||||
player.tfWerewolf()
|
||||
}
|
||||
}
|
||||
|
||||
4 -> {
|
||||
val current = Game.current ?: return
|
||||
val timeGestion = current.timeGestion
|
||||
|
||||
val menu = PlayerSelectMenu(current.remainingPlayer)
|
||||
player.openInventory(menu.inventory)
|
||||
|
||||
menu.future.whenComplete { selectedPlayer, _ ->
|
||||
val target = selectedPlayer ?: return@whenComplete
|
||||
|
||||
val cooldown =
|
||||
(
|
||||
(
|
||||
timeGestion.duration.day + timeGestion.duration.vote + timeGestion.duration.night +
|
||||
timeGestion.duration.crepuscular -
|
||||
30
|
||||
) *
|
||||
2
|
||||
) *
|
||||
20
|
||||
|
||||
player.setCooldown(item, cooldown)
|
||||
|
||||
val targetRole = Role.getRole(target)
|
||||
|
||||
player.sendMessage(
|
||||
target
|
||||
.displayName()
|
||||
.append(Component.text(" est "))
|
||||
.append(
|
||||
targetRole?.displayName ?: Component.text("Inconnu").hoverEvent(
|
||||
HoverEvent.showText(
|
||||
targetRole?.lineDescription ?: Component.empty(),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package fr.azur.tcoww.events
|
||||
|
||||
import fr.azur.tcoww.game.Phase
|
||||
import org.bukkit.World
|
||||
import org.bukkit.event.Event
|
||||
import org.bukkit.event.HandlerList
|
||||
|
||||
class TimePhaseChangeEvent(
|
||||
val world: World,
|
||||
val newPhase: Phase
|
||||
) : Event() {
|
||||
override fun getHandlers(): HandlerList {
|
||||
return handlerList
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val handlerList: HandlerList = HandlerList()
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,56 @@
|
||||
package fr.azur.tcoww.events
|
||||
|
||||
import fr.azur.tcoww.utils.BedGestion
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import fr.azur.tcoww.utils.BedGestion.getHeadBed
|
||||
import fr.azur.tcoww.utils.BedGestion.isBed
|
||||
import fr.azur.tcoww.utils.DataKeys
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.player.PlayerInteractEvent
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
|
||||
class ToolsEvents(val plugin: JavaPlugin) : Listener {
|
||||
object ToolsEvents : Listener {
|
||||
@EventHandler
|
||||
fun clickEvent(event: PlayerInteractEvent) {
|
||||
val tool = event.player.inventory.itemInMainHand
|
||||
|
||||
if (!tool.persistentDataContainer.has(NamespacedKey("tcoww", "tools"))) return
|
||||
if (!tool.persistentDataContainer.has(DataKeys.ToolsItems) || event.player.hasCooldown(tool)) return
|
||||
|
||||
when (tool.persistentDataContainer.get(NamespacedKey("tcoww", "tools"), PersistentDataType.INTEGER)) {
|
||||
event.player.setCooldown(tool, 20)
|
||||
|
||||
when (tool.persistentDataContainer.get(DataKeys.ToolsItems, PersistentDataType.INTEGER)) {
|
||||
1 -> {
|
||||
event.isCancelled = true
|
||||
val interactloc = event.interactionPoint
|
||||
if (interactloc != null) {
|
||||
if (BedGestion.isBed(interactloc.block)) {
|
||||
val list = plugin.config.getMapList("bedLocation")
|
||||
val interactLoc = event.interactionPoint
|
||||
if (interactLoc != null) {
|
||||
if (interactLoc.block.isBed()) {
|
||||
val list =
|
||||
Tcoww.config
|
||||
.getList("bed-locations")
|
||||
.orEmpty()
|
||||
.mapNotNull { it as? Location }
|
||||
.toMutableList()
|
||||
|
||||
val block = BedGestion.getHeadBed(interactloc.block)
|
||||
val block = interactLoc.block.getHeadBed()
|
||||
|
||||
if (!list.contains(block.location.serialize())) {
|
||||
list.add(block.location.serialize())
|
||||
plugin.config.set("bedLocation", list)
|
||||
plugin.saveConfig()
|
||||
if (!list.contains(block.location)) {
|
||||
list.add(block.location)
|
||||
Tcoww.config.set("bed-locations", list)
|
||||
Tcoww.saveConfig()
|
||||
event.player.sendMessage(
|
||||
Component.text("Bed location add.").color(NamedTextColor.LIGHT_PURPLE)
|
||||
Component.text("Bed location add.", NamedTextColor.LIGHT_PURPLE),
|
||||
)
|
||||
} else {
|
||||
event.player.sendMessage(
|
||||
Component.text("Bed location already exists.").color(NamedTextColor.DARK_RED)
|
||||
Component.text("Bed location already exists.", NamedTextColor.DARK_RED),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
event.player.sendMessage(
|
||||
Component.text("It's not a bed...").color(NamedTextColor.DARK_RED)
|
||||
Component.text("It's not a bed...", NamedTextColor.DARK_RED),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -49,34 +58,29 @@ class ToolsEvents(val plugin: JavaPlugin) : Listener {
|
||||
|
||||
2 -> {
|
||||
event.isCancelled = true
|
||||
val interactloc = event.interactionPoint
|
||||
if (interactloc != null) {
|
||||
interactloc.x = interactloc.blockX.toDouble()
|
||||
interactloc.y = interactloc.blockY.toDouble() + 1
|
||||
interactloc.z = interactloc.blockZ.toDouble()
|
||||
plugin.config.set("spawnLocation", interactloc)
|
||||
plugin.saveConfig()
|
||||
event.player.sendMessage(Component.text("Spawn location set.").color(NamedTextColor.LIGHT_PURPLE))
|
||||
val interactLoc = event.interactionPoint
|
||||
if (interactLoc != null) {
|
||||
interactLoc.x = interactLoc.blockX.toDouble()
|
||||
interactLoc.y = interactLoc.blockY.toDouble() + 1
|
||||
interactLoc.z = interactLoc.blockZ.toDouble()
|
||||
Tcoww.config.set("spawn-location", interactLoc)
|
||||
Tcoww.saveConfig()
|
||||
event.player.sendMessage(Component.text("Spawn location set.", NamedTextColor.LIGHT_PURPLE))
|
||||
}
|
||||
}
|
||||
|
||||
3 -> {
|
||||
event.isCancelled = true
|
||||
val interactloc = event.interactionPoint
|
||||
if (interactloc != null) {
|
||||
interactloc.x = interactloc.blockX.toDouble()
|
||||
interactloc.y = interactloc.blockY.toDouble() + 1
|
||||
interactloc.z = interactloc.blockZ.toDouble()
|
||||
plugin.config.set("lobbyLocation", interactloc)
|
||||
plugin.saveConfig()
|
||||
event.player.sendMessage(Component.text("Lobby location set.").color(NamedTextColor.LIGHT_PURPLE))
|
||||
val interactLoc = event.interactionPoint
|
||||
if (interactLoc != null) {
|
||||
interactLoc.x = interactLoc.blockX.toDouble()
|
||||
interactLoc.y = interactLoc.blockY.toDouble() + 1
|
||||
interactLoc.z = interactLoc.blockZ.toDouble()
|
||||
Tcoww.config.set("lobby-location", interactLoc)
|
||||
Tcoww.saveConfig()
|
||||
event.player.sendMessage(Component.text("Lobby location set.", NamedTextColor.LIGHT_PURPLE))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @EventHandler
|
||||
// fun reloadAfterWorld(worldInitEvent: WorldInitEvent) {
|
||||
//
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
27
src/main/kotlin/fr/azur/tcoww/events/UIEvents.kt
Normal file
27
src/main/kotlin/fr/azur/tcoww/events/UIEvents.kt
Normal file
@@ -0,0 +1,27 @@
|
||||
package fr.azur.tcoww.events
|
||||
|
||||
import fr.azur.tcoww.ui.CustomUI
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
|
||||
object UIEvents : Listener {
|
||||
@EventHandler
|
||||
fun onInventoryClick(event: InventoryClickEvent) {
|
||||
val inventory = event.inventory
|
||||
val holder = inventory.getHolder(false)
|
||||
if (holder is CustomUI) {
|
||||
holder.onClick(event)
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onInventoryClick(event: InventoryCloseEvent) {
|
||||
val inventory = event.inventory
|
||||
val holder = inventory.getHolder(false)
|
||||
if (holder is CustomUI) {
|
||||
holder.onClose(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,42 @@
|
||||
package fr.azur.tcoww.game
|
||||
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import fr.azur.tcoww.roles.Villager
|
||||
import fr.azur.tcoww.roles.Werewolf
|
||||
import fr.azur.tcoww.roles.Role.Companion.werewolfRole
|
||||
import fr.azur.tcoww.utils.Players.tfHuman
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.World
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
import org.bukkit.plugin.Plugin
|
||||
import org.bukkit.potion.PotionEffect
|
||||
import org.bukkit.potion.PotionEffectType
|
||||
import org.bukkit.scheduler.BukkitTask
|
||||
import kotlin.math.ceil
|
||||
|
||||
class Game(var plugin: Plugin, val world: World, val players: Iterable<Player>, var roles: Iterable<Role>) {
|
||||
val werewolfPercentage: Float = plugin.config.getInt("wwcount").toFloat()
|
||||
val timeGestion: TimeGestion
|
||||
val playersMutable = players.toMutableList()
|
||||
val timeGestShedule: BukkitTask
|
||||
var wwcankill = false
|
||||
class Game(
|
||||
var plugin: Plugin,
|
||||
val world: World,
|
||||
val players: Iterable<Player>,
|
||||
var roles: Map<NamespacedKey, Int>,
|
||||
) {
|
||||
val timeGestion: NightLightCycle
|
||||
val remainingPlayer = players.toMutableList()
|
||||
val beds =
|
||||
Tcoww.config
|
||||
.getList("bed-locations")
|
||||
.orEmpty()
|
||||
.mapNotNull { it as? Location }
|
||||
|
||||
init {
|
||||
players.forEach { player ->
|
||||
player.persistentDataContainer.set(NamespacedKey("tcoww", "dead"), PersistentDataType.BOOLEAN, false)
|
||||
player.persistentDataContainer.set(NamespacedKey("tcoww", "wwtranform"), PersistentDataType.BOOLEAN, false)
|
||||
player.teleport(plugin.config.getLocation("spawnLocation")!!)
|
||||
player.tfHuman()
|
||||
val spawnLoc = plugin.config.getLocation("spawn-location")
|
||||
if (spawnLoc != null) player.teleport(spawnLoc)
|
||||
player.inventory.clear()
|
||||
player.gameMode = GameMode.ADVENTURE
|
||||
player.health = 20.0
|
||||
player.addPotionEffect(
|
||||
PotionEffect(
|
||||
@@ -37,47 +44,27 @@ class Game(var plugin: Plugin, val world: World, val players: Iterable<Player>,
|
||||
PotionEffect.INFINITE_DURATION,
|
||||
1,
|
||||
false,
|
||||
false
|
||||
)
|
||||
false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
assignRoles()
|
||||
|
||||
timeGestion = TimeGestion(plugin, world)
|
||||
|
||||
timeGestShedule = Bukkit.getScheduler().runTaskTimer(plugin, Runnable {
|
||||
timeGestion.tick()
|
||||
}, 0L, 1L)
|
||||
timeGestion = NightLightCycle(plugin, world)
|
||||
|
||||
current = this
|
||||
}
|
||||
|
||||
fun getWerewolfInt(): Int {
|
||||
val playerCount = players.count()
|
||||
return ceil(playerCount * (werewolfPercentage / 100f)).toInt()
|
||||
}
|
||||
|
||||
private fun assignRoles() {
|
||||
val playerList = players.shuffled().toMutableList()
|
||||
|
||||
val werewolfCount = getWerewolfInt()
|
||||
val specialRolesCount = roles.count()
|
||||
|
||||
if (werewolfCount + specialRolesCount > playerList.size) {
|
||||
throw IllegalArgumentException("Not enough players for the given number of werewolves and special roles.")
|
||||
}
|
||||
|
||||
repeat(werewolfCount) { i ->
|
||||
Role.setRole(playerList[i], Werewolf())
|
||||
}
|
||||
|
||||
roles.forEachIndexed { idx, role ->
|
||||
Role.setRole(playerList[werewolfCount + idx], role)
|
||||
}
|
||||
|
||||
for (i in werewolfCount + specialRolesCount until playerList.size) {
|
||||
Role.setRole(playerList[i], Villager())
|
||||
val playersShuffled = players.shuffled()
|
||||
var playerIndex = 0
|
||||
roles.forEach {
|
||||
val role = Role.registerRoles.getValue(it.key)
|
||||
for (i in 0..<it.value) {
|
||||
playersShuffled[playerIndex].werewolfRole = role
|
||||
playerIndex++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,56 +72,54 @@ class Game(var plugin: Plugin, val world: World, val players: Iterable<Player>,
|
||||
var current: Game? = null
|
||||
}
|
||||
|
||||
fun gameEnded(): Boolean {
|
||||
var hasWerewolf = false
|
||||
var hasVillager = false
|
||||
|
||||
for (player in playersMutable) {
|
||||
val isWerewolf = Role.getRole(player)?.lg ?: false
|
||||
if (isWerewolf) hasWerewolf = true else hasVillager = true
|
||||
if (hasWerewolf && hasVillager) return false
|
||||
}
|
||||
|
||||
return true
|
||||
fun checkGameEnd(): Boolean {
|
||||
val team = players.map { player -> player.werewolfRole.team }.toSet()
|
||||
return team.count() <= 1
|
||||
}
|
||||
|
||||
fun stopGame(withoutResult: Boolean = false) {
|
||||
current ?: return
|
||||
current = null
|
||||
timeGestShedule.cancel()
|
||||
timeGestion.stop()
|
||||
world.time = 18000
|
||||
players.forEach { player ->
|
||||
player.gameMode = GameMode.SPECTATOR
|
||||
player.sendMessage(
|
||||
Component.text("La partie est terminée !", NamedTextColor.DARK_GREEN)
|
||||
Component
|
||||
.text("La partie est terminée !", NamedTextColor.DARK_GREEN)
|
||||
.appendNewline()
|
||||
.append {
|
||||
if (withoutResult)
|
||||
Component.empty()
|
||||
else {
|
||||
val villageHasWolf = playersMutable.any {
|
||||
Role.getRole(it)?.lg ?: false
|
||||
}
|
||||
if (villageHasWolf) {
|
||||
Component.text(
|
||||
"Les loups-garous ont finalement dévoré le village.",
|
||||
NamedTextColor.DARK_RED
|
||||
)
|
||||
} else {
|
||||
Component.text(
|
||||
"Les villageois ont finalement sauvé le village.",
|
||||
NamedTextColor.DARK_BLUE
|
||||
.apply {
|
||||
if (!withoutResult) return@apply
|
||||
remainingPlayer.forEachIndexed { index, player ->
|
||||
append(player.displayName())
|
||||
|
||||
if (index != remainingPlayer.lastIndex) {
|
||||
append(
|
||||
Component.text(
|
||||
when (index) {
|
||||
remainingPlayer.lastIndex - 1 -> " et "
|
||||
else -> ", "
|
||||
},
|
||||
NamedTextColor.DARK_GREEN,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
append(Component.text(" ont gagné !", NamedTextColor.DARK_GREEN))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
Bukkit.getScheduler().runTaskLater(plugin, Runnable {
|
||||
players.forEach { player ->
|
||||
player.teleport(plugin.config.getLocation("lobbyLocation")!!)
|
||||
player.gameMode = GameMode.ADVENTURE
|
||||
}
|
||||
}, 200)
|
||||
val lobbyLoc = plugin.config.getLocation("lobby-location")
|
||||
Bukkit.getScheduler().runTaskLater(
|
||||
plugin,
|
||||
Runnable {
|
||||
players.forEach { player ->
|
||||
if (lobbyLoc != null) player.teleport(lobbyLoc)
|
||||
player.gameMode = GameMode.ADVENTURE
|
||||
}
|
||||
},
|
||||
200,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
127
src/main/kotlin/fr/azur/tcoww/game/NightLightCycle.kt
Normal file
127
src/main/kotlin/fr/azur/tcoww/game/NightLightCycle.kt
Normal file
@@ -0,0 +1,127 @@
|
||||
package fr.azur.tcoww.game
|
||||
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.GameRule
|
||||
import org.bukkit.World
|
||||
import org.bukkit.event.Event
|
||||
import org.bukkit.event.HandlerList
|
||||
import org.bukkit.plugin.Plugin
|
||||
import org.bukkit.scheduler.BukkitTask
|
||||
|
||||
class NightLightCycle(
|
||||
plugin: Plugin,
|
||||
val world: World,
|
||||
) {
|
||||
enum class Phase {
|
||||
DAY,
|
||||
VOTE,
|
||||
NIGHT,
|
||||
CREPUSCULAR,
|
||||
}
|
||||
|
||||
class NightLightCyclePhaseChangeEvent(
|
||||
val world: World,
|
||||
val newPhase: Phase,
|
||||
val duration: Duration,
|
||||
) : Event() {
|
||||
override fun getHandlers(): HandlerList = handlerList
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val handlerList: HandlerList = HandlerList()
|
||||
}
|
||||
}
|
||||
|
||||
data class Duration(
|
||||
val day: Int,
|
||||
val vote: Int,
|
||||
val night: Int,
|
||||
val crepuscular: Int,
|
||||
) {
|
||||
companion object {
|
||||
fun fromPlugin(plugin: Plugin): Duration {
|
||||
val dayDuration = plugin.config.getInt("duration.day")
|
||||
val voteDuration = plugin.config.getInt("duration.vote")
|
||||
val nightDuration = plugin.config.getInt("duration.night")
|
||||
val crepuscularDuration = plugin.config.getInt("duration.crepuscular")
|
||||
return Duration(dayDuration, voteDuration, nightDuration, crepuscularDuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var phase: Phase = Phase.DAY
|
||||
val phases = Phase.entries
|
||||
val process: BukkitTask
|
||||
|
||||
val duration = Duration.fromPlugin(plugin)
|
||||
|
||||
var targetInstant: Long
|
||||
var tickOrigin: Int = 0
|
||||
var realDifference: Int
|
||||
var tickDifference: Int
|
||||
|
||||
var dayCount: Int = 0
|
||||
|
||||
init {
|
||||
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false)
|
||||
realDifference = duration.day * 1000
|
||||
targetInstant = System.currentTimeMillis() + realDifference.toLong()
|
||||
tickDifference = 12_000
|
||||
Bukkit.getPluginManager().callEvent(NightLightCyclePhaseChangeEvent(world, phase, duration))
|
||||
|
||||
process =
|
||||
Bukkit.getScheduler().runTaskTimer(
|
||||
plugin,
|
||||
Runnable {
|
||||
this.tick()
|
||||
},
|
||||
0L,
|
||||
1L,
|
||||
)
|
||||
}
|
||||
|
||||
fun changePhase(newPhase: Phase) {
|
||||
when (newPhase) {
|
||||
Phase.DAY -> {
|
||||
tickDifference = 12_000
|
||||
tickOrigin = 0
|
||||
realDifference = duration.day * 1000
|
||||
}
|
||||
|
||||
Phase.VOTE -> {
|
||||
tickDifference = 1_000
|
||||
tickOrigin = 12_000
|
||||
realDifference = duration.vote * 1000
|
||||
}
|
||||
|
||||
Phase.NIGHT -> {
|
||||
tickDifference = 11_000
|
||||
tickOrigin = 13_000
|
||||
realDifference = duration.night * 1000
|
||||
}
|
||||
|
||||
Phase.CREPUSCULAR -> {
|
||||
tickDifference = 1_000
|
||||
tickOrigin = 23_000
|
||||
realDifference = duration.crepuscular * 1000
|
||||
}
|
||||
}
|
||||
targetInstant = System.currentTimeMillis() + realDifference
|
||||
phase = newPhase
|
||||
Bukkit.getPluginManager().callEvent(NightLightCyclePhaseChangeEvent(world, newPhase, duration))
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
if (System.currentTimeMillis() >= targetInstant) {
|
||||
val phase = phases[(phases.indexOf(phase) + 1) % phases.count()]
|
||||
if (phase == Phase.DAY) {
|
||||
dayCount += 1
|
||||
}
|
||||
changePhase(phase)
|
||||
}
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
process.cancel()
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package fr.azur.tcoww.game
|
||||
|
||||
enum class Phase {
|
||||
DAY,
|
||||
VOTE,
|
||||
NIGHT,
|
||||
CREPUSCULAR
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package fr.azur.tcoww.game
|
||||
|
||||
import fr.azur.tcoww.events.TimePhaseChangeEvent
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.World
|
||||
import org.bukkit.GameRule
|
||||
import org.bukkit.plugin.Plugin
|
||||
import java.util.Calendar
|
||||
|
||||
class TimeGestion(plugin: Plugin, val world: World) {
|
||||
var calendar: Calendar = Calendar.getInstance()
|
||||
var targetCalendar: Calendar = calendar.clone() as Calendar
|
||||
var difference: Long
|
||||
var differencetick: Int
|
||||
|
||||
val dayDuration: Int = plugin.config.getInt("duration.day")
|
||||
val voteDuration: Int = plugin.config.getInt("duration.vote")
|
||||
val nightDuration: Int = plugin.config.getInt("duration.night")
|
||||
val crepuscularDuration: Int = plugin.config.getInt("duration.crepuscular")
|
||||
|
||||
var phase: Phase = Phase.DAY
|
||||
var tickcorrecter = 0
|
||||
|
||||
init {
|
||||
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false)
|
||||
targetCalendar.add(Calendar.SECOND, dayDuration)
|
||||
difference = targetCalendar.timeInMillis - calendar.timeInMillis
|
||||
differencetick = 12500
|
||||
Bukkit.getPluginManager().callEvent(TimePhaseChangeEvent(world,phase))
|
||||
}
|
||||
|
||||
fun changePhase() {
|
||||
calendar = Calendar.getInstance()
|
||||
targetCalendar = calendar.clone() as Calendar
|
||||
|
||||
when (phase) {
|
||||
// vote
|
||||
Phase.DAY -> {
|
||||
phase = Phase.VOTE
|
||||
tickcorrecter = 12_500
|
||||
differencetick = 1_500
|
||||
targetCalendar.add(Calendar.SECOND, voteDuration)
|
||||
}
|
||||
// night
|
||||
Phase.VOTE -> {
|
||||
phase = Phase.NIGHT
|
||||
tickcorrecter = 14_000
|
||||
differencetick = 8_500
|
||||
targetCalendar.add(Calendar.SECOND, nightDuration)
|
||||
}
|
||||
// crepuscular
|
||||
Phase.NIGHT -> {
|
||||
phase = Phase.CREPUSCULAR
|
||||
tickcorrecter = 22_500
|
||||
differencetick = 1_500
|
||||
targetCalendar.add(Calendar.SECOND, crepuscularDuration)
|
||||
}
|
||||
// day
|
||||
Phase.CREPUSCULAR -> {
|
||||
phase = Phase.DAY
|
||||
tickcorrecter = 0
|
||||
differencetick = 12_500
|
||||
targetCalendar.add(Calendar.SECOND, dayDuration)
|
||||
}
|
||||
}
|
||||
Bukkit.getPluginManager().callEvent(TimePhaseChangeEvent(world,phase))
|
||||
|
||||
difference = targetCalendar.timeInMillis - calendar.timeInMillis
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
if (System.currentTimeMillis() >= targetCalendar.timeInMillis) {
|
||||
changePhase()
|
||||
}
|
||||
|
||||
if (difference == 0L) return
|
||||
|
||||
val result = tickcorrecter + ((differencetick.toDouble() * (System.currentTimeMillis() - calendar.timeInMillis)) / difference).toInt()
|
||||
world.time = result.coerceIn(0, 23999).toLong()
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,12 @@ package fr.azur.tcoww.items
|
||||
|
||||
import fr.azur.tcoww.game.Game
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import fr.azur.tcoww.utils.DataKeys
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import net.kyori.adventure.text.format.TextDecoration
|
||||
import org.bukkit.Color
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.enchantments.Enchantment
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.ItemRarity
|
||||
@@ -19,181 +19,205 @@ import org.bukkit.persistence.PersistentDataType
|
||||
import org.bukkit.potion.PotionEffect
|
||||
import org.bukkit.potion.PotionEffectType
|
||||
|
||||
enum class CustomItems(val cache: Boolean, val supplier: () -> ItemStack) {
|
||||
enum class CustomItems(
|
||||
val cache: Boolean,
|
||||
val supplier: () -> ItemStack,
|
||||
) {
|
||||
WereWolfTransformItem(true, {
|
||||
ItemStack.of(Material.BONE).apply {
|
||||
itemMeta = itemMeta.apply {
|
||||
customName(Component.text("Os de transformation").color(NamedTextColor.DARK_RED))
|
||||
persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "power"),
|
||||
PersistentDataType.INTEGER,
|
||||
3
|
||||
)
|
||||
lore(
|
||||
listOf(
|
||||
Component.text("Clique pour basculer en forme loup-garou.")
|
||||
.color(NamedTextColor.GOLD)
|
||||
itemMeta =
|
||||
itemMeta.apply {
|
||||
customName(Component.text("Os de transformation", NamedTextColor.DARK_RED))
|
||||
persistentDataContainer.set(
|
||||
DataKeys.PowerItems,
|
||||
PersistentDataType.INTEGER,
|
||||
3,
|
||||
)
|
||||
)
|
||||
}
|
||||
lore(
|
||||
listOf(
|
||||
Component
|
||||
.text("Clique pour basculer en forme loup-garou.")
|
||||
.color(NamedTextColor.GOLD),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}),
|
||||
GunBullet(true, {
|
||||
ItemStack(Material.TIPPED_ARROW).apply {
|
||||
itemMeta = (itemMeta as PotionMeta).apply {
|
||||
color = Color.ORANGE
|
||||
displayName(Component.text("Balle de fusil.", NamedTextColor.YELLOW))
|
||||
basePotionType = basePotionType.apply {
|
||||
addCustomEffect(PotionEffect(PotionEffectType.INSTANT_DAMAGE, 20, 99), true)
|
||||
itemMeta =
|
||||
(itemMeta as PotionMeta).apply {
|
||||
color = Color.ORANGE
|
||||
displayName(Component.text("Balle de fusil.", NamedTextColor.YELLOW))
|
||||
basePotionType =
|
||||
basePotionType.apply {
|
||||
addCustomEffect(PotionEffect(PotionEffectType.INSTANT_DAMAGE, 20, 99), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
BlasTechDL44(true, {
|
||||
ItemStack.of(Material.CROSSBOW).apply {
|
||||
itemMeta = (itemMeta as CrossbowMeta).apply {
|
||||
addChargedProjectile(GunBullet.item)
|
||||
displayName(Component.text("BlasTech DL-44", NamedTextColor.GOLD))
|
||||
addEnchant(Enchantment.INFINITY, 1, true)
|
||||
}
|
||||
itemMeta = (itemMeta as Damageable).apply {
|
||||
setMaxDamage(1)
|
||||
}
|
||||
itemMeta =
|
||||
(itemMeta as DamageableCrossbow).apply {
|
||||
addChargedProjectile(GunBullet.item)
|
||||
displayName(Component.text("BlasTech DL-44", NamedTextColor.GOLD))
|
||||
addEnchant(Enchantment.INFINITY, 1, true)
|
||||
setMaxDamage(1)
|
||||
}
|
||||
}
|
||||
}),
|
||||
CrystalBall(true, {
|
||||
ItemStack.of(Material.GLASS).apply {
|
||||
itemMeta = itemMeta.apply {
|
||||
customName(
|
||||
Component.text("Boule de cristal").color(NamedTextColor.AQUA)
|
||||
)
|
||||
persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "power"),
|
||||
PersistentDataType.INTEGER,
|
||||
4
|
||||
)
|
||||
lore(listOf(Component.text("/power view <pseudo> pour l'utiliser.").color(NamedTextColor.GOLD)))
|
||||
}
|
||||
itemMeta =
|
||||
itemMeta.apply {
|
||||
customName(
|
||||
Component.text("Boule de cristal", NamedTextColor.AQUA),
|
||||
)
|
||||
persistentDataContainer.set(
|
||||
DataKeys.PowerItems,
|
||||
PersistentDataType.INTEGER,
|
||||
4,
|
||||
)
|
||||
setMaxStackSize(1)
|
||||
lore(listOf(Component.text("Click droit pour utiliser.", NamedTextColor.GOLD)))
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
}),
|
||||
DeathPotion(true, {
|
||||
ItemStack.of(Material.POTION).apply {
|
||||
itemMeta = (itemMeta as PotionMeta).apply {
|
||||
customName(
|
||||
Component.text("Potion de poison").color(NamedTextColor.DARK_PURPLE)
|
||||
)
|
||||
persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "power"),
|
||||
PersistentDataType.INTEGER,
|
||||
1
|
||||
)
|
||||
color = Color.BLACK
|
||||
lore(
|
||||
listOf(
|
||||
Component.text("/power kill <pseudo> pour l'utiliser.").color(NamedTextColor.GOLD)
|
||||
itemMeta =
|
||||
(itemMeta as DamageablePotion).apply {
|
||||
setMaxStackSize(1)
|
||||
setMaxDamage(1)
|
||||
customName(
|
||||
Component.text("Potion de poison", NamedTextColor.DARK_PURPLE),
|
||||
)
|
||||
)
|
||||
}
|
||||
persistentDataContainer.set(
|
||||
DataKeys.PowerItems,
|
||||
PersistentDataType.INTEGER,
|
||||
1,
|
||||
)
|
||||
color = Color.BLACK
|
||||
lore(
|
||||
listOf(
|
||||
Component.text("Click droit pour utiliser.", NamedTextColor.GOLD),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}),
|
||||
HealPotion(true, {
|
||||
ItemStack.of(Material.POTION).apply {
|
||||
itemMeta = (itemMeta as PotionMeta).apply {
|
||||
customName(
|
||||
Component.text("Potion de vie").color(NamedTextColor.DARK_PURPLE)
|
||||
)
|
||||
persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "power"),
|
||||
PersistentDataType.INTEGER,
|
||||
2
|
||||
)
|
||||
color = Color.RED
|
||||
lore(listOf(Component.text("/power save <pseudo> pour l'utiliser.").color(NamedTextColor.GOLD)))
|
||||
}
|
||||
itemMeta =
|
||||
(itemMeta as DamageablePotion).apply {
|
||||
setMaxStackSize(1)
|
||||
setMaxDamage(1)
|
||||
customName(
|
||||
Component.text("Potion de vie", NamedTextColor.DARK_PURPLE),
|
||||
)
|
||||
persistentDataContainer.set(
|
||||
DataKeys.PowerItems,
|
||||
PersistentDataType.INTEGER,
|
||||
2,
|
||||
)
|
||||
color = Color.RED
|
||||
lore(listOf(Component.text("Click droit pour utiliser.", NamedTextColor.GOLD)))
|
||||
}
|
||||
}
|
||||
}),
|
||||
SpawnLocTool(true, {
|
||||
ItemStack.of(Material.SUGAR_CANE).apply {
|
||||
itemMeta = itemMeta.apply {
|
||||
setRarity(ItemRarity.EPIC)
|
||||
persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "tools"),
|
||||
PersistentDataType.INTEGER,
|
||||
2
|
||||
)
|
||||
lore(listOf(Component.text("Spawn location tool").color(NamedTextColor.GOLD)))
|
||||
}
|
||||
itemMeta =
|
||||
itemMeta.apply {
|
||||
setRarity(ItemRarity.EPIC)
|
||||
persistentDataContainer.set(
|
||||
DataKeys.ToolsItems,
|
||||
PersistentDataType.INTEGER,
|
||||
2,
|
||||
)
|
||||
lore(listOf(Component.text("Spawn location tool", NamedTextColor.GOLD)))
|
||||
}
|
||||
}
|
||||
}),
|
||||
BedLocTool(true, {
|
||||
ItemStack.of(Material.WOODEN_HOE).apply {
|
||||
itemMeta = itemMeta.apply {
|
||||
setRarity(ItemRarity.EPIC)
|
||||
persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "tools"),
|
||||
PersistentDataType.INTEGER,
|
||||
1
|
||||
)
|
||||
lore(listOf(Component.text("bed location tool").color(NamedTextColor.GOLD)))
|
||||
}
|
||||
itemMeta =
|
||||
itemMeta.apply {
|
||||
setRarity(ItemRarity.EPIC)
|
||||
persistentDataContainer.set(
|
||||
DataKeys.ToolsItems,
|
||||
PersistentDataType.INTEGER,
|
||||
1,
|
||||
)
|
||||
lore(listOf(Component.text("bed location tool", NamedTextColor.GOLD)))
|
||||
}
|
||||
}
|
||||
}),
|
||||
LobbyLocTool(true, {
|
||||
ItemStack.of(Material.POPPED_CHORUS_FRUIT).apply {
|
||||
itemMeta = itemMeta.apply {
|
||||
setRarity(ItemRarity.EPIC)
|
||||
persistentDataContainer.set(
|
||||
NamespacedKey("tcoww", "tools"),
|
||||
PersistentDataType.INTEGER,
|
||||
3
|
||||
)
|
||||
lore(listOf(Component.text("Lobby location tool").color(NamedTextColor.GOLD)))
|
||||
}
|
||||
itemMeta =
|
||||
itemMeta.apply {
|
||||
setRarity(ItemRarity.EPIC)
|
||||
persistentDataContainer.set(
|
||||
DataKeys.ToolsItems,
|
||||
PersistentDataType.INTEGER,
|
||||
3,
|
||||
)
|
||||
lore(listOf(Component.text("Lobby location tool", NamedTextColor.GOLD)))
|
||||
}
|
||||
}
|
||||
}),
|
||||
ListHint(false, {
|
||||
val finalLore = buildList {
|
||||
add(
|
||||
Component.text("C'est une liste de nom.", NamedTextColor.RED)
|
||||
)
|
||||
add(
|
||||
Component.text("Il y a écrit que un de ces 3 citoyens", NamedTextColor.DARK_RED)
|
||||
)
|
||||
add(
|
||||
Component.text("est un loup-garou.", NamedTextColor.DARK_RED)
|
||||
)
|
||||
val finalLore =
|
||||
buildList {
|
||||
add(
|
||||
Component.text("C'est une liste de nom.", NamedTextColor.RED),
|
||||
)
|
||||
add(
|
||||
Component.text("Il y a écrit que un de ces 3 citoyens", NamedTextColor.DARK_RED),
|
||||
)
|
||||
add(
|
||||
Component.text("est un loup-garou.", NamedTextColor.DARK_RED),
|
||||
)
|
||||
|
||||
val players = Game.current?.playersMutable?.shuffled().orEmpty()
|
||||
val players =
|
||||
Game.current
|
||||
?.remainingPlayer
|
||||
?.shuffled()
|
||||
.orEmpty()
|
||||
|
||||
val (villagers, werewolves) = players.partition {
|
||||
Role.getRole(it)?.lg == false
|
||||
val (villagers, werewolves) =
|
||||
players.partition {
|
||||
Role.getRole(it)?.team != Role.Team.LG
|
||||
}
|
||||
|
||||
val lg = werewolves.firstOrNull()
|
||||
val names = mutableListOf<Player>()
|
||||
|
||||
if (lg != null) names.add(lg)
|
||||
names.addAll(villagers.take(2))
|
||||
|
||||
val colors = NamedColors.namedColors.shuffled().toMutableList()
|
||||
|
||||
names.shuffled().forEach {
|
||||
val color = colors.removeFirst()
|
||||
add(Component.text("- ").append(it.displayName()).color(color))
|
||||
}
|
||||
|
||||
if (isEmpty()) {
|
||||
add(Component.text("nothing", NamedTextColor.DARK_RED, TextDecoration.OBFUSCATED))
|
||||
}
|
||||
}
|
||||
|
||||
val lg = werewolves.firstOrNull()
|
||||
val names = mutableListOf<Player>()
|
||||
|
||||
if (lg != null) names.add(lg)
|
||||
names.addAll(villagers.take(2))
|
||||
|
||||
val colors = NamedColors.namedColors.shuffled().toMutableList()
|
||||
|
||||
names.shuffled().forEach {
|
||||
val color = colors.removeFirst()
|
||||
add(Component.text("- ").append(it.displayName()).color(color))
|
||||
}
|
||||
|
||||
if (isEmpty()) {
|
||||
add(Component.text("nothing", NamedTextColor.DARK_RED, TextDecoration.OBFUSCATED))
|
||||
}
|
||||
}
|
||||
ItemStack(Material.PAPER).apply {
|
||||
itemMeta = itemMeta.apply {
|
||||
displayName(Component.text("Liste de nom", NamedTextColor.GOLD))
|
||||
lore(finalLore)
|
||||
}
|
||||
itemMeta =
|
||||
itemMeta.apply {
|
||||
displayName(Component.text("Liste de nom", NamedTextColor.GOLD))
|
||||
lore(finalLore)
|
||||
}
|
||||
}
|
||||
});
|
||||
}),
|
||||
;
|
||||
|
||||
private var cachedItem: ItemStack? = null
|
||||
|
||||
@@ -206,21 +230,31 @@ enum class CustomItems(val cache: Boolean, val supplier: () -> ItemStack) {
|
||||
}
|
||||
}
|
||||
|
||||
data object NamedColors {
|
||||
val namedColors = listOf(
|
||||
NamedTextColor.DARK_RED,
|
||||
NamedTextColor.RED,
|
||||
NamedTextColor.GOLD,
|
||||
NamedTextColor.YELLOW,
|
||||
NamedTextColor.DARK_GREEN,
|
||||
NamedTextColor.GREEN,
|
||||
NamedTextColor.AQUA,
|
||||
NamedTextColor.DARK_AQUA,
|
||||
NamedTextColor.DARK_BLUE,
|
||||
NamedTextColor.BLUE,
|
||||
NamedTextColor.LIGHT_PURPLE,
|
||||
NamedTextColor.DARK_PURPLE
|
||||
)
|
||||
interface DamageableCrossbow :
|
||||
Damageable,
|
||||
CrossbowMeta
|
||||
|
||||
interface DamageablePotion :
|
||||
Damageable,
|
||||
PotionMeta {
|
||||
override fun clone(): DamageablePotion
|
||||
}
|
||||
}
|
||||
|
||||
data object NamedColors {
|
||||
val namedColors =
|
||||
listOf(
|
||||
NamedTextColor.DARK_RED,
|
||||
NamedTextColor.RED,
|
||||
NamedTextColor.GOLD,
|
||||
NamedTextColor.YELLOW,
|
||||
NamedTextColor.DARK_GREEN,
|
||||
NamedTextColor.GREEN,
|
||||
NamedTextColor.AQUA,
|
||||
NamedTextColor.DARK_AQUA,
|
||||
NamedTextColor.DARK_BLUE,
|
||||
NamedTextColor.BLUE,
|
||||
NamedTextColor.LIGHT_PURPLE,
|
||||
NamedTextColor.DARK_PURPLE,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,22 @@ package fr.azur.tcoww.roles
|
||||
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class Child : Role {
|
||||
override fun handle(player: Player) {}
|
||||
|
||||
override fun onDeath(player: Player) {}
|
||||
|
||||
override var lg = false
|
||||
override var id = NamespacedKey("tcoww", "child")
|
||||
override val displayName = Component.text("Petite Fille")
|
||||
object Child : Role {
|
||||
override val id = NamespacedKey("tcoww", "child")
|
||||
override val team = Role.Team.Villager
|
||||
override val displayName = Component.text("Petite Fille", NamedTextColor.LIGHT_PURPLE)
|
||||
override val icon = Material.MAGENTA_WOOL
|
||||
override val order: Int = 2
|
||||
override val hasPowerCommand = false
|
||||
override val description =
|
||||
Component.text("Extrêmement discrette et au coeur du risque.", NamedTextColor.BLUE).appendNewline()
|
||||
.append(
|
||||
Component.text("Vous n'êtes pas obliger de dormir la nuit, vous pouvez donc observer les loups le soir.", NamedTextColor.BLUE)
|
||||
)
|
||||
}
|
||||
listOf(
|
||||
Component.text("Extrêmement discrette et au coeur du risque.", NamedTextColor.BLUE),
|
||||
Component.text(
|
||||
"Vous n'êtes pas obliger de dormir la nuit, vous pouvez donc observer les loups le soir.",
|
||||
NamedTextColor.BLUE,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,23 +3,27 @@ package fr.azur.tcoww.roles
|
||||
import fr.azur.tcoww.items.CustomItems
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class FortuneTeller : Role {
|
||||
object FortuneTeller : Role {
|
||||
override fun handle(player: Player) {
|
||||
player.inventory.addItem(CustomItems.CrystalBall.item)
|
||||
}
|
||||
|
||||
override fun onDeath(player: Player) {}
|
||||
|
||||
override var lg = false
|
||||
override val team = Role.Team.Villager
|
||||
override var id = NamespacedKey("tcoww", "fortune_teller")
|
||||
override val displayName = Component.text("Voyante")
|
||||
override val icon = Material.GLASS
|
||||
override val order: Int = 3
|
||||
override val displayName = Component.text("Voyante", NamedTextColor.AQUA)
|
||||
override val hasPowerCommand = true
|
||||
override val description =
|
||||
Component.text("Vous voyez des choses mais quoi ?.", NamedTextColor.BLUE).appendNewline()
|
||||
.append(
|
||||
Component.text("Tout les 2 jours vous pouvez regarder le role d'un joueur.", NamedTextColor.BLUE)
|
||||
)
|
||||
}
|
||||
listOf(
|
||||
Component.text("Vous voyez des choses mais quoi ?.", NamedTextColor.BLUE),
|
||||
Component
|
||||
.text("Tout les 2 jours vous pouvez regarder le role d'un joueur grâce à votre ", NamedTextColor.BLUE)
|
||||
.append(CustomItems.CrystalBall.item.displayName())
|
||||
.append(Component.text(".", NamedTextColor.BLUE)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,32 +3,32 @@ package fr.azur.tcoww.roles
|
||||
import fr.azur.tcoww.items.CustomItems
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class Hunter : Role {
|
||||
object Hunter : Role {
|
||||
override fun handle(player: Player) {
|
||||
player.inventory.addItem(CustomItems.BlasTechDL44.item)
|
||||
}
|
||||
|
||||
override fun onDeath(player: Player) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override var lg = false
|
||||
override val team = Role.Team.Villager
|
||||
override var id = NamespacedKey("tcoww", "hunter")
|
||||
override val displayName = Component.text("Chaseur")
|
||||
override val displayName = Component.text("Chaseur", NamedTextColor.GOLD)
|
||||
override val icon = Material.ARROW
|
||||
override val order: Int = 5
|
||||
override val hasPowerCommand = false
|
||||
override val description =
|
||||
Component.text(
|
||||
"Vous êtes la personne, la plus redouter des animaux (et en particulier des loups).",
|
||||
NamedTextColor.BLUE
|
||||
).appendNewline()
|
||||
.append(
|
||||
Component.text("Vous possedez un ", NamedTextColor.BLUE)
|
||||
.append(CustomItems.BlasTechDL44.item.displayName())
|
||||
.append(
|
||||
Component.text(" qui permet de one shot n'importe quoi... (Usage Unique.)", NamedTextColor.BLUE)
|
||||
)
|
||||
)
|
||||
}
|
||||
listOf(
|
||||
Component.text(
|
||||
"Vous êtes la personne, la plus redouter des animaux (et en particulier des loups).",
|
||||
NamedTextColor.BLUE,
|
||||
),
|
||||
Component
|
||||
.text("Vous possedez un ", NamedTextColor.BLUE)
|
||||
.append(CustomItems.BlasTechDL44.item.displayName())
|
||||
.append(
|
||||
Component.text(" qui permet de one shot n'importe quoi... (Usage Unique)", NamedTextColor.BLUE),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,48 +2,87 @@ package fr.azur.tcoww.roles
|
||||
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
|
||||
interface Role {
|
||||
fun handle(player: Player)
|
||||
fun onDeath(player: Player)
|
||||
val lg: Boolean
|
||||
enum class Team {
|
||||
LG {
|
||||
override val displayName = Component.text("loups-garous").color(NamedTextColor.DARK_RED)
|
||||
},
|
||||
Villager {
|
||||
override val displayName: Component = Component.text("villageois", NamedTextColor.GREEN)
|
||||
},
|
||||
Solo {
|
||||
override val displayName: Component = Component.text("solo", NamedTextColor.YELLOW)
|
||||
}, ;
|
||||
|
||||
abstract val displayName: Component
|
||||
}
|
||||
|
||||
fun handle(player: Player) {}
|
||||
|
||||
fun onDeath(player: Player) {}
|
||||
|
||||
fun onVote(player: Player) {}
|
||||
|
||||
val id: NamespacedKey
|
||||
val icon: Material
|
||||
val order: Int
|
||||
val team: Team
|
||||
val displayName: Component
|
||||
val hasPowerCommand: Boolean
|
||||
val description: Component
|
||||
val description: List<Component>
|
||||
val lineDescription: Component
|
||||
get() {
|
||||
return Component.empty().apply {
|
||||
description.forEach {
|
||||
append(it)
|
||||
appendNewline()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
var registerRoles = hashMapOf<NamespacedKey, Role>()
|
||||
private val rolekey = NamespacedKey("tcoww", "role")
|
||||
fun setRole(player: Player, role: Role) {
|
||||
player.persistentDataContainer.set(
|
||||
rolekey,
|
||||
PersistentDataType.STRING,
|
||||
role.id.toString()
|
||||
private val roleKey = NamespacedKey("tcoww", "role")
|
||||
|
||||
fun setRole(
|
||||
player: Player,
|
||||
role: Role,
|
||||
) {
|
||||
player.sendMessage(
|
||||
Component.text("Votre role est ", NamedTextColor.DARK_AQUA).append(role.displayName),
|
||||
)
|
||||
player.sendMessage(
|
||||
Component.text("Votre role est ").append(role.displayName).color(NamedTextColor.DARK_AQUA)
|
||||
role.lineDescription.append {
|
||||
if (role.team == Team.Solo) {
|
||||
Component.text("Vous gagnez Seul.", NamedTextColor.AQUA)
|
||||
} else {
|
||||
Component
|
||||
.text("Vous gagnez avec les ", NamedTextColor.AQUA)
|
||||
.append(role.team.displayName)
|
||||
.append(Component.text(".", NamedTextColor.AQUA))
|
||||
}
|
||||
},
|
||||
)
|
||||
player.sendMessage(role.description.appendNewline().append {
|
||||
if (role.lg)
|
||||
Component.text("Vous gagnez avec les loups-garous.", NamedTextColor.AQUA)
|
||||
else
|
||||
Component.text("Vous gagnez avec les villageois.", NamedTextColor.AQUA)
|
||||
})
|
||||
role.handle(player)
|
||||
|
||||
player.persistentDataContainer.set(roleKey, PersistentDataType.STRING, role.id.toString())
|
||||
}
|
||||
|
||||
fun getRole(player: Player): Role? {
|
||||
val rolestr = player.persistentDataContainer.get(rolekey, PersistentDataType.STRING)
|
||||
if (rolestr == null) return null
|
||||
return registerRoles[NamespacedKey.fromString(rolestr)]
|
||||
val roleKey = player.persistentDataContainer.get(roleKey, PersistentDataType.STRING) ?: return null
|
||||
return registerRoles[NamespacedKey.fromString(roleKey)]
|
||||
}
|
||||
|
||||
var Player.werewolfRole: Role
|
||||
get() = getRole(this)!!
|
||||
set(role) = setRole(this, role)
|
||||
|
||||
fun registerRole(role: Role) {
|
||||
registerRoles.put(role.id, role)
|
||||
registerRoles[role.id] = role
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,25 +2,19 @@ package fr.azur.tcoww.roles
|
||||
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class Villager : Role {
|
||||
override fun handle(player: Player) {
|
||||
|
||||
}
|
||||
|
||||
override fun onDeath(player: Player) {
|
||||
|
||||
}
|
||||
|
||||
override var lg: Boolean = false
|
||||
object Villager : Role {
|
||||
override val team = Role.Team.Villager
|
||||
override var id = NamespacedKey("tcoww", "villager")
|
||||
override val displayName = Component.text("Villageois")
|
||||
override val displayName = Component.text("Villageois", NamedTextColor.GRAY)
|
||||
override val icon = Material.DIRT
|
||||
override val order: Int = 0
|
||||
override val hasPowerCommand = false
|
||||
override val description =
|
||||
Component.text("En tant que villageois, vous n'avez aucun pouvoir.", NamedTextColor.BLUE).appendNewline()
|
||||
.append(
|
||||
Component.text("Profiter en pour risquer pour trouver des indices ! ^^", NamedTextColor.BLUE)
|
||||
)
|
||||
}
|
||||
listOf(
|
||||
Component.text("En tant que villageois, vous n'avez aucun pouvoir.", NamedTextColor.BLUE),
|
||||
Component.text("Profiter en pour risquer pour trouver des indices ! ^^", NamedTextColor.BLUE),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,25 +1,32 @@
|
||||
package fr.azur.tcoww.roles
|
||||
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import fr.azur.tcoww.items.CustomItems
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class Werewolf : Role {
|
||||
override fun handle(player: Player) {}
|
||||
|
||||
override fun onDeath(player: Player) {}
|
||||
|
||||
override var lg = true
|
||||
object Werewolf : Role {
|
||||
override val team = Role.Team.LG
|
||||
override var id = NamespacedKey("tcoww", "werewolf")
|
||||
override val displayName = Component.text("Loup-Garou")
|
||||
override val displayName = Component.text("Loup-Garou", NamedTextColor.DARK_GRAY)
|
||||
override val icon = Material.BONE
|
||||
override val order: Int = 1
|
||||
override val hasPowerCommand = false
|
||||
override val description =
|
||||
Component.text("Pour la faire courte, vous avez faim, très faim.", NamedTextColor.BLUE).appendNewline()
|
||||
.append(
|
||||
Component.text(
|
||||
"Votre but est de tuer les villageois. Sans vous faire atraper et voter. Toute les nuits, vous pouvez vous tranformer en loup pour manger un villageois.",
|
||||
NamedTextColor.BLUE
|
||||
)
|
||||
)
|
||||
}
|
||||
listOf(
|
||||
Component.text("Pour la faire courte, vous avez faim, très faim.", NamedTextColor.BLUE),
|
||||
Component.text(
|
||||
"Votre but est de tuer les villageois. Sans vous faire atraper et voter. Toute les nuits, vous pouvez vous tranformer en loup pour manger un villageois.",
|
||||
NamedTextColor.BLUE,
|
||||
),
|
||||
)
|
||||
|
||||
override fun handle(player: Player) {
|
||||
val tfItem = CustomItems.WereWolfTransformItem.item
|
||||
player.inventory.addItem(tfItem)
|
||||
player.setCooldown(tfItem, ((Tcoww.config.getInt("duration.day") + Tcoww.config.getInt("duration.day")) * 20))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,27 +3,28 @@ package fr.azur.tcoww.roles
|
||||
import fr.azur.tcoww.items.CustomItems
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class Witch : Role {
|
||||
object Witch : Role {
|
||||
override fun handle(player: Player) {
|
||||
player.inventory.addItem(CustomItems.DeathPotion.item)
|
||||
player.inventory.addItem(CustomItems.HealPotion.item)
|
||||
}
|
||||
|
||||
override fun onDeath(player: Player) {}
|
||||
|
||||
override var lg = false
|
||||
override val team = Role.Team.Villager
|
||||
override var id = NamespacedKey("tcoww", "witch")
|
||||
override val displayName = Component.text("Sorcière")
|
||||
override val icon = Material.GLASS_BOTTLE
|
||||
override val order: Int = 4
|
||||
override val hasPowerCommand = true
|
||||
override val description =
|
||||
Component.text("Une potion = Une solution.", NamedTextColor.BLUE).appendNewline()
|
||||
.append(
|
||||
Component.text(
|
||||
"Vous possédez deux potions : une pour tuer et une pour ressusciter quelqu'un.",
|
||||
NamedTextColor.BLUE
|
||||
)
|
||||
).appendNewline()
|
||||
}
|
||||
listOf(
|
||||
Component.text("Une potion = Une solution.", NamedTextColor.BLUE),
|
||||
Component.text(
|
||||
"Vous possédez deux potions : une pour tuer et une pour ressusciter quelqu'un.",
|
||||
NamedTextColor.BLUE,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
11
src/main/kotlin/fr/azur/tcoww/ui/CustomUI.kt
Normal file
11
src/main/kotlin/fr/azur/tcoww/ui/CustomUI.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package fr.azur.tcoww.ui
|
||||
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
import org.bukkit.inventory.InventoryHolder
|
||||
|
||||
interface CustomUI : InventoryHolder {
|
||||
fun onClick(event: InventoryClickEvent) {}
|
||||
|
||||
fun onClose(event: InventoryCloseEvent) {}
|
||||
}
|
||||
121
src/main/kotlin/fr/azur/tcoww/ui/GameConfig.kt
Normal file
121
src/main/kotlin/fr/azur/tcoww/ui/GameConfig.kt
Normal file
@@ -0,0 +1,121 @@
|
||||
package fr.azur.tcoww.ui
|
||||
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
import org.bukkit.inventory.Inventory
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.Damageable
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import kotlin.math.ceil
|
||||
|
||||
class GameConfig(
|
||||
playerCount: Int,
|
||||
) : CustomUI {
|
||||
// [index, [role key, amount]]
|
||||
val rolesConfig = hashMapOf<Int, Pair<NamespacedKey, Int>>()
|
||||
val size = (Role.registerRoles.count() / 9 + 1) * 9
|
||||
val future = CompletableFuture<Map<NamespacedKey, Int>>()
|
||||
|
||||
private val inventory =
|
||||
Tcoww.server.createInventory(this, size, Component.text("Game Config.", NamedTextColor.GREEN)).apply {
|
||||
Role.registerRoles.values.sortedBy { it.order }.onEachIndexed { index, role ->
|
||||
setItem(index, createItem(index, role))
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
val werewolfCount = ceil((playerCount * (Tcoww.config.getInt("werewolf-default-percentage") / 100f))).toInt()
|
||||
editItem(0, playerCount - werewolfCount)
|
||||
editItem(1, werewolfCount)
|
||||
}
|
||||
|
||||
private fun createItem(
|
||||
index: Int,
|
||||
role: Role,
|
||||
): ItemStack {
|
||||
rolesConfig[index] = Pair(role.id, 0)
|
||||
|
||||
return ItemStack.of(role.icon).apply {
|
||||
itemMeta =
|
||||
(itemMeta as Damageable).apply {
|
||||
lore(
|
||||
role.description,
|
||||
)
|
||||
itemName(
|
||||
role.displayName,
|
||||
)
|
||||
setMaxStackSize(1)
|
||||
setMaxDamage(1)
|
||||
damage = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun editItem(
|
||||
index: Int,
|
||||
newAmount: Int,
|
||||
) {
|
||||
if (newAmount !in 0..99) throw IllegalArgumentException("Amount must be in 0 and 99 !")
|
||||
rolesConfig[index] = Pair(rolesConfig[index]!!.first, newAmount)
|
||||
val item = inventory.getItem(index) ?: return
|
||||
item.itemMeta =
|
||||
(item.itemMeta as Damageable).apply {
|
||||
if (newAmount == 0) {
|
||||
setMaxStackSize(1)
|
||||
setMaxDamage(1)
|
||||
damage = 1
|
||||
} else {
|
||||
damage = 0
|
||||
setMaxStackSize(99)
|
||||
item.amount = newAmount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInventory(): Inventory = inventory
|
||||
|
||||
override fun onClick(event: InventoryClickEvent) {
|
||||
event.isCancelled = true
|
||||
val index = event.slot
|
||||
if (index !in 0..<Role.registerRoles.size || event.clickedInventory != inventory) return
|
||||
if (event.isLeftClick) {
|
||||
for (i in 0..<Role.registerRoles.size) {
|
||||
if (i == index) continue
|
||||
val count = rolesConfig[i]!!.second
|
||||
if (count != 0) {
|
||||
val targetCount = rolesConfig[index]!!.second
|
||||
editItem(i, count - 1)
|
||||
editItem(index, targetCount + 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if (event.isRightClick) {
|
||||
for (i in 0..<Role.registerRoles.size) {
|
||||
if (i == index) continue
|
||||
val count = rolesConfig[i]!!.second
|
||||
if (count != 0) {
|
||||
val targetCount = rolesConfig[index]!!.second
|
||||
if (targetCount == 0) break
|
||||
editItem(i, count + 1)
|
||||
editItem(index, targetCount - 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClose(event: InventoryCloseEvent) {
|
||||
future.complete(
|
||||
buildMap {
|
||||
rolesConfig.forEach {
|
||||
if (it.value.second != 0) put(it.value.first, it.value.second)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
46
src/main/kotlin/fr/azur/tcoww/ui/PlayerSelectMenu.kt
Normal file
46
src/main/kotlin/fr/azur/tcoww/ui/PlayerSelectMenu.kt
Normal file
@@ -0,0 +1,46 @@
|
||||
package fr.azur.tcoww.ui
|
||||
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
import org.bukkit.inventory.Inventory
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.SkullMeta
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class PlayerSelectMenu(
|
||||
val players: Iterable<Player>,
|
||||
) : CustomUI {
|
||||
val size = (players.count() / 9 + 1) * 9
|
||||
val future = CompletableFuture<Player?>()
|
||||
|
||||
private val inventory =
|
||||
Tcoww.server.createInventory(this, size, Component.text("Select a player.", NamedTextColor.GREEN)).apply {
|
||||
players.forEachIndexed { index, player ->
|
||||
val item =
|
||||
ItemStack.of(Material.PLAYER_HEAD).apply {
|
||||
itemMeta =
|
||||
(itemMeta as SkullMeta).apply {
|
||||
playerProfile = player.playerProfile
|
||||
}
|
||||
}
|
||||
setItem(index, item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInventory(): Inventory = inventory
|
||||
|
||||
override fun onClick(event: InventoryClickEvent) {
|
||||
val index = event.slot
|
||||
if (index !in 0..<players.count() || event.clickedInventory != inventory) return
|
||||
future.complete(players.elementAt(index))
|
||||
}
|
||||
|
||||
override fun onClose(event: InventoryCloseEvent) {
|
||||
future.complete(null)
|
||||
}
|
||||
}
|
||||
@@ -4,21 +4,19 @@ import org.bukkit.block.Block
|
||||
import org.bukkit.block.data.type.Bed
|
||||
|
||||
object BedGestion {
|
||||
fun isBed(block: Block): Boolean {
|
||||
return block.blockData is Bed
|
||||
}
|
||||
fun Block.isBed() = blockData is Bed
|
||||
|
||||
fun getHeadBed(block: Block): Block {
|
||||
val bedData = block.blockData as Bed
|
||||
fun Block.getHeadBed(): Block {
|
||||
val bedData = blockData as Bed
|
||||
return if (bedData.part == Bed.Part.FOOT) {
|
||||
block.getRelative(bedData.facing)
|
||||
getRelative(bedData.facing)
|
||||
} else {
|
||||
block
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
fun isOcupied(block: Block): Boolean {
|
||||
val bedData = block.blockData as Bed
|
||||
fun Block.isOccupied(): Boolean {
|
||||
val bedData = blockData as Bed
|
||||
return bedData.isOccupied
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
src/main/kotlin/fr/azur/tcoww/utils/DataKeys.kt
Normal file
11
src/main/kotlin/fr/azur/tcoww/utils/DataKeys.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package fr.azur.tcoww.utils
|
||||
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import org.bukkit.NamespacedKey
|
||||
|
||||
data object DataKeys {
|
||||
val PlayerDead = NamespacedKey(Tcoww, "dead")
|
||||
val PowerItems = NamespacedKey(Tcoww, "power")
|
||||
val Insomnia = NamespacedKey(Tcoww, "insomnia")
|
||||
val ToolsItems = NamespacedKey(Tcoww, "tools")
|
||||
}
|
||||
118
src/main/kotlin/fr/azur/tcoww/utils/Players.kt
Normal file
118
src/main/kotlin/fr/azur/tcoww/utils/Players.kt
Normal file
@@ -0,0 +1,118 @@
|
||||
package fr.azur.tcoww.utils
|
||||
|
||||
import fr.azur.tcoww.game.Game
|
||||
import fr.azur.tcoww.roles.Role.Companion.werewolfRole
|
||||
import fr.azur.tcoww.utils.skins.Manager
|
||||
import io.papermc.paper.datacomponent.item.ResolvableProfile
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import net.kyori.adventure.title.Title
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.attribute.Attribute
|
||||
import org.bukkit.attribute.AttributeModifier
|
||||
import org.bukkit.entity.Mannequin
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.entity.Pose
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
import java.time.Duration
|
||||
|
||||
object Players {
|
||||
private val transformKey = NamespacedKey("tcoww", "werewolf_transform")
|
||||
val corpseKey = NamespacedKey("tcoww", "corpse")
|
||||
val corpseRoleKey = NamespacedKey("tcoww", "corpse_role")
|
||||
private val noCollisionTeam =
|
||||
Bukkit
|
||||
.getServer()
|
||||
.scoreboardManager.mainScoreboard
|
||||
.getTeam("NoCollide")
|
||||
|
||||
fun Player.tfWerewolf() {
|
||||
if (isTransformed()) return
|
||||
|
||||
Manager.applyWerewolfFur(this)
|
||||
|
||||
persistentDataContainer.set(
|
||||
transformKey,
|
||||
PersistentDataType.BOOLEAN,
|
||||
true,
|
||||
)
|
||||
|
||||
val speedAtr = getAttribute(Attribute.MOVEMENT_SPEED)!!
|
||||
val scaleAtr = getAttribute(Attribute.SCALE)!!
|
||||
|
||||
speedAtr.addModifier(
|
||||
AttributeModifier(
|
||||
transformKey,
|
||||
0.02,
|
||||
AttributeModifier.Operation.ADD_NUMBER,
|
||||
),
|
||||
)
|
||||
scaleAtr.addModifier(
|
||||
AttributeModifier(
|
||||
transformKey,
|
||||
0.1,
|
||||
AttributeModifier.Operation.ADD_NUMBER,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun Player.tfHuman() {
|
||||
if (!isTransformed()) return
|
||||
|
||||
Manager.unapplySkin(this)
|
||||
|
||||
persistentDataContainer.set(
|
||||
transformKey,
|
||||
PersistentDataType.BOOLEAN,
|
||||
false,
|
||||
)
|
||||
|
||||
val speedAtr = getAttribute(Attribute.MOVEMENT_SPEED)!!
|
||||
val scaleAtr = getAttribute(Attribute.SCALE)!!
|
||||
speedAtr.removeModifier(transformKey)
|
||||
scaleAtr.removeModifier(transformKey)
|
||||
}
|
||||
|
||||
fun Player.isTransformed(): Boolean =
|
||||
persistentDataContainer.getOrDefault(
|
||||
transformKey,
|
||||
PersistentDataType.BOOLEAN,
|
||||
false,
|
||||
)
|
||||
|
||||
fun Player.kill() {
|
||||
if (isTransformed()) tfHuman()
|
||||
|
||||
val current = Game.current ?: return
|
||||
|
||||
val corpse = createCorpse(this)
|
||||
corpse.spawnAt(this.location)
|
||||
|
||||
this.gameMode = GameMode.SPECTATOR
|
||||
this.isInvulnerable = false
|
||||
current.remainingPlayer.remove(this)
|
||||
|
||||
this.showTitle(
|
||||
Title.title(
|
||||
Component.text("Vous êtes mort.", NamedTextColor.DARK_RED),
|
||||
Component.empty(),
|
||||
Title.Times.times(Duration.ZERO, Duration.ofSeconds(2), Duration.ofMillis(500)),
|
||||
),
|
||||
)
|
||||
|
||||
if (current.checkGameEnd()) current.stopGame()
|
||||
}
|
||||
|
||||
fun createCorpse(player: Player): Mannequin =
|
||||
player.world.createEntity(player.location, Mannequin::class.java).apply {
|
||||
profile = ResolvableProfile.resolvableProfile(player.playerProfile)
|
||||
noCollisionTeam?.addEntity(this)
|
||||
isInvulnerable = true
|
||||
pose = Pose.SLEEPING
|
||||
persistentDataContainer.set(corpseKey, PersistentDataType.BOOLEAN, true)
|
||||
val role = player.werewolfRole
|
||||
persistentDataContainer.set(corpseRoleKey, PersistentDataType.STRING, role.id.toString())
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package fr.azur.tcoww.utils
|
||||
|
||||
import net.skinsrestorer.api.SkinsRestorer
|
||||
import net.skinsrestorer.api.property.SkinProperty
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.plugin.Plugin
|
||||
import java.util.*
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import kotlin.random.Random
|
||||
|
||||
class Skin(private val plugin: Plugin, private val skinsRestorer: SkinsRestorer) {
|
||||
|
||||
var maxSkinId: Int = 0
|
||||
private set
|
||||
|
||||
init {
|
||||
reloadSkin()
|
||||
}
|
||||
|
||||
fun reloadSkin() {
|
||||
val skinsValue = plugin.config.getStringList("wwskinsvalue")
|
||||
val skinsSignature = plugin.config.getStringList("wwskinssignature")
|
||||
Stockage.wwPlayerFur.clear()
|
||||
|
||||
maxSkinId = 0
|
||||
skinsValue.zip(skinsSignature).forEachIndexed { index, (value, signature) ->
|
||||
skinsRestorer.skinStorage.setCustomSkinData("tcoww_$index", SkinProperty.of(value, signature))
|
||||
maxSkinId = index
|
||||
}
|
||||
}
|
||||
|
||||
fun applyWerewolfFur(player: Player) {
|
||||
val skin = skinsRestorer.playerStorage.getSkinIdOfPlayer(player.uniqueId)
|
||||
Stockage.oldPlayerSkin[player.uniqueId] = skin.getOrNull()
|
||||
|
||||
val result = skinsRestorer.skinStorage.findOrCreateSkinData("tcoww_${getWerewolfFur(player.uniqueId)}")
|
||||
|
||||
if (!result.isEmpty) {
|
||||
skinsRestorer.playerStorage.setSkinIdOfPlayer(player.uniqueId, result.get().identifier)
|
||||
skinsRestorer.getSkinApplier(Player::class.java).applySkin(player)
|
||||
}
|
||||
}
|
||||
|
||||
fun unApplySkin(player: Player) {
|
||||
val skin = Stockage.oldPlayerSkin[player.uniqueId]
|
||||
if (skin == null) {
|
||||
skinsRestorer.playerStorage.removeSkinIdOfPlayer(player.uniqueId)
|
||||
} else {
|
||||
skinsRestorer.playerStorage.setSkinIdOfPlayer(player.uniqueId,skin)
|
||||
}
|
||||
skinsRestorer.getSkinApplier(Player::class.java).applySkin(player)
|
||||
}
|
||||
|
||||
private fun getWerewolfFur(playerUUID: UUID): Int {
|
||||
return Stockage.wwPlayerFur[playerUUID]
|
||||
?: randomFur(playerUUID)
|
||||
}
|
||||
|
||||
private fun randomFur(playerUUID: UUID): Int {
|
||||
val id = if (maxSkinId == 0) 0 else Random(playerUUID.mostSignificantBits xor playerUUID.leastSignificantBits).nextInt(maxSkinId)
|
||||
Stockage.wwPlayerFur[playerUUID] = id
|
||||
return id
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package fr.azur.tcoww.utils
|
||||
|
||||
import net.skinsrestorer.api.property.SkinIdentifier
|
||||
import org.bukkit.Location
|
||||
import java.util.*
|
||||
|
||||
|
||||
object Stockage {
|
||||
var backLocation = mutableMapOf<UUID, Location>()
|
||||
var vote = mutableMapOf<UUID, UUID>()
|
||||
var oldPlayerSkin = mutableMapOf<UUID, SkinIdentifier?>()
|
||||
var wwPlayerFur = mutableMapOf<UUID, Int>()
|
||||
}
|
||||
58
src/main/kotlin/fr/azur/tcoww/utils/VoiceChatPlugin.kt
Normal file
58
src/main/kotlin/fr/azur/tcoww/utils/VoiceChatPlugin.kt
Normal file
@@ -0,0 +1,58 @@
|
||||
package fr.azur.tcoww.utils
|
||||
|
||||
import de.maxhenkel.voicechat.api.Group
|
||||
import de.maxhenkel.voicechat.api.VoicechatPlugin
|
||||
import de.maxhenkel.voicechat.api.VoicechatServerApi
|
||||
import de.maxhenkel.voicechat.api.events.EventRegistration
|
||||
import de.maxhenkel.voicechat.api.events.VoicechatServerStartedEvent
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
import kotlin.random.Random
|
||||
|
||||
object VoiceChatPlugin : VoicechatPlugin {
|
||||
lateinit var api: VoicechatServerApi
|
||||
lateinit var werewolfGroup: Group
|
||||
|
||||
override fun getPluginId(): String = "tcoww"
|
||||
|
||||
override fun registerEvents(registration: EventRegistration) {
|
||||
registration.registerEvent(VoicechatServerStartedEvent::class.java, this::onServerStarted)
|
||||
}
|
||||
|
||||
private fun onServerStarted(event: VoicechatServerStartedEvent) {
|
||||
api = event.voicechat
|
||||
werewolfGroup =
|
||||
api
|
||||
.groupBuilder()
|
||||
.setPersistent(true)
|
||||
.setName("werewolf")
|
||||
.setPassword(Random.nextInt().toString())
|
||||
.setType(Group.Type.NORMAL)
|
||||
.setHidden(true)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun addWerewolf(player: Player) {
|
||||
val connection = api.getConnectionOf(player.uniqueId) ?: return
|
||||
connection.group = werewolfGroup
|
||||
}
|
||||
|
||||
fun createSoloGroup(player: Player) {
|
||||
val connection = api.getConnectionOf(player.uniqueId) ?: return
|
||||
val soloGroup =
|
||||
api
|
||||
.groupBuilder()
|
||||
.setName(UUID.randomUUID().toString())
|
||||
.setHidden(true)
|
||||
.setPassword(Random.nextInt().toString())
|
||||
.setType(Group.Type.ISOLATED)
|
||||
.setPersistent(false)
|
||||
.build()
|
||||
connection.group = soloGroup
|
||||
}
|
||||
|
||||
fun degroupPlayer(player: Player) {
|
||||
val connection = api.getConnectionOf(player.uniqueId) ?: return
|
||||
connection.group = null
|
||||
}
|
||||
}
|
||||
77
src/main/kotlin/fr/azur/tcoww/utils/skins/Manager.kt
Normal file
77
src/main/kotlin/fr/azur/tcoww/utils/skins/Manager.kt
Normal file
@@ -0,0 +1,77 @@
|
||||
package fr.azur.tcoww.utils.skins
|
||||
|
||||
import fr.azur.tcoww.Tcoww
|
||||
import net.skinsrestorer.api.SkinsRestorer
|
||||
import net.skinsrestorer.api.SkinsRestorerProvider
|
||||
import net.skinsrestorer.api.property.SkinIdentifier
|
||||
import net.skinsrestorer.api.property.SkinProperty
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import kotlin.random.Random
|
||||
|
||||
object Manager {
|
||||
var maxSkinId: Int = 0
|
||||
private lateinit var skinsRestorer: SkinsRestorer
|
||||
var oldPlayerSkin = mutableMapOf<UUID, SkinIdentifier?>()
|
||||
var wwPlayerFur = mutableMapOf<UUID, Int>()
|
||||
|
||||
fun handle() {
|
||||
skinsRestorer = SkinsRestorerProvider.get()
|
||||
reloadSkin()
|
||||
}
|
||||
|
||||
fun reloadSkin() {
|
||||
val skinsValue =
|
||||
Tcoww.config
|
||||
.getList("werewolf-skins")
|
||||
.orEmpty()
|
||||
.mapNotNull { it as? WerewolfSkin }
|
||||
|
||||
wwPlayerFur.clear()
|
||||
|
||||
maxSkinId = skinsValue.size
|
||||
skinsValue.forEachIndexed { index, skin ->
|
||||
skinsRestorer.skinStorage.setCustomSkinData("tcoww$index", SkinProperty.of(skin.value, skin.signature))
|
||||
}
|
||||
}
|
||||
|
||||
fun applyWerewolfFur(player: Player) {
|
||||
val skin = skinsRestorer.playerStorage.getSkinIdOfPlayer(player.uniqueId)
|
||||
oldPlayerSkin[player.uniqueId] = skin.getOrNull()
|
||||
|
||||
val result = skinsRestorer.skinStorage.findOrCreateSkinData("tcoww_${getWerewolfFur(player.uniqueId)}")
|
||||
|
||||
if (!result.isEmpty) {
|
||||
skinsRestorer.playerStorage.setSkinIdOfPlayer(player.uniqueId, result.get().identifier)
|
||||
skinsRestorer.getSkinApplier(Player::class.java).applySkin(player)
|
||||
}
|
||||
}
|
||||
|
||||
fun unapplySkin(player: Player) {
|
||||
val skin = oldPlayerSkin[player.uniqueId]
|
||||
if (skin == null) {
|
||||
skinsRestorer.playerStorage.removeSkinIdOfPlayer(player.uniqueId)
|
||||
} else {
|
||||
skinsRestorer.playerStorage.setSkinIdOfPlayer(player.uniqueId, skin)
|
||||
}
|
||||
skinsRestorer.getSkinApplier(Player::class.java).applySkin(player)
|
||||
}
|
||||
|
||||
private fun getWerewolfFur(playerUUID: UUID): Int =
|
||||
wwPlayerFur[playerUUID]
|
||||
?: randomFur(playerUUID)
|
||||
|
||||
private fun randomFur(playerUUID: UUID): Int {
|
||||
val id =
|
||||
if (maxSkinId == 0) {
|
||||
0
|
||||
} else {
|
||||
Random(playerUUID.mostSignificantBits xor playerUUID.leastSignificantBits).nextInt(
|
||||
maxSkinId,
|
||||
)
|
||||
}
|
||||
wwPlayerFur[playerUUID] = id
|
||||
return id
|
||||
}
|
||||
}
|
||||
22
src/main/kotlin/fr/azur/tcoww/utils/skins/WerewolfSkin.kt
Normal file
22
src/main/kotlin/fr/azur/tcoww/utils/skins/WerewolfSkin.kt
Normal file
@@ -0,0 +1,22 @@
|
||||
package fr.azur.tcoww.utils.skins
|
||||
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable
|
||||
|
||||
data class WerewolfSkin(
|
||||
val value: String,
|
||||
val signature: String,
|
||||
) : ConfigurationSerializable {
|
||||
constructor(args: MutableMap<String, Object>) : this(
|
||||
args["value"] as String,
|
||||
args["signature"] as String,
|
||||
)
|
||||
|
||||
override fun serialize(): Map<String, String> {
|
||||
val data: MutableMap<String, String> = HashMap()
|
||||
|
||||
data["value"] = value
|
||||
data["signature"] = signature
|
||||
|
||||
return data
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package fr.azur.tcoww.voicechat
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatPlugin
|
||||
import de.maxhenkel.voicechat.api.events.EventRegistration
|
||||
|
||||
class VoiceChatPlugin: VoicechatPlugin {
|
||||
override fun getPluginId(): String {
|
||||
return "tcow"
|
||||
}
|
||||
|
||||
override fun registerEvents(registration: EventRegistration) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,35 @@
|
||||
spawnLocation:
|
||||
==: org.bukkit.Location
|
||||
world: world
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
pitch: 0.0
|
||||
yaw: 0.0
|
||||
lobbyLocation:
|
||||
==: org.bukkit.Location
|
||||
world: world
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
pitch: 0.0
|
||||
yaw: 0.0
|
||||
# Bukkit Location
|
||||
spawn-location: null
|
||||
|
||||
# Bukkit Location
|
||||
lobby-location: null
|
||||
|
||||
# List of Bukkit Location
|
||||
bed-locations: null
|
||||
|
||||
duration: # In seconds
|
||||
day: 600
|
||||
vote: 120
|
||||
night: 300
|
||||
crepuscular: 20
|
||||
wwcount: 10
|
||||
|
||||
werewolf-default-percentage: 20
|
||||
|
||||
# The skin value
|
||||
wwskinsvalue: [
|
||||
"ewogICJ0aW1lc3RhbXAiIDogMTYxNzQ2NzI1ODQxMCwKICAicHJvZmlsZUlkIiA6ICJjMGYzYjI3YTUwMDE0YzVhYjIxZDc5ZGRlMTAxZGZlMiIsCiAgInByb2ZpbGVOYW1lIiA6ICJDVUNGTDEzIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2Y5NmM4OWUwZWYwZmVlZjZkODc4ZDUzYzQ4OWIyMzliNDdlNmViODQyZDJmM2MzZTlhZDdkMjliZmYxYTM0OWUiCiAgICB9CiAgfQp9",
|
||||
"ewogICJ0aW1lc3RhbXAiIDogMTYxNTYxMTkwOTY4MCwKICAicHJvZmlsZUlkIiA6ICIwMGM2Yjk0YTY5YmU0MzY3OTkwOTQxNjFjMjAxOWI3ZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJLQUVWRVJZIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2I0MGRjNTcxZGUwZGQ4ZmQ5NzBjNzNmOTE2NGJjMTQ0Njk1MWFlNDhkNWFiZTQyMzI5MGVlYjFhODc4NDU1ZmUiCiAgICB9CiAgfQp9",
|
||||
"ewogICJ0aW1lc3RhbXAiIDogMTc0Nzk4MDc5ODQyMywKICAicHJvZmlsZUlkIiA6ICI2NWI5NTU1YWQyMGU0NWM5YjFkNmU3MjQwNjU0NTBkNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJKYXZhUHJvZmlsZU5hbWVYIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzJlZTlmNjcxYzFmNjY4Y2IwYWUwNGE5YzhiZWM0OTVlYTVmNzNmNTNmYmY3ZjM5MmNkYjdlMTc1ZmVjZDFjYmUiCiAgICB9CiAgfQp9",
|
||||
"ewogICJ0aW1lc3RhbXAiIDogMTY0Mjc4ODk3NDg1NSwKICAicHJvZmlsZUlkIiA6ICIzYzE0YmVkNDFiOGE0MDIzOGM3MDgzMTA1NzEwMTZmYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJOb2Jpa28iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWZlNzIzMDdjZTEyNmI1Y2I0ZDQ0ZGFlZTcwZDI1ZmQwNDMwOGJjN2M0MzI4OWM3ZDk3MDY4NDY5NWI2MGJhIgogICAgfQogIH0KfQ=="
|
||||
]
|
||||
# The skin signature (see mineskin.org)
|
||||
wwskinssignature: [
|
||||
"uWIu/2R3zImj87H7x//O/04eJ1SwsHvLSxaj1YQuI1vBndUVHhN42Ja7AOJoAieVO8yN1qn/rJj1oK5z5koQ2fZwjNCc0mKTrakCMWGqjaAImDw8RWriUQ3ClPCw6NtCmB1qVUp60kUEpGha/btUSsAEUnVZ0ghM4SXTcS2izbDe/dRfbi5EDr2Uue3sz6+med3hjecZzrKJUX19wP1WwPifEOH2X/smzzGOdqlQtylMZQh3nNeho/GBwbDVXsXsR6LcDgoInDnw63cDV7n4dTs6giGmcx0knhDWH24Z/vrgNSqzbNY9hIgVBNWUqs/1o7/xrbK1HilYBPAiVO0F6+vJOpzdFrpEZVr0M++u+X2Zkt1sfshKZqt0O07KbH8h4xj3J+6iDF5RHHFGmZy0awFGZGIi8wqlffwQfZ+l7nPU1hpMD5DkArxBWJWgnquyCNpQ44OlmTpPRa/gopRpuMwJ1r6vDPhgIavJX6cKQ2lKTYKG2/HB+ZEl/IUtuXxKO7bFe4KOvjJpMwBjOmzqbn2sk3GqbSg8NfNMFA4FjRBvHXOaMsDCqz0MJxLFKvIfYRVWG8XAU6BU82RoS3qGFSOhI6N/DvD7dx1V40q52iWv2j4/S41P5zrtMqQm7wofocptz6sS7GLE1u9rPCBLRIck0wzi3OF7MV2p4wlw6lw=",
|
||||
"kVGwx98YPc6tIZ306TiGI5eoK4v7oEjIvCaOPS03jq4LjBWV12NBTWW67u+HrI2/2m3r8pvAyx1Ddpw4YWyaDbaG0FvLuurWbETqtwvyvVx7R3BZHgw2EnVOYk4+WPmA8xUgzoIbZF/Ch4bSqP7UlZy7/fz4AQwFK/qLMzApOAeV4Kzn4p6+MK2uOkfSjGgwxqAO/+TZj6u01mk1NKNh4ors9RGDG3DBHZKSxTG/PzY5ErKABRXkB/RBMA5IvU5Rzn5cH+Sfkus/7LtYp5u+5i+HcpN/klyBBw4D5di3WzFOAIX78ZiyKzKzWpSN0z6Cb2DZdo1ufeZH9mw8nv+A8VfpGXwphwde+oGBP4l4OffE7YvbnWyVHmlG0L36iI2/FkWQl91GIT15YBHrjeQ9pmvbzCQUMyAHi2jZePTTcT1rDnSzBk7fc9IwfcBRNyqbveTNu9zikfx0W6GnXAbV4qOTIIVEHlpxQ9KW017sqmgiF5l/3ZVwqbEQzglNehYHA55vRfKY0HKbGB54k1oTnM3X7mNXIu6fk8dVgCvT8lVdDm3LWcE6aWF8Yp6QrXNvTNW1yxSRAhigsHrvbajp2Odg18lMTng0oh/4JiYOQAgb6tFdRtQ4nrSVHRBOEvY09IRFzVTTd7n2JaYZ6QcCMOiKOX25fv22rbjSeAZ/Whk=",
|
||||
"wGc2rNbc7+nziEDMKFoBIltHZwx5PQfsfMGyRTfTUdtVi3O4iu0idcpTsTVJ80njIFZvmLpzlwjPu6ULrXJwgQQyGCNdp60jQMl9vGjzgJzs6uqhSCke3EvjOCuAGkv2ScRY5hDGQOnIruxwmgYgDeXHnujt+zTBvW+imxLVaZhXoKVPyqlvm6njWp0XECyAi8DFKbzIdDVp+NsRzIGjKeVoMgWd4xlNazUZGgTsXNCD/+aZOJ1LxA51I8Wgsm888MUXnaGhNI3U4jJNKHAPZMS4++JEuwWzlptJdZIa1jOfwMD6HvIPKEmC5+eDCRFvPIEh84VqErtNTPEUAz7wZAJvO+j+x5A/9VnQmKJhEBxBjlw1Ky+mQcLJnRX/x9jc4EvEd9gWGIUj46y3IF8jWn71eXvinSJ4Op4LQEiv5BfuyMTfY2xwFTlGWjdYF6Xnac+Gz6+E1gjCBSuqKWd56QFDcrqCcvbG50ERhenCUEhUgI33rXNxS/hwz2iClVM26GFJlUtZkZ7/021FjEQNLEYivI1ZkHe9ip8sxx2QVKd5k7Ui/hXkP4xSal3okL4Ar/cThMh0aoWzziYsoAahtoxFWEags7lNOffMoLGmPbgGVRUGHogNu2CES0SNs4AhHVUVERo8OTJHx46XJxXqvLzeEn6zXFD63XXQR8AyXTQ=",
|
||||
"hJ/FhIMQY9G/BqOvGJ0nhuJk/7Y/q/unCpeC7LxGvcYjXzsY/kcInwUzgfjRqNI0oI5ggOAdxIiaGvBRqWCshjxcx6iRyJZBMKwFchM1baHntRl22yxvBA16gpMxbWTihQ0Jtz9m/Dj8clYgyEkMOKFEOya5YiyyqjK+YOl5xWiM1pGAomFixqr7VBLk/NE7e+qYXuFjDl3IZ1OP+tgdgyjkqUZE3OBGQfXP6wvTFjgk/maCPUmzffnbw/yH4JZIa3N/vhK+jzowcV+ymZK/9+10ge8hIZ5LZPdU90xLWd2zPYFjju/vr9TFWUG4YkV8l1vSsG7P8MYjMKFh/YQoTyyjJUZw9YGfnRENZrdegttUxefJywpBgp0xVt5vyAMM9XjTEtwK/A5gef0fD52lKWpwD6xamPBnhb8yRPUnncapGBrQvFhB8uQnkS8BKqtiJyz8XJHg8quzUXjYd+Ywn5p+lzP5zsDXQDYOfcm4FZGYp3oFwJZz1s4YOjP8Abjd+4v0sQIcP+Kj8lBzrADQSvTIJaQZO/emnpkZYoW/ggSJLa+BrRUXK5gNHdZzUI/EDOJggrGn3ezSLd96DyDlosG+lGM/EpuiB504YNzQfrm1scVbk9R4YHNhy+sau04DJcRY0p52qeaVDswMkfjUA6JBvBFT9SqQeB7q9qRwLrk="
|
||||
]
|
||||
werewolf-skins:
|
||||
- ==: fr.azur.tcoww.utils.skins.WerewolfSkin
|
||||
value: "ewogICJ0aW1lc3RhbXAiIDogMTYxNzQ2NzI1ODQxMCwKICAicHJvZmlsZUlkIiA6ICJjMGYzYjI3YTUwMDE0YzVhYjIxZDc5ZGRlMTAxZGZlMiIsCiAgInByb2ZpbGVOYW1lIiA6ICJDVUNGTDEzIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2Y5NmM4OWUwZWYwZmVlZjZkODc4ZDUzYzQ4OWIyMzliNDdlNmViODQyZDJmM2MzZTlhZDdkMjliZmYxYTM0OWUiCiAgICB9CiAgfQp9"
|
||||
signature: "uWIu/2R3zImj87H7x//O/04eJ1SwsHvLSxaj1YQuI1vBndUVHhN42Ja7AOJoAieVO8yN1qn/rJj1oK5z5koQ2fZwjNCc0mKTrakCMWGqjaAImDw8RWriUQ3ClPCw6NtCmB1qVUp60kUEpGha/btUSsAEUnVZ0ghM4SXTcS2izbDe/dRfbi5EDr2Uue3sz6+med3hjecZzrKJUX19wP1WwPifEOH2X/smzzGOdqlQtylMZQh3nNeho/GBwbDVXsXsR6LcDgoInDnw63cDV7n4dTs6giGmcx0knhDWH24Z/vrgNSqzbNY9hIgVBNWUqs/1o7/xrbK1HilYBPAiVO0F6+vJOpzdFrpEZVr0M++u+X2Zkt1sfshKZqt0O07KbH8h4xj3J+6iDF5RHHFGmZy0awFGZGIi8wqlffwQfZ+l7nPU1hpMD5DkArxBWJWgnquyCNpQ44OlmTpPRa/gopRpuMwJ1r6vDPhgIavJX6cKQ2lKTYKG2/HB+ZEl/IUtuXxKO7bFe4KOvjJpMwBjOmzqbn2sk3GqbSg8NfNMFA4FjRBvHXOaMsDCqz0MJxLFKvIfYRVWG8XAU6BU82RoS3qGFSOhI6N/DvD7dx1V40q52iWv2j4/S41P5zrtMqQm7wofocptz6sS7GLE1u9rPCBLRIck0wzi3OF7MV2p4wlw6lw="
|
||||
- ==: fr.azur.tcoww.utils.skins.WerewolfSkin
|
||||
value: "ewogICJ0aW1lc3RhbXAiIDogMTYxNTYxMTkwOTY4MCwKICAicHJvZmlsZUlkIiA6ICIwMGM2Yjk0YTY5YmU0MzY3OTkwOTQxNjFjMjAxOWI3ZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJLQUVWRVJZIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2I0MGRjNTcxZGUwZGQ4ZmQ5NzBjNzNmOTE2NGJjMTQ0Njk1MWFlNDhkNWFiZTQyMzI5MGVlYjFhODc4NDU1ZmUiCiAgICB9CiAgfQp9"
|
||||
signature: "kVGwx98YPc6tIZ306TiGI5eoK4v7oEjIvCaOPS03jq4LjBWV12NBTWW67u+HrI2/2m3r8pvAyx1Ddpw4YWyaDbaG0FvLuurWbETqtwvyvVx7R3BZHgw2EnVOYk4+WPmA8xUgzoIbZF/Ch4bSqP7UlZy7/fz4AQwFK/qLMzApOAeV4Kzn4p6+MK2uOkfSjGgwxqAO/+TZj6u01mk1NKNh4ors9RGDG3DBHZKSxTG/PzY5ErKABRXkB/RBMA5IvU5Rzn5cH+Sfkus/7LtYp5u+5i+HcpN/klyBBw4D5di3WzFOAIX78ZiyKzKzWpSN0z6Cb2DZdo1ufeZH9mw8nv+A8VfpGXwphwde+oGBP4l4OffE7YvbnWyVHmlG0L36iI2/FkWQl91GIT15YBHrjeQ9pmvbzCQUMyAHi2jZePTTcT1rDnSzBk7fc9IwfcBRNyqbveTNu9zikfx0W6GnXAbV4qOTIIVEHlpxQ9KW017sqmgiF5l/3ZVwqbEQzglNehYHA55vRfKY0HKbGB54k1oTnM3X7mNXIu6fk8dVgCvT8lVdDm3LWcE6aWF8Yp6QrXNvTNW1yxSRAhigsHrvbajp2Odg18lMTng0oh/4JiYOQAgb6tFdRtQ4nrSVHRBOEvY09IRFzVTTd7n2JaYZ6QcCMOiKOX25fv22rbjSeAZ/Whk="
|
||||
- ==: fr.azur.tcoww.utils.skins.WerewolfSkin
|
||||
value: "ewogICJ0aW1lc3RhbXAiIDogMTc0Nzk4MDc5ODQyMywKICAicHJvZmlsZUlkIiA6ICI2NWI5NTU1YWQyMGU0NWM5YjFkNmU3MjQwNjU0NTBkNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJKYXZhUHJvZmlsZU5hbWVYIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzJlZTlmNjcxYzFmNjY4Y2IwYWUwNGE5YzhiZWM0OTVlYTVmNzNmNTNmYmY3ZjM5MmNkYjdlMTc1ZmVjZDFjYmUiCiAgICB9CiAgfQp9"
|
||||
signature: "wGc2rNbc7+nziEDMKFoBIltHZwx5PQfsfMGyRTfTUdtVi3O4iu0idcpTsTVJ80njIFZvmLpzlwjPu6ULrXJwgQQyGCNdp60jQMl9vGjzgJzs6uqhSCke3EvjOCuAGkv2ScRY5hDGQOnIruxwmgYgDeXHnujt+zTBvW+imxLVaZhXoKVPyqlvm6njWp0XECyAi8DFKbzIdDVp+NsRzIGjKeVoMgWd4xlNazUZGgTsXNCD/+aZOJ1LxA51I8Wgsm888MUXnaGhNI3U4jJNKHAPZMS4++JEuwWzlptJdZIa1jOfwMD6HvIPKEmC5+eDCRFvPIEh84VqErtNTPEUAz7wZAJvO+j+x5A/9VnQmKJhEBxBjlw1Ky+mQcLJnRX/x9jc4EvEd9gWGIUj46y3IF8jWn71eXvinSJ4Op4LQEiv5BfuyMTfY2xwFTlGWjdYF6Xnac+Gz6+E1gjCBSuqKWd56QFDcrqCcvbG50ERhenCUEhUgI33rXNxS/hwz2iClVM26GFJlUtZkZ7/021FjEQNLEYivI1ZkHe9ip8sxx2QVKd5k7Ui/hXkP4xSal3okL4Ar/cThMh0aoWzziYsoAahtoxFWEags7lNOffMoLGmPbgGVRUGHogNu2CES0SNs4AhHVUVERo8OTJHx46XJxXqvLzeEn6zXFD63XXQR8AyXTQ="
|
||||
- ==: fr.azur.tcoww.utils.skins.WerewolfSkin
|
||||
value: "ewogICJ0aW1lc3RhbXAiIDogMTY0Mjc4ODk3NDg1NSwKICAicHJvZmlsZUlkIiA6ICIzYzE0YmVkNDFiOGE0MDIzOGM3MDgzMTA1NzEwMTZmYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJOb2Jpa28iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWZlNzIzMDdjZTEyNmI1Y2I0ZDQ0ZGFlZTcwZDI1ZmQwNDMwOGJjN2M0MzI4OWM3ZDk3MDY4NDY5NWI2MGJhIgogICAgfQogIH0KfQ=="
|
||||
signature: "hJ/FhIMQY9G/BqOvGJ0nhuJk/7Y/q/unCpeC7LxGvcYjXzsY/kcInwUzgfjRqNI0oI5ggOAdxIiaGvBRqWCshjxcx6iRyJZBMKwFchM1baHntRl22yxvBA16gpMxbWTihQ0Jtz9m/Dj8clYgyEkMOKFEOya5YiyyqjK+YOl5xWiM1pGAomFixqr7VBLk/NE7e+qYXuFjDl3IZ1OP+tgdgyjkqUZE3OBGQfXP6wvTFjgk/maCPUmzffnbw/yH4JZIa3N/vhK+jzowcV+ymZK/9+10ge8hIZ5LZPdU90xLWd2zPYFjju/vr9TFWUG4YkV8l1vSsG7P8MYjMKFh/YQoTyyjJUZw9YGfnRENZrdegttUxefJywpBgp0xVt5vyAMM9XjTEtwK/A5gef0fD52lKWpwD6xamPBnhb8yRPUnncapGBrQvFhB8uQnkS8BKqtiJyz8XJHg8quzUXjYd+Ywn5p+lzP5zsDXQDYOfcm4FZGYp3oFwJZz1s4YOjP8Abjd+4v0sQIcP+Kj8lBzrADQSvTIJaQZO/emnpkZYoW/ggSJLa+BrRUXK5gNHdZzUI/EDOJggrGn3ezSLd96DyDlosG+lGM/EpuiB504YNzQfrm1scVbk9R4YHNhy+sau04DJcRY0p52qeaVDswMkfjUA6JBvBFT9SqQeB7q9qRwLrk="
|
||||
|
||||
# The time in second before teleport no sleeping player
|
||||
playerSleep: 20
|
||||
player-sleep: 30
|
||||
@@ -9,8 +9,9 @@ dependencies:
|
||||
server:
|
||||
SkinsRestorer:
|
||||
load: BEFORE
|
||||
required: true
|
||||
required: false
|
||||
join-classpath: true
|
||||
voicechat:
|
||||
load: BEFORE
|
||||
required: true
|
||||
required: false
|
||||
join-classpath: true
|
||||
Reference in New Issue
Block a user