269 lines
6.5 KiB
Markdown
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 >}}
|