Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Docs

on:
push:
branches: [ main ]
paths:
- 'docsite/**'
- '.github/workflows/docs.yaml'
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ main ]
paths:
- 'docsite/**'
- '.github/workflows/docs.yaml'

permissions:
contents: read

concurrency:
group: ${{ github.event_name == 'pull_request' && format('docs-pr-{0}', github.event.pull_request.number) || 'pages' }}
cancel-in-progress: true

jobs:
build:
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false

runs-on: ubuntu-latest
defaults:
run:
working-directory: docsite
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Install pngquant
run: sudo apt-get update && sudo apt-get install -y pngquant

- name: Setup Python
uses: actions/setup-python@v6
with:
python-version-file: "docsite/pyproject.toml"

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- name: Install the project
run: uv sync --locked --all-extras --dev

- name: Build documentation
run: uv run zensical build -f zensical.toml --clean

- name: Upload artifact
if: github.event_name == 'push'
uses: actions/upload-pages-artifact@v4
with:
path: docsite/site

deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Setup Pages
uses: actions/configure-pages@v5

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
38 changes: 38 additions & 0 deletions .github/workflows/publish-preview.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Publish Preview

on:
workflow_dispatch:
push:
branches:
- main
paths-ignore:
- 'docs/**'
- 'docsite/**'
- 'README.md'

permissions:
contents: write
pull-requests: write

jobs:
build:
uses: LayeredCraft/devops-templates/.github/workflows/publish-preview.yml@v10.1
with:
solution: SharpMud.slnx
dotnetVersion: |
10.0.x
11.0.x
hasTests: true
prereleaseIdentifier: alpha
secrets: inherit

push:
needs: build
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: LayeredCraft/devops-templates/.github/actions/nuget-push@v10.1
with:
nuget_user: ${{ secrets.NUGET_USER }}
30 changes: 30 additions & 0 deletions .github/workflows/publish-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Publish Release

on:
release:
types: [published]

permissions:
contents: write

jobs:
build:
uses: LayeredCraft/devops-templates/.github/workflows/publish-release.yml@v10.1
with:
solution: SharpMud.slnx
dotnetVersion: |
10.0.x
11.0.x
hasTests: true
secrets: inherit

push:
needs: build
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: LayeredCraft/devops-templates/.github/actions/nuget-push@v10.1
with:
nuget_user: ${{ secrets.NUGET_USER }}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -495,3 +495,7 @@ sharpmud.db
sharpmud.db-wal
sharpmud.db-shm
sharpmud.db-journal

# docsite (Zensical/uv) build output and Python venv (uv.lock IS committed)
docsite/site/
docsite/.venv/
54 changes: 54 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<Project>
<PropertyGroup>
<!-- No VersionPrefix - release-drafter resolves the version from
conventional-commit PR titles, see
docs/adr/0006-nuget-package-distribution.md's Versioning and CI
section and .github/workflows/publish-preview.yaml/
publish-release.yaml. -->
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryUrl>https://github.com/LayeredCraft/sharp-mud</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Authors>Nick Cipollina</Authors>
<PackageProjectUrl>https://github.com/LayeredCraft/sharp-mud</PackageProjectUrl>
Comment thread
ncipollina marked this conversation as resolved.
<PackageIcon>icon.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!-- CS1591 (missing XML doc comment on a public member) is suppressed
repo-wide, not fixed here - documentation.md already tracks the
zero-XML-doc-comments gap as separate, open backfill work; turning
on GenerateDocumentationFile for packaging shouldn't silently turn
that into hundreds of build warnings as a side effect of this
change. New/substantially-changed public members still get real
doc comments per documentation.md - this only suppresses the
warning, it doesn't relax the convention. -->
<NoWarn>$(NoWarn);CS1591</NoWarn>
</PropertyGroup>

<PropertyGroup>
<DebugType>embedded</DebugType>
<NoPackageAnalysis>true</NoPackageAnalysis>
<LangVersion>latest</LangVersion>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
</PropertyGroup>

<!-- Samples/tests never get packed - only src/ packages are consumer-facing. -->
<PropertyGroup Condition="'$(IsTestProject)' == 'true'">
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup Condition="'$(IsPackable)' != 'false'">
<None Include="$(MSBuildThisFileDirectory)icon.png" Pack="true" PackagePath="" Visible="false" Condition="Exists('$(MSBuildThisFileDirectory)icon.png')" />
<None Include="$(MSBuildThisFileDirectory)README.md" Pack="true" PackagePath="" Visible="false" Condition="Exists('$(MSBuildThisFileDirectory)README.md')" />
</ItemGroup>

