Mod textures, display names, and atlas injection

Mod Atlas (ModAtlas.cpp/h):
- Build merged terrain.png and items.png from mod assets (blocks/*.png, items/*.png)
- Scan vanilla atlas for empty (fully transparent) cells; place mod textures only there
- Install merged atlases over game files before Minecraft::init; restore originals after
- Hook loadUVs to create SimpleIcon objects for mod textures
- Hook registerIcon to return mod icons when requested by name
- FixupModIcons: copy field_0x48 (source-image ptr) from vanilla icons after init

Mod Strings (ModStrings.cpp/h):
- Store mod display names by description ID
- Hook GetString to serve mod names for blocks/items

API changes:
- BlockProperties/ItemProperties: .Name(displayName), namespaced .Icon()
- NativeInterop: displayName params, native_allocate_description_id, native_register_string
- Registry.Assets for string registration
- Output: mods/LegacyForge.API/, mods/ExampleMod/ (per-mod folders)

Mod discovery:
- Scan mods/*/ for mod folders; load DLLs from each
- LegacyForge.API as mod in mods/LegacyForge.API/

ExampleMod:
- Ruby ore block and ruby item with custom textures and names
- Assets: blocks/ruby_ore.png, items/ruby.png, lang files
- Furnace recipe: ruby_ore -> ruby

Runtime: loadUVs, registerIcon, getResourceAsStream, GetString hooks; stb_image for PNG
This commit is contained in:
Jacobwasbeast
2026-03-06 22:04:15 -06:00
parent 336e037730
commit 2280cb1192
34 changed files with 10770 additions and 50 deletions

View File

@@ -20,13 +20,15 @@ public class ExampleMod : IMod
.Hardness(3.0f)
.Resistance(15f)
.Sound(SoundType.Stone)
.Icon("ruby_ore")
.Icon("examplemod:ruby_ore") // From assets/blocks/ruby_ore.png
.Name("Ruby Ore")
.InCreativeTab(CreativeTab.BuildingBlocks));
Ruby = Registry.Item.Register("examplemod:ruby",
new ItemProperties()
.MaxStackSize(64)
.Icon("ruby")
.Icon("examplemod:ruby") // From assets/items/ruby.png
.Name("Ruby")
.InCreativeTab(CreativeTab.Materials));
Registry.Recipe.AddFurnace("examplemod:ruby_ore", "examplemod:ruby", 1.0f);

View File

@@ -8,13 +8,20 @@
<AssemblyName>ExampleMod</AssemblyName>
<Description>Example mod for LegacyForge demonstrating the mod API</Description>
<Version>1.0.0</Version>
<OutputPath>..\build\mods</OutputPath>
<OutputPath>..\build\mods\ExampleMod</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\LegacyForge.API\LegacyForge.API.csproj" />
<!-- Private=false: do not copy LegacyForge.API into ExampleMod. API lives in mods/LegacyForge.API/ -->
<ProjectReference Include="..\LegacyForge.API\LegacyForge.API.csproj">
<Private>false</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="assets\**\*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,25 @@
# ExampleMod Assets
## Language files
Language files live in `assets/lang/` with the format `{locale}.lang` (e.g. `en-GB.lang`, `de-DE.lang`).
**Current API:** Use `BlockProperties.Name()` and `ItemProperties.Name()` when registering blocks and items. These set the display name shown in-game. The ModLoader hooks into the game's string lookup so your names appear correctly.
**Future:** Multi-locale support may load from these `.lang` files. Format: `key=value` per line, with `#` for comments.
## Textures
Mod textures are supported via the dynamic atlas system. Place PNG files in:
- **Blocks:** `assets/blocks/{name}.png` → icon `{modid}:{name}` (e.g. `ruby_ore.png``examplemod:ruby_ore`)
- **Items:** `assets/items/{name}.png` → icon `{modid}:{name}` (e.g. `ruby.png``examplemod:ruby`)
The mod ID is derived from the mod folder name (lowercase, hyphens removed). Use the namespaced icon in `BlockProperties.Icon()` and `ItemProperties.Icon()`:
```csharp
.Icon("examplemod:ruby_ore") // block from assets/blocks/ruby_ore.png
.Icon("examplemod:ruby") // item from assets/items/ruby.png
```
Textures must be 16×16 pixels (or any size; they are scaled). For vanilla icons, use names like `gold_ore`, `diamond`, etc.

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

View File

@@ -0,0 +1,5 @@
# ExampleMod language file (de-DE)
# German translations for ExampleMod content.
block.examplemod.ruby_ore=Rubinerz
item.examplemod.ruby=Rubin

View File

@@ -0,0 +1,7 @@
# ExampleMod language file (en-GB)
# Display names for blocks and items.
# In the current API, use BlockProperties.Name() and ItemProperties.Name() instead.
# This file documents the expected format for future multi-locale support.
block.examplemod.ruby_ore=Ruby Ore
item.examplemod.ruby=Ruby