プレイヤーがゲームサーバを動的に作成・管理できる Minecraft サーバーネットワーク。Velocity プロキシ + Ktor 製 Manager API + Paper サーバ群を docker-compose で統合し、Web ダッシュボードでプレイヤーが自分の統計やサーバを管理できる。
- 動的サーバ作成 — プレイヤーが
/dango createで自分専用の Minecraft サーバを Docker コンテナとして起動 - アクセス制御 — PRIVATE / PUBLIC / PASSWORD のアクセスモード、メンバー招待・権限管理
- 経済システム — 残高・送金・取引履歴、ショップ(チェスト GUI)
- 統計 + レベル — ブロック採掘/設置・モブ討伐・プレイ時間を計測し、5 種の専門レベルにリアルタイム反映
- ランクシステム — 5 段階のランクでサーバ作成上限が変動、ランクアップ購入可能
- Web ダッシュボード — 公開ページ(サーバ一覧、リーダーボード) + 認証付きマイページ
- AutoStop — 10 分以上アイドルの動的サーバを自動停止
Minecraftクライアント
│
▼
Velocity プロキシ (velocity-plugin) ──HTTP REST──▶ Manager (Ktor API)
│ │ │
├─ lobby(静的サーバー) ▼ ▼
├─ master(静的サーバー) PostgreSQL Docker デーモン
└─ mc-xxx(動的サーバー、paper-plugin入り) │
│ ▼
└──HTTP REST(30秒バッチ)──▶ Manager 動的サーバーコンテナ生成
- Docker + Docker Compose v2(Linux / macOS / WSL2)
- ホストに Java や Gradle は不要(
builderコンテナが JAR を自動ビルド)
# 1. リポジトリを取得
git clone https://github.com/aida0710/dango.git
cd dango
# 2. 環境変数を設定
cp .env.sample .env
$EDITOR .env # change-me を全て書き換える
# 3. lobby ワールドを配置 (下節「lobby ワールドの追加方法」を参照)
# 4. 起動
./setup.sh任意のプラグインを
docker/plugins/に配置すると動的サーバで利用可能になります(下節「プラグインの追加」を参照)。
起動後:
| サービス | URL |
|---|---|
| Minecraft プロキシ | localhost:25565 |
| Manager API | http://localhost:3015 |
| Web ダッシュボード | http://localhost:3016 |
world/lobby/ 配下に Minecraft の通常ワールドファイル(level.dat、region/、playerdata/ 等)を配置します。lobby サービスは起動時にここからワールドをコピーして展開します。
配置例:
world/lobby/
├── level.dat
├── level.dat_old
├── region/
│ ├── r.0.0.mca
│ └── ...
├── data/
└── playerdata/
シングルプレイで作ったワールドや別サーバから持ってきたワールドをそのまま world/lobby/ にコピー。
vanilla や Paper サーバを単独で起動して lobby 用のワールドを生成 → 生成されたワールドディレクトリ(level.dat を含む)を world/lobby/ にコピー。
NOTE:
world/は.gitignoreで除外されているため、各自のワールドはコミットされません。
docker/plugins/ に JAR を配置すると、動的サーバ起動時に読み込まれます。必須ではありません。
代表例として、docker/plugins/worldedit-bukkit-*.jar を配置すると、クリエイティブモードで作成された動的サーバで WorldEdit が自動的に利用可能になります(WorldEdit は EngineHub のサイトから取得してください)。
Gradle マルチモジュール。
| モジュール | 役割 |
|---|---|
common/ |
manager / velocity-plugin / paper-plugin で共有する DTO・enum |
manager/ |
ビジネスロジック・Ktor REST API・Docker 制御・PostgreSQL 永続化 |
velocity-plugin/ |
Velocity プロキシ用シンクライアント。コマンドを Manager API に委譲 |
paper-plugin/ |
動的サーバ用シンクライアント。プレイイベントを 30 秒バッチで Manager に送信 |
web/ |
Web ダッシュボード(React + Vite + shadcn/ui) |
| コマンド | エイリアス | 説明 |
|---|---|---|
/dango <subcmd> |
サーバ管理(create / join / list / invite / settings / web 等) | |
/lobby |
/hub |
ロビーサーバへ移動 |
/balance |
/bal |
残高確認 |
/pay <player> <amount> |
送金 | |
/rank / /rankup |
ランク確認 / ランクアップ購入 | |
/title [<title>|clear] |
カスタム称号(1000 通貨/変更) |
/dango サブコマンド: list, create, join, stop, delete, info, invite, kick, invitations, accept, decline, settings, members, web。
ゲーム内 /dango web → 6 桁コード発行 → Web に入力 → JWT 発行(24 時間有効)。
.env で定義(.env.sample を参照)。
| 変数 | 説明 |
|---|---|
POSTGRES_USER |
PostgreSQL ユーザー名 |
DANGO_POSTGRES_DB |
データベース名 |
DANGO_POSTGRES_PASSWORD |
DB パスワード |
DANGO_JWT_SECRET |
Web 認証 JWT 署名鍵 |
VELOCITY_SECRET |
Velocity Modern Forwarding 共有シークレット |
INTERNAL_API_KEY |
plugin → manager 内部 API キー |
OPS |
OP プレイヤー名(カンマ区切り) |
WHITELIST |
ホワイトリスト(カンマ区切り) |
ENFORCE_WHITELIST |
TRUE で whitelist を強制 |
ランダムシークレット生成例:
openssl rand -base64 48./gradlew build # 全モジュールビルド + テスト
./gradlew build -x test # テストなし
./gradlew :manager:test # 単一モジュールのテスト
./gradlew ktlintCheck # コードスタイルチェック
./gradlew ktlintFormat # 自動フォーマット
./gradlew detekt # 静的解析cd web
npm install
npm run dev # http://localhost:5173 (API は localhost:3015 にプロキシ)ソース更新後の再デプロイ:
git pull
./deploy.shdeploy.sh の動作:
- 動的サーバ(
mc-*)を停止 docker compose downdocker compose up -d --build(JAR を再ビルド)
- 言語: Kotlin 2.3.0 (JVM 21)
- API: Ktor 3.4.0
- シリアライズ: kotlinx.serialization
- DB: Exposed 1.0.0 + PostgreSQL 16 + HikariCP
- Docker 制御: docker-java 3.7.0
- Minecraft: Velocity API 3.5.0-SNAPSHOT, Paper API 1.21.4
- Web: React 19, Vite, TypeScript, shadcn/ui, Tailwind CSS v4, React Router v7, TanStack Query v5
- テスト: kotlin-test, MockK, H2
MIT License © 2026 aida0710