Skip to content

Mod Examples

Complete examples of mods for Evoker Engine, from simple content mods to complex gameplay additions.

Example 1: Simple Item Mod

Add new items to the game.

using EvokerEngine.Modding;
using EvokerEngine.Inventory;
using EvokerEngine.Core;

public class SimpleItemMod : Mod
{
    public SimpleItemMod()
    {
        Info = new ModInfo
        {
            ModId = "simpleitems",
            Name = "Simple Items Mod",
            Version = "1.0.0",
            Author = "ModAuthor",
            Description = "Adds basic items to the game"
        };
    }

    public override void OnInitialize()
    {
        base.OnInitialize();

        // Ruby gem
        var ruby = new SimpleItem("simpleitems:ruby", "Ruby")
        {
            Description = "A precious red gemstone",
            MaxStackSize = 64,
            Value = 500,
            Weight = 0.1f,
            Rarity = ItemRarity.Rare
        };
        ModAPI.RegisterItem(ruby);

        // Emerald gem
        var emerald = new SimpleItem("simpleitems:emerald", "Emerald")
        {
            Description = "A valuable green gemstone",
            MaxStackSize = 64,
            Value = 750,
            Weight = 0.1f,
            Rarity = ItemRarity.Epic
        };
        ModAPI.RegisterItem(emerald);

        // Magic potion
        var magicPotion = new MagicPotion();
        ModAPI.RegisterItem(magicPotion);

        Log("Registered 3 new items");
    }
}

public class MagicPotion : Item
{
    public MagicPotion()
    {
        Id = new ResourceKey("simpleitems", "magic_potion");
        Name = "Magic Potion";
        Description = "Restores mana";
        MaxStackSize = 10;
        Value = 100;
        Rarity = ItemRarity.Uncommon;
    }

    public override bool OnUse(object? context = null)
    {
        // Restore mana logic
        Logger.Info("Mana restored!");
        return true;  // Consumed
    }
}

Example 2: Block Mod with Ores

Add new ore blocks and materials.

using EvokerEngine.Modding;
using EvokerEngine.Blocks;
using EvokerEngine.Inventory;
using EvokerEngine.Core;

public class OresMod : Mod
{
    public OresMod()
    {
        Info = new ModInfo
        {
            ModId = "oresmod",
            Name = "Ores Expansion",
            Version = "1.0.0",
            Author = "MinerCrafter",
            Description = "Adds new ores and materials"
        };
    }

    public override void OnInitialize()
    {
        base.OnInitialize();

        // Register ore items
        RegisterOreItems();

        // Register ore blocks
        RegisterOreBlocks();

        // Register smelting recipes
        RegisterRecipes();
    }

    private void RegisterOreItems()
    {
        var copperIngot = new SimpleItem("oresmod:copper_ingot", "Copper Ingot")
        {
            Description = "Refined copper",
            MaxStackSize = 64,
            Value = 50
        };
        ModAPI.RegisterItem(copperIngot);

        var tinIngot = new SimpleItem("oresmod:tin_ingot", "Tin Ingot")
        {
            Description = "Refined tin",
            MaxStackSize = 64,
            Value = 40
        };
        ModAPI.RegisterItem(tinIngot);

        var bronzeIngot = new SimpleItem("oresmod:bronze_ingot", "Bronze Ingot")
        {
            Description = "Copper and tin alloy",
            MaxStackSize = 64,
            Value = 100
        };
        ModAPI.RegisterItem(bronzeIngot);
    }

    private void RegisterOreBlocks()
    {
        var copperOre = new OreBlock("Copper Ore", new ResourceKey("oresmod", "copper_ingot"))
        {
            Hardness = 3.0f,
            MinDrops = 1,
            MaxDrops = 1
        };
        ModAPI.RegisterBlock(copperOre);

        var tinOre = new OreBlock("Tin Ore", new ResourceKey("oresmod", "tin_ingot"))
        {
            Hardness = 2.5f,
            MinDrops = 1,
            MaxDrops = 1
        };
        ModAPI.RegisterBlock(tinOre);
    }

    private void RegisterRecipes()
    {
        // Smelt copper ore
        var copperSmelting = new SmeltingRecipe
        {
            Id = new ResourceKey("oresmod", "copper_smelting"),
            Type = new ResourceKey("evoker", "smelting"),
            Ingredients = new() { new Ingredient("oresmod:copper_ore", 1) },
            Result = new RecipeResult("oresmod:copper_ingot", 1),
            CookTime = 10f
        };
        ModAPI.RegisterRecipe(copperSmelting);

        // Bronze alloy (crafting)
        var bronzeRecipe = new ShapelessRecipe
        {
            Id = new ResourceKey("oresmod", "bronze_crafting"),
            Type = new ResourceKey("evoker", "shapeless_crafting"),
            Ingredients = new()
            {
                new Ingredient("oresmod:copper_ingot", 3),
                new Ingredient("oresmod:tin_ingot", 1)
            },
            Result = new RecipeResult("oresmod:bronze_ingot", 4)
        };
        ModAPI.RegisterRecipe(bronzeRecipe);

        Log("Registered smelting and crafting recipes");
    }
}

public class OreBlock : Block
{
    public ResourceKey DropItemId { get; set; }
    public int MinDrops { get; set; } = 1;
    public int MaxDrops { get; set; } = 1;

    public OreBlock(string name, ResourceKey dropItem)
    {
        Id = new ResourceKey("oresmod", name.ToLower().Replace(" ", "_"));
        Name = name;
        Hardness = 3.0f;
        DropItemId = dropItem;
    }

    public override List<(ResourceKey itemId, int quantity)> GetDrops(object? context = null)
    {
        var amount = Random.Shared.Next(MinDrops, MaxDrops + 1);
        return new List<(ResourceKey, int)> { (DropItemId, amount) };
    }
}

Example 3: Custom Dimension Mod

Add a new dimension with unique properties.

using EvokerEngine.Modding;
using EvokerEngine.World;
using EvokerEngine.Core;
using System.Numerics;

public class SkyworldMod : Mod
{
    public SkyworldMod()
    {
        Info = new ModInfo
        {
            ModId = "skyworld",
            Name = "Skyworld Dimension",
            Version = "1.0.0",
            Author = "CloudBuilder",
            Description = "Adds a floating island dimension"
        };
    }

    public override void OnInitialize()
    {
        base.OnInitialize();

        var skyworld = new Dimension
        {
            Id = new ResourceKey("skyworld", "skyworld"),
            Name = "Skyworld",
            Type = DimensionType.Custom,

            // Bright and open
            AmbientLight = 15,
            HasSky = true,
            HasCeiling = false,
            SkyColor = new Vector3(0.4f, 0.7f, 1.0f),
            FogColor = new Vector3(0.9f, 0.95f, 1.0f),

            // High altitude
            MinHeight = 0,
            MaxHeight = 512,

            // Lighter gravity
            Gravity = 0.7f,

            // Normal gameplay
            BedsWork = true,
            WaterEvaporates = false
        };

        ModAPI.RegisterDimension(skyworld);

        // Create portal block
        var portal = new SkyworldPortal();
        ModAPI.RegisterBlock(portal);

        Log("Skyworld dimension registered");
    }
}

public class SkyworldPortal : Block
{
    public SkyworldPortal()
    {
        Id = new ResourceKey("skyworld", "skyworld_portal");
        Name = "Skyworld Portal";
        IsTransparent = true;
        LightLevel = 15;
    }

    public override bool OnInteract(Vector3 position, object? context = null)
    {
        // Teleport player to Skyworld
        Logger.Info("Teleporting to Skyworld!");
        // Teleportation logic here
        return true;
    }
}

Example 4: Tool and Weapon Mod

Add custom tools and weapons with durability.

using EvokerEngine.Modding;
using EvokerEngine.Inventory;
using EvokerEngine.Core;

public class ToolsMod : Mod
{
    public ToolsMod()
    {
        Info = new ModInfo
        {
            ModId = "customtools",
            Name = "Custom Tools",
            Version = "1.0.0",
            Author = "Blacksmith",
            Description = "Adds new tools and weapons"
        };
    }

    public override void OnInitialize()
    {
        base.OnInitialize();

        // Ruby tools
        var rubySword = new RubySword();
        var rubyPickaxe = new RubyPickaxe();

        ModAPI.RegisterItem(rubySword);
        ModAPI.RegisterItem(rubyPickaxe);

        // Tool recipes
        RegisterToolRecipes();
    }

