Skip to content
On this page

Item Render Markers

Item render markers are lightweight client-side item models shown in the world. They are useful for hologram-like rewards, previews, quest targets, temporary pickups, and animated markers.

Markers are not entities. They have no collision, selector target, persistence, or vanilla entity sync. A server script sends marker packets to the clients that should see them.

Show a Marker

Create a ClientItemRenderMarker with itemRenderMarker, then send it with showItemRenderMarker.

kotlin
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import top.katton.api.itemRenderMarker
import top.katton.api.showItemRenderMarker

fun showRewardMarker(player: net.minecraft.server.level.ServerPlayer) {
    val marker = itemRenderMarker(
        level = player.level().dimension(),
        pos = player.position().add(0.0, 1.4, 0.0),
        stack = ItemStack(Items.DIAMOND),
        scale = 1.25f,
        fullBright = true,
        lifetimeTicks = 100
    )

    showItemRenderMarker(player, marker)
}

Use showItemRenderMarker(marker) to broadcast to every connected player, or showItemRenderMarker(player, marker) for one viewer.

Debug Commands

Fabric and NeoForge expose a small /katton itemrender command group for trying markers in-game without writing a script:

CommandEffect
/katton itemrender spawn <item>Spawns the item two blocks in front of the command source with the showcase preset.
/katton itemrender spawn <item> <preset>Uses one preset: still, spin, float, pulse, or showcase.
/katton itemrender spawn <item> <preset> <scale>Sets the marker scale.
/katton itemrender spawn <item> <preset> <scale> <lifetimeTicks>Sets the marker lifetime. Use -1 for a marker that stays until cleared.
/katton itemrender clear <radius>Removes tracked markers in the current dimension within radius blocks of the command source.

The spawn command uses ItemDisplayContext.FIXED, maxDistance = 96.0, and broadcasts the marker to connected clients. It is mainly a visual preview and debugging helper; scripts should use the API below for gameplay logic.

Animate a Marker

Markers can carry named animation sets. A set can animate translation, rotation, and scale with easing curves.

kotlin
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.server.level.ServerPlayer
import top.katton.api.ClientItemRenderEasing
import top.katton.api.itemRenderMarker
import top.katton.api.showItemRenderMarker

fun showSpinningMarker(player: ServerPlayer) {
    val marker = itemRenderMarker(
        level = player.level().dimension(),
        pos = player.position().add(0.0, 1.4, 0.0),
        stack = ItemStack(Items.EMERALD),
        animations = mapOf(
            "spin" to {
                durationTicks = 40
                loop = true
                rotate {
                    keyframe(0.0f, 0.0, 0.0, 0.0)
                    keyframe(1.0f, 0.0, 360.0, 0.0, ClientItemRenderEasing.LINEAR)
                }
                translate {
                    keyframe(0.0f, 0.0, 0.0, 0.0)
                    keyframe(0.5f, 0.0, 0.25, 0.0, ClientItemRenderEasing.EASE_IN_OUT_SINE)
                    keyframe(1.0f, 0.0, 0.0, 0.0, ClientItemRenderEasing.EASE_IN_OUT_SINE)
                }
            }
        ),
        playingAnimationID = listOf("spin")
    )

    val id = showItemRenderMarker(player, marker)
}

You can later call playItemRenderAnimationSet(id, "spin") or stopItemRenderAnimationSet(id, "spin") for tracked markers.

Remove Markers

Use removeItemRenderMarker(id) to remove one tracked marker, clearItemRenderMarkers() to clear all markers for all players, or clearItemRenderMarkersInRange(level, center, radius) for area cleanup.

Markers with lifetimeTicks >= 0 expire on the client automatically, but explicit cleanup is still useful for long-lived UI or world hints.