diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 147541c..f32b714 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1 +1,10 @@ FROM mcr.microsoft.com/devcontainers/java:21 + +RUN apt-get update && apt-get install -y \ + maven \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# .m2ディレクトリの権限を vscode に設定 +RUN mkdir -p /home/vscode/.m2/repository \ + && chown -R vscode /home/vscode/.m2 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 98b9f44..357e71f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -11,5 +11,5 @@ ] } }, - "postCreateCommand": "mvn dependency:go-offline" + "shutdownAction": "none" } diff --git a/.gitignore b/.gitignore index b8c3a52..abddb0f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ # Maven target/ +dependency-reduced-pom.xml \ No newline at end of file diff --git a/Makefile b/Makefile index d85c78f..1b6f8dc 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Minecraft LogTime Plugin - 開発用Makefile -.PHONY: help build start stop clean logs test reload +.PHONY: help build start stop clean logs test reload dev-rebuild dev-logs # デフォルトターゲット help: @@ -12,6 +12,8 @@ help: @echo " make logs - Paper サーバーのログを表示" @echo " make test - テストを実行" @echo " make reload - プラグインをリビルドしてサーバー再起動" + @echo " make dev-rebuild - 開発用コマンド: プラグインをリビルドしてサーバー再起動" + @echo " make dev-logs - 開発用コマンド: Paper サーバーのログを表示" # プラグインをビルド build: @@ -55,3 +57,13 @@ init: docker-compose build make build @echo "初期化完了!'make start' でサーバーを起動できます。" + +# 開発用コマンド +dev-rebuild: + docker-compose build paper + docker-compose restart paper + @echo "Plugin reloaded!" + +# 開発用コマンド +dev-logs: + docker-compose logs -f paper diff --git a/docker-compose.yml b/docker-compose.yml index c4f53df..1659d4d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,14 +12,12 @@ services: build: context: . dockerfile: ./paper/Dockerfile - container_name: mc-plugin-paper + target: runtime ports: - "25565:25565" volumes: - - ./target:/server/plugins - paper_data:/server - depends_on: - - dev + - ./target:/server/plugins volumes: paper_data: diff --git a/paper/Dockerfile b/paper/Dockerfile index d9894eb..9b24900 100644 --- a/paper/Dockerfile +++ b/paper/Dockerfile @@ -1,20 +1,17 @@ -# === ビルド用ステージ === -FROM debian:stable-slim AS builder - -ARG MC_VERSION="1.21" -ARG BUILD_NUMBER="130" - +# === Paperサーバーダウンロード用ステージ === +FROM debian:stable-slim AS server-builder +ARG MC_VERSION="1.21.8" +ARG BUILD_NUMBER="53" RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/* RUN wget -O paper.jar "https://api.papermc.io/v2/projects/paper/versions/${MC_VERSION}/builds/${BUILD_NUMBER}/downloads/paper-${MC_VERSION}-${BUILD_NUMBER}.jar" -# === 起動用ステージ === -FROM eclipse-temurin:21-jre-jammy - +# === 実行用ステージ === +FROM eclipse-temurin:21-jre-jammy AS runtime WORKDIR /server -COPY --from=builder /paper.jar . +# Paperサーバーをコピー +COPY --from=server-builder /paper.jar . COPY paper/eula.txt . EXPOSE 25565 - CMD ["java", "-Xms1G", "-Xmx1G", "-jar", "paper.jar", "--nogui"] diff --git a/pom.xml b/pom.xml index ef04699..23d3409 100644 --- a/pom.xml +++ b/pom.xml @@ -79,6 +79,43 @@ + + + org.apache.maven.plugins + maven-shade-plugin + 3.4.1 + + + package + + shade + + + + + org.jetbrains.kotlin:kotlin-stdlib + + + + + com.pool25m.logtime.LogTimePlugin + + + ${project.artifactId}-${project.version} + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + diff --git a/src/main/kotlin/com/pool25m/logtime/LogTimePlugin.kt b/src/main/kotlin/com/pool25m/logtime/LogTimePlugin.kt index e53fa91..f175108 100644 --- a/src/main/kotlin/com/pool25m/logtime/LogTimePlugin.kt +++ b/src/main/kotlin/com/pool25m/logtime/LogTimePlugin.kt @@ -4,9 +4,10 @@ import org.bukkit.plugin.java.JavaPlugin class LogTimePlugin : JavaPlugin() { override fun onEnable() { - logger.info("LogTime Plugin has been enabled!") + val playerStatsService = PlayerStatsService() + getCommand("ranking")?.setExecutor(RankingCommand(playerStatsService)) - getCommand("ranking")?.setExecutor(RankingCommand()) + logger.info("LogTime Plugin has been enabled!") } override fun onDisable() { diff --git a/src/main/kotlin/com/pool25m/logtime/PlayerStatsService.kt b/src/main/kotlin/com/pool25m/logtime/PlayerStatsService.kt new file mode 100644 index 0000000..08804b2 --- /dev/null +++ b/src/main/kotlin/com/pool25m/logtime/PlayerStatsService.kt @@ -0,0 +1,44 @@ +package com.pool25m.logtime + +import org.bukkit.Bukkit +import org.bukkit.Statistic +import java.util.concurrent.TimeUnit + +data class PlayerRankData( + val playerName: String, + val playTicks: Long, + val formattedPlayTime: String, +) + +class PlayerStatsService { + /** + * サーバーにログインしたことのある全プレイヤーの総プレイ時間ランキングを取得する + */ + fun getPlayerRankings(): List { + return Bukkit + .getOfflinePlayers() + .map { player -> + val playTicks = player.getStatistic(Statistic.PLAY_ONE_MINUTE).toLong() + + PlayerRankData( + // OfflinePlayer の場合は name が null になる可能性がある + playerName = player.name ?: "Unknown Player", + playTicks = playTicks, + formattedPlayTime = formatPlayTimeFromTicks(playTicks), + ) + }.sortedByDescending { it.playTicks } // 正確な時間でソート + } + + private fun formatPlayTimeFromTicks(ticks: Long): String { + val millis = ticks * 50 // 1 tick = 50ms + val hours = TimeUnit.MILLISECONDS.toHours(millis) + val minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60 + val seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60 + + return buildString { + if (hours > 0) append("${hours}h ") + if (minutes > 0) append("${minutes}m ") + append("${seconds}s") + }.ifEmpty { "0s" } + } +} diff --git a/src/main/kotlin/com/pool25m/logtime/RankingCommand.kt b/src/main/kotlin/com/pool25m/logtime/RankingCommand.kt index b942fd7..10666a8 100644 --- a/src/main/kotlin/com/pool25m/logtime/RankingCommand.kt +++ b/src/main/kotlin/com/pool25m/logtime/RankingCommand.kt @@ -4,14 +4,27 @@ import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender -class RankingCommand : CommandExecutor { +class RankingCommand( + private val playerStatsService: PlayerStatsService, +) : CommandExecutor { override fun onCommand( sender: CommandSender, command: Command, label: String, args: Array, ): Boolean { - sender.sendMessage("LogTime plugin is working!") + val rankedList = playerStatsService.getPlayerRankings() + + if (rankedList.isEmpty()) { + sender.sendMessage("No players found.") + return true + } + + sender.sendMessage("--- 総プレイ時間ランキング ---") + rankedList.forEachIndexed { index, rankData -> + val rank = index + 1 + sender.sendMessage("$rank. ${rankData.playerName} - ${rankData.formattedPlayTime}") + } return true }