time-proof usages of tick

This commit is contained in:
Isse 2023-09-28 01:03:42 +02:00
parent b11aac2b5b
commit a152e4dfb4
17 changed files with 121 additions and 66 deletions

View File

@ -52,22 +52,24 @@ layout(location = 1) out uvec4 tgt_mat;
#include <light.glsl> #include <light.glsl>
#include <lod.glsl> #include <lod.glsl>
vec4 water_col(vec4 posx, vec4 posy) { vec4 water_col(vec2 pos) {
posx = (posx + focus_off.x) * 0.1; pos = pos + focus_off.xy;
posy = (posy + focus_off.y) * 0.1; vec2 v = floor(f_vel);
float x0 = tick_loop(1, -v.x * 0.1, pos.x * 0.1);
float x1 = tick_loop(1, -(v.x + 1) * 0.1, pos.x * 0.1);
float y0 = tick_loop(1, -v.y * 0.1, pos.y * 0.1);
float y1 = tick_loop(1, -(v.y + 1) * 0.1, pos.y * 0.1);
return 0.5 + (vec4( return 0.5 + (vec4(
textureLod(sampler2D(t_noise, s_noise), vec2(posx.x, posy.x), 0).x, textureLod(sampler2D(t_noise, s_noise), vec2(x0, y0), 0).x,
textureLod(sampler2D(t_noise, s_noise), vec2(posx.y, posy.y), 0).x, textureLod(sampler2D(t_noise, s_noise), vec2(x1, y0), 0).x,
textureLod(sampler2D(t_noise, s_noise), vec2(posx.z, posy.z), 0).x, textureLod(sampler2D(t_noise, s_noise), vec2(x0, y1), 0).x,
textureLod(sampler2D(t_noise, s_noise), vec2(posx.w, posy.w), 0).x textureLod(sampler2D(t_noise, s_noise), vec2(x1, y1), 0).x
) - 0.5) * 1.0; ) - 0.5) * 1.0;
} }
float water_col_vel(vec2 pos){ float water_col_vel(vec2 pos){
vec4 cols = water_col( vec4 cols = water_col(pos);
pos.x - tick.x * floor(f_vel.x) - vec2(0.0, tick.x).xyxy,
pos.y - tick.x * floor(f_vel.y) - vec2(0.0, tick.x).xxyy
);
return mix( return mix(
mix(cols.x, cols.y, fract(f_vel.x + 1.0)), mix(cols.x, cols.y, fract(f_vel.x + 1.0)),
mix(cols.z, cols.w, fract(f_vel.x + 1.0)), mix(cols.z, cols.w, fract(f_vel.x + 1.0)),
@ -183,7 +185,7 @@ void main() {
// vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0)); // vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0));
float max_light = 0.0; float max_light = 0.0;
max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, sun_view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, /*vec3(0.0)*/k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light); max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, /*time_of_day.x*//*-cam_to_frag*/sun_view_dir/*view_dir*/, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, /*vec3(0.0)*/k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
emitted_light *= not_underground; emitted_light *= not_underground;
reflected_light *= not_underground; reflected_light *= not_underground;

View File

@ -54,13 +54,16 @@ layout(location = 1) out uvec4 tgt_mat;
#include <light.glsl> #include <light.glsl>
#include <lod.glsl> #include <lod.glsl>
void wave_dx(vec4 posx, vec4 posy, vec2 dir, float speed, float frequency, float timeshift, out vec4 wave, out vec4 dx) { void wave_dx(vec2 pos, vec2 dir, float speed, float frequency, float factor, vec4 accumx, vec4 accumy, out vec4 wave, out vec4 dx) {
vec2 v = floor(f_vel);
float ff = frequency * factor;
vec4 x = vec4( vec4 x = vec4(
dot(dir, vec2(posx.x, posy.x)), tick_loop(2.0 * PI, speed - ff * (dir.x * v.x + dir.y * v.y), frequency * (dir.x * (factor * pos.x + accumx.x) + dir.y * (factor * pos.y + accumy.x))),
dot(dir, vec2(posx.y, posy.y)), tick_loop(2.0 * PI, speed - ff * (dir.x * (v.x + 1.0) + dir.y * v.y), frequency * (dir.x * (factor * pos.x + accumx.y) + dir.y * (factor * pos.y + accumy.y))),
dot(dir, vec2(posx.z, posy.z)), tick_loop(2.0 * PI, speed - ff * (dir.x * v.x + dir.y * (v.y + 1.0)), frequency * (dir.x * (factor * pos.x + accumx.z) + dir.y * (factor * pos.y + accumy.z))),
dot(dir, vec2(posx.w, posy.w)) tick_loop(2.0 * PI, speed - ff * (dir.x * (v.x + 1.0) + dir.y * (v.y + 1.0)), frequency * (dir.x * (factor * pos.x + accumx.w) + dir.y * (factor * pos.y + accumy.w)))
) * frequency + timeshift * speed; );
wave = sin(x) + 0.5; wave = sin(x) + 0.5;
wave *= wave; wave *= wave;
dx = -wave * cos(x); dx = -wave * cos(x);
@ -70,7 +73,7 @@ void wave_dx(vec4 posx, vec4 posy, vec2 dir, float speed, float frequency, float
// Modified to allow calculating the wave function 4 times at once using different positions (used for intepolation // Modified to allow calculating the wave function 4 times at once using different positions (used for intepolation
// for moving water). The general idea is to sample the wave function at different positions, where those positions // for moving water). The general idea is to sample the wave function at different positions, where those positions
// depend on increments of the velocity, and then interpolate between those velocities to get a smooth water velocity. // depend on increments of the velocity, and then interpolate between those velocities to get a smooth water velocity.
vec4 wave_height(vec4 posx, vec4 posy) { vec4 wave_height(vec2 pos) {
float iter = 0.0; float iter = 0.0;
float phase = 4.0; float phase = 4.0;
float weight = 1.5; float weight = 1.5;
@ -79,27 +82,28 @@ vec4 wave_height(vec4 posx, vec4 posy) {
const float speed_per_iter = 0.1; const float speed_per_iter = 0.1;
#if (FLUID_MODE == FLUID_MODE_HIGH) #if (FLUID_MODE == FLUID_MODE_HIGH)
float speed = 1.0; float speed = 1.0;
posx *= 0.2; float factor = 0.2;
posy *= 0.2;
const float drag_factor = 0.035; const float drag_factor = 0.035;
const int iters = 21; const int iters = 21;
const float scale = 15.0; const float scale = 15.0;
#else #else
float speed = 2.0; float speed = 2.0;
posx *= 0.3; float factor = 0.3;
posy *= 0.3;
const float drag_factor = 0.04; const float drag_factor = 0.04;
const int iters = 11; const int iters = 11;
const float scale = 3.0; const float scale = 3.0;
#endif #endif
const float iter_shift = (3.14159 * 2.0) / 7.3; const float iter_shift = (3.14159 * 2.0) / 7.3;
vec4 accumx = vec4(0);
vec4 accumy = vec4(0);
for(int i = 0; i < iters; i ++) { for(int i = 0; i < iters; i ++) {
vec2 p = vec2(sin(iter), cos(iter)); vec2 p = vec2(sin(iter), cos(iter));
vec4 wave, dx; vec4 wave, dx;
wave_dx(posx, posy, p, speed, phase, tick.x, wave, dx); wave_dx(pos, p, speed, phase, factor, accumx, accumy, wave, dx);
posx += p.x * dx * weight * drag_factor; accumx += p.x * dx * weight * drag_factor;
posy += p.y * dx * weight * drag_factor; accumy += p.y * dx * weight * drag_factor;
w += wave * weight; w += wave * weight;
iter += iter_shift * 1.5; iter += iter_shift * 1.5;
ws += weight; ws += weight;
@ -111,10 +115,7 @@ vec4 wave_height(vec4 posx, vec4 posy) {
} }
float wave_height_vel(vec2 pos) { float wave_height_vel(vec2 pos) {
vec4 heights = wave_height( vec4 heights = wave_height(pos);
pos.x - tick.x * floor(f_vel.x) - vec2(0.0, tick.x).xyxy,
pos.y - tick.x * floor(f_vel.y) - vec2(0.0, tick.x).xxyy
);
return mix( return mix(
mix(heights.x, heights.y, fract(f_vel.x + 1.0)), mix(heights.x, heights.y, fract(f_vel.x + 1.0)),
mix(heights.z, heights.w, fract(f_vel.x + 1.0)), mix(heights.z, heights.w, fract(f_vel.x + 1.0)),

View File

@ -65,7 +65,7 @@ void main() {
// Terrain 'pop-in' effect // Terrain 'pop-in' effect
#ifndef EXPERIMENTAL_BAREMINIMUM #ifndef EXPERIMENTAL_BAREMINIMUM
#ifndef EXPERIMENTAL_NOTERRAINPOP #ifndef EXPERIMENTAL_NOTERRAINPOP
f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0)); f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(time_since(load_time), 10.0), 1.0));
// f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0)); // f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0));
#endif #endif
#endif #endif

View File

@ -39,4 +39,24 @@ mat4 threshold_matrix = mat4(
float distance_divider = 2; float distance_divider = 2;
float shadow_dithering = 0.5; float shadow_dithering = 0.5;
float tick_loop_time = 300000.0;
// Get a scaled time with an offset that loops at a period.
float tick_loop(float period, float scale, float offset) {
float loop = tick_loop_time * scale;
float rem = mod(loop, period);
float rest = rem * tick.y;
return mod(rest + tick.x * scale + offset, period);
}
float tick_loop(float period) {
return tick_loop(period, 1.0, 0.0);
}
// Only works if t happened within tick_loop_time
float time_since(float t) {
return tick.x > t ? (tick_loop_time - t + tick.x) : (tick.x - t);
}
#endif #endif

View File

@ -58,7 +58,7 @@ vec3 apply_point_glow(vec3 wpos, vec3 dir, float max_dist, vec3 color) {
#endif #endif
#ifdef FLASHING_LIGHTS_ENABLED #ifdef FLASHING_LIGHTS_ENABLED
float time_since_lightning = tick.x - last_lightning.w; float time_since_lightning = time_since(last_lightning.w);
if (time_since_lightning < MAX_LIGHTNING_PERIOD) { if (time_since_lightning < MAX_LIGHTNING_PERIOD) {
// Apply lightning // Apply lightning
apply_point_glow_light(Light(last_lightning.xyzw + vec4(0, 0, LIGHTNING_HEIGHT, 0), vec4(vec3(0.2, 0.4, 1) * lightning_intensity() * 0.003, 1)), wpos, dir, max_dist, color); apply_point_glow_light(Light(last_lightning.xyzw + vec4(0, 0, LIGHTNING_HEIGHT, 0), vec4(vec3(0.2, 0.4, 1) * lightning_intensity() * 0.003, 1)), wpos, dir, max_dist, color);

View File

@ -17,7 +17,7 @@ struct DirectionalLight {
// float brightness; // float brightness;
}; };
const float PI = 3.141592; const float PI = 3.141592653;
const vec3 SKY_DAWN_TOP = vec3(0.10, 0.1, 0.10); const vec3 SKY_DAWN_TOP = vec3(0.10, 0.1, 0.10);
const vec3 SKY_DAWN_MID = vec3(1.2, 0.3, 0.2); const vec3 SKY_DAWN_MID = vec3(1.2, 0.3, 0.2);
@ -236,7 +236,7 @@ const float LIGHTNING_HEIGHT = 25.0;
const float MAX_LIGHTNING_PERIOD = 5.0; const float MAX_LIGHTNING_PERIOD = 5.0;
float lightning_intensity() { float lightning_intensity() {
float time_since_lightning = tick.x - last_lightning.w; float time_since_lightning = time_since(last_lightning.w);
return return
// Strength // Strength
1000000 1000000
@ -247,7 +247,7 @@ float lightning_intensity() {
} }
vec3 lightning_at(vec3 wpos) { vec3 lightning_at(vec3 wpos) {
float time_since_lightning = tick.x - last_lightning.w; float time_since_lightning = time_since(last_lightning.w);
if (time_since_lightning < MAX_LIGHTNING_PERIOD) { if (time_since_lightning < MAX_LIGHTNING_PERIOD) {
vec3 diff = wpos + focus_off.xyz - (last_lightning.xyz + vec3(0, 0, LIGHTNING_HEIGHT)); vec3 diff = wpos + focus_off.xyz - (last_lightning.xyz + vec3(0, 0, LIGHTNING_HEIGHT));
float dist = length(diff); float dist = length(diff);

View File

@ -20,7 +20,7 @@
layout(location = 0) in vec3 v_pos; layout(location = 0) in vec3 v_pos;
// in uint v_col; // in uint v_col;
layout(location = 1) in uint v_norm_ao; layout(location = 1) in uint v_norm_ao;
layout(location = 2) in float inst_time; layout(location = 2) in vec3 inst_time;
layout(location = 3) in float inst_lifespan; layout(location = 3) in float inst_lifespan;
layout(location = 4) in float inst_entropy; layout(location = 4) in float inst_entropy;
layout(location = 5) in int inst_mode; layout(location = 5) in int inst_mode;
@ -94,7 +94,13 @@ struct Attr {
mat4 rot; mat4 rot;
}; };
float lifetime = tick.x - inst_time; float lifetime = max((tick.y - inst_time.y - 1.0), 0.0) * tick_loop_time + (tick.y > inst_time.y ? (tick_loop_time - inst_time.x + tick.x) : (tick.x - inst_time.x));
float loop_inst_time(float period) {
float rest = mod(tick_loop_time, period) * inst_time.y;
return mod(rest + inst_time.x, period);
}
vec3 linear_motion(vec3 init_offs, vec3 vel) { vec3 linear_motion(vec3 init_offs, vec3 vel) {
return init_offs + vel * lifetime; return init_offs + vel * lifetime;
@ -419,14 +425,14 @@ void main() {
break; break;
case LIFESTEAL_BEAM: case LIFESTEAL_BEAM:
f_reflect = 0.0; f_reflect = 0.0;
float green_col = 0.8 + 0.8 * sin(tick.x * 5 + lifetime * 5); float green_col = 0.8 + 0.8 * sin(tick_loop(2 * PI, 5, lifetime * 5));
float purple_col = 0.6 + 0.5 * sin(tick.x * 4 - lifetime * 4) - min(max(green_col - 1, 0), 0.3); float purple_col = 0.6 + 0.5 * sin(tick_loop(2 * PI, 4, lifetime * 4)) - min(max(green_col - 1, 0), 0.3);
float red_col = 1.15 + 0.1 * sin(tick.x * 3 - lifetime * 3) - min(max(green_col - 1, 0), 0.3) - max(purple_col - 0.5, 0); float red_col = 1.15 + 0.1 * sin(tick_loop(2 * PI, 3, lifetime * 3)) - min(max(green_col - 1, 0), 0.3) - max(purple_col - 0.5, 0);
attr = Attr( attr = Attr(
spiral_motion(inst_dir, 0.3 * (floor(2 * rand0 + 0.5) - 0.5) * min(linear_scale(10), 1), lifetime / inst_lifespan, 10.0, inst_time), spiral_motion(inst_dir, 0.3 * (floor(2 * rand0 + 0.5) - 0.5) * min(linear_scale(10), 1), lifetime / inst_lifespan, 10.0, loop_inst_time(PI * 2.0)),
vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 4))), vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick_loop(2 * PI, 10, lifetime * 4)))),
vec4(vec3(red_col + purple_col * 0.6, green_col + purple_col * 0.35, purple_col), 1), vec4(vec3(red_col + purple_col * 0.6, green_col + purple_col * 0.35, purple_col), 1),
spin_in_axis(inst_dir, tick.z) spin_in_axis(inst_dir, tick_loop(2 * PI))
); );
break; break;
case ENERGY_NATURE: case ENERGY_NATURE:

View File

@ -244,7 +244,9 @@ void main() {
vec2 sample_uv = uv; vec2 sample_uv = uv;
#ifdef EXPERIMENTAL_UNDERWARPER #ifdef EXPERIMENTAL_UNDERWARPER
if (medium.x == MEDIUM_WATER) { if (medium.x == MEDIUM_WATER) {
sample_uv += sin(uv.yx * 60 + tick.xx * 3.0) * 0.003; float x = tick_loop(2.0 * PI, 3.0, uv.y * 60);
float y = tick_loop(2.0 * PI, 3.0, uv.x * 60);
sample_uv += sin(vec2(x, y)) * 0.003;
} }
#endif #endif

View File

@ -83,8 +83,8 @@ float wind_wave(float off, float scaling, float speed, float strength) {
strength = max(strength, 6.0); strength = max(strength, 6.0);
aspeed = max(aspeed, 5.0); aspeed = max(aspeed, 5.0);
return (sin(tick.x * 0.35 * scaling * floor(aspeed) + off) * (1.0 - fract(aspeed)) return (sin(tick_loop(2.0 * PI, 0.35 * scaling * floor(aspeed), off)) * (1.0 - fract(aspeed))
+ sin(tick.x * 0.35 * scaling * ceil(aspeed) + off) * fract(aspeed)) * abs(strength) * 0.25; + sin(tick_loop(2.0 * PI, 0.35 * scaling * ceil(aspeed), off)) * fract(aspeed)) * abs(strength) * 0.25;
//return sin(tick.x * 1.5 * scaling + off) + sin(tick.x * 0.35 * scaling + off); //return sin(tick.x * 1.5 * scaling + off) + sin(tick.x * 0.35 * scaling + off);
} }
@ -152,7 +152,7 @@ void main() {
#ifndef EXPERIMENTAL_BAREMINIMUM #ifndef EXPERIMENTAL_BAREMINIMUM
#ifndef EXPERIMENTAL_NOTERRAINPOP #ifndef EXPERIMENTAL_NOTERRAINPOP
// Terrain 'pop-in' effect // Terrain 'pop-in' effect
f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0)); f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(time_since(load_time), 10.0), 1.0));
#endif #endif
#endif #endif

View File

@ -267,12 +267,14 @@ void main() {
if (puddle > 0.0) { if (puddle > 0.0) {
f_alpha = puddle * 0.2 * max(1.0 + cam_to_frag.z, 0.3); f_alpha = puddle * 0.2 * max(1.0 + cam_to_frag.z, 0.3);
#ifdef EXPERIMENTAL_PUDDLEDETAILS #ifdef EXPERIMENTAL_PUDDLEDETAILS
float h = (noise_2d((f_pos.xy + focus_off.xy) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3) let t0 = sin(tick_loop(2.0 * PI, 8.0, f_pos.x * 3));
+ (noise_2d((f_pos.xy + focus_off.xy) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6); let t1 = sin(tick_loop(2.0 * PI, 3.5, -f_pos.x * 6));
float hx = (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3) float h = (noise_2d((f_pos.xy + focus_off.xy) * 0.3) - 0.5) * t0
+ (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6); + (noise_2d((f_pos.xy + focus_off.xy) * 0.6) - 0.5) * t1;
float hy = (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3) float hx = (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.3) - 0.5) * t0
+ (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6); + (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.6) - 0.5) * t1;
float hy = (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.3) - 0.5) * t0
+ (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.6) - 0.5) * t1;
f_norm.xy += mix(vec2(0), vec2(h - hx, h - hy) / 0.1 * 0.03, puddle); f_norm.xy += mix(vec2(0), vec2(h - hx, h - hy) / 0.1 * 0.03, puddle);
#endif #endif
alpha = mix(1.0, 0.2, puddle); alpha = mix(1.0, 0.2, puddle);

View File

@ -82,7 +82,7 @@ void main() {
// Terrain 'pop-in' effect // Terrain 'pop-in' effect
#ifndef EXPERIMENTAL_BAREMINIMUM #ifndef EXPERIMENTAL_BAREMINIMUM
#ifndef EXPERIMENTAL_NOTERRAINPOP #ifndef EXPERIMENTAL_NOTERRAINPOP
v_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0)); v_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(time_since(load_time), 10.0), 1.0));
// f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0)); // f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0));
#endif #endif
#endif #endif

View File

@ -376,6 +376,7 @@ impl Client {
let ServerInit::GameSync { let ServerInit::GameSync {
entity_package, entity_package,
time_of_day, time_of_day,
true_time,
max_group_size, max_group_size,
client_timeout, client_timeout,
world_map, world_map,
@ -414,6 +415,7 @@ impl Client {
state.ecs_mut().register::<comp::Last<CharacterState>>(); state.ecs_mut().register::<comp::Last<CharacterState>>();
let entity = state.ecs_mut().apply_entity_package(entity_package); let entity = state.ecs_mut().apply_entity_package(entity_package);
*state.ecs_mut().write_resource() = time_of_day; *state.ecs_mut().write_resource() = time_of_day;
*state.ecs_mut().write_resource() = true_time;
*state.ecs_mut().write_resource() = PlayerEntity(Some(entity)); *state.ecs_mut().write_resource() = PlayerEntity(Some(entity));
state.ecs_mut().insert(material_stats); state.ecs_mut().insert(material_stats);
state.ecs_mut().insert(ability_map); state.ecs_mut().insert(ability_map);
@ -2276,12 +2278,13 @@ impl Client {
self.target_time_of_day = Some(time_of_day); self.target_time_of_day = Some(time_of_day);
*self.state.ecs_mut().write_resource() = calendar; *self.state.ecs_mut().write_resource() = calendar;
*self.state.ecs_mut().write_resource() = new_true_time; *self.state.ecs_mut().write_resource() = new_true_time;
*self.state.ecs_mut().write_resource() = time_scale;
let mut time = self.state.ecs_mut().write_resource::<Time>(); let mut time = self.state.ecs_mut().write_resource::<Time>();
// Avoid side-eye from Einstein // Avoid side-eye from Einstein
// If new time from server is at least 5 seconds ahead, replace client time. // If new time from server is at least 5 seconds ahead, replace client time.
// Otherwise try to slightly twean client time (by 1%) to keep it in line with // Otherwise try to slightly twean client time (by 1%) to keep it in line with
// server time. // server time.
let dt_adjustment = if new_time.0 > time.0 + 5.0 { self.dt_adjustment = if new_time.0 > time.0 + 5.0 {
*time = new_time; *time = new_time;
1.0 1.0
} else if new_time.0 > time.0 { } else if new_time.0 > time.0 {
@ -2289,7 +2292,6 @@ impl Client {
} else { } else {
0.99 0.99
}; };
self.dt_adjustment = dt_adjustment * time_scale.0;
}, },
ServerGeneral::EntitySync(entity_sync_package) => { ServerGeneral::EntitySync(entity_sync_package) => {
let uid = self.uid(); let uid = self.uid();
@ -2693,6 +2695,8 @@ impl Client {
&& self.state.get_true_time() - self.last_server_pong && self.state.get_true_time() - self.last_server_pong
> self.client_timeout.as_secs() as f64 > self.client_timeout.as_secs() as f64
{ {
dbg!(self.state.get_true_time());
dbg!(self.last_server_pong);
return Err(Error::ServerTimeout); return Err(Error::ServerTimeout);
} }

View File

@ -60,6 +60,7 @@ pub enum ServerInit {
GameSync { GameSync {
entity_package: sync::EntityPackage<EcsCompPacket>, entity_package: sync::EntityPackage<EcsCompPacket>,
time_of_day: TimeOfDay, time_of_day: TimeOfDay,
true_time: TrueTime,
max_group_size: u32, max_group_size: u32,
client_timeout: Duration, client_timeout: Duration,
world_map: crate::msg::world_msg::WorldMapMsg, world_map: crate::msg::world_msg::WorldMapMsg,

View File

@ -2,7 +2,7 @@ use crate::client::Client;
use common::{ use common::{
comp::{ChatMode, ChatType, Content, Group, Player}, comp::{ChatMode, ChatType, Content, Group, Player},
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
resources::Time, resources::TrueTime,
uid::Uid, uid::Uid,
}; };
use common_ecs::{Job, Origin, Phase, System}; use common_ecs::{Job, Origin, Phase, System};
@ -81,7 +81,7 @@ impl<'a> System<'a> for Sys {
type SystemData = ( type SystemData = (
Entities<'a>, Entities<'a>,
Read<'a, EventBus<ServerEvent>>, Read<'a, EventBus<ServerEvent>>,
Read<'a, Time>, Read<'a, TrueTime>,
ReadStorage<'a, Uid>, ReadStorage<'a, Uid>,
ReadStorage<'a, ChatMode>, ReadStorage<'a, ChatMode>,
ReadStorage<'a, Player>, ReadStorage<'a, Player>,

View File

@ -9,7 +9,7 @@ use common::{
comp::{self, Admin, Player, Stats}, comp::{self, Admin, Player, Stats},
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
recipe::{default_component_recipe_book, default_recipe_book, default_repair_recipe_book}, recipe::{default_component_recipe_book, default_recipe_book, default_repair_recipe_book},
resources::TimeOfDay, resources::{TimeOfDay, TrueTime},
shared_server_config::ServerConstants, shared_server_config::ServerConstants,
uid::{IdMaps, Uid}, uid::{IdMaps, Uid},
}; };
@ -48,6 +48,7 @@ pub struct ReadData<'a> {
settings: ReadExpect<'a, Settings>, settings: ReadExpect<'a, Settings>,
editable_settings: ReadExpect<'a, EditableSettings>, editable_settings: ReadExpect<'a, EditableSettings>,
time_of_day: Read<'a, TimeOfDay>, time_of_day: Read<'a, TimeOfDay>,
true_time: Read<'a, TrueTime>,
material_stats: ReadExpect<'a, comp::item::MaterialStatManifest>, material_stats: ReadExpect<'a, comp::item::MaterialStatManifest>,
ability_map: ReadExpect<'a, comp::item::tool::AbilityMap>, ability_map: ReadExpect<'a, comp::item::tool::AbilityMap>,
map: ReadExpect<'a, WorldMapMsg>, map: ReadExpect<'a, WorldMapMsg>,
@ -329,6 +330,7 @@ impl<'a> System<'a> for Sys {
.trackers .trackers
.create_entity_package_with_uid(entity, *uid, None, None, None), .create_entity_package_with_uid(entity, *uid, None, None, None),
time_of_day: *read_data.time_of_day, time_of_day: *read_data.time_of_day,
true_time: *read_data.true_time,
max_group_size: read_data.settings.max_player_group_size, max_group_size: read_data.settings.max_player_group_size,
client_timeout: read_data.settings.client_timeout, client_timeout: read_data.settings.client_timeout,
world_map: (*read_data.map).clone(), world_map: (*read_data.map).clone(),

View File

@ -91,6 +91,8 @@ pub struct Shadow {
pos_radius: [f32; 4], pos_radius: [f32; 4],
} }
pub const TIME_PRECISION: f64 = 300000.0;
impl Globals { impl Globals {
/// Create global consts from the provided parameters. /// Create global consts from the provided parameters.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
@ -129,13 +131,18 @@ impl Globals {
view_distance: [view_distance, tgt_detail, map_bounds.x, map_bounds.y], view_distance: [view_distance, tgt_detail, map_bounds.x, map_bounds.y],
time_of_day: [ time_of_day: [
(time_of_day % (3600.0 * 24.0)) as f32, (time_of_day % (3600.0 * 24.0)) as f32,
(time_of_day / (3600.0 * 24.0) % (300_000.0)) as f32, (time_of_day / (3600.0 * 24.0) % TIME_PRECISION) as f32,
0.0, 0.0,
0.0, 0.0,
], ],
sun_dir: Vec4::from_direction(Self::get_sun_dir(time_of_day)).into_array(), sun_dir: Vec4::from_direction(Self::get_sun_dir(time_of_day)).into_array(),
moon_dir: Vec4::from_direction(Self::get_moon_dir(time_of_day)).into_array(), moon_dir: Vec4::from_direction(Self::get_moon_dir(time_of_day)).into_array(),
tick: [tick as f32; 4], tick: [
(tick % TIME_PRECISION) as f32,
(tick / TIME_PRECISION).floor() as f32,
tick as f32,
0.0,
],
// Provide the shadow map far plane as well. // Provide the shadow map far plane as well.
screen_res: [ screen_res: [
screen_res.x as f32, screen_res.x as f32,
@ -170,7 +177,7 @@ impl Globals {
gamma_exposure: [gamma, exposure, 0.0, 0.0], gamma_exposure: [gamma, exposure, 0.0, 0.0],
last_lightning: last_lightning last_lightning: last_lightning
.0 .0
.with_w(last_lightning.1 as f32) .with_w((last_lightning.1 % TIME_PRECISION) as f32)
.into_array(), .into_array(),
wind_vel: wind_vel.into_array(), wind_vel: wind_vel.into_array(),
ambiance: ambiance.clamped(0.0, 1.0), ambiance: ambiance.clamped(0.0, 1.0),

View File

@ -109,7 +109,7 @@ impl ParticleMode {
pub struct Instance { pub struct Instance {
// created_at time, so we can calculate time relativity, needed for relative animation. // created_at time, so we can calculate time relativity, needed for relative animation.
// can save 32 bits per instance, for particles that are not relatively animated. // can save 32 bits per instance, for particles that are not relatively animated.
inst_time: f32, inst_time: [f32; 3],
// The lifespan in seconds of the particle // The lifespan in seconds of the particle
inst_lifespan: f32, inst_lifespan: f32,
@ -147,7 +147,11 @@ impl Instance {
) -> Self { ) -> Self {
use rand::Rng; use rand::Rng;
Self { Self {
inst_time: inst_time as f32, inst_time: [
(inst_time % super::TIME_PRECISION) as f32,
(inst_time / super::TIME_PRECISION).floor() as f32,
inst_time as f32,
],
inst_lifespan: lifespan, inst_lifespan: lifespan,
inst_entropy: rand::thread_rng().gen(), inst_entropy: rand::thread_rng().gen(),
inst_mode: inst_mode as i32, inst_mode: inst_mode as i32,
@ -165,7 +169,11 @@ impl Instance {
) -> Self { ) -> Self {
use rand::Rng; use rand::Rng;
Self { Self {
inst_time: inst_time as f32, inst_time: [
(inst_time % super::TIME_PRECISION) as f32,
(inst_time / super::TIME_PRECISION).floor() as f32,
inst_time as f32,
],
inst_lifespan: lifespan, inst_lifespan: lifespan,
inst_entropy: rand::thread_rng().gen(), inst_entropy: rand::thread_rng().gen(),
inst_mode: inst_mode as i32, inst_mode: inst_mode as i32,
@ -175,7 +183,7 @@ impl Instance {
} }
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
const ATTRIBUTES: [wgpu::VertexAttribute; 6] = wgpu::vertex_attr_array![2 => Float32, 3 => Float32, 4 => Float32, 5 => Sint32, 6 => Float32x3, 7 => Float32x3]; const ATTRIBUTES: [wgpu::VertexAttribute; 6] = wgpu::vertex_attr_array![2 => Float32x3, 3 => Float32, 4 => Float32, 5 => Sint32, 6 => Float32x3, 7 => Float32x3];
wgpu::VertexBufferLayout { wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Self>() as wgpu::BufferAddress, array_stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Instance, step_mode: wgpu::InputStepMode::Instance,