Skip to content

Repository files navigation

PRE-ALPHA NO RELEASE

Smithy

Smithy

Open-source mapping tools for Source SDK-family games, and eventually a level editor to replace Hammer++.

Built in the order that makes each step independently useful:

  1. Standalone tools: texture browser, VMT editor, RAD generator, compile GUI. These replace nem's unmaintained tools.
  2. Clean libraries underneath them: VMF, VTF/VMT, FGD, MDL, filesystem.
  3. A viewport.
  4. An editor.

Each step is usable on its own.

Status

Early. What works today:

Piece State
smithy-browser Texture browser. Mounts VPKs, indexes ~70k materials from a stock CS:S install, decodes VTF thumbnails, shows VMT source and which mount each material came from.
smithy Editor shell. Game detection, VMF load/save with lossless round-trip, wireframe viewport, compile-plan preview. Not an editor yet.
Game detection Reads gameinfo.txt, resolves the real mount order, matches a profile by AppID, and shows every inference it made.
Compile driver Plans vbsp/vvis/vrad invocations from profile data. Does not run them yet.
Brush geometry Plane clipping to real polygons, primitives (block, wedge, cylinder, spike, sphere, arch, torus, stairs), split, convex hull, ray picking, lossless VMF round-trip.
Scripting Embedded Python 3 with a smithy module, plus a plugin system: a plugin is a folder with a plugin.json, and it can register menu commands.

Not started: VMT editor, RAD generator, compile GUI, selection, displacements.

Design

Smithy never writes a BSP

Every game's own vbsp/vvis/vrad does that. This is what Hammer, Hammer++, and CompilePal all do, and it is correct: BSP v19 vs v20 vs v21 vs Strata's v25 is not Smithy's problem. The deliverable is a correct VMF plus a correct compile invocation.

Multi-game is data, not code

Five interfaces separate everything branch-specific from everything else:

Seam Header Backed by
Filesystem game/ifilesystem.h loose dirs + vpkpp
Entity schema (FGD) game/ientityschema.h toolpp
Shader schema (VMT) game/ishaderschema.h per-profile data (not yet written)
Model loader game/imodelloader.h mdlpp (not yet wired)
Compile driver game/icompiledriver.h SourceCompileDriver

A game is a JSON profile: FGD list, asset version ranges, shader schema, compile steps, engine limits. Someone who mains TF2 will write and test a TF2 profile if the price is a file instead of a fork.

Scope: Source SDK 2006/2007/2013: HL2, CS:S, TF2, L4D1/2, Portal 1/2, Black Mesa, Garry's Mod. Dark Messiah, Bloodlines, and Titanfall diverged into separate engines wearing a Source badge. Strata is a second engine: reachable through the seams, not on the roadmap.

Third-party libraries, not reimplementations

sourcepp already maintains the binary formats that are expensive per branch: vtfpp (VTF 7.0–7.6), vpkpp (VPK/BSP-pak/ZIP/WAD mounts), mdlpp (MDL 44–49 with VVD/VTX), toolpp (FGD), steampp (Steam library discovery). Smithy adapts them to its seams.

Smithy keeps its own KeyValues and VMF implementation. It has to round-trip unknown blocks, duplicate sibling keys and file order losslessly so that maps can be shared with Hammer, which is a stricter contract than a general-purpose KV1 reader offers. A dispinfo block Smithy does not model yet still survives a load/save cycle byte-for-byte.

Open source all the way down

Hammer++ and its ++ compile tools are closed source and Windows-only. Smithy invokes whatever compilers a user already has, but it bundles none of them, and it ships no extracted art: its icons are drawn in code. Reading a closed tool closely enough to write an open one is fine; redistributing its files is not. See assets/icons/NOTICE.md and the roadmap.

No game configuration wizard

gameinfo.txt already declares the mount order and the Steam AppID. Point Smithy at a game folder and it reads what the engine already knows, then shows its work: every resolved path, every missing one, which profile matched, which compile tools it found. Hammer's game-config dialog asks for all of this by hand.

Scripting

Smithy embeds Python 3, in the spirit of Blender's API: the editor exposes its own operations, so repetitive work can be scripted.

import smithy

smithy.add_block((0, 0, 0), (512, 512, 16), "DEV/DEV_MEASUREGENERIC01B")
smithy.add_primitive("arch", (-256, -256, 0), (256, 256, 128), sides=12, arc=180.0)
smithy.add_entity("info_player_terrorist", (64, 64, 32))

def build():
    smithy.log(f"{len(smithy.entities())} entities")

smithy.register_operator("mine.build", "Build Thing", build, menu="Plugins/Mine")

A plugin is a directory with a plugin.json and an entry point; drop it in the plugin folder and enable it in Plugins → Plugin Manager. plugins/surf_ramp_helper is a worked example. There is a Python console under the same menu.

Building

Requires Qt 6.11, CMake 3.24+, a C++20 compiler, and Python 3.10+ development headers (python3-devel). sourcepp is fetched at configure time.

cmake --preset release
cmake --build build/release
ctest --test-dir build/release

Binaries land in build/release/bin/.

Trying it headlessly

# What does Smithy infer about an install?
./build/release/bin/smithy --detect ~/.steam/steam/steamapps/common/Counter-Strike\ Source

# Mount it and index every material.
./build/release/bin/smithy-browser --index --game <same path>

Layout

src/core      math, Result/Error, logging
src/io        KeyValues (KV1) and VMF: lossless round-trip
src/geom      brush geometry: half-spaces in, polygons out
src/script    embedded Python and the plugin system
src/game      the five seams, game profiles, gameinfo detection, mounting
src/assets    Qt boundary over sourcepp's asset loaders
src/render    OpenGL 4.6 viewport
src/tools     standalone tools (shared toolkit + browser)
src/editor    the editor shell
profiles/     game profiles, one per branch

About

Smithy is an open-source VMF (Valve Map Format) level editor

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages