mirror of
https://github.com/Jacobwasbeast/LegacyWeaveLoader.git
synced 2026-07-04 10:04:26 +00:00
Rebrand LegacyForge to Weave Loader
Rename across entire codebase: - LegacyForge -> WeaveLoader (identifiers, namespaces, classes, DLLs) - LegacyForgeRuntime -> WeaveLoaderRuntime (C++ project) - LegacyForge.API/Core/Launcher -> WeaveLoader.API/Core/Launcher (C# projects) - [LegacyForge] -> [WeaveLoader] (log prefixes) - legacyforge -> weaveloader (config files, log files, backup suffixes) - Display name "Weave Loader" in README, CONTRIBUTING, LICENSE
This commit is contained in:
3
WeaveLoader.API/AssemblyInfo.cs
Normal file
3
WeaveLoader.API/AssemblyInfo.cs
Normal file
@@ -0,0 +1,3 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WeaveLoader.Core")]
|
||||
27
WeaveLoader.API/Assets/AssetRegistry.cs
Normal file
27
WeaveLoader.API/Assets/AssetRegistry.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
namespace WeaveLoader.API.Assets;
|
||||
|
||||
/// <summary>
|
||||
/// Asset registration for mods. Use for language strings and (future) texture paths.
|
||||
/// Block and item display names are typically set via BlockProperties.Name() and ItemProperties.Name().
|
||||
/// Use this registry for additional strings (e.g. GUI labels, messages).
|
||||
/// </summary>
|
||||
public static class AssetRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// Register a display string for a custom description ID.
|
||||
/// Use native_allocate_description_id() to get an ID, then wire it to your custom UI/entity.
|
||||
/// </summary>
|
||||
public static void RegisterString(int descriptionId, string displayName)
|
||||
{
|
||||
NativeInterop.native_register_string(descriptionId, displayName ?? "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocate a new description ID for custom strings.
|
||||
/// IDs are in the mod range (10000+) and are looked up via the GetString hook.
|
||||
/// </summary>
|
||||
public static int AllocateDescriptionId()
|
||||
{
|
||||
return NativeInterop.native_allocate_description_id();
|
||||
}
|
||||
}
|
||||
64
WeaveLoader.API/Block/BlockProperties.cs
Normal file
64
WeaveLoader.API/Block/BlockProperties.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
namespace WeaveLoader.API.Block;
|
||||
|
||||
public enum MaterialType
|
||||
{
|
||||
Air = 0,
|
||||
Stone = 1,
|
||||
Wood = 2,
|
||||
Cloth = 3,
|
||||
Plant = 4,
|
||||
Dirt = 5,
|
||||
Sand = 6,
|
||||
Glass = 7,
|
||||
Water = 8,
|
||||
Lava = 9,
|
||||
Ice = 10,
|
||||
Metal = 11,
|
||||
Snow = 12,
|
||||
Clay = 13,
|
||||
Explosive = 14,
|
||||
Web = 15
|
||||
}
|
||||
|
||||
public enum SoundType
|
||||
{
|
||||
None = 0,
|
||||
Stone = 1,
|
||||
Wood = 2,
|
||||
Gravel = 3,
|
||||
Grass = 4,
|
||||
Metal = 5,
|
||||
Glass = 6,
|
||||
Cloth = 7,
|
||||
Sand = 8,
|
||||
Snow = 9
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fluent builder for defining block properties.
|
||||
/// </summary>
|
||||
public class BlockProperties
|
||||
{
|
||||
internal MaterialType MaterialValue = MaterialType.Stone;
|
||||
internal float HardnessValue = 1.0f;
|
||||
internal float ResistanceValue = 5.0f;
|
||||
internal SoundType SoundValue = SoundType.Stone;
|
||||
internal string IconValue = "stone";
|
||||
internal float LightEmissionValue = 0.0f;
|
||||
internal int LightBlockValue = 255;
|
||||
internal CreativeTab CreativeTabValue = CreativeTab.None;
|
||||
internal string? NameValue;
|
||||
|
||||
public BlockProperties Material(MaterialType material) { MaterialValue = material; return this; }
|
||||
public BlockProperties Hardness(float hardness) { HardnessValue = hardness; return this; }
|
||||
public BlockProperties Resistance(float resistance) { ResistanceValue = resistance; return this; }
|
||||
public BlockProperties Sound(SoundType sound) { SoundValue = sound; return this; }
|
||||
/// <summary>Icon name in the terrain atlas. Use namespaced ID for mod textures (e.g. "examplemod:ruby_ore" from assets/blocks/ruby_ore.png), or vanilla names like "stone", "gold_ore".</summary>
|
||||
public BlockProperties Icon(string iconName) { IconValue = iconName; return this; }
|
||||
public BlockProperties LightLevel(float level) { LightEmissionValue = level; return this; }
|
||||
public BlockProperties LightBlocking(int level) { LightBlockValue = level; return this; }
|
||||
public BlockProperties Indestructible() { HardnessValue = -1.0f; ResistanceValue = 6000000f; return this; }
|
||||
public BlockProperties InCreativeTab(CreativeTab tab) { CreativeTabValue = tab; return this; }
|
||||
/// <summary>Display name shown in-game (e.g. "Ruby Ore"). Used for localization.</summary>
|
||||
public BlockProperties Name(string displayName) { NameValue = displayName; return this; }
|
||||
}
|
||||
58
WeaveLoader.API/Block/BlockRegistry.cs
Normal file
58
WeaveLoader.API/Block/BlockRegistry.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
namespace WeaveLoader.API.Block;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a block that has been registered with the game engine.
|
||||
/// </summary>
|
||||
public class RegisteredBlock
|
||||
{
|
||||
/// <summary>The namespaced string ID (e.g. "mymod:ruby_ore").</summary>
|
||||
public Identifier StringId { get; }
|
||||
|
||||
/// <summary>The numeric ID allocated by the engine.</summary>
|
||||
public int NumericId { get; }
|
||||
|
||||
internal RegisteredBlock(Identifier id, int numericId)
|
||||
{
|
||||
StringId = id;
|
||||
NumericId = numericId;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Block registration via the WeaveLoader registry.
|
||||
/// Accessed through <see cref="Registry.Block"/>.
|
||||
/// </summary>
|
||||
public static class BlockRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// Register a new block with the game engine.
|
||||
/// </summary>
|
||||
/// <param name="id">Namespaced identifier (e.g. "mymod:ruby_ore").</param>
|
||||
/// <param name="properties">Block properties built with <see cref="BlockProperties"/>.</param>
|
||||
/// <returns>A handle to the registered block.</returns>
|
||||
public static RegisteredBlock Register(Identifier id, BlockProperties properties)
|
||||
{
|
||||
int numericId = NativeInterop.native_register_block(
|
||||
id.ToString(),
|
||||
(int)properties.MaterialValue,
|
||||
properties.HardnessValue,
|
||||
properties.ResistanceValue,
|
||||
(int)properties.SoundValue,
|
||||
properties.IconValue,
|
||||
properties.LightEmissionValue,
|
||||
properties.LightBlockValue,
|
||||
properties.NameValue ?? "");
|
||||
|
||||
if (numericId < 0)
|
||||
throw new InvalidOperationException($"Failed to register block '{id}'. No free IDs or invalid parameters.");
|
||||
|
||||
if (properties.CreativeTabValue != CreativeTab.None)
|
||||
{
|
||||
NativeInterop.native_add_to_creative(numericId, 1, 0, (int)properties.CreativeTabValue);
|
||||
Logger.Debug($"Block '{id}' added to creative tab {properties.CreativeTabValue}");
|
||||
}
|
||||
|
||||
Logger.Debug($"Registered block '{id}' -> numeric ID {numericId}");
|
||||
return new RegisteredBlock(id, numericId);
|
||||
}
|
||||
}
|
||||
21
WeaveLoader.API/CreativeTab.cs
Normal file
21
WeaveLoader.API/CreativeTab.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace WeaveLoader.API;
|
||||
|
||||
/// <summary>
|
||||
/// Creative inventory tabs matching the game's internal group indices.
|
||||
/// Use with <see cref="Block.BlockProperties.CreativeTab"/> or
|
||||
/// <see cref="Item.ItemProperties.CreativeTab"/> to make content
|
||||
/// appear in the creative menu.
|
||||
/// </summary>
|
||||
public enum CreativeTab
|
||||
{
|
||||
None = -1,
|
||||
BuildingBlocks = 0,
|
||||
Decoration = 1,
|
||||
Redstone = 2,
|
||||
Transport = 3,
|
||||
Materials = 4,
|
||||
Food = 5,
|
||||
ToolsAndWeapons = 6,
|
||||
Brewing = 7,
|
||||
Misc = 12
|
||||
}
|
||||
16
WeaveLoader.API/Entity/EntityDefinition.cs
Normal file
16
WeaveLoader.API/Entity/EntityDefinition.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace WeaveLoader.API.Entity;
|
||||
|
||||
/// <summary>
|
||||
/// Fluent builder for defining entity properties.
|
||||
/// </summary>
|
||||
public class EntityDefinition
|
||||
{
|
||||
internal float WidthValue = 0.6f;
|
||||
internal float HeightValue = 1.8f;
|
||||
internal int TrackingRangeValue = 80;
|
||||
|
||||
public EntityDefinition Width(float width) { WidthValue = width; return this; }
|
||||
public EntityDefinition Height(float height) { HeightValue = height; return this; }
|
||||
public EntityDefinition TrackingRange(int range) { TrackingRangeValue = range; return this; }
|
||||
public EntityDefinition Size(float width, float height) { WidthValue = width; HeightValue = height; return this; }
|
||||
}
|
||||
38
WeaveLoader.API/Entity/EntityRegistry.cs
Normal file
38
WeaveLoader.API/Entity/EntityRegistry.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
namespace WeaveLoader.API.Entity;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an entity type that has been registered with the game engine.
|
||||
/// </summary>
|
||||
public class RegisteredEntity
|
||||
{
|
||||
public Identifier StringId { get; }
|
||||
public int NumericId { get; }
|
||||
|
||||
internal RegisteredEntity(Identifier id, int numericId)
|
||||
{
|
||||
StringId = id;
|
||||
NumericId = numericId;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entity registration via the WeaveLoader registry.
|
||||
/// Accessed through <see cref="Registry.Entity"/>.
|
||||
/// </summary>
|
||||
public static class EntityRegistry
|
||||
{
|
||||
public static RegisteredEntity Register(Identifier id, EntityDefinition definition)
|
||||
{
|
||||
int numericId = NativeInterop.native_register_entity(
|
||||
id.ToString(),
|
||||
definition.WidthValue,
|
||||
definition.HeightValue,
|
||||
definition.TrackingRangeValue);
|
||||
|
||||
if (numericId < 0)
|
||||
throw new InvalidOperationException($"Failed to register entity '{id}'.");
|
||||
|
||||
Logger.Debug($"Registered entity '{id}' -> numeric ID {numericId}");
|
||||
return new RegisteredEntity(id, numericId);
|
||||
}
|
||||
}
|
||||
60
WeaveLoader.API/Events/GameEvents.cs
Normal file
60
WeaveLoader.API/Events/GameEvents.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
namespace WeaveLoader.API.Events;
|
||||
|
||||
public class TickEventArgs : EventArgs { }
|
||||
|
||||
public class BlockBreakEventArgs : EventArgs
|
||||
{
|
||||
public string BlockId { get; init; } = "";
|
||||
public int X { get; init; }
|
||||
public int Y { get; init; }
|
||||
public int Z { get; init; }
|
||||
public int PlayerId { get; init; }
|
||||
}
|
||||
|
||||
public class BlockPlaceEventArgs : EventArgs
|
||||
{
|
||||
public string BlockId { get; init; } = "";
|
||||
public int X { get; init; }
|
||||
public int Y { get; init; }
|
||||
public int Z { get; init; }
|
||||
public int PlayerId { get; init; }
|
||||
}
|
||||
|
||||
public class ChatEventArgs : EventArgs
|
||||
{
|
||||
public string Message { get; init; } = "";
|
||||
public int PlayerId { get; init; }
|
||||
}
|
||||
|
||||
public class EntitySpawnEventArgs : EventArgs
|
||||
{
|
||||
public string EntityId { get; init; } = "";
|
||||
public float X { get; init; }
|
||||
public float Y { get; init; }
|
||||
public float Z { get; init; }
|
||||
}
|
||||
|
||||
public class PlayerJoinEventArgs : EventArgs
|
||||
{
|
||||
public int PlayerId { get; init; }
|
||||
public string PlayerName { get; init; } = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Global game event subscriptions. Subscribe to these in your mod's OnInitialize().
|
||||
/// Events are fired from the game's main thread via hooks in WeaveLoaderRuntime.
|
||||
/// </summary>
|
||||
public static class GameEvents
|
||||
{
|
||||
public static event EventHandler<BlockBreakEventArgs>? OnBlockBreak;
|
||||
public static event EventHandler<BlockPlaceEventArgs>? OnBlockPlace;
|
||||
public static event EventHandler<ChatEventArgs>? OnChat;
|
||||
public static event EventHandler<EntitySpawnEventArgs>? OnEntitySpawn;
|
||||
public static event EventHandler<PlayerJoinEventArgs>? OnPlayerJoin;
|
||||
|
||||
internal static void FireBlockBreak(BlockBreakEventArgs e) => OnBlockBreak?.Invoke(null, e);
|
||||
internal static void FireBlockPlace(BlockPlaceEventArgs e) => OnBlockPlace?.Invoke(null, e);
|
||||
internal static void FireChat(ChatEventArgs e) => OnChat?.Invoke(null, e);
|
||||
internal static void FireEntitySpawn(EntitySpawnEventArgs e) => OnEntitySpawn?.Invoke(null, e);
|
||||
internal static void FirePlayerJoin(PlayerJoinEventArgs e) => OnPlayerJoin?.Invoke(null, e);
|
||||
}
|
||||
39
WeaveLoader.API/IMod.cs
Normal file
39
WeaveLoader.API/IMod.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
namespace WeaveLoader.API;
|
||||
|
||||
/// <summary>
|
||||
/// The main interface all WeaveLoader mods must implement.
|
||||
/// Default interface methods allow mods to only override what they need.
|
||||
/// </summary>
|
||||
public interface IMod
|
||||
{
|
||||
/// <summary>
|
||||
/// Called before vanilla registries are populated.
|
||||
/// Use for very early setup that must happen before any game content loads.
|
||||
/// </summary>
|
||||
void OnPreInit() { }
|
||||
|
||||
/// <summary>
|
||||
/// Called after vanilla registries are populated.
|
||||
/// This is the main initialization point -- register your blocks, items,
|
||||
/// entities, recipes, and event handlers here.
|
||||
/// </summary>
|
||||
void OnInitialize();
|
||||
|
||||
/// <summary>
|
||||
/// Called after the game client has finished its own initialization.
|
||||
/// Use for client-side setup like custom renderers or UI.
|
||||
/// </summary>
|
||||
void OnPostInitialize() { }
|
||||
|
||||
/// <summary>
|
||||
/// Called once per game tick (20 times per second).
|
||||
/// Use for ongoing mod logic.
|
||||
/// </summary>
|
||||
void OnTick() { }
|
||||
|
||||
/// <summary>
|
||||
/// Called when the game is shutting down.
|
||||
/// Use for cleanup and saving mod state.
|
||||
/// </summary>
|
||||
void OnShutdown() { }
|
||||
}
|
||||
39
WeaveLoader.API/Identifier.cs
Normal file
39
WeaveLoader.API/Identifier.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
namespace WeaveLoader.API;
|
||||
|
||||
/// <summary>
|
||||
/// A namespaced identifier in the form "namespace:path" (e.g. "minecraft:stone", "mymod:ruby_ore").
|
||||
/// </summary>
|
||||
public readonly record struct Identifier
|
||||
{
|
||||
public string Namespace { get; }
|
||||
public string Path { get; }
|
||||
|
||||
public Identifier(string ns, string path)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(ns);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
Namespace = ns;
|
||||
Path = path;
|
||||
}
|
||||
|
||||
public Identifier(string id)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(id);
|
||||
|
||||
var colonIndex = id.IndexOf(':');
|
||||
if (colonIndex < 0)
|
||||
{
|
||||
Namespace = "minecraft";
|
||||
Path = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
Namespace = id[..colonIndex];
|
||||
Path = id[(colonIndex + 1)..];
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => $"{Namespace}:{Path}";
|
||||
|
||||
public static implicit operator Identifier(string id) => new(id);
|
||||
}
|
||||
26
WeaveLoader.API/Item/ItemProperties.cs
Normal file
26
WeaveLoader.API/Item/ItemProperties.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace WeaveLoader.API.Item;
|
||||
|
||||
/// <summary>
|
||||
/// Fluent builder for defining item properties.
|
||||
/// </summary>
|
||||
public class ItemProperties
|
||||
{
|
||||
internal int MaxStackSizeValue = 64;
|
||||
internal int MaxDamageValue = 0;
|
||||
internal string IconValue = "";
|
||||
internal CreativeTab CreativeTabValue = CreativeTab.None;
|
||||
internal string? NameValue;
|
||||
|
||||
public ItemProperties MaxStackSize(int size) { MaxStackSizeValue = size; return this; }
|
||||
/// <summary>Icon name in the items atlas. Use namespaced ID for mod textures (e.g. "examplemod:ruby" from assets/items/ruby.png), or vanilla names like "diamond", "ingotIron".</summary>
|
||||
public ItemProperties Icon(string iconName) { IconValue = iconName; return this; }
|
||||
|
||||
/// <summary>
|
||||
/// Set max damage for a tool/armor item. Setting this to a positive value
|
||||
/// makes the item damageable with a durability bar.
|
||||
/// </summary>
|
||||
public ItemProperties MaxDamage(int damage) { MaxDamageValue = damage; MaxStackSizeValue = 1; return this; }
|
||||
public ItemProperties InCreativeTab(CreativeTab tab) { CreativeTabValue = tab; return this; }
|
||||
/// <summary>Display name shown in-game (e.g. "Ruby"). Used for localization.</summary>
|
||||
public ItemProperties Name(string displayName) { NameValue = displayName; return this; }
|
||||
}
|
||||
54
WeaveLoader.API/Item/ItemRegistry.cs
Normal file
54
WeaveLoader.API/Item/ItemRegistry.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
namespace WeaveLoader.API.Item;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an item that has been registered with the game engine.
|
||||
/// </summary>
|
||||
public class RegisteredItem
|
||||
{
|
||||
/// <summary>The namespaced string ID (e.g. "mymod:ruby").</summary>
|
||||
public Identifier StringId { get; }
|
||||
|
||||
/// <summary>The numeric ID allocated by the engine.</summary>
|
||||
public int NumericId { get; }
|
||||
|
||||
internal RegisteredItem(Identifier id, int numericId)
|
||||
{
|
||||
StringId = id;
|
||||
NumericId = numericId;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Item registration via the WeaveLoader registry.
|
||||
/// Accessed through <see cref="Registry.Item"/>.
|
||||
/// </summary>
|
||||
public static class ItemRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// Register a new item with the game engine.
|
||||
/// </summary>
|
||||
/// <param name="id">Namespaced identifier (e.g. "mymod:ruby").</param>
|
||||
/// <param name="properties">Item properties built with <see cref="ItemProperties"/>.</param>
|
||||
/// <returns>A handle to the registered item.</returns>
|
||||
public static RegisteredItem Register(Identifier id, ItemProperties properties)
|
||||
{
|
||||
int numericId = NativeInterop.native_register_item(
|
||||
id.ToString(),
|
||||
properties.MaxStackSizeValue,
|
||||
properties.MaxDamageValue,
|
||||
properties.IconValue,
|
||||
properties.NameValue ?? "");
|
||||
|
||||
if (numericId < 0)
|
||||
throw new InvalidOperationException($"Failed to register item '{id}'. No free IDs or invalid parameters.");
|
||||
|
||||
if (properties.CreativeTabValue != CreativeTab.None)
|
||||
{
|
||||
NativeInterop.native_add_to_creative(numericId, 1, 0, (int)properties.CreativeTabValue);
|
||||
Logger.Debug($"Item '{id}' added to creative tab {properties.CreativeTabValue}");
|
||||
}
|
||||
|
||||
Logger.Debug($"Registered item '{id}' -> numeric ID {numericId}");
|
||||
return new RegisteredItem(id, numericId);
|
||||
}
|
||||
}
|
||||
36
WeaveLoader.API/Logger.cs
Normal file
36
WeaveLoader.API/Logger.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace WeaveLoader.API;
|
||||
|
||||
public enum LogLevel
|
||||
{
|
||||
Debug = 0,
|
||||
Info = 1,
|
||||
Warning = 2,
|
||||
Error = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logging facade that routes messages through the native runtime to the game's debug output.
|
||||
/// </summary>
|
||||
public static class Logger
|
||||
{
|
||||
private static Action<string, LogLevel>? LogHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Set the log handler that routes messages to the native runtime.
|
||||
/// Called by WeaveLoader.Core during initialization.
|
||||
/// </summary>
|
||||
public static void SetLogHandler(Action<string, LogLevel> handler) => LogHandler = handler;
|
||||
|
||||
public static void Debug(string message) => Log(message, LogLevel.Debug);
|
||||
public static void Info(string message) => Log(message, LogLevel.Info);
|
||||
public static void Warning(string message) => Log(message, LogLevel.Warning);
|
||||
public static void Error(string message) => Log(message, LogLevel.Error);
|
||||
|
||||
public static void Log(string message, LogLevel level = LogLevel.Info)
|
||||
{
|
||||
if (LogHandler != null)
|
||||
LogHandler(message, level);
|
||||
else
|
||||
Console.WriteLine($"[WeaveLoader/{level}] {message}");
|
||||
}
|
||||
}
|
||||
41
WeaveLoader.API/ModAttribute.cs
Normal file
41
WeaveLoader.API/ModAttribute.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
namespace WeaveLoader.API;
|
||||
|
||||
/// <summary>
|
||||
/// Marks a class as a WeaveLoader mod and provides metadata.
|
||||
/// The class must also implement <see cref="IMod"/>.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class ModAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// The unique mod identifier (e.g. "examplemod"). Used as the default namespace
|
||||
/// for content registered by this mod.
|
||||
/// </summary>
|
||||
public string Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable display name.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Semantic version string (e.g. "1.0.0").
|
||||
/// </summary>
|
||||
public string Version { get; set; } = "1.0.0";
|
||||
|
||||
/// <summary>
|
||||
/// Mod author(s).
|
||||
/// </summary>
|
||||
public string Author { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Short description of the mod.
|
||||
/// </summary>
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
public ModAttribute(string id)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(id);
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
76
WeaveLoader.API/NativeInterop.cs
Normal file
76
WeaveLoader.API/NativeInterop.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace WeaveLoader.API;
|
||||
|
||||
/// <summary>
|
||||
/// Internal P/Invoke bindings to WeaveLoaderRuntime.dll native exports.
|
||||
/// Mod authors should use the Registry and Logger classes instead of calling these directly.
|
||||
/// </summary>
|
||||
internal static class NativeInterop
|
||||
{
|
||||
private const string RuntimeDll = "WeaveLoaderRuntime";
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern int native_register_block(
|
||||
string namespacedId,
|
||||
int materialId,
|
||||
float hardness,
|
||||
float resistance,
|
||||
int soundType,
|
||||
string iconName,
|
||||
float lightEmission,
|
||||
int lightBlock,
|
||||
string displayName);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern int native_register_item(
|
||||
string namespacedId,
|
||||
int maxStackSize,
|
||||
int maxDamage,
|
||||
string iconName,
|
||||
string displayName);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern int native_allocate_description_id();
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern void native_register_string(int descriptionId, string displayName);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern int native_register_entity(
|
||||
string namespacedId,
|
||||
float width,
|
||||
float height,
|
||||
int trackingRange);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern void native_add_shaped_recipe(
|
||||
string resultId,
|
||||
int resultCount,
|
||||
string pattern,
|
||||
string ingredientIds);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern void native_add_furnace_recipe(
|
||||
string inputId,
|
||||
string outputId,
|
||||
float xp);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern void native_log(string message, int level);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern int native_get_block_id(string namespacedId);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern int native_get_item_id(string namespacedId);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern int native_get_entity_id(string namespacedId);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
internal static extern void native_subscribe_event(string eventName, IntPtr managedFnPtr);
|
||||
|
||||
[DllImport(RuntimeDll, CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void native_add_to_creative(int numericId, int count, int auxValue, int groupIndex);
|
||||
}
|
||||
40
WeaveLoader.API/Recipe/RecipeRegistry.cs
Normal file
40
WeaveLoader.API/Recipe/RecipeRegistry.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
namespace WeaveLoader.API.Recipe;
|
||||
|
||||
/// <summary>
|
||||
/// Recipe registration via the WeaveLoader registry.
|
||||
/// Accessed through <see cref="Registry.Recipe"/>.
|
||||
/// </summary>
|
||||
public static class RecipeRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// Add a shaped crafting recipe.
|
||||
/// </summary>
|
||||
/// <param name="result">The output item identifier.</param>
|
||||
/// <param name="resultCount">Number of items produced.</param>
|
||||
/// <param name="pattern">Crafting grid pattern rows (e.g. "XXX", " | ", " | " for a pickaxe).</param>
|
||||
/// <param name="keys">Character-to-ingredient mappings.</param>
|
||||
public static void AddShaped(Identifier result, int resultCount, string[] pattern,
|
||||
params (char key, Identifier ingredient)[] keys)
|
||||
{
|
||||
string patternStr = string.Join(";", pattern);
|
||||
string ingredientStr = string.Join(";",
|
||||
keys.Select(k => $"{k.key}={k.ingredient}"));
|
||||
|
||||
NativeInterop.native_add_shaped_recipe(
|
||||
result.ToString(), resultCount, patternStr, ingredientStr);
|
||||
|
||||
Logger.Debug($"Added shaped recipe -> {resultCount}x {result}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a furnace/smelting recipe.
|
||||
/// </summary>
|
||||
/// <param name="input">The input item/block identifier.</param>
|
||||
/// <param name="output">The output item identifier.</param>
|
||||
/// <param name="xp">Experience granted per smelt.</param>
|
||||
public static void AddFurnace(Identifier input, Identifier output, float xp)
|
||||
{
|
||||
NativeInterop.native_add_furnace_recipe(input.ToString(), output.ToString(), xp);
|
||||
Logger.Debug($"Added furnace recipe: {input} -> {output} ({xp} xp)");
|
||||
}
|
||||
}
|
||||
55
WeaveLoader.API/Registry.cs
Normal file
55
WeaveLoader.API/Registry.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using WeaveLoader.API.Block;
|
||||
using WeaveLoader.API.Item;
|
||||
using WeaveLoader.API.Entity;
|
||||
using WeaveLoader.API.Recipe;
|
||||
using WeaveLoader.API.Assets;
|
||||
|
||||
namespace WeaveLoader.API;
|
||||
|
||||
/// <summary>
|
||||
/// Central access point for all WeaveLoader registries.
|
||||
/// Use Registry.Block, Registry.Item, Registry.Entity, Registry.Recipe, or Registry.Assets.
|
||||
/// </summary>
|
||||
public static class Registry
|
||||
{
|
||||
/// <summary>Block registration. Call Register() with a namespaced ID and BlockProperties.</summary>
|
||||
public static class Block
|
||||
{
|
||||
public static RegisteredBlock Register(Identifier id, BlockProperties properties)
|
||||
=> BlockRegistry.Register(id, properties);
|
||||
}
|
||||
|
||||
/// <summary>Item registration. Call Register() with a namespaced ID and ItemProperties.</summary>
|
||||
public static class Item
|
||||
{
|
||||
public static RegisteredItem Register(Identifier id, ItemProperties properties)
|
||||
=> ItemRegistry.Register(id, properties);
|
||||
}
|
||||
|
||||
/// <summary>Entity registration. Call Register() with a namespaced ID and EntityDefinition.</summary>
|
||||
public static class Entity
|
||||
{
|
||||
public static RegisteredEntity Register(Identifier id, EntityDefinition definition)
|
||||
=> EntityRegistry.Register(id, definition);
|
||||
}
|
||||
|
||||
/// <summary>Recipe registration for crafting and smelting.</summary>
|
||||
public static class Recipe
|
||||
{
|
||||
public static void AddShaped(Identifier result, int count, string[] pattern,
|
||||
params (char key, Identifier ingredient)[] keys)
|
||||
=> RecipeRegistry.AddShaped(result, count, pattern, keys);
|
||||
|
||||
public static void AddFurnace(Identifier input, Identifier output, float xp)
|
||||
=> RecipeRegistry.AddFurnace(input, output, xp);
|
||||
}
|
||||
|
||||
/// <summary>Asset registration for language strings and (future) textures.</summary>
|
||||
public static class Assets
|
||||
{
|
||||
public static void RegisterString(int descriptionId, string displayName)
|
||||
=> AssetRegistry.RegisterString(descriptionId, displayName);
|
||||
public static int AllocateDescriptionId()
|
||||
=> AssetRegistry.AllocateDescriptionId();
|
||||
}
|
||||
}
|
||||
16
WeaveLoader.API/WeaveLoader.API.csproj
Normal file
16
WeaveLoader.API/WeaveLoader.API.csproj
Normal file
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>WeaveLoader.API</RootNamespace>
|
||||
<AssemblyName>WeaveLoader.API</AssemblyName>
|
||||
<Description>Mod API for WeaveLoader - Minecraft Legacy Edition mod loader</Description>
|
||||
<Version>1.0.0</Version>
|
||||
<OutputPath>..\build\mods\WeaveLoader.API</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user