diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 0221d03..5c24893 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -1,4 +1,4 @@ -name: Build VS Mod +name: Build & Release on: push: @@ -12,13 +12,21 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Build and package mod + - name: Install Docker CLI + run: | + apt-get update -qq && apt-get install -y -qq ca-certificates curl >/dev/null + install -m 0755 -d /etc/apt/keyrings + curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc + echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list + apt-get update -qq && apt-get install -y -qq docker-ce-cli >/dev/null + + - name: Build mod run: | VERSION=$(grep -oPm1 '"version":\s*"\K[^"]+' resources/modinfo.json) MODID="welcomescreen" - OUTPUT="${MODID}_${VERSION}.zip" + echo "Building ${MODID} v${VERSION}..." - # Build inside .NET SDK container using docker cp (DinD — bind mounts don't work) + # DinD: bind mounts don't work — use docker cp with a volume docker volume create mod-build docker pull alpine:3 >/dev/null 2>&1 HELPER=$(docker create -v mod-build:/src alpine:3 true) @@ -28,50 +36,50 @@ jobs: docker run --rm -v mod-build:/src -w /src mcr.microsoft.com/dotnet/sdk:8.0 \ dotnet build -c Release - # Extract artifacts from volume + # Extract build output from volume HELPER=$(docker create -v mod-build:/src alpine:3 true) docker cp $HELPER:/src/bin/Release/WelcomeScreen.dll ./WelcomeScreen.dll docker rm $HELPER >/dev/null docker volume rm mod-build >/dev/null - # Package ZIP + # Package mod ZIP mkdir -p dist cp WelcomeScreen.dll dist/ cp resources/modinfo.json dist/ - cd dist && zip -j "../${OUTPUT}" WelcomeScreen.dll modinfo.json + cd dist && zip -j "../${MODID}_${VERSION}.zip" WelcomeScreen.dll modinfo.json cd .. - echo "MOD_ZIP=${OUTPUT}" >> $GITHUB_ENV + echo "MOD_ZIP=${MODID}_${VERSION}.zip" >> $GITHUB_ENV echo "MOD_VERSION=${VERSION}" >> $GITHUB_ENV - echo "Built ${OUTPUT}" + echo "Built: ${MODID}_${VERSION}.zip" - name: Create release if: startsWith(github.ref, 'refs/tags/v') run: | TAG="${GITHUB_REF#refs/tags/}" - # Generate a temporary token for the API call - TOKEN=$(docker exec gitea gitea admin user generate-access-token \ - --user git --username calic --scopes write 2>&1 | grep -oPm1 '(?<=: ).*') + TOKEN_NAME="ci-release-$$" - # Create release with artifact + # Generate temporary Gitea API token + # --user git = container OS user; -u calic = Gitea account + TOKEN=$(docker exec --user git gitea gitea admin user generate-access-token \ + -u calic -t "$TOKEN_NAME" --scopes all --raw 2>/dev/null) + + # Create release RELEASE_ID=$(curl -sf \ -H "Authorization: token ${TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"tag_name\":\"${TAG}\",\"name\":\"Welcome Screen ${MOD_VERSION}\",\"body\":\"Release ${MOD_VERSION}\"}" \ - "http://gitea:3000/api/v1/repos/calic/vs-welcome-screen/releases" | grep -oPm1 '"id":\K[0-9]+') + "http://gitea:3000/api/v1/repos/calic/vs-welcome-screen/releases" \ + | grep -oPm1 '"id":\K[0-9]+') - # Upload artifact + # Attach mod ZIP to release curl -sf \ -H "Authorization: token ${TOKEN}" \ -F "attachment=@${MOD_ZIP}" \ "http://gitea:3000/api/v1/repos/calic/vs-welcome-screen/releases/${RELEASE_ID}/assets" - # Clean up token - TOKEN_ID=$(curl -sf \ - -H "Authorization: token ${TOKEN}" \ - "http://gitea:3000/api/v1/users/calic/tokens" | grep -oPm1 '"id":\K[0-9]+') - curl -sf -X DELETE \ - -H "Authorization: token ${TOKEN}" \ - "http://gitea:3000/api/v1/users/calic/tokens/${TOKEN_ID}" + echo "Release ${TAG} created with ${MOD_ZIP}" - echo "Release ${TAG} created with artifact ${MOD_ZIP}" + # Clean up token + curl -sf -X DELETE -u "calic:${TOKEN}" \ + "http://gitea:3000/api/v1/users/calic/tokens/${TOKEN_NAME}" >/dev/null 2>&1 || true diff --git a/.gitignore b/.gitignore index 2789d71..f6b4108 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ bin/ obj/ +dist/ *.user *.suo .vs/ +*.zip diff --git a/README.md b/README.md new file mode 100644 index 0000000..10d0ffc --- /dev/null +++ b/README.md @@ -0,0 +1,97 @@ +# Welcome Screen — Vintage Story Mod + +Server-side configurable welcome dialog that opens automatically when players join. Displays Markdown content rendered as VTML (Vintage Text Markup Language) in a scrollable GUI window. + +## Features + +- **Auto-open on join** — dialog appears when a player connects +- **Markdown content** — write `welcome.md` in the server data directory, rendered as rich text (headings, bold, italic, links, lists, blockquotes, code) +- **Mod checker** — server compares client's installed mods against a recommended/blacklisted list and shows the result in the dialog +- **Reopen with HOME** — players can press HOME to reopen the dialog at any time + +## Installation + +Download the latest `welcomescreen_x.x.x.zip` from [Releases](../../releases) and place it in your server's `Mods/` directory. Do **not** extract the ZIP. + +This is a **universal** mod — it must be installed on both server and client. + +## Configuration + +All config files are auto-generated on first run in the server's `ModConfig/` directory. + +### `WelcomeScreenConfig.json` + +```json +{ + "Title": "Welcome", + "WelcomeFile": "welcome.md" +} +``` + +- `Title` — dialog window title +- `WelcomeFile` — path to the Markdown file (relative to server data dir) + +### `WelcomeScreenModCheck.json` + +```json +{ + "Enabled": true, + "RecommendedMods": [ + { "ModId": "rpvoicechat", "DisplayName": "RPVoiceChat", "Reason": "Proximity voice chat" } + ], + "BlacklistedMods": [] +} +``` + +- `RecommendedMods` — mods the server suggests clients should have +- `BlacklistedMods` — mods the server disallows (shown as warning) + +### `welcome.md` + +Place this file in the server's data directory. Standard Markdown syntax is supported: + +```markdown +# Server Name + +Welcome to our server! + +## Rules +1. Be respectful +2. No griefing + +**Have fun!** +``` + +## Building + +Requires .NET 8 SDK and the Vintage Story API DLLs in `lib/`. + +```bash +# Build locally +./build.sh + +# Build and install to server +./build.sh --install +``` + +## Project Structure + +``` +src/ + WelcomeScreenMod.cs Main mod — server/client logic, network packets, config + WelcomeScreenDialog.cs GUI dialog with scrollable VTML content + MarkdownToVtml.cs Markdown → VTML converter +resources/ + modinfo.json Mod metadata (version, dependencies) +lib/ + VintagestoryAPI.dll VS API reference (not distributed) + protobuf-net.dll Protobuf serialization (not distributed) +``` + +## CI/CD + +Push a tag (`v*`) to trigger the build pipeline, which compiles the mod, packages the ZIP, and creates a Gitea release with the artifact attached. + +## License + +Private mod — not publicly distributed.