🖍️Main commit
This commit is contained in:
120
.gitignore
vendored
Normal file
120
.gitignore
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
# User-specific stuff
|
||||
.idea/
|
||||
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
.kotlin/
|
||||
.gradle
|
||||
build/
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
|
||||
**/build/
|
||||
|
||||
# Common working directory
|
||||
run/
|
||||
runs/
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
5
README.md
Normal file
5
README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# TCOWW
|
||||
TCOWW is a small paper plugin created for an event on the French Discord server, [The Court of Gaming](https://discord.gg/evCYTnRrpU).
|
||||
The event is a simple game of "Loup-Garou de Thiercelieux" in Minecraft with a role-play dimension.
|
||||
|
||||
Write in kotlin with the paper 1.21.4 api.
|
||||
69
build.gradle.kts
Normal file
69
build.gradle.kts
Normal file
@@ -0,0 +1,69 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "2.2.0-Beta1"
|
||||
id("com.gradleup.shadow") version "8.3.0"
|
||||
id("xyz.jpenilla.run-paper") version "2.3.1"
|
||||
id("io.papermc.paperweight.userdev") version "2.0.0-beta.16"
|
||||
}
|
||||
|
||||
group = "fr.azur"
|
||||
version = "1.0-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven("https://repo.papermc.io/repository/maven-public/") {
|
||||
name = "papermc-repo"
|
||||
}
|
||||
maven("https://oss.sonatype.org/content/groups/public/") {
|
||||
name = "sonatype"
|
||||
}
|
||||
maven("https://repo.codemc.org/repository/maven-public/") {
|
||||
name = "codemc"
|
||||
}
|
||||
maven("https://repo.plasmoverse.com/releases")
|
||||
maven("https://repo.plasmoverse.com/snapshots")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT")
|
||||
|
||||
|
||||
compileOnly("net.skinsrestorer:skinsrestorer-api:15.6.3")
|
||||
compileOnly("su.plo.voice.api:server:2.1.4")
|
||||
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
}
|
||||
|
||||
val targetJavaVersion = 21
|
||||
kotlin {
|
||||
jvmToolchain(targetJavaVersion)
|
||||
}
|
||||
|
||||
tasks {
|
||||
runServer {
|
||||
downloadPlugins {
|
||||
modrinth("plasmo-voice", "spigot-2.1.4")
|
||||
modrinth("skinsrestorer", "15.6.3")
|
||||
}
|
||||
minecraftVersion("1.21.4")
|
||||
}
|
||||
build {
|
||||
dependsOn("shadowJar")
|
||||
}
|
||||
processResources {
|
||||
val props = mapOf("version" to version)
|
||||
inputs.properties(props)
|
||||
filteringCharset = "UTF-8"
|
||||
filesMatching("paper-plugin.yml") {
|
||||
expand(props)
|
||||
}
|
||||
}
|
||||
shadowJar {
|
||||
archiveBaseName.set("tcoww")
|
||||
|
||||
minimize()
|
||||
|
||||
// exclude("META-INF/*.kotlin_module")
|
||||
// exclude("META-INF/*.version")
|
||||
}
|
||||
}
|
||||
0
gradle.properties
Normal file
0
gradle.properties
Normal file
1
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
1
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1 @@
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
1
settings.gradle.kts
Normal file
1
settings.gradle.kts
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = "Werewolf Role Play"
|
||||
51
src/main/kotlin/fr/azur/tcoww/Tcoww.kt
Normal file
51
src/main/kotlin/fr/azur/tcoww/Tcoww.kt
Normal file
@@ -0,0 +1,51 @@
|
||||
package fr.azur.tcoww
|
||||
|
||||
import fr.azur.tcoww.events.GameEvent
|
||||
import fr.azur.tcoww.events.ToolsEvents
|
||||
import fr.azur.tcoww.plasmovoice.addon.PlasmoAddon
|
||||
import fr.azur.tcoww.roles.*
|
||||
import fr.azur.tcoww.utils.Skin
|
||||
import net.skinsrestorer.api.SkinsRestorer
|
||||
import net.skinsrestorer.api.SkinsRestorerProvider
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
import su.plo.voice.api.server.PlasmoVoiceServer
|
||||
|
||||
class Tcoww : JavaPlugin() {
|
||||
private lateinit var skinsRestorer: SkinsRestorer
|
||||
private lateinit var skinManager: Skin
|
||||
val plasmoAddon = PlasmoAddon()
|
||||
|
||||
override fun onEnable() {
|
||||
saveResource("config.yml", false)
|
||||
saveDefaultConfig()
|
||||
|
||||
PlasmoVoiceServer.getAddonsLoader().load(plasmoAddon)
|
||||
|
||||
skinsRestorer = SkinsRestorerProvider.get()
|
||||
skinManager = Skin(this, skinsRestorer)
|
||||
|
||||
server.pluginManager.registerEvents(ToolsEvents(this), this)
|
||||
server.pluginManager.registerEvents(GameEvent(this, skinManager), this)
|
||||
|
||||
registerRoles()
|
||||
}
|
||||
|
||||
override fun onDisable() {
|
||||
|
||||
}
|
||||
|
||||
fun reload(withPlasmoAddon: Boolean) {
|
||||
this.reloadConfig()
|
||||
skinManager.reloadSkin()
|
||||
if (withPlasmoAddon) plasmoAddon.onConfigLoaded()
|
||||
}
|
||||
|
||||
private fun registerRoles() {
|
||||
Role.registerRole(Villager())
|
||||
Role.registerRole(Werewolf())
|
||||
Role.registerRole(Child())
|
||||
Role.registerRole(FortuneTeller())
|
||||
Role.registerRole(Hunter())
|
||||
Role.registerRole(Witch())
|
||||
}
|
||||
}
|
||||
24
src/main/kotlin/fr/azur/tcoww/TcowwBootstrap.kt
Normal file
24
src/main/kotlin/fr/azur/tcoww/TcowwBootstrap.kt
Normal file
@@ -0,0 +1,24 @@
|
||||
package fr.azur.tcoww
|
||||
|
||||
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 {
|
||||
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())
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/main/kotlin/fr/azur/tcoww/commands/GameCommand.kt
Normal file
67
src/main/kotlin/fr/azur/tcoww/commands/GameCommand.kt
Normal file
@@ -0,0 +1,67 @@
|
||||
package fr.azur.tcoww.commands
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.arguments.StringArgumentType
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
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 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.Bukkit
|
||||
import org.bukkit.NamespacedKey
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
)
|
||||
)
|
||||
).then(
|
||||
Commands.literal("stop").executes { ctx ->
|
||||
Game.current?.stopGame(true)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
}
|
||||
156
src/main/kotlin/fr/azur/tcoww/commands/Power.kt
Normal file
156
src/main/kotlin/fr/azur/tcoww/commands/Power.kt
Normal file
@@ -0,0 +1,156 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
18
src/main/kotlin/fr/azur/tcoww/commands/ReloadCommands.kt
Normal file
18
src/main/kotlin/fr/azur/tcoww/commands/ReloadCommands.kt
Normal file
@@ -0,0 +1,18 @@
|
||||
package fr.azur.tcoww.commands
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
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
|
||||
}
|
||||
}
|
||||
44
src/main/kotlin/fr/azur/tcoww/commands/TimeGest.kt
Normal file
44
src/main/kotlin/fr/azur/tcoww/commands/TimeGest.kt
Normal file
@@ -0,0 +1,44 @@
|
||||
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
|
||||
}
|
||||
)
|
||||
}
|
||||
146
src/main/kotlin/fr/azur/tcoww/commands/Tools.kt
Normal file
146
src/main/kotlin/fr/azur/tcoww/commands/Tools.kt
Normal file
@@ -0,0 +1,146 @@
|
||||
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 fr.azur.tcoww.Tcoww
|
||||
import fr.azur.tcoww.items.CustomItems
|
||||
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.event.ClickEvent
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import net.kyori.adventure.text.format.TextDecoration
|
||||
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()
|
||||
|
||||
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 { ctx ->
|
||||
val plugin = Bukkit.getPluginManager().getPlugin("tcoww") as Tcoww
|
||||
plugin.reload(true)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
).then(
|
||||
Commands.literal("customitem").then(
|
||||
Commands.argument("item", StringArgumentType.greedyString())
|
||||
.suggests { ctx, 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
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
}"
|
||||
)
|
||||
)
|
||||
.color(NamedTextColor.LIGHT_PURPLE)
|
||||
.decorate(TextDecoration.UNDERLINED)
|
||||
)
|
||||
.appendNewline()
|
||||
}
|
||||
return Component.text("Current bed locations :")
|
||||
.color(NamedTextColor.DARK_PURPLE)
|
||||
.appendNewline()
|
||||
.append(bedLocationComponent)
|
||||
}
|
||||
}
|
||||
32
src/main/kotlin/fr/azur/tcoww/commands/Vote.kt
Normal file
32
src/main/kotlin/fr/azur/tcoww/commands/Vote.kt
Normal file
@@ -0,0 +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 fr.azur.tcoww.game.Phase
|
||||
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 org.bukkit.entity.Player
|
||||
|
||||
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()
|
||||
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
|
||||
}
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
}
|
||||
432
src/main/kotlin/fr/azur/tcoww/events/GameEvent.kt
Normal file
432
src/main/kotlin/fr/azur/tcoww/events/GameEvent.kt
Normal file
@@ -0,0 +1,432 @@
|
||||
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.addPotionEffect(PotionEffect(PotionEffectType.WITHER, 1200, 10))
|
||||
target.addPotionEffect(PotionEffect(PotionEffectType.POISON, 1200, 10))
|
||||
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
|
||||
)
|
||||
)
|
||||
event.player.addPotionEffect(
|
||||
PotionEffect(
|
||||
PotionEffectType.SATURATION,
|
||||
PotionEffect.INFINITE_DURATION,
|
||||
1,
|
||||
false,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@EventHandler(
|
||||
priority = EventPriority.MONITOR,
|
||||
ignoreCancelled = true
|
||||
)
|
||||
fun endSleep(event: PlayerBedLeaveEvent) {
|
||||
event.player.removePotionEffect(PotionEffectType.SATURATION)
|
||||
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.1,
|
||||
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)
|
||||
}
|
||||
20
src/main/kotlin/fr/azur/tcoww/events/TimePhaseChangeEvent.kt
Normal file
20
src/main/kotlin/fr/azur/tcoww/events/TimePhaseChangeEvent.kt
Normal file
@@ -0,0 +1,20 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
82
src/main/kotlin/fr/azur/tcoww/events/ToolsEvents.kt
Normal file
82
src/main/kotlin/fr/azur/tcoww/events/ToolsEvents.kt
Normal file
@@ -0,0 +1,82 @@
|
||||
package fr.azur.tcoww.events
|
||||
|
||||
import fr.azur.tcoww.utils.BedGestion
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.NamespacedKey
|
||||
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 {
|
||||
@EventHandler
|
||||
fun clickEvent(event: PlayerInteractEvent) {
|
||||
val tool = event.player.inventory.itemInMainHand
|
||||
|
||||
if (!tool.persistentDataContainer.has(NamespacedKey("tcoww", "tools"))) return
|
||||
|
||||
when (tool.persistentDataContainer.get(NamespacedKey("tcoww", "tools"), 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 block = BedGestion.getHeadBed(interactloc.block)
|
||||
|
||||
if (!list.contains(block.location.serialize())) {
|
||||
list.add(block.location.serialize())
|
||||
plugin.config.set("bedLocation", list)
|
||||
plugin.saveConfig()
|
||||
event.player.sendMessage(
|
||||
Component.text("Bed location add.").color(NamedTextColor.LIGHT_PURPLE)
|
||||
)
|
||||
} else {
|
||||
event.player.sendMessage(
|
||||
Component.text("Bed location already exists.").color(NamedTextColor.DARK_RED)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
event.player.sendMessage(
|
||||
Component.text("It's not a bed...").color(NamedTextColor.DARK_RED)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @EventHandler
|
||||
// fun reloadAfterWorld(worldInitEvent: WorldInitEvent) {
|
||||
//
|
||||
// }
|
||||
}
|
||||
129
src/main/kotlin/fr/azur/tcoww/game/Game.kt
Normal file
129
src/main/kotlin/fr/azur/tcoww/game/Game.kt
Normal file
@@ -0,0 +1,129 @@
|
||||
package fr.azur.tcoww.game
|
||||
|
||||
import fr.azur.tcoww.roles.Role
|
||||
import fr.azur.tcoww.roles.Villager
|
||||
import fr.azur.tcoww.roles.Werewolf
|
||||
import net.kyori.adventure.text.Component
|
||||
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.persistence.PersistentDataType
|
||||
import org.bukkit.plugin.Plugin
|
||||
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
|
||||
|
||||
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.inventory.clear()
|
||||
player.health = 20.0
|
||||
}
|
||||
|
||||
assignRoles()
|
||||
|
||||
timeGestion = TimeGestion(plugin, world)
|
||||
|
||||
timeGestShedule = Bukkit.getScheduler().runTaskTimer(plugin, Runnable {
|
||||
timeGestion.tick()
|
||||
}, 0L, 1L)
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
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 stopGame(withoutResult: Boolean = false) {
|
||||
current ?: return
|
||||
current = null
|
||||
timeGestShedule.cancel()
|
||||
world.time = 18000
|
||||
players.forEach { player ->
|
||||
player.gameMode = GameMode.SPECTATOR
|
||||
player.sendMessage(
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
Bukkit.getScheduler().runTaskLater(plugin, Runnable {
|
||||
players.forEach { player ->
|
||||
player.teleport(plugin.config.getLocation("lobbyLocation")!!)
|
||||
player.gameMode = GameMode.ADVENTURE
|
||||
}
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
8
src/main/kotlin/fr/azur/tcoww/game/Phase.kt
Normal file
8
src/main/kotlin/fr/azur/tcoww/game/Phase.kt
Normal file
@@ -0,0 +1,8 @@
|
||||
package fr.azur.tcoww.game
|
||||
|
||||
enum class Phase {
|
||||
DAY,
|
||||
VOTE,
|
||||
NIGHT,
|
||||
CREPUSCULAR
|
||||
}
|
||||
81
src/main/kotlin/fr/azur/tcoww/game/TimeGestion.kt
Normal file
81
src/main/kotlin/fr/azur/tcoww/game/TimeGestion.kt
Normal file
@@ -0,0 +1,81 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
226
src/main/kotlin/fr/azur/tcoww/items/CustomItems.kt
Normal file
226
src/main/kotlin/fr/azur/tcoww/items/CustomItems.kt
Normal file
@@ -0,0 +1,226 @@
|
||||
package fr.azur.tcoww.items
|
||||
|
||||
import fr.azur.tcoww.game.Game
|
||||
import fr.azur.tcoww.roles.Role
|
||||
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
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.CrossbowMeta
|
||||
import org.bukkit.inventory.meta.Damageable
|
||||
import org.bukkit.inventory.meta.PotionMeta
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
import org.bukkit.potion.PotionEffect
|
||||
import org.bukkit.potion.PotionEffectType
|
||||
|
||||
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)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}),
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
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)
|
||||
}
|
||||
}
|
||||
}),
|
||||
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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
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)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}),
|
||||
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)))
|
||||
}
|
||||
}
|
||||
}),
|
||||
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)))
|
||||
}
|
||||
}
|
||||
}),
|
||||
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)))
|
||||
}
|
||||
}
|
||||
}),
|
||||
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)))
|
||||
}
|
||||
}
|
||||
}),
|
||||
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 players = Game.current?.playersMutable?.shuffled().orEmpty()
|
||||
|
||||
val (villagers, werewolves) = players.partition {
|
||||
Role.getRole(it)?.lg == false
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private var cachedItem: ItemStack? = null
|
||||
|
||||
val item: ItemStack
|
||||
get() {
|
||||
return if (cache) {
|
||||
cachedItem ?: supplier().also { cachedItem = it }
|
||||
} else {
|
||||
supplier()
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package fr.azur.tcoww.plasmovoice.addon
|
||||
|
||||
import su.plo.voice.api.addon.AddonInitializer
|
||||
import su.plo.voice.api.addon.InjectPlasmoVoice
|
||||
import su.plo.voice.api.addon.annotation.Addon
|
||||
import su.plo.voice.api.event.EventSubscribe
|
||||
import su.plo.voice.api.server.PlasmoVoiceServer
|
||||
import su.plo.voice.api.server.event.player.PlayerInfoCreateEvent
|
||||
|
||||
|
||||
@Addon(
|
||||
id = "tcoww",
|
||||
name = "The court of werewolf",
|
||||
version = "1.0.0",
|
||||
authors = ["Azur"]
|
||||
)
|
||||
class PlasmoAddon : AddonInitializer {
|
||||
@InjectPlasmoVoice
|
||||
private lateinit var voiceServer: PlasmoVoiceServer
|
||||
|
||||
override fun onAddonInitialize() {
|
||||
onConfigLoaded()
|
||||
}
|
||||
|
||||
override fun onAddonShutdown() {
|
||||
|
||||
}
|
||||
|
||||
fun onConfigLoaded() {
|
||||
|
||||
}
|
||||
|
||||
@EventSubscribe
|
||||
fun onPlayerInfoCreate(event: PlayerInfoCreateEvent) {
|
||||
event.voicePlayerInfo.playerNick = "..."
|
||||
}
|
||||
}
|
||||
22
src/main/kotlin/fr/azur/tcoww/roles/Child.kt
Normal file
22
src/main/kotlin/fr/azur/tcoww/roles/Child.kt
Normal file
@@ -0,0 +1,22 @@
|
||||
package fr.azur.tcoww.roles
|
||||
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
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")
|
||||
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)
|
||||
)
|
||||
}
|
||||
25
src/main/kotlin/fr/azur/tcoww/roles/FortuneTeller.kt
Normal file
25
src/main/kotlin/fr/azur/tcoww/roles/FortuneTeller.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
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.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class FortuneTeller : Role {
|
||||
override fun handle(player: Player) {
|
||||
player.inventory.addItem(CustomItems.CrystalBall.item)
|
||||
}
|
||||
|
||||
override fun onDeath(player: Player) {}
|
||||
|
||||
override var lg = false
|
||||
override var id = NamespacedKey("tcoww", "fortune_teller")
|
||||
override val displayName = Component.text("Voyante")
|
||||
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)
|
||||
)
|
||||
}
|
||||
34
src/main/kotlin/fr/azur/tcoww/roles/Hunter.kt
Normal file
34
src/main/kotlin/fr/azur/tcoww/roles/Hunter.kt
Normal file
@@ -0,0 +1,34 @@
|
||||
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.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class 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 var id = NamespacedKey("tcoww", "hunter")
|
||||
override val displayName = Component.text("Chaseur")
|
||||
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)
|
||||
)
|
||||
)
|
||||
}
|
||||
49
src/main/kotlin/fr/azur/tcoww/roles/Role.kt
Normal file
49
src/main/kotlin/fr/azur/tcoww/roles/Role.kt
Normal file
@@ -0,0 +1,49 @@
|
||||
package fr.azur.tcoww.roles
|
||||
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
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
|
||||
val id: NamespacedKey
|
||||
val displayName: Component
|
||||
val hasPowerCommand: Boolean
|
||||
val description: Component
|
||||
|
||||
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()
|
||||
)
|
||||
player.sendMessage(
|
||||
Component.text("Votre role est ").append(role.displayName).color(NamedTextColor.DARK_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)
|
||||
}
|
||||
|
||||
fun getRole(player: Player): Role? {
|
||||
val rolestr = player.persistentDataContainer.get(rolekey, PersistentDataType.STRING)
|
||||
if (rolestr == null) return null
|
||||
return registerRoles[NamespacedKey.fromString(rolestr)]
|
||||
}
|
||||
|
||||
fun registerRole(role: Role) {
|
||||
registerRoles.put(role.id, role)
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/main/kotlin/fr/azur/tcoww/roles/Villager.kt
Normal file
26
src/main/kotlin/fr/azur/tcoww/roles/Villager.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
package fr.azur.tcoww.roles
|
||||
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
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
|
||||
override var id = NamespacedKey("tcoww", "villager")
|
||||
override val displayName = Component.text("Villageois")
|
||||
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)
|
||||
)
|
||||
}
|
||||
25
src/main/kotlin/fr/azur/tcoww/roles/Werewolf.kt
Normal file
25
src/main/kotlin/fr/azur/tcoww/roles/Werewolf.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
package fr.azur.tcoww.roles
|
||||
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
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
|
||||
override var id = NamespacedKey("tcoww", "werewolf")
|
||||
override val displayName = Component.text("Loup-Garou")
|
||||
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
|
||||
)
|
||||
)
|
||||
}
|
||||
29
src/main/kotlin/fr/azur/tcoww/roles/Witch.kt
Normal file
29
src/main/kotlin/fr/azur/tcoww/roles/Witch.kt
Normal file
@@ -0,0 +1,29 @@
|
||||
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.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class 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 var id = NamespacedKey("tcoww", "witch")
|
||||
override val displayName = Component.text("Sorcière")
|
||||
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()
|
||||
}
|
||||
24
src/main/kotlin/fr/azur/tcoww/utils/BedGestion.kt
Normal file
24
src/main/kotlin/fr/azur/tcoww/utils/BedGestion.kt
Normal file
@@ -0,0 +1,24 @@
|
||||
package fr.azur.tcoww.utils
|
||||
|
||||
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 getHeadBed(block: Block): Block {
|
||||
val bedData = block.blockData as Bed
|
||||
return if (bedData.part == Bed.Part.FOOT) {
|
||||
block.getRelative(bedData.facing)
|
||||
} else {
|
||||
block
|
||||
}
|
||||
}
|
||||
|
||||
fun isOcupied(block: Block): Boolean {
|
||||
val bedData = block.blockData as Bed
|
||||
return bedData.isOccupied
|
||||
}
|
||||
}
|
||||
65
src/main/kotlin/fr/azur/tcoww/utils/Skin.kt
Normal file
65
src/main/kotlin/fr/azur/tcoww/utils/Skin.kt
Normal file
@@ -0,0 +1,65 @@
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
13
src/main/kotlin/fr/azur/tcoww/utils/Stockage.kt
Normal file
13
src/main/kotlin/fr/azur/tcoww/utils/Stockage.kt
Normal file
@@ -0,0 +1,13 @@
|
||||
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>()
|
||||
}
|
||||
38
src/main/resources/config.yml
Normal file
38
src/main/resources/config.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
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
|
||||
duration: # In seconds
|
||||
day: 600
|
||||
vote: 120
|
||||
night: 300
|
||||
crepuscular: 20
|
||||
wwcount: 10
|
||||
# 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="
|
||||
]
|
||||
# The time in second before teleport no sleeping player
|
||||
playerSleep: 20
|
||||
16
src/main/resources/paper-plugin.yml
Normal file
16
src/main/resources/paper-plugin.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
name: tcoww
|
||||
version: '1.0-SNAPSHOT'
|
||||
main: fr.azur.tcoww.Tcoww
|
||||
api-version: '1.21'
|
||||
load: POSTWORLD
|
||||
authors: [ Azur84 ]
|
||||
bootstrapper: fr.azur.tcoww.TcowwBootstrap
|
||||
dependencies:
|
||||
server:
|
||||
SkinsRestorer:
|
||||
load: BEFORE
|
||||
required: true
|
||||
join-classpath: true
|
||||
PlasmoVoice:
|
||||
load: BEFORE
|
||||
required: true
|
||||
Reference in New Issue
Block a user