Take a 3D model from Blender to the Paralives Build Mode catalogue, in two clicks.
ParaForge is a Blender add-on for Paralives.
It checks a mesh against every rule the game imposes, fixes what can be fixed,
rebuilds the textures into the maps the game actually reads, writes the FBX and
its PNGs straight into a .mod folder, and then declares the item in the Build
Mode catalogue.
The game never has to be running, and no file inside the installation is ever touched.
Interface in French by default, English on request, switchable from the panel header.
Blender 4.2 or newer. Developed and tested against Blender 5.2 LTS.
Tip
Complementary Modding Tool: Pair ParaForge with ParaReload, an in-game BepInEx plugin for Paralives that hot-reloads modified 3D models, textures, and settings live without restarting the game. Save in Blender with ParaForge, and see your asset update instantly in-game!
Note
Extracting from The Sims: sims-package2glb reads The Sims 2, 3 and 4 .package mods and writes the models and textures out as glTF.
ParaForge panel in Blender 5.2 showing automated checklist validation, asset rules, and export tools.
Exported custom 3D asset placed live in Paralives Build Mode alongside hot-reloading console commands.
- Screenshots
- Why this exists
- Install
- Use it
- What the checklist verifies
- Colour zones, three ways in
- Textures, and the naming that configures them
- A downloaded GLB, converted on its own
- Writing the item without the Control Panel
- What the wiki does not say, and the game does
- Undo, and safety
- Calibration
- Limits
- Build from source
- Tests
- Project layout
- Credits and licence
Paralives ships a real modding toolkit inside the game, and it works. What it
does not do is stop you from getting the mesh wrong. The official path is:
export from Blender, drop the files in a mod folder, restart the game, open the
Control Panel, create an Item, create a Prefab, add an ItemMeshReference, pick
the mesh, fit the bounding box, assign a surface, tag it, pick a swatch group,
then find out whether the orientation, the scale, the origin and the texture
roles were right.
Every mistake costs a full game restart, because the game imports its assets at launch and has no hot reload.
ParaForge moves the whole verification into Blender, where a mistake costs nothing, and then writes the catalogue entry itself so the Control Panel pass disappears.
Download paraforge-x.y.z.zip from the Releases page,
then in Blender:
Edit > Preferences > Get Extensions > Install from Disk, and pick the zip.
The panel appears in the 3D viewport sidebar, tab ParaForge. Press N to
open the sidebar.
- Pick the target mod, or create one with the
+next to the selector. Mods live in%USERPROFILE%\AppData\LocalLow\Paralives\Paralives\. AvoidLocal.mod: it is the game's own scratch folder, fine for a quick try, but it cannot be published to the Workshop. - Select the mesh. The checklist appears in the panel and as an overlay in the viewport.
- Fix everything safe sorts out unit scale, transforms, origin, the colour attribute and the texture roles.
- Check the orientation against the green arrow, then confirm. This is the one thing no tool can work out for you.
- 1. Export to Paralives writes the mesh and the textures.
- 2. Create the item in the catalogue declares the item.
Both steps are needed. Without the second, the files sit in the mod and nothing appears in Build Mode.
Then restart Paralives. There is no hot reload.
Each line is green, orange or red, with the reason, and a button that fixes it where a fix exists.
| Check | What it means |
|---|---|
| Scene unit scale | Paralives works in metres at scale 1.0 |
| Transforms applied | Rotation and scale baked, or the item arrives wrong |
| Origin placement | Per item type, see below |
| Bounding size | Sanity check against the tile size |
| Faces Y+ | Manual, compared with the arrow drawn in the viewport |
| Colour zones | Legal zone colours only, four maximum |
| UV map | Present, and UV2 reported when it is there |
| Texture coordinates | A Mapping node is baked into the exported UVs, since an FBX cannot carry one |
| Triangle count | Against your own budget, with a decimate button |
| N-gons | They triangulate on export and can shade badly |
| Texture naming | Every image classified into a role the game knows |
| Texture size | Nothing in the game is above 2K |
| Target mod folder | Exists, ends in .mod, and is not inside the game |
Origin rules, from the wiki:
| Item type | Rule |
|---|---|
| Floor item | Centred in X and Y, base at Z=0 |
| Wall item | Centred in X and Z, back at Y=0 |
| Window or door | Centred on all three axes |
Paralives reads up to four recolourable zones from vertex colours, plus yellow for decals. Painting them by hand is slow, and an asset that arrives from a marketplace or a generator has none at all.
- Select faces, click a zone. The obvious one, with coloured buttons.
- One material per zone. Most imported assets already split that way, so the slots map straight onto zones.
- Pick a colour off the model, then grow it by tolerance. This is the one that rescues an asset whose only texture is a single bake. The picker samples the texture through a raycast rather than reading screen pixels, so viewport lighting never shifts the result, and the tolerance slider is live in the redo panel.
The legal colours are exact, and nothing else is read by the game:
| Zone | Colour |
|---|---|
| 0 | white 1, 1, 1 |
| 1 | red 1, 0, 0 |
| 2 | green 0, 1, 0 |
| 3 | blue 0, 0, 1 |
| Decal | yellow 1, 1, 0, never recolourable |
The suffix on the file name is what makes the game assign the right import settings. Getting it right removes a manual configuration pass per texture, which is the single largest saving in the whole pipeline.
| Suffix | Content | Note |
|---|---|---|
GrayMask |
Recolourable base, 50 percent gray is the neutral tone | sRGB |
Detail |
Free colour, not recolourable | one per item |
NormalOcclusion |
Normal map in RGB, occlusion in the alpha | data |
Smoothness |
White is glossy, black is matte | data |
ColorZone |
Zone map, for meshes that cannot carry vertex colours | data |
Master |
Walls and floors: R GrayMask, G variant, B hue shift | sRGB |
ParaForge also writes the .meta sidecar next to each asset, carrying its GUID
and its import flags, which makes the import deterministic instead of depending
on the game parsing the file name.
A model taken off the web never arrives in the right shape. glTF gives you
roughness where the game wants smoothness, packs occlusion into the red
channel of an ORM texture, and gltfpack strips image names so Blender calls
them Image_0, Image_1, Image_2.
ParaForge identifies each image from three sources of evidence, most reliable first:
- the shader graph, meaning what the image is actually wired to. That is a fact rather than a guess, and it is the only clue left when the names are gone;
- the file name:
_Diffuse,-ORM,_Normal,_BaseColor; - the pixels: a normal map is recognisable, and a texture with no colour is never an albedo.
Then it rebuilds:
baseColor -> Detail (exact copy) or GrayMask (desaturated, recentred on 50%)
normal + occlusion -> NormalOcclusion (RGB + alpha)
roughness -> Smoothness (1 - roughness)
metallic -> no channel, folded into smoothness
emissive -> no channel, folded back into the colour
Nothing is invented. An image that nothing identifies stays marked unknown and is not written, rather than putting the wrong map into someone's mod.
Paralives gives one surface per mesh. An asset split across five materials therefore does not import as it is. Merge into one surface repacks the UVs of the whole selection into an atlas, bakes every channel, and replaces the materials with one. The look is preserved, the UVs are not.
A Paralives item is three pieces of plain text, all inside your own mod:
<Mod>/<Name>.prefab the object tree, its size, its mesh
<Mod>/Settings/Items.setting the catalogue entry and its tag
<Mod>/Settings/Translations.setting the label the player reads
A mod carries only what it adds and the game merges everything: the game's own
French translation mod contains nothing but a Translations.setting. That is
why no game file is ever modified.
Merging is done on the text rather than by rebuilding the file from a parsed
model. An Items.setting written by the game may hold fields this add-on has
never heard of, and re-serialising it would drop them in silence.
Paralives ships its own content as a mod: Main.mod, in the installation
folder, is an ordinary folder of FBX, PNG and text. Every number below was
measured there, not assumed. This section is the part of the project most
likely to be useful to other tools.
The game multiplies the raw vertex coordinates of an FBX by 0.01. It ignores both the file's unit declaration and any scaling on the node, so a mesh authored in metres arrives a hundred times too small: present, correctly placed, with the right footprint, and far too small to see.
Read out of the .import files, which are what the game made of each FBX:
| Mesh | Size in its prefab | Coordinates in the import |
|---|---|---|
CityGravelPile |
4.4642 m | around 2.24 |
| Cereal box | around 0.3 m | around 0.15 |
| An early ParaForge export | 1.9086 m | around 0.0088 |
No Blender export option produces this, because Blender puts the factor on the node. ParaForge scales the geometry on a throwaway copy instead.
Same cause. Blender writes its axis conversion as a rotation on the node, and the game ignores the node, so the mesh arrives Z up in a Y up world, lying on its back. Importing with the conversion switched off shows the files as they are:
CityGravelPile.fbx base sits on Y=0 node rotation 180 deg about Z
Barbecue.fbx base sits on Y=0 node rotation 180 deg about Z
an early export base sits on Z=0 node rotation 90 deg about X
ParaForge bakes the rotation into the geometry too, and then tells the exporter to convert nothing.
This one is worth knowing for anyone writing .setting files by hand.
A collection can be written three ways, and the marker decides what the game does with the base game's own entries:
| Marker | Meaning |
|---|---|
i<index> |
Positional. Authoring a collection from scratch. Used by a mod on a list the base game also fills, it drops the base collection and keeps only what the mod wrote |
@<GUID> |
Add a new member to a list the base game already fills. What a content mod wants |
g<GUID> |
Merge fields onto a member that already exists |
The symptom of getting this wrong is spectacular and misleading: a
Translations.setting with one entry wipes the entire translation table, and
every menu label in the game turns into a raw key such as
UIBuildModeCatalog_XCancel.
Verified in the game's own data: French.mod extends Translations.Items
using g<GUID> markers with no s<N> size line, and never uses
i<index>. Credit to paralives-modgen
for documenting the @<GUID> form first.
The game does not give each item its own surface. Surfaces are a shared
material library: 397 of the 2434 shipped prefabs point at GenericGrayMask,
and 370 of those lay their own texture over it through DetailMap. Of the 486
DetailMap textures, 344 are used by exactly one prefab and live next to their
mesh, so it really is the per item slot.
That is one of the two shapes ParaForge writes, copied from
CityGravelPile.prefab:
ItemMeshReference:
Surfaces:
Surface:
GUID:4303346223996877069 identity of this list entry
Value:6533686579680309849 GenericGrayMask
DetailMap:4868737352193020236 the item's own texture
The other shape gives the item a surface of its own, which is the only place a
normal map and a smoothness value can live. No prefab field anywhere mentions
smoothness, metallic or occlusion, checked across 300 prefabs, so an item
borrowing a shared surface has no relief at all. The entry is modelled on
TextileQuiltedSquares, one of the 75 shipped surfaces carrying a real normal
map:
#Setting.Surfaces
=AllSurfaces
@2693213273477870343
=DisplayName:Stool
=Texture:4272001606441780869 the game's neutral gray base
=NormalAndAmbientOcclusionMap:... the item's relief
=AmbientOcclusionStrength:1
=SmoothnessValue:0.42
=DefaultSwatchGroup:0
=DefaultSwatch:0
Note that the item's colour is not in there. A surface's Texture is the
base the shader tints, and across the game's 925 references it is a GrayMask
634 times, a Master 100 times, and a Detail 133 times, the last almost always
under a vegetation or special shader. The colour of an ordinary item arrives
through DetailMap on the prefab, over that base. Putting the colour in
Texture and dropping DetailMap renders the item white.
Note the @ marker and the absent size line. Writing this positionally is what
made the game throw NullReferenceException in SurfaceThumbnailManager.Start()
at every launch: the mod was not adding a surface, it was replacing all 950 of
them with one.
There is no slot for a smoothness texture anywhere, only a single
SmoothnessValue per surface, used by 329 of the shipped ones. A Smoothness map
is therefore averaged into that number on export.
The game reads the presence of a colour attribute, not its contents. Any
attribute at all makes the mesh ZoneDefinition:VertexZones and demands a
recolourable shader that a plain surface cannot provide:
Material builder got given parameters that don't match any shaders -
ShaderType:Simple ZoneDefinition:VertexZones ...
The item then loads, takes its footprint, and draws nothing. Exporting a single
white zone is therefore not neutral, it is what makes the item invisible. The
game's own meshes confirm it: CityGravelPile.fbx and
ClutterKitchenIngredientCereal.fbx carry no colour attribute at all.
ParaForge only exports them when the item really is recolourable.
Triangle budget. 159 meshes taken at random from Environments/Items and
imported into Blender: median 294 triangles, 90th percentile 1 380, maximum
4 060. That maximum is ParaForge's default budget. A downloaded asset at
560 000 triangles is a hundred times the largest object in the game.
Texture resolution. Across 1 446 item textures: 512 px leads, then 256, then 1 024. Nothing above 2 048. A 4K map is four times the largest in the game.
Map usage. Detail 524, GrayMask 474, ColorZone 52, NormalOcclusion 41, Smoothness 22, Master 8. A normal map appears on one item in twenty.
Catalogue tags. The 298 Build Mode tags are extracted from the game by
tools/extract_catalog.py into paraforge/catalog.py, with their GUID and
their hierarchy. Run it again after a game update.
A door is 2.112 m tall, a single leaf 1.04 m wide. Useful for judging the scale of an imported model by eye.
Everything the game imposes is gathered in
paraforge/spec.py, so a game update should never require
touching another file.
Every generation is journalled in _paraforge/journal.json inside the mod,
with a copy of any file it changed. Undo the last write removes what was
created, restores what was changed, and cleans up folders left empty. Pressing
it twice walks back two generations. Regenerating an unchanged item does
nothing and does not add a step.
Export refuses any folder inside the Paralives installation. Assets belong in a
.mod under AppData\LocalLow, or a game update wipes them and they cannot be
shared.
Three values the developers have never published live in the Calibration panel, so a game update can be absorbed without a new release:
- Tile size, the size of one Build Mode grid tile in metres
- Triangle budget, your own ceiling, used for a warning only
- FBX units per metre, measured at 100
- Script mods are out of scope. The developers provide no tools for them and they are not allowed on the Steam Workshop. ParaForge only ever produces mods that can be uploaded.
- A smoothness map becomes one number. The game has no slot for a smoothness texture, only a value per surface.
- Recolourable items are only partly tested. The GrayMask base and the colour zones are written, but swatch groups have had far less use than the plain path.
- The format is not a published contract. Paralives is in early access. Every finding above is recorded with the game build it was measured on.
python build.pyOr let Blender validate the manifest while it packages:
python build.py --blender "C:/Program Files/Blender Foundation/Blender 5.2/blender.exe"The zip lands in dist/. Releases are built the same way by
the release workflow.
python tests/test_i18n.pyblender --background --factory-startup --python tests/test_headless.pyblender --background --factory-startup --python tests/test_ui_contract.pyThe first checks that no string was left out of the French catalogue. The
second covers geometry, zones, texture detection, baking, units, axes, the
.setting merge and the export. The third draws every panel and validates every
icon, property and operator against the live API, which catches the errors that
only show up on screen.
All three run on every push, against Blender 4.2 and 5.2, in the CI workflow.
paraforge/
spec.py everything Paralives imposes, in one place
validate.py the checklist
fixes.py one button per failed check
geo.py measurements shared by the validator, overlay and fixers
zones.py colour zone authoring, including the texture picker
textures.py role detection, naming, export
imaging.py channel rebuilding for glTF and ORM sources
bake.py merging several materials into one surface
exporter.py FBX and texture export into a .mod
item.py the prefab and the catalogue entry
setting.py reading and extending a .setting file
sidecar.py .meta files and GUID derivation
journal.py undo history for everything written into a mod
catalog.py Build Mode tags, generated from the game
overlay.py viewport guides and heads up checklist
ui.py the sidebar panel
i18n.py French and English strings
tools/
extract_catalog.py regenerate catalog.py from an installed game
mod_diff.py snapshot and diff a mod folder, without Blender
tests/
Created by infinition.
Thanks to the Paralives team for shipping a moddable game with a transparent, plain text data format, and to paralives-modgen for documenting the collection merge syntax.
Licensed under the GNU General Public License v3.0 or later. See
LICENSE for the full text. Blender add-ons link against bpy and are
distributed under the GPL for that reason.