Hytale Modding
Server Plugins

Custom Item and Interaction

Learn how you can create a custom item interactions for your custom items

Creating a custom item follows the same setup than the Creating custom blocks.

Setup

  1. Enable asset packs in manifest.json by setting IncludesAssetPack to true
  2. Create the following folder structure:
my_new_item.json
my_new_item_icon.png
model.blockymodel
model_texture.png

The following files are relevant for the item:

FileLocationDescription
my_new_item.jsonServer/Item/ItemsDefines the item properties and behavior
my_new_item_icon.pngCommon/Icons/ItemsGeneratedIcon for the item in inventory
model.blockymodelCommon/Items/my_new_item3D model of the item
model_texture.pngCommon/Items/my_new_itemTexture for the item model

Custom Item Definition

Create Server/Item/Items/my_new_item.json:

{
  "TranslationProperties": {
    "Name": "My New Item", // Alternatively, use localization keys
    "Description": "My New Item Description" // Alternatively, use localization keys
  },
   "Id": "My_New_Item",
  "Icon": "Icons/ItemsGenerated/my_new_item_icon.png",
  "Model": "Resources/my_new_item/model.blockymodel",
  "Texture": "Resources/my_new_item/model_texture.png",
  "Quality": "Common",
  "MaxStack": 1,
  "Categories": [
    "Items.Example"
  ]
}

This JSON file defines a new item with a unique ID, icon, 3D model, texture, quality, maximum stack size, and category. Ensure all referenced files exist in their respective folders, and the paths are correct.

Adding Recipe for the Item

To allow players to craft the new item, you can define a crafting recipe. Inside the metadata for the item, add the following recipe definition:

{
  ... // existing item properties from above
  "Recipe": {
    "TimeSeconds": 3.5, // Time taken to craft the item
    "Input": [
      {
        "ItemId": "Ingredient_1", // Example ingredient item ID
        "Quantity": 15
      },
      {
        "ItemId": "Ingredient_2", // Example ingredient item ID
        "Quantity": 15
      },
      {
        "ItemId": "Ingredient_3", // Example ingredient item ID
        "Quantity": 15
      }
    ],
    "BenchRequirement": [
      {
        "Id": "Workbench", // What type of crafting bench is required
        "Type": "Crafting",
        "Categories": [
          "Workbench_Survival" // Which category of workbench tab
        ]
      }
    ]
  }
}

This recipe allows players to craft "My New Item" using specified ingredients at a workbench.

Item Interaction

To create a custom interaction, you will need to define the interaction behavior in your plugin code. This typically involves handling events when the item is used by the player. Inherit from SimpleInstantInteraction and override the necessary methods to define what happens when the item is used.

Plugin Code

public class MyCustomInteraction extends SimpleInstantInteraction {
    @Override
    protected void firstRun(@NonNullDecl InteractionType interactionType, @NonNullDecl InteractionContext interactionContext, @NonNullDecl CooldownHandler cooldownHandler) {
        // Custom behavior when the item is used
    }
}

What is missing is a custom CODEC to link the interaction to the item.

public class MyCustomInteraction extends SimpleInstantInteraction {
    public static final BuilderCodec<MyCustomInteraction> CODEC = BuilderCodec.builder(
            MyCustomInteraction.class, MyCustomInteraction::new, SimpleInstantInteraction.CODEC
    ).build();

    @Override
    protected void firstRun(@NonNullDecl InteractionType interactionType, @NonNullDecl InteractionContext interactionContext, @NonNullDecl CooldownHandler cooldownHandler) {
        // Custom behavior when the item is used
    }
}

Finally, register the interaction in your plugin's main class:

public class MyPlugin extends JavaPlugin {
    public MyPlugin(@NonNull JavaPluginInit init) {
        super(init);
    }

    @Override
    protected void setup() {
        this.getCodecRegistry(Interaction.CODEC).register("my_custom_interaction_id", MyCustomInteraction.class, MyCustomInteraction.CODEC);
    }
}

This code registers the custom interaction with a unique ID, allowing the game to recognize and use it when any item with with this interaction id is used.

Linking Interaction to Item

To link the custom interaction to the item, add the following property to the item JSON definition:

{
  ... // existing item properties from above
  "Interactions": {
    "Secondary": { // depending on the type of interaction you want
      "Interactions": [
        {
          "Type": "my_custom_interaction_id",
        }
      ]
    }
  }
}

Full Interaction Example

Here is a complete example of a custom interaction that sends a message with the item ID to the player when the item is used:

public class SendMessageInteraction extends SimpleInstantInteraction {
    public static final BuilderCodec<SendMessageInteraction> CODEC = BuilderCodec.builder(
            SendMessageInteraction.class, SendMessageInteraction::new, SimpleInstantInteraction.CODEC
    ).build();

    public static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();

    @Override
    protected void firstRun(@NonNullDecl InteractionType interactionType, @NonNullDecl InteractionContext interactionContext, @NonNullDecl CooldownHandler cooldownHandler) {
        CommandBuffer<EntityStore> commandBuffer = interactionContext.getCommandBuffer();
        if (commandBuffer == null) {
            interactionContext.getState().state = InteractionState.Failed;
            LOGGER.atInfo().log("CommandBuffer is null");
            return;
        }

        World world = commandBuffer.getExternalData().getWorld(); // just to show how to get the world if needed
        Store<EntityStore> store = commandBuffer.getExternalData().getStore(); // just to show how to get the store if needed
        Ref<EntityStore> ref = interactionContext.getEntity();
        Player player = commandBuffer.getComponent(ref, Player.getComponentType());
        if (player == null) {
            interactionContext.getState().state = InteractionState.Failed;
            LOGGER.atInfo().log("Player is null");
            return;
        }

        ItemStack itemStack = interactionContext.getHeldItem();
        if (itemStack == null) {
            interactionContext.getState().state = InteractionState.Failed;
            LOGGER.atInfo().log("ItemStack is null");
            return;
        }

        player.sendMessage(Message.raw("You have used the custom item +" + itemStack.getItemId()));
    }
}

Conclusion

You have now created a custom item with a unique interaction in your Hytale plugin. You can expand upon this foundation to create more complex items and interactions as needed for your mod.

Written by Marcel-TO