<ItemGroup Condition="'$(IsPackable)' != 'false'">
<PackageReference Include="Microsoft.SourceLink.GitHub">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
56 changes: 46 additions & 10 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,26 @@
<ItemGroup>
<!-- App -->
<PackageVersion Include="LayeredCraft.OptimizedEnums" Version="1.4.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.9" />
<!-- Pin past the transitive SQLitePCLRaw.lib.e_sqlite3 2.1.11 that
Microsoft.Data.Sqlite.Core 10.0.9 pulls in - flagged NU1903 high
severity (GHSA-2m69-gcr7-jv3q). -->
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="10.0.9" />
<PackageVersion Include="SQLitePCLRaw.lib.e_sqlite3" Version="3.53.3" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.9" />
<!-- SharpMud.Persistence.DynamoDb - pinned to the stable EF Core 10
build, not the net11.0 preview build, per ADR-0006. A net11.0
build does exist (11.0.1-preview.93), but as of this writing it
depends on Microsoft.EntityFrameworkCore 11.0.0-preview.5.26302.115
- one preview behind the preview.6 line pinned below - so taking
it now would mean this project alone downgrading off preview.6.
Revisit once the provider catches up. Persistence.DynamoDb only
ever targets net10.0, so this is never conditional on
TargetFramework the way the other EF Core/Microsoft.Extensions.*
packages below are. -->
<PackageVersion Include="EntityFrameworkCore.DynamoDb" Version="10.0.0" />
<!-- NuGet package metadata (Directory.Build.props). Build-time-only
tool, versioned in lockstep with the .NET SDK preview builds here -
pinned to match global.json's SDK pin, same as the
Microsoft.Extensions.*/EF Core net11.0 group below. -->
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="11.0.100-preview.6.26359.118" />
<!-- Logging: Serilog + LayeredCraft.StructuredLogging call-site extensions,
per .agents/skills/engineering-workflow/references/coding-standards.md.
Console sink only - this repo runs in Docker (docs/deployment.md),
Expand All @@ -24,27 +36,51 @@
<!-- Configuration: appsettings.json + env vars feeding Serilog.Settings.Configuration
and IOptions<T> - see ADR-0003 (docs/adr/0003-allow-appsettingsjson-for-non-secret-config.md). -->
<PackageVersion Include="Serilog.Settings.Configuration" Version="10.0.1" />
</ItemGroup>
<!-- Microsoft.Extensions.*/EF Core packages ship parallel net10.0 (stable)
and net11.0 (preview) build lines - pin each per-TargetFramework
rather than floating one version across both, matching
structured-logging's Directory.Packages.props shape. The net11.0
preview version is pinned to match global.json's SDK pin
(11.0.100-preview.6.26359.118) - bump both together. -->
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.10" />
<!-- SharpMud.Hosting's composition-root builder wraps this directly -
see docs/adr/0006-nuget-package-distribution.md. -->
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.10" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.9" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.9" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.9" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net11.0'">
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="11.0.0-preview.6.26359.118" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="11.0.0-preview.6.26359.118" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="11.0.0-preview.6.26359.118" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="11.0.0-preview.6.26359.118" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="11.0.0-preview.6.26359.118" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="11.0.0-preview.6.26359.118" />
</ItemGroup>
<ItemGroup>
<!-- Test Framework: xUnit v3 on Microsoft.Testing.Platform v2 (MTP v2), per docs/architecture.md.
Use xunit.v3.mtp-v2, not the plain xunit.v3 meta-package - the latter resolves
xunit.v3.core.mtp-v1, whose Microsoft.Testing.Platform version is incompatible with
a directly-referenced/newer Microsoft.Testing.Platform and throws TypeLoadException
(IDataConsumer) at test-host startup. -->
<PackageVersion Include="Microsoft.Testing.Platform" Version="2.3.1" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.7.0" />
<PackageVersion Include="Microsoft.Testing.Platform" Version="2.3.2" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.8.1" />
<PackageVersion Include="xunit.v3.mtp-v2" Version="3.2.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
<!-- AutoFixture -->
<PackageVersion Include="AutoFixture" Version="4.18.1" />
<PackageVersion Include="AutoFixture.Xunit3" Version="4.19.0" />
<PackageVersion Include="AutoFixture.AutoNSubstitute" Version="4.18.1" />
<!-- Mocking -->
<!-- Mocking. Pinned below NSubstitute 6.0.0 - AutoFixture.AutoNSubstitute
4.18.1 (the latest stable release) requires NSubstitute < 6.0.0;
only unreleased AutoFixture.AutoNSubstitute previews support
NSubstitute 6.x so far. Revisit once a stable release does. -->
<PackageVersion Include="NSubstitute" Version="5.3.0" />
<!-- Assertions -->
<PackageVersion Include="AwesomeAssertions" Version="9.4.0" />
<PackageVersion Include="AwesomeAssertions" Version="9.5.0" />
</ItemGroup>
</Project>
18 changes: 10 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
# Multi-stage build. Pinned to the same .NET 11 preview SDK/runtime version
# as global.json - see docs/architecture.md Open Items for the fallback-to-
# .NET-10-LTS plan if preview tooling support lags.
FROM mcr.microsoft.com/dotnet/sdk:11.0.100-preview.5 AS build
FROM mcr.microsoft.com/dotnet/sdk:11.0.100-preview.6 AS build
WORKDIR /src

COPY Directory.Packages.props global.json ./
COPY Directory.Build.props Directory.Packages.props global.json ./
COPY src/SharpMud.Engine/SharpMud.Engine.csproj src/SharpMud.Engine/
COPY src/SharpMud.Ruleset.Classic/SharpMud.Ruleset.Classic.csproj src/SharpMud.Ruleset.Classic/
COPY src/SharpMud.Hosting/SharpMud.Hosting.csproj src/SharpMud.Hosting/
COPY src/SharpMud.Persistence/SharpMud.Persistence.csproj src/SharpMud.Persistence/
COPY src/SharpMud.Persistence.Sqlite/SharpMud.Persistence.Sqlite.csproj src/SharpMud.Persistence.Sqlite/
COPY src/SharpMud.Adapters.Cli/SharpMud.Adapters.Cli.csproj src/SharpMud.Adapters.Cli/
COPY src/SharpMud.Adapters.Telnet/SharpMud.Adapters.Telnet.csproj src/SharpMud.Adapters.Telnet/
COPY src/SharpMud.Host/SharpMud.Host.csproj src/SharpMud.Host/
RUN dotnet restore src/SharpMud.Host/SharpMud.Host.csproj
COPY samples/SharpMud.Samples.Classic/SharpMud.Samples.Classic.csproj samples/SharpMud.Samples.Classic/
RUN dotnet restore samples/SharpMud.Samples.Classic/SharpMud.Samples.Classic.csproj

COPY src/ src/
RUN dotnet publish src/SharpMud.Host/SharpMud.Host.csproj -c Release -o /app --no-restore
COPY samples/ samples/
RUN dotnet publish samples/SharpMud.Samples.Classic/SharpMud.Samples.Classic.csproj -c Release -o /app --no-restore

FROM mcr.microsoft.com/dotnet/runtime:11.0.0-preview.5-alpine3.24 AS runtime
FROM mcr.microsoft.com/dotnet/runtime:11.0.0-preview.6-alpine3.24 AS runtime
WORKDIR /app
COPY --from=build /app .

Expand All @@ -40,4 +42,4 @@ VOLUME /data
# needing the larger -extra image just for culture data we don't use.
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true

ENTRYPOINT ["dotnet", "SharpMud.Host.dll"]
ENTRYPOINT ["dotnet", "SharpMud.Samples.Classic.dll"]
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 LayeredCraft

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
21 changes: 21 additions & 0 deletions NOTICE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Notice

sharp-mud is licensed under the [MIT License](LICENSE).

## Design inspiration

sharp-mud's engine design (the `Thing`/`Behavior` composition model, the
generic event system, session/transport abstractions, and several other
architectural decisions) is informed by a close reading of
[WheelMUD](https://github.com/DavidRieman/WheelMUD)'s source code and
architecture. See [docs/research/wheelmud-findings.md](docs/research/wheelmud-findings.md)
for the full source-dive record of what was adopted, what was deliberately
changed, and why.

sharp-mud is a clean-room reimplementation, not a fork or derivative of
WheelMUD's source — no WheelMUD code is included in this repository.
WheelMUD itself is licensed under the
[Microsoft Public License (MS-PL)](https://github.com/DavidRieman/WheelMUD/blob/main/src/LICENSE.txt),
which does not apply to sharp-mud's own, independently-written code (see
[ADR-0006](docs/adr/0006-nuget-package-distribution.md)'s License and
naming section for the full reasoning).
Loading