Skip to content

About

Valheim mod. Extra inventory slots dedicated to certain item types.

Resources

Stars

11 stars

Watchers

1 watching

Forks

Latest commit

 

History

286 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Extra Slots

More inventory slots dedicated for equipment, food, ammo and misc items. Extra utility slots. Quick slots. Custom slots API. Player inventory resize. Gamepad friendly. Slot obtaining progression.

Game compatibility

ExtraSlots 1.2.1 targets Valheim 1.0.7. The visible inventory uses the character's native row count plus the configured ExtraSlots row adjustment, with at least one regular row. Equipment and quick-slot storage is additional to those visible rows.

Inventory recovery accepts both the older 106/107 saves and compact 108/109 saves. Items that cannot be placed in the current topology remain deferred rather than being dropped by the game's inventory-size update.

Conditional Config Sync

  • Config values marked with [Synced with Server] are synchronized from the server by default. Core slot counts, slot availability, progression, item eligibility, weight factors, death rules and other gameplay-affecting settings use this default.
  • UI layout, panel positions, hotkeys, labels, colors, tooltips, logging and compatibility presentation settings remain client-controlled by default.
  • Server administrators can change the synchronization policy for policy-controlled settings in BepInEx/config/shudnal.ConditionalConfigSync/ConditionalConfigSync.SyncPolicy.cfg.
  • Prefix an exact setting or whole-section identifier with + to force server control or - to make it client-controlled. Exact-setting rules take precedence over whole-section rules.
  • General / Lock Configuration is always server-controlled and cannot be made client-controlled through the policy.
  • Use shared modpack configs or distribute your config manually if you also want client-controlled appearance, controls and compatibility settings to be identical for all players initially.
  • ExtraSlots does not require every connecting player to have the mod at the synchronization protocol level, but a player needs ExtraSlots installed to use its additional inventory UI and slot behavior.
  • If you install this mod manually, do not forget to install ConditionalConfigSync.

Mod description

Extra Slots API

I can add more methods to API if you miss something reasonable. Open a github issue.

You can either use this API with ExtraSlots set as BepInEx hard dependency or soft dependency.

API methods with summary

Hard dependency

Hard dependency means your mod will not work without ExtraSlots installed.

Add attribute [BepInDependency("shudnal.ExtraSlots", BepInDependency.DependencyFlags.HardDependency)] before your BaseUnityPlugin declaration

Add reference to ExtraSlots.dll and use its API methods from main mod like ExtraSlots.API.GetExtraSlots().

Soft dependency

Soft dependency means you will be able to use ExtraSlotsAPI.API methods wherever main ExtraSlots mod is installed or not.

To be sure your mod is always loaded after ExtraSlots add attribute [BepInDependency("shudnal.ExtraSlots", BepInDependency.DependencyFlags.SoftDependency)] before your BaseUnityPlugin declaration

In this case you need to merge ExtraSlotsAPI.dll into your mod's dll.

You need NuGet Package ILRepack.Lib.MSBuild.Task to merge your dll with ExtraSlotsAPI.dll.

If you use VisualStudio:

  • right click on the project
  • Manage NuGet packages
  • set tab to Browse
  • find ILRepack.Lib.MSBuild.Task and install most downloaded version

ILRepacks read the contents of file ILRepack.targets located in the root folder of your project.

  • Add new file to your project and name it ILRepack.targets
  • Insert following block in the file and save it
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
	<Target Name="ILRepacker" AfterTargets="Build">
		<ItemGroup>
			<InputAssemblies Include="$(TargetPath)" />
			<InputAssemblies Include="$(OutputPath)ExtraSlotsAPI.dll" />
		</ItemGroup>
		<ILRepack Parallel="true" DebugInfo="true" Internalize="true" InputAssemblies="@(InputAssemblies)" OutputFile="$(TargetPath)" TargetKind="SameAsPrimaryAssembly" LibraryPath="$(OutputPath)" />
	</Target>
</Project>

Try to build a project and see if you are getting similar lines in build output

1>  Added assembly 'bin\Debug\ExtraSlotsAPI.dll'
1>  Merging 2 assembies to '...\bin\Debug\YourModName.dll'

Now you can be sure your ExtraSlotsAPI.API is always available.

For more info about what API method result see API methods with summary.

In short you can add/remove slots and get various slots related info.

Now to API calls:

  • Add a reference to ExtraSlotsAPI.dll to your project
  • Paste line ExtraSlotsAPI.API.IsReady() into your mod Awake function and see if it works as correct method call

Example

I use ExtraSlotsAPI to add custom slot in my CircletExtended and HipLantern mods.

Next will be an example from CircletExtended mod.

I need my Circlet slot to appear before Lantern slot for more intuitive layout.

I define related config entries that state should mod create an extra slot, how it should be named and should it wait for item discovery for slot to be active.

public static ConfigEntry<bool> itemSlotExtraSlots; // Enable or disable slot entirely
public static ConfigEntry<string> itemSlotNameExtraSlots; // Slot name (any string)
public static ConfigEntry<int> itemSlotIndexExtraSlots; // Slot position in layout
public static ConfigEntry<bool> itemSlotExtraSlotsDiscovery; // Should slot be active only after circlet discovery

then I initialize config variables

itemSlotExtraSlots = Config.Bind("Circlet - Custom slot", "ExtraSlots - Create slot", true, "Create custom equipment slot with ExtraSlots.");
itemSlotNameExtraSlots = Config.Bind("Circlet - Custom slot", "ExtraSlots - Slot name", "Circlet", "Custom equipment slot name.");
itemSlotIndexExtraSlots = Config.Bind("Circlet - Custom slot", "ExtraSlots - Slot index", -1, "Slot index (position). Game restart is required to apply changes.");
itemSlotExtraSlotsDiscovery = Config.Bind("Circlet - Custom slot", "ExtraSlots - Available after discovery", true, "If enabled - slot will be active only if you know circlet item.");

itemSlotExtraSlots.SettingChanged += (s, e) => ExtraSlotsAPI.API.UpdateSlots(); // After enabling/disabling slot call a method to update slots layout

And then all I need is to call this in Awake function

if (ExtraSlotsAPI.API.IsReady())
    if (itemSlotIndexExtraSlots.Value < 0)
        ExtraSlotsAPI.API.AddSlotBefore("CircletExtended", () => itemSlotNameExtraSlots.Value, item => IsCircletItem(item), () => IsCircletSlotAvailable(), "HipLantern");
    else
        ExtraSlotsAPI.API.AddSlotWithIndex("CircletExtended", itemSlotIndexExtraSlots.Value, () => itemSlotNameExtraSlots.Value, item => IsCircletItem(item), () => IsCircletSlotAvailable());

First argument "CircletExtended" is slot ID which should be unique and can be used later to get if slot in grid is that slot.

This defines slot name as a function and if you change itemSlotNameExtraSlots config value it will be automatically updated.

IsCircletItem is the function to check if item type is correct. It should return if item fits the slot.

IsCircletSlotAvailable is the function that return should slot be active. If the result is changed for best result you should call ExtraSlots.API.UpdateSlots() to update layout. In this example it is handled by action on itemSlotExtraSlots.SettingChanged.

Used functions (example):

internal static bool IsCircletItem(ItemDrop.ItemData item) => item != null && item.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Helmet; // There could be more intricate logic

internal static bool IsCircletSlotAvailable() => itemSlotExtraSlots.Value && (!itemSlotExtraSlotsDiscovery.Value || IsCircletKnown());

internal static bool IsCircletKnown()
{
    if (!Player.m_localPlayer || Player.m_localPlayer.m_isLoading) // m_isLoading check is recommended to properly load inventory layout without item to be moved to other slot, even if only temporarily.
        return true;

    return Player.m_localPlayer.IsKnownMaterial("$item_helmet_dverger"); // There could be more intricate logic
}

This is the basic example. Real logic for CircletExtended is there.

If you have questions feel free to reach me at discord or just open a GitHub issue.

Local packaging

ILRepack.targets updates embedded translations before compilation, then reads the built DLL version, prepares the Thunderstore package, updates its manifest, creates the ZIP and copies the DLL to the configured r2modman profile. UpdateThunderstoreManifest.ps1 is self-contained and only updates the local manifest. No publishing credentials or upload scripts are used. The package uses the external YamlDotNet dependency from its manifest; the built DLL is not rewritten after packaging. Debug symbols are not shipped.

Donation

Buy Me a Coffee

Discord

Join server

About

Valheim mod. Extra inventory slots dedicated to certain item types.

Resources

Stars

11 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages