diff --git a/Guide.md b/Guide.md new file mode 100644 index 0000000..1ab1c79 --- /dev/null +++ b/Guide.md @@ -0,0 +1,66 @@ +# Site Guide + +A quick guide for creators keeping their packs and models compatible with the site. + +## 1. Pick the right category + +Every project belongs to one of: **NoN Pack**, **Model**, **Skin**, **Mod**, **Modpack**, or **Guide**. The site auto-detects compatibility from what you upload, so choosing the right category is the most important step. + +## 2. NoN Packs + +- Include a `pack.mcmeta` with an `animationframework` block: + ```json + { + "pack": { "pack_format": 64, "description": "..." }, + "animationframework": { "id": "yournamespace:yourpack" } + } + ``` +- Pack content goes under `assets//` and `data//afw_animdefs/`, using the `afw_*` model keys. +- The `id` is what the in-game auto-updater queries (`/api/packs///latest`), so make it stable. + +## 3. Models + +- Build in **Blockbench** with **GeckoLib 5+**. +- Upload `.bbmodel`, `.geo.json`, or `.jem` — these render in the viewer. +- `.gltf` / `.glb` are recognized but **cannot be previewed** (the import is desktop-only). +- Species auto-tagging only recognizes vanilla mobs. + +## 4. Plugins + +If a Model upload contains a `plugins/` folder with `.js` plugin files, the Models tab gains a **Plugins** tab that can **hotload** them. A `plugins/autoload.txt` lists the plugins loaded automatically. + +## 5. Skins + +- Use **64×32, 64×64, or 128×128** PNGs. +- Pick **Steve (wide)** or **Alex (slim)** when rendering. + +## 6. Mods + +- Upload the `.jar` file(s), or a zip with the jars at its **root** — subfolders are ignored. +- Loader (`fabric`, `quilt`, `neoforge`, `forge`) and the Minecraft version are auto-detected from the mod metadata. + +## 7. Modpacks + +- Upload a `.zip` (CurseForge/Modrinth folder or instance export) or a `.mrpack`. +- Loader and Minecraft version are inferred from the embedded mods. + +## 8. Guides + +- Upload `.md` files, or a zip containing `.md` files plus their images. +- Image and file links are **auto-rewritten** to the served files, so relative paths just work. +- **Tip:** the site's textareas are plain inputs — write your guide in a Markdown editor (e.g. any Markdown editor with live preview, or GitHub's editor) and copy all the text with syntax onto the site. + +## 9. Tags + +- Tags use e621 style: `category:tag` (e.g. `loader:fabric`, `species:dragon`). +- The site auto-tags loader, version, format, and species — you can add manual tags too. + +## 10. Upload flow + +My Projects → **New Project** (the draft autosaves as you type) → add the version file(s), a thumbnail, and gallery media. Each file is classified by its extension. + +## 11. Compatibility checklist + +- Zip multi-file uploads before uploading. +- Include the Minecraft version in mod metadata. +- Use clear, stable filenames and pack ids. diff --git a/nonpacks/library/tests.py b/nonpacks/library/tests.py index e39779c..514e1b9 100644 --- a/nonpacks/library/tests.py +++ b/nonpacks/library/tests.py @@ -135,6 +135,27 @@ class UGCProjectTests(UGCMediaTestCase, UGCGatedTestCase): creator_cat = TagCategory.objects.get(slug='creator') self.assertTrue(Tag.objects.filter(name='alice', category=creator_cat).exists()) + def test_create_links_auto_tags(self): + """Auto tags (from version metadata) must be linked to the project on + creation, not just created as orphan Tag rows.""" + self.gate() + self.client.login(username='Alice', password='pw') + uuid = self.client.get(reverse('library:project_create_new')).url.rstrip('/').split('/')[-1] + self._upload_temp( + 'version', 'testmod.jar', + _zip_bytes({'META-INF/mods.toml': 'modLoader="javafml"\nloaderVersion="[1,)"\n[[mods]]\nmodId="testmod"\nversion="1.0.0"\ndisplayName="Test Mod"\n'}), + 'application/java-archive', + draft_uuid=uuid, + ) + self.client.post(reverse('library:project_create', args=[uuid]), { + 'title': 'Auto Tag Mod', 'category': 'mod', 'version_name': '1.0.0', + }) + project = Project.objects.get(slug='auto-tag-mod') + loader_links = TagList.objects.filter( + project=project, tag__category__slug='loader', + ) + self.assertTrue(loader_links.exists(), 'auto loader tag should be linked to the project') + def test_create_requires_version_file(self): self.gate() self.client.login(username='Alice', password='pw') diff --git a/nonpacks/library/views.py b/nonpacks/library/views.py index e1723d6..7115ca8 100644 --- a/nonpacks/library/views.py +++ b/nonpacks/library/views.py @@ -1279,6 +1279,7 @@ def project_create(request, uuid): _apply_tags(project, data['tags'], request.user) project.sync_creator_tags(actor=request.user) + _sync_auto_tags(project, request.user) draft.delete() messages.success(request, 'Project created.') return redirect('library:project_detail', slug=project.slug)