Skip to content

Commit dc5d3a7

Browse files
committed
Add per-player shadow direction override via set_lighting
Add an optional shadow.direction field to the lighting struct, allowing server mods to override the shadow light direction on a per-player basis. This is needed for games that use custom skyboxes where the sun/moon position in the skybox texture does not correspond to the engine's internal time-of-day cycle. When shadow_direction is set, Game::updateShadows() uses it directly instead of computing direction from getSunDirection()/getMoonDirection(), and applies shadow_intensity unconditionally (bypassing the sun/moon visibility check that would otherwise zero out shadows). Lua API: player:set_lighting({shadows = {direction = vector.new(0.3, 0.9, 0.3)}}) player:set_lighting({shadows = {direction = vector.zero()}}) -- clear A zero vector is treated as "unset" throughout: Lua API, network protocol, and client all use the same convention. The shadow direction is always sent as a v3f on the wire (no flag byte), with {0,0,0} meaning "use default sun/moon-based direction". Removed dead code: the timeoftheday fmod computation in updateShadows() was unused even before this change, and is now removed. The remaining timeoftheday variable is scoped to the else branch where it is needed. Updated TOCLIENT_SET_LIGHTING packet documentation in networkprotocol.h to reflect all fields actually sent and parsed, plus the new shadow direction. Network compatibility: the new field is appended to the end of the packet. Old clients ignore the extra bytes. New clients handle missing bytes via the existing hasRemainingBytes() pattern, falling back to sun/moon-based shadows when the server does not send a direction. Bump LATEST_PROTOCOL_VERSION to 52 so servers can tell older clients to disable shadows, or an alternative skybox, or no skybox, otherwise things will look really weird for those players. Also bump unittests' list of core versions.
1 parent 3b67e73 commit dc5d3a7

File tree

9 files changed

+43
-7
lines changed

9 files changed

+43
-7
lines changed

builtin/game/misc_s.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ core.protocol_versions = {
133133
["5.13.0"] = 49,
134134
["5.14.0"] = 50,
135135
["5.15.0"] = 51,
136+
["5.16.0"] = 52,
136137
}
137138

138139
setmetatable(core.protocol_versions, {__newindex = function()

doc/lua_api.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9147,6 +9147,11 @@ child will follow movement and rotation of that bone.
91479147
* `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness)
91489148
* `tint` tints the shadows with the provided color, with RGB values ranging from 0 to 255.
91499149
(default `{r=0, g=0, b=0}`)
9150+
* `direction` is a direction vector that can override the direction of the light,
9151+
disregarding the sun/moon position. This is useful for custom skyboxes.
9152+
The default is a zero vector and disables the override.
9153+
Note: the vector points "outwards" so that `(0, 1, 0)` is equivalent to
9154+
the sun at midday shining straight down.
91509155
* `exposure` is a table that controls automatic exposure.
91519156
The basic exposure factor equation is `e = 2^exposure_correction / clamp(luminance, 2^luminance_min, 2^luminance_max)`
91529157
* This has no effect on clients who have the "Automatic Exposure" effect disabled.

src/client/game.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3591,17 +3591,23 @@ void Game::updateShadows()
35913591

35923592
float in_timeofday = std::fmod(runData.time_of_day_smooth, 1.0f);
35933593

3594-
float timeoftheday = getWickedTimeOfDay(in_timeofday);
3595-
bool is_day = timeoftheday > 0.25 && timeoftheday < 0.75;
3596-
bool is_shadow_visible = is_day ? sky->getSunVisible() : sky->getMoonVisible();
35973594
const auto &lighting = client->getEnv().getLocalPlayer()->getLighting();
3598-
shadow->setShadowIntensity(is_shadow_visible ? lighting.shadow_intensity : 0.0f);
35993595
shadow->setShadowTint(lighting.shadow_tint);
36003596

3601-
timeoftheday = std::fmod(timeoftheday + 0.75f, 0.5f) + 0.25f;
36023597
const float offset_constant = 10000.0f;
36033598

3604-
v3f light = is_day ? sky->getSunDirection() : sky->getMoonDirection();
3599+
v3f light;
3600+
if (lighting.shadow_direction.getLengthSQ() > 0.0f) {
3601+
// Custom shadow direction: bypass sun/moon visibility check
3602+
shadow->setShadowIntensity(lighting.shadow_intensity);
3603+
light = lighting.shadow_direction;
3604+
} else {
3605+
float timeoftheday = getWickedTimeOfDay(in_timeofday);
3606+
bool is_day = timeoftheday > 0.25f && timeoftheday < 0.75f;
3607+
bool is_shadow_visible = is_day ? sky->getSunVisible() : sky->getMoonVisible();
3608+
shadow->setShadowIntensity(is_shadow_visible ? lighting.shadow_intensity : 0.0f);
3609+
light = is_day ? sky->getSunDirection() : sky->getMoonDirection();
3610+
}
36053611

36063612
v3f sun_pos = light * offset_constant;
36073613
shadow->getDirectionalLight().setDirection(sun_pos);

src/lighting.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#pragma once
66
#include "SColor.h"
7+
#include "irr_v3d.h"
78

89

910
/**
@@ -51,4 +52,5 @@ struct Lighting
5152
float bloom_intensity {0.05f};
5253
float bloom_strength_factor {1.0f};
5354
float bloom_radius {1.0f};
55+
v3f shadow_direction;
5456
};

src/network/clientpackethandler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,5 +1875,10 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
18751875
*pkt >> lighting.bloom_intensity
18761876
>> lighting.bloom_strength_factor
18771877
>> lighting.bloom_radius;
1878+
1879+
if (!pkt->hasRemainingBytes())
1880+
break;
1881+
// >= 5.16.0-dev
1882+
*pkt >> lighting.shadow_direction;
18781883
} while (0);
18791884
}

src/network/networkprotocol.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
*/
7878

7979
// Note: Also update core.protocol_versions in builtin when bumping
80-
const u16 LATEST_PROTOCOL_VERSION = 51;
80+
const u16 LATEST_PROTOCOL_VERSION = 52;
8181

8282
// See also formspec [Version History] in doc/lua_api.md
8383
const u16 FORMSPEC_API_VERSION = 10;

src/network/networkprotocol.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,13 @@ enum ToClientCommand : u16
692692
f32 speed_dark_bright
693693
f32 speed_bright_dark
694694
f32 center_weight_power
695+
f32 volumetric_light_strength
696+
SColor shadow_tint
697+
bloom parameters
698+
f32 bloom_intensity
699+
f32 bloom_strength_factor
700+
f32 bloom_radius
701+
v3f shadow_direction ({0,0,0} = unset)
695702
*/
696703

697704
TOCLIENT_SPAWN_PARTICLE_BATCH = 0x64,

src/script/lua_api/l_object.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,6 +2691,10 @@ int ObjectRef::l_set_lighting(lua_State *L)
26912691
lua_getfield(L, -1, "tint");
26922692
read_color(L, -1, &lighting.shadow_tint);
26932693
lua_pop(L, 1); // tint
2694+
lua_getfield(L, -1, "direction");
2695+
if (!lua_isnil(L, -1))
2696+
lighting.shadow_direction = check_v3f(L, -1);
2697+
lua_pop(L, 1); // direction
26942698
}
26952699
lua_pop(L, 1); // shadows
26962700

@@ -2744,6 +2748,10 @@ int ObjectRef::l_get_lighting(lua_State *L)
27442748
lua_setfield(L, -2, "intensity");
27452749
push_ARGB8(L, lighting.shadow_tint);
27462750
lua_setfield(L, -2, "tint");
2751+
if (lighting.shadow_direction.getLengthSQ() > 0.0f) {
2752+
push_v3f(L, lighting.shadow_direction);
2753+
lua_setfield(L, -2, "direction");
2754+
}
27472755
lua_setfield(L, -2, "shadows");
27482756
lua_pushnumber(L, lighting.saturation);
27492757
lua_setfield(L, -2, "saturation");

src/server.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,6 +2024,8 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
20242024
pkt << lighting.bloom_intensity << lighting.bloom_strength_factor <<
20252025
lighting.bloom_radius;
20262026

2027+
pkt << lighting.shadow_direction;
2028+
20272029
Send(&pkt);
20282030
}
20292031

0 commit comments

Comments
 (0)