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

269 lines
6.5 KiB
Markdown

---
title: Dynamic Lights
type: docs
weight: 2
---
Dynamic lights add glow effects to entities using the `DynamicLight` component.
## ColorLight Structure
The `ColorLight` class defines light properties:
```java
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:
```java
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:
```java
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
```java
// 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
```java
// Remove the component to disable light
componentAccessor.removeComponent(
entityRef,
DynamicLight.getComponentType()
);
```
## Common Light Configurations
### Fire/Warm Glow
```java
ColorLight fireLight = new ColorLight(
(byte) 12,
(byte) 255, // High red
(byte) 150, // Medium orange
(byte) 50 // Low blue
);
```
### Ice/Cold Glow
```java
ColorLight iceLight = new ColorLight(
(byte) 10,
(byte) 100, // Low red
(byte) 200, // Medium green
(byte) 255 // High blue
);
```
### Magic/Purple Glow
```java
ColorLight magicLight = new ColorLight(
(byte) 15,
(byte) 200, // High red
(byte) 50, // Low green
(byte) 255 // High blue
);
```
### Healing/Green Glow
```java
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
```java
// 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:
```java
// 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 >}}