commit e27f4ddb5ca0af23f761e60eb8608066193f3937 Author: Fortern Date: Mon Jan 27 02:00:46 2025 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8e5b89f --- /dev/null +++ b/.gitignore @@ -0,0 +1,117 @@ +# User-specific stuff +.idea/ + +*.iml +*.ipr +*.iws + +# IntelliJ +out/ + + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.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 + +target/ + +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next + +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar +.flattened-pom.xml + +# Common working directory +run/ + +# Gradle +.gradle/ +build/ diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..08e49f3 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,34 @@ +plugins { + kotlin("jvm") version "2.1.0" + id("com.gradleup.shadow") version "8.3.5" +} + +group = "xyz.fortern" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() + maven("https://repo.papermc.io/repository/maven-public/") { + name = "papermc-repo" + } + maven("https://oss.sonatype.org/content/groups/public/") { + name = "sonatype" + } +} + +dependencies { + // Paper API + compileOnly("io.papermc.paper:paper-api:1.21.3-R0.1-SNAPSHOT") + // Adventure API + compileOnly("net.kyori:adventure-api:4.14.0") + // Kotlin Stdlib https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib + implementation(kotlin("stdlib")) +} + +kotlin { + jvmToolchain(21) +} + +tasks.build { + dependsOn("shadowJar") +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..9bf7bd3 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..ec09a3e --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "Minehunt" diff --git a/src/main/kotlin/xyz/fortern/minehunt/Console.kt b/src/main/kotlin/xyz/fortern/minehunt/Console.kt new file mode 100644 index 0000000..a8221ac --- /dev/null +++ b/src/main/kotlin/xyz/fortern/minehunt/Console.kt @@ -0,0 +1,117 @@ +package xyz.fortern.minehunt + +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.Difficulty +import org.bukkit.GameRule +import org.bukkit.scheduler.BukkitTask +import org.bukkit.scoreboard.Team + +/** + * 游戏控制台 + */ +class Console { + + var stage: GameStage = GameStage.PREPARING + + /** + * 速通者队伍 + */ + val speedrunnerTeam: Team + + /** + * 猎人队伍 + */ + private val hunterTeam: Team + + /** + * 观察者队伍 + */ + private val spectatorTeam: Team + + /** + * 猎人持有的指南针指向的速通者在speedrunnerList中的index + */ + val trackRunnerMap: Map = HashMap() + + /** + * 用于遍历的速通者列表 + */ + val speedrunnerList: MutableList = ArrayList() + + private var countdownTask: BukkitTask? = null + + companion object { + @JvmStatic + private lateinit var instance: Console + + @JvmStatic + fun getInstance() = instance + } + + init { + instance = this + // 设置游戏规则 + val world = Bukkit.getWorld("world")!! + world.worldBorder.size = 32.0 + world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false) + world.setGameRule(GameRule.DO_WEATHER_CYCLE, false) + world.setGameRule(GameRule.DO_MOB_SPAWNING, false) + world.setGameRule(GameRule.KEEP_INVENTORY, true) + world.setGameRule(GameRule.SPAWN_RADIUS, 0) + world.setGameRule(GameRule.SPECTATORS_GENERATE_CHUNKS, false) + world.difficulty = Difficulty.HARD + + // 配置队伍 + val scoreboard = Bukkit.getScoreboardManager().mainScoreboard + + speedrunnerTeam = scoreboard.getTeam("speedrunner") ?: scoreboard.registerNewTeam("speedrunner") + hunterTeam = scoreboard.getTeam("hunter") ?: scoreboard.registerNewTeam("hunter") + spectatorTeam = scoreboard.getTeam("spectator") ?: scoreboard.registerNewTeam("spectator") + + speedrunnerTeam.entries.forEach { speedrunnerTeam.removeEntries(it) } + hunterTeam.entries.forEach { hunterTeam.removeEntries(it) } + spectatorTeam.entries.forEach { spectatorTeam.removeEntries(it) } + } + + fun tryStart(): Boolean { + if (speedrunnerTeam.size == 0) return false + if (Bukkit.getOnlinePlayers().count { it.isDead } > 0) return false + + return true + } + + fun countdownToStart() { + countdownTask = Bukkit.getScheduler().runTaskTimerAsynchronously(Minehunt.instance(), object : Runnable { + private var countdown = 6 + override fun run() { + if (--countdown > 0) { + Bukkit.getOnlinePlayers().forEach { + val title = Title.title( + Component.text(countdown.toString(), NamedTextColor.DARK_PURPLE), + Component.text("开始倒计时", NamedTextColor.GRAY) + ) + it.showTitle(title) + } + } else { + countdownTask = null + start() + } + } + }, 0, 20) + } + + fun start() { + + } + + + /** + * 游戏阶段 + */ + enum class GameStage { + PREPARING, PROCESSING, OVER + } +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/fortern/minehunt/Minehunt.kt b/src/main/kotlin/xyz/fortern/minehunt/Minehunt.kt new file mode 100644 index 0000000..859283e --- /dev/null +++ b/src/main/kotlin/xyz/fortern/minehunt/Minehunt.kt @@ -0,0 +1,34 @@ +package xyz.fortern.minehunt + +import org.bukkit.Bukkit +import org.bukkit.plugin.java.JavaPlugin +import xyz.fortern.minehunt.command.GodCommand +import xyz.fortern.minehunt.listener.PlayerListener + +class Minehunt : JavaPlugin() { + + companion object { + @JvmStatic + private lateinit var instance: Minehunt + + @JvmStatic + fun instance() = instance + } + + override fun onEnable() { + // Plugin startup logic + + // 初始化 + instance = this + val console = Console() + Bukkit.getPluginManager().registerEvents(PlayerListener(console), this) + + Bukkit.getPluginCommand("god")!!.setExecutor(GodCommand()) + + } + + override fun onDisable() { + // Plugin shutdown logic + } +} + diff --git a/src/main/kotlin/xyz/fortern/minehunt/command/GodCommand.kt b/src/main/kotlin/xyz/fortern/minehunt/command/GodCommand.kt new file mode 100644 index 0000000..93a87a7 --- /dev/null +++ b/src/main/kotlin/xyz/fortern/minehunt/command/GodCommand.kt @@ -0,0 +1,14 @@ +package xyz.fortern.minehunt.command + +import org.bukkit.command.Command +import org.bukkit.command.CommandExecutor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +class GodCommand: CommandExecutor { + override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array?): Boolean { + if (sender is Player) + sender.isInvulnerable = !sender.isInvulnerable + return true + } +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/fortern/minehunt/listener/PlayerListener.kt b/src/main/kotlin/xyz/fortern/minehunt/listener/PlayerListener.kt new file mode 100644 index 0000000..a074e9e --- /dev/null +++ b/src/main/kotlin/xyz/fortern/minehunt/listener/PlayerListener.kt @@ -0,0 +1,53 @@ +package xyz.fortern.minehunt.listener + +import org.bukkit.Bukkit +import org.bukkit.GameMode +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.PlayerDeathEvent +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.event.player.PlayerJoinEvent +import org.bukkit.event.player.PlayerQuitEvent +import xyz.fortern.minehunt.Console + +class PlayerListener( + private val console: Console +) : Listener { + + @EventHandler + fun onPlayerJoin(event: PlayerJoinEvent) { + val player = event.player + val stage = console.stage + if (stage == Console.GameStage.PREPARING) { + player.gameMode = GameMode.ADVENTURE + } else if (stage == Console.GameStage.PROCESSING && console.speedrunnerTeam.hasEntry(player.name)) { + console.speedrunnerList.add(player.name) + } + } + + @EventHandler + fun onPlayerQuit(event: PlayerQuitEvent) { + val player = event.player + val stage = console.stage + if (stage == Console.GameStage.PREPARING) { + player.scoreboard.teams.forEach { it.removeEntry(player.name) } + } else if (stage == Console.GameStage.PROCESSING && console.speedrunnerTeam.hasEntry(player.name)) { + console.speedrunnerList.remove(player.name) + } + player.spigot().respawn() + + } + + @EventHandler + fun onIn(event: PlayerInteractEvent) { + val team = Bukkit.getScoreboardManager().mainScoreboard.getTeam("A")!! + val size = team.entries.size + + } + + @EventHandler + fun onPlayerDeath(event: PlayerDeathEvent) { + val player = event.player + player.spigot().respawn() + } +} \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..2ba23cb --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,9 @@ +name: Minehunt +version: '1.0-SNAPSHOT' +main: xyz.fortern.minehunt.Minehunt +api-version: '1.21' +authors: [ Fortern ] + +commands: + god: + description: "使自己无敌"