    private void RegisterToolRecipes()
    {
        // Ruby Sword
        var swordRecipe = new ShapedRecipe
        {
            Id = new ResourceKey("customtools", "ruby_sword"),
            Type = new ResourceKey("evoker", "shaped_crafting"),
            Pattern = new[] { " R ", " R ", " S " },
            IngredientMap = new Dictionary<char, ResourceKey>
            {
                { 'R', new ResourceKey("simpleitems", "ruby") },
                { 'S', new ResourceKey("evoker", "stick") }
            },
            Result = new RecipeResult("customtools:ruby_sword", 1)
        };
        ModAPI.RegisterRecipe(swordRecipe);

        // Ruby Pickaxe
        var pickaxeRecipe = new ShapedRecipe
        {
            Id = new ResourceKey("customtools", "ruby_pickaxe"),
            Type = new ResourceKey("evoker", "shaped_crafting"),
            Pattern = new[] { "RRR", " S ", " S " },
            IngredientMap = new Dictionary<char, ResourceKey>
            {
                { 'R', new ResourceKey("simpleitems", "ruby") },
                { 'S', new ResourceKey("evoker", "stick") }
            },
            Result = new RecipeResult("customtools:ruby_pickaxe", 1)
        };
        ModAPI.RegisterRecipe(pickaxeRecipe);
    }
}

public class RubySword : Item
{
    private int _durability = 500;
    private int _maxDurability = 500;

    public RubySword()
    {
        Id = new ResourceKey("customtools", "ruby_sword");
        Name = "Ruby Sword";
        Description = "A powerful sword made of ruby";
        MaxStackSize = 1;
        Value = 1000;
        Rarity = ItemRarity.Rare;
    }

    public override bool OnUse(object? context = null)
    {
        // Attack logic
        _durability--;

        if (_durability <= 0)
        {
            Logger.Info("Ruby Sword broke!");
            return true;  // Item consumed (broken)
        }

        Logger.Info($"Ruby Sword durability: {_durability}/{_maxDurability}");
        return false;  // Not consumed
    }
}

public class RubyPickaxe : Item
{
    private int _durability = 800;

    public RubyPickaxe()
    {
        Id = new ResourceKey("customtools", "ruby_pickaxe");
        Name = "Ruby Pickaxe";
        Description = "An efficient pickaxe for mining";
        MaxStackSize = 1;
        Value = 1200;
        Rarity = ItemRarity.Rare;
    }
}

Example 5: Gameplay Mechanics Mod

Add new gameplay mechanics with update logic.

using EvokerEngine.Modding;
using EvokerEngine.Core;

public class SeasonsMod : Mod
{
    private float _seasonTime = 0f;
    private const float SEASON_DURATION = 600f;  // 10 minutes
    private Season _currentSeason = Season.Spring;

    public SeasonsMod()
    {
        Info = new ModInfo
        {
            ModId = "seasons",
            Name = "Seasons",
            Version = "1.0.0",
            Author = "WeatherMan",
            Description = "Adds seasonal changes to the game"
        };
    }

    public override void OnInitialize()
    {
        base.OnInitialize();
        Log("Seasons system initialized - Starting in Spring");
    }

    public override void OnUpdate(float deltaTime)
    {
        _seasonTime += deltaTime;

        if (_seasonTime >= SEASON_DURATION)
        {
            _seasonTime = 0f;
            ChangeSeason();
        }
    }

    private void ChangeSeason()
    {
        _currentSeason = _currentSeason switch
        {
            Season.Spring => Season.Summer,
            Season.Summer => Season.Autumn,
            Season.Autumn => Season.Winter,
            Season.Winter => Season.Spring,
            _ => Season.Spring
        };

        Log($"Season changed to: {_currentSeason}");
        ApplySeasonEffects();
    }

    private void ApplySeasonEffects()
    {
        switch (_currentSeason)
        {
            case Season.Spring:
                // Increase crop growth
                Log("Crops grow faster in Spring");
                break;
            case Season.Summer:
                // Increase temperature
                Log("Hot summer days");
                break;
            case Season.Autumn:
                // Change foliage colors
                Log("Leaves change color");
                break;
            case Season.Winter:
                // Add snow
                Log("Winter snowfall begins");
                break;
        }
    }

    private enum Season
    {
        Spring,
        Summer,
        Autumn,
        Winter
    }
}

Best Practices

✅ Do's

  • Use unique mod IDs (namespace)
  • Document your mod's features
  • Handle dependencies properly
  • Test with and without other mods
  • Provide configuration options
  • Use semantic versioning

❌ Don'ts

  • Don't use generic mod IDs
  • Don't hardcode values (use config files)
  • Don't break compatibility without version bump
  • Don't access private engine internals
  • Don't forget to clean up resources in OnUnload()

See Also