feat(models): add block model boxes + picking

This commit is contained in:
Jacobwasbeast
2026-03-11 15:12:35 -05:00
parent 6fabb8fd39
commit 788b7167a2
26 changed files with 1429 additions and 4 deletions

View File

@@ -1,3 +1,4 @@
using System.Collections.Generic;
using WeaveLoader.API;
namespace WeaveLoader.API.Block;
@@ -61,14 +62,18 @@ public class BlockProperties
internal float ResistanceValue = 5.0f;
internal SoundType SoundValue = SoundType.Stone;
internal string IconValue = "stone";
internal string? ModelValue;
internal float LightEmissionValue = 0.0f;
internal int LightBlockValue = 255;
internal bool LightBlockExplicit;
internal CreativeTab CreativeTabValue = CreativeTab.None;
internal CreativePlacement? CreativePlacementValue;
internal Text? NameValue;
internal int RequiredHarvestLevelValue = -1;
internal ToolType RequiredToolValue = ToolType.None;
internal bool AcceptsRedstonePowerValue;
internal List<Assets.ModelBox>? ModelBoxes;
internal bool ModelIsFullCube;
public BlockProperties Material(MaterialType material) { MaterialValue = material; return this; }
public BlockProperties Hardness(float hardness) { HardnessValue = hardness; return this; }
@@ -79,8 +84,14 @@ public class BlockProperties
/// from assets/examplemod/textures/block/ruby_ore.png, or vanilla names like "stone", "gold_ore".
/// </summary>
public BlockProperties Icon(string iconName) { IconValue = iconName; return this; }
/// <summary>
/// Optional Java-style model name (e.g. "examplemod:block/ruby_ore").
/// When provided, WeaveLoader will read assets/&lt;namespace&gt;/models/block/&lt;name&gt;.json
/// and use its texture for the block icon.
/// </summary>
public BlockProperties Model(string modelName) { ModelValue = modelName; return this; }
public BlockProperties LightLevel(float level) { LightEmissionValue = level; return this; }
public BlockProperties LightBlocking(int level) { LightBlockValue = level; return this; }
public BlockProperties LightBlocking(int level) { LightBlockValue = level; LightBlockExplicit = true; return this; }
public BlockProperties Indestructible() { HardnessValue = -1.0f; ResistanceValue = 6000000f; return this; }
public BlockProperties InCreativeTab(CreativeTab tab) { CreativeTabValue = tab; return this; }
public BlockProperties CreativePlacement(CreativePlacement placement) { CreativePlacementValue = placement; return this; }

View File

@@ -50,6 +50,8 @@ public static class BlockRegistry
/// <returns>A handle to the registered block.</returns>
public static RegisteredBlock Register(Identifier id, BlockProperties properties)
{
Assets.ModelResolver.ApplyBlockModel(id, properties);
ApplyModelLightDefaults(properties);
int numericId = NativeInterop.native_register_block(
id.ToString(),
(int)properties.MaterialValue,
@@ -70,6 +72,11 @@ public static class BlockRegistry
throw new InvalidOperationException($"Failed to register block '{id}'. No free IDs or invalid parameters.");
}
if (properties.ModelBoxes != null && properties.ModelBoxes.Count > 0)
{
NativeInterop.native_register_block_model(numericId, properties.ModelBoxes.ToArray(), properties.ModelBoxes.Count);
}
AddToCreative(id, numericId, properties);
Logger.Debug($"Registered block '{id}' -> numeric ID {numericId}");
@@ -88,6 +95,8 @@ public static class BlockRegistry
if (managedBlock is FallingBlock)
return RegisterFalling(id, managedBlock, properties);
Assets.ModelResolver.ApplyBlockModel(id, properties);
ApplyModelLightDefaults(properties);
int numericId = NativeInterop.native_register_managed_block(
id.ToString(),
(int)properties.MaterialValue,
@@ -108,6 +117,11 @@ public static class BlockRegistry
throw new InvalidOperationException($"Failed to register managed block '{id}'.");
}
if (properties.ModelBoxes != null && properties.ModelBoxes.Count > 0)
{
NativeInterop.native_register_block_model(numericId, properties.ModelBoxes.ToArray(), properties.ModelBoxes.Count);
}
AddToCreative(id, numericId, properties);
ManagedBlockDispatcher.RegisterBlock(id, numericId, managedBlock);
@@ -134,6 +148,8 @@ public static class BlockRegistry
private static RegisteredBlock RegisterFalling(Identifier id, Block? managedBlock, BlockProperties properties)
{
Assets.ModelResolver.ApplyBlockModel(id, properties);
ApplyModelLightDefaults(properties);
int numericId = NativeInterop.native_register_falling_block(
id.ToString(),
(int)properties.MaterialValue,
@@ -154,6 +170,11 @@ public static class BlockRegistry
throw new InvalidOperationException($"Failed to register falling block '{id}'.");
}
if (properties.ModelBoxes != null && properties.ModelBoxes.Count > 0)
{
NativeInterop.native_register_block_model(numericId, properties.ModelBoxes.ToArray(), properties.ModelBoxes.Count);
}
AddToCreative(id, numericId, properties);
if (managedBlock != null)
@@ -180,6 +201,8 @@ public static class BlockRegistry
public static RegisteredSlabBlock RegisterSlab(Identifier id, BlockProperties properties)
{
Assets.ModelResolver.ApplyBlockModel(id, properties);
ApplyModelLightDefaults(properties);
Identifier doubleId = new($"{id}_double");
int numericId = NativeInterop.native_register_slab_block(
id.ToString(),
@@ -207,6 +230,11 @@ public static class BlockRegistry
throw new InvalidOperationException($"Failed to resolve generated slab pair '{doubleId}'.");
}
if (properties.ModelBoxes != null && properties.ModelBoxes.Count > 0)
{
NativeInterop.native_register_block_model(numericId, properties.ModelBoxes.ToArray(), properties.ModelBoxes.Count);
}
AddToCreative(id, numericId, properties);
lock (s_lock)
@@ -217,6 +245,18 @@ public static class BlockRegistry
return new RegisteredSlabBlock(id, doubleId, numericId, doubleNumericId);
}
private static void ApplyModelLightDefaults(BlockProperties properties)
{
if (properties.ModelBoxes == null || properties.ModelBoxes.Count == 0)
return;
if (properties.LightBlockExplicit)
return;
if (!properties.ModelIsFullCube)
properties.LightBlockValue = 0;
}
internal static bool TryGetIdentifier(int numericId, out Identifier id)
{
lock (s_lock)