Files
Documentation/content/advanced/effects/dynamic-lights.en.md
2026-01-20 20:33:59 +01:00

6.5 KiB

title, type, weight
title type weight
Dynamic Lights docs 2

Dynamic lights add glow effects to entities using the DynamicLight component.

ColorLight Structure

The ColorLight class defines light properties:

import com.hypixel.hytale.protocol.ColorLight;

public class ColorLight {
    public byte radius;     // 0-255 (light radius/intensity)
    public byte red;        // 0-255 (red channel)
    public byte green;      // 0-255 (green channel)
    public byte blue;       // 0-255 (blue channel)

    public ColorLight(byte radius, byte red, byte green, byte blue) {
        this.radius = radius;
        this.red = red;
        this.green = green;
        this.blue = blue;
    }
}

DynamicLight Component

Add temporary glow effects to entities:

import com.hypixel.hytale.server.core.modules.entity.component.DynamicLight;
import com.hypixel.hytale.protocol.ColorLight;

// Create colored light (radius, R, G, B)
ColorLight light = new ColorLight(
    (byte) 15,      // Radius (0-255)
    (byte) 255,     // Red (0-255)
    (byte) 100,     // Green (0-255)
    (byte) 50       // Blue (0-255)
);

// Add DynamicLight component
DynamicLight dynamicLight = new DynamicLight(light);
componentAccessor.putComponent(
    entityRef,
    DynamicLight.getComponentType(),
    dynamicLight
);

PersistentDynamicLight Component

Use this component when light should be saved with entity data:

import com.hypixel.hytale.server.core.modules.entity.component.PersistentDynamicLight;

// Create persistent light
PersistentDynamicLight persistentLight = new PersistentDynamicLight(light);
componentAccessor.putComponent(
    entityRef,
    PersistentDynamicLight.getComponentType(),
    persistentLight
);

Updating Light Properties

// Get existing light component
DynamicLight dynamicLight = store.getComponent(
    entityRef,
    DynamicLight.getComponentType()
);

if (dynamicLight != null) {
    // Create new light properties
    ColorLight newLight = new ColorLight(
        (byte) 20,      // New radius
        (byte) 0,       // No red
        (byte) 255,     // Full green
        (byte) 100      // Some blue
    );

    // Update and mark for network sync
    dynamicLight.setColorLight(newLight);
    // isNetworkOutdated is set automatically
}

Removing Light

// Remove the component to disable light
componentAccessor.removeComponent(
    entityRef,
    DynamicLight.getComponentType()
);

Common Light Configurations

Fire/Warm Glow

ColorLight fireLight = new ColorLight(
    (byte) 12,
    (byte) 255,    // High red
    (byte) 150,    // Medium orange
    (byte) 50      // Low blue
);

Ice/Cold Glow

ColorLight iceLight = new ColorLight(
    (byte) 10,
    (byte) 100,    // Low red
    (byte) 200,    // Medium green
    (byte) 255     // High blue
);

Magic/Purple Glow

ColorLight magicLight = new ColorLight(
    (byte) 15,
    (byte) 200,    // High red
    (byte) 50,     // Low green
    (byte) 255     // High blue
);

Healing/Green Glow

ColorLight healLight = new ColorLight(
    (byte) 10,
    (byte) 50,     // Low red
    (byte) 255,    // High green
    (byte) 100     // Medium blue
);

Practical Examples

Adding a Glow Effect to a Player

// Add temporary glow effect to a player
public void addGlowEffect(Player player, ComponentAccessor<EntityStore> componentAccessor,
                          ScheduledExecutorService scheduler) {
    World world = player.getWorld();

    // Add temporary glow
    ColorLight glow = new ColorLight(
        (byte) 8,
        (byte) 255,
        (byte) 215,
        (byte) 0    // Gold color
    );

    DynamicLight light = new DynamicLight(glow);
    Ref<EntityStore> entityRef = player.getReference();
    componentAccessor.putComponent(
        entityRef,
        DynamicLight.getComponentType(),
        light
    );

    // Remove after 3 seconds using standard Java scheduling
    scheduler.schedule(() -> {
        world.execute(() -> {
            if (entityRef.isValid()) {
                componentAccessor.removeComponent(
                    entityRef,
                    DynamicLight.getComponentType()
                );
            }
        });
    }, 3, TimeUnit.SECONDS);
}

{{< callout type="warning" >}} Note: Use player.getReference() to get the entity reference, not player.getEntityRef(). Use standard Java ScheduledExecutorService for delayed tasks. {{< /callout >}}

Pulsing Light Effect

Implement pulsing effects by updating the light in a tick handler:

// Track pulsing entities
private final Map<Ref<EntityStore>, Integer> pulsingEntities = new ConcurrentHashMap<>();

// Call this method each tick
public void onTick(float deltaTime) {
    for (Map.Entry<Ref<EntityStore>, Integer> entry : pulsingEntities.entrySet()) {
        Ref<EntityStore> entityRef = entry.getKey();
        int tick = entry.getValue() + 1;
        entry.setValue(tick);

        // Calculate pulsing intensity
        double pulse = Math.sin(tick * 0.1) * 0.5 + 0.5;
        byte radius = (byte) (5 + pulse * 10);

        ColorLight light = new ColorLight(
            radius,
            (byte) 255,
            (byte) (int)(100 + pulse * 100),
            (byte) 50
        );

        DynamicLight dynamicLight = store.getComponent(
            entityRef,
            DynamicLight.getComponentType()
        );

        if (dynamicLight != null) {
            dynamicLight.setColorLight(light);
        }
    }
}

public void startPulsingLight(Ref<EntityStore> entityRef) {
    pulsingEntities.put(entityRef, 0);
}

public void stopPulsingLight(Ref<EntityStore> entityRef) {
    pulsingEntities.remove(entityRef);
}

Network Synchronization

{{< callout type="info" >}} Sync Details:

  • DynamicLight changes are automatically marked for sync when using setColorLight()
  • The isNetworkOutdated flag triggers client updates
  • Use consumeNetworkOutdated() before manual sync operations {{< /callout >}}

DynamicLight vs PersistentDynamicLight

Feature DynamicLight PersistentDynamicLight
Saved to disk No Yes
Survives restart No Yes
Use case Temporary effects Permanent glows
Performance Lighter Slightly heavier

Best Practices

{{< callout type="warning" >}} Light Guidelines:

  • Keep radius values reasonable (5-20 for most effects)
  • Don't add lights to too many entities simultaneously
  • Remove temporary lights when no longer needed
  • Use PersistentDynamicLight only when persistence is required {{< /callout >}}