package com.hypixel.hytale.builtin.beds.sleep.systems.world;
import com.hypixel.hytale.builtin.beds.sleep.components.PlayerSleep;
import com.hypixel.hytale.builtin.beds.sleep.components.PlayerSomnolence;
import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSleep;
import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSlumber;
import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSomnolence;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.system.DelayedSystem;
import com.hypixel.hytale.server.core.modules.time.WorldTimeResource;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Collection;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
public class StartSlumberSystem extends DelayedSystem<EntityStore> {
public static final Duration NODDING_OFF_DURATION = Duration.ofMillis(3200L);
public static final Duration WAKE_UP_AUTOSLEEP_DELAY = Duration.ofHours(1L);
public StartSlumberSystem() {
super(0.3F);
}
public void delayedTick(float dt, int systemIndex, @Nonnull Store<EntityStore> store) {
this.checkIfEveryoneIsReadyToSleep(store);
}
private void checkIfEveryoneIsReadyToSleep(Store<EntityStore> store) {
World world = ((EntityStore)store.getExternalData()).getWorld();
Collection<PlayerRef> playerRefs = world.getPlayerRefs();
if (!playerRefs.isEmpty()) {
if (!CanSleepInWorld.check(world).isNegative()) {
float wakeUpHour = world.getGameplayConfig().getWorldConfig().getSleepConfig().getWakeUpHour();
WorldSomnolence worldSomnolenceResource = (WorldSomnolence)store.getResource(WorldSomnolence.getResourceType());
WorldSleep worldState = worldSomnolenceResource.getState();
if (worldState == WorldSleep.Awake.INSTANCE) {
if (this.isEveryoneReadyToSleep(store)) {
WorldTimeResource timeResource = (WorldTimeResource)store.getResource(WorldTimeResource.getResourceType());
Instant now = timeResource.getGameTime();
Instant target = this.computeWakeupInstant(now, wakeUpHour);
float irlSeconds = computeIrlSeconds(now, target);
worldSomnolenceResource.setState(new WorldSlumber(now, target, irlSeconds));
store.forEachEntityParallel(PlayerSomnolence.getComponentType(), (index, archetypeChunk, commandBuffer) -> {
Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
commandBuffer.putComponent(ref, PlayerSomnolence.getComponentType(), PlayerSleep.Slumber.createComponent(timeResource));
});
}
}
}
}
}
private Instant computeWakeupInstant(@Nonnull Instant now, float wakeUpHour) {
LocalDateTime ldt = LocalDateTime.ofInstant(now, ZoneOffset.UTC);
int hours = (int)wakeUpHour;
float fractionalHour = wakeUpHour - (float)hours;
LocalDateTime wakeUpTime = ldt.toLocalDate().atTime(hours, (int)(fractionalHour * 60.0F));
if (!ldt.isBefore(wakeUpTime)) {
wakeUpTime = wakeUpTime.plusDays(1L);
}
return wakeUpTime.toInstant(ZoneOffset.UTC);
}
private static float computeIrlSeconds(Instant startInstant, Instant targetInstant) {
long ms = Duration.between(startInstant, targetInstant).toMillis();
long hours = TimeUnit.MILLISECONDS.toHours(ms);
double seconds = Math.max(3.0, (double)hours / 6.0);
return (float)Math.ceil(seconds);
}
private boolean isEveryoneReadyToSleep(ComponentAccessor<EntityStore> store) {
World world = ((EntityStore)store.getExternalData()).getWorld();
Collection<PlayerRef> playerRefs = world.getPlayerRefs();
if (playerRefs.isEmpty()) {
return false;
} else {
for(PlayerRef playerRef : playerRefs) {
if (!isReadyToSleep(store, playerRef.getReference())) {
return false;
}
}
return true;
}
}
public static boolean isReadyToSleep(ComponentAccessor<EntityStore> store, Ref<EntityStore> ref) {
PlayerSomnolence somnolence = (PlayerSomnolence)store.getComponent(ref, PlayerSomnolence.getComponentType());
if (somnolence == null) {
return false;
} else {
PlayerSleep sleepState = somnolence.getSleepState();
Objects.requireNonNull(sleepState);
byte var5 = 0;
boolean var10000;
switch (sleepState.typeSwitch<invokedynamic>(sleepState, var5)) {
case 0:
PlayerSleep.FullyAwake fullyAwake = (PlayerSleep.FullyAwake)sleepState;
var10000 = false;
break;
case 1:
PlayerSleep.MorningWakeUp morningWakeUp = (PlayerSleep.MorningWakeUp)sleepState;
WorldTimeResource worldTimeResource = (WorldTimeResource)store.getResource(WorldTimeResource.getResourceType());
Instant readyTime = morningWakeUp.gameTimeStart().plus(WAKE_UP_AUTOSLEEP_DELAY);
var10000 = worldTimeResource.getGameTime().isAfter(readyTime);
break;
case 2:
PlayerSleep.NoddingOff noddingOff = (PlayerSleep.NoddingOff)sleepState;
Instant sleepStart = noddingOff.realTimeStart().plus(NODDING_OFF_DURATION);
var10000 = Instant.now().isAfter(sleepStart);
break;
case 3:
PlayerSleep.Slumber slumber = (PlayerSleep.Slumber)sleepState;
var10000 = true;
break;
default:
throw new MatchException((String)null, (Throwable)null);
}
return var10000;
}
}
}