This commit is contained in:
2025-01-27 02:00:46 +08:00
commit e27f4ddb5c
9 changed files with 385 additions and 0 deletions

117
.gitignore vendored Normal file
View File

@@ -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/

34
build.gradle.kts Normal file
View File

@@ -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")
}

View File

@@ -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

1
settings.gradle.kts Normal file
View File

@@ -0,0 +1 @@
rootProject.name = "Minehunt"

View File

@@ -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<String, Int> = HashMap()
/**
* 用于遍历的速通者列表
*/
val speedrunnerList: MutableList<String> = 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
}
}

View File

@@ -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
}
}

View File

@@ -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<out String>?): Boolean {
if (sender is Player)
sender.isInvulnerable = !sender.isInvulnerable
return true
}
}

View File

@@ -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()
}
}

View File

@@ -0,0 +1,9 @@
name: Minehunt
version: '1.0-SNAPSHOT'
main: xyz.fortern.minehunt.Minehunt
api-version: '1.21'
authors: [ Fortern ]
commands:
god:
description: "使自己无敌"