package com.hypixel.hytale.builtin.weather.systems;
import com.hypixel.hytale.assetstore.map.IndexedLookupTableAssetMap;
import com.hypixel.hytale.builtin.weather.components.WeatherTracker;
import com.hypixel.hytale.builtin.weather.resources.WeatherResource;
import com.hypixel.hytale.common.map.IWeightedMap;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.Archetype;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.dependency.Dependency;
import com.hypixel.hytale.component.dependency.Order;
import com.hypixel.hytale.component.dependency.SystemDependency;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.system.HolderSystem;
import com.hypixel.hytale.component.system.RefChangeSystem;
import com.hypixel.hytale.component.system.StoreSystem;
import com.hypixel.hytale.component.system.tick.EntityTickingSystem;
import com.hypixel.hytale.server.core.asset.type.environment.config.Environment;
import com.hypixel.hytale.server.core.asset.type.environment.config.WeatherForecast;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.teleport.Teleport;
import com.hypixel.hytale.server.core.modules.entity.teleport.TeleportSystems;
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.storage.EntityStore;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class WeatherSystem {
private static final float JOIN_TRANSITION_SECONDS = 0.5F;
private static final float WEATHERCHANGE_TRANSITION_SECONDS = 10.0F;
public WeatherSystem() {
}
public static class WorldAddedSystem extends StoreSystem<EntityStore> {
@Nonnull
private final ResourceType<EntityStore, WeatherResource> weatherResourceType = WeatherResource.getResourceType();
public WorldAddedSystem() {
}
public void onSystemAddedToStore(@Nonnull Store<EntityStore> store) {
String forcedWeather = ((EntityStore)store.getExternalData()).getWorld().getWorldConfig().getForcedWeather();
((WeatherResource)store.getResource(this.weatherResourceType)).setForcedWeather(forcedWeather);
}
public void onSystemRemovedFromStore(@Nonnull Store<EntityStore> store) {
}
}
public static class PlayerAddedSystem extends HolderSystem<EntityStore> {
private static final ComponentType<EntityStore, PlayerRef> PLAYER_REF_COMPONENT_TYPE = PlayerRef.getComponentType();
private static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
private static final ComponentType<EntityStore, WeatherTracker> WEATHER_TRACKER_COMPONENT_TYPE = WeatherTracker.getComponentType();
private static final Query<EntityStore> QUERY;
public PlayerAddedSystem() {
}
public Query<EntityStore> getQuery() {
return QUERY;
}
public void onEntityAdd(@Nonnull Holder<EntityStore> holder, @Nonnull AddReason reason, @Nonnull Store<EntityStore> store) {
holder.ensureComponent(WEATHER_TRACKER_COMPONENT_TYPE);
}
public void onEntityRemoved(@Nonnull Holder<EntityStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store) {
WeatherTracker weatherTrackerComponent = (WeatherTracker)holder.ensureAndGetComponent(WEATHER_TRACKER_COMPONENT_TYPE);
weatherTrackerComponent.clear();
}
static {
QUERY = Archetype.of(PLAYER_REF_COMPONENT_TYPE, TRANSFORM_COMPONENT_TYPE);
}
}
public static class TickingSystem extends EntityTickingSystem<EntityStore> {
private static final ComponentType<EntityStore, PlayerRef> PLAYER_REF_COMPONENT_TYPE = PlayerRef.getComponentType();
private static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
private static final ComponentType<EntityStore, WeatherTracker> WEATHER_TRACKER_COMPONENT_TYPE = WeatherTracker.getComponentType();
private static final ResourceType<EntityStore, WeatherResource> WEATHER_RESOURCE_TYPE = WeatherResource.getResourceType();
private static final Query<EntityStore> QUERY;
public TickingSystem() {
}
public Query<EntityStore> getQuery() {
return QUERY;
}
public void tick(float dt, int systemIndex, @Nonnull Store<EntityStore> store) {
WeatherResource weatherResource = (WeatherResource)store.getResource(WEATHER_RESOURCE_TYPE);
if (weatherResource.consumeForcedWeatherChange()) {
weatherResource.playerUpdateDelay = 1.0F;
store.tick(this, dt, systemIndex);
} else {
if (weatherResource.getForcedWeatherIndex() == 0) {
WorldTimeResource worldTimeResource = (WorldTimeResource)store.getResource(WorldTimeResource.getResourceType());
int currentHour = worldTimeResource.getCurrentHour();
if (weatherResource.compareAndSwapHour(currentHour)) {
Int2IntMap environmentWeather = weatherResource.getEnvironmentWeather();
ThreadLocalRandom random = ThreadLocalRandom.current();
IndexedLookupTableAssetMap<String, Environment> assetMap = Environment.getAssetMap();
for(Map.Entry<String, Environment> entry : assetMap.getAssetMap().entrySet()) {
String key = (String)entry.getKey();
int index = assetMap.getIndex(key);
if (index == -2147483648) {
throw new IllegalArgumentException("Unknown key! " + key);
}
IWeightedMap<WeatherForecast> weatherForecast = ((Environment)entry.getValue()).getWeatherForecast(currentHour);
int selectedWeatherIndex = ((WeatherForecast)weatherForecast.get((Random)random)).getWeatherIndex();
environmentWeather.put(index, selectedWeatherIndex);
}
}
}
weatherResource.playerUpdateDelay -= dt;
if (weatherResource.playerUpdateDelay <= 0.0F) {
weatherResource.playerUpdateDelay = 1.0F;
store.tick(this, dt, systemIndex);
}
}
}
public boolean isParallel(int archetypeChunkSize, int taskCount) {
return false;
}
public void tick(float dt, int index, @Nonnull ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
WeatherResource weatherResource = (WeatherResource)store.getResource(WEATHER_RESOURCE_TYPE);
PlayerRef playerRefComponent = (PlayerRef)archetypeChunk.getComponent(index, PLAYER_REF_COMPONENT_TYPE);
assert playerRefComponent != null;
TransformComponent transformComponent = (TransformComponent)archetypeChunk.getComponent(index, TRANSFORM_COMPONENT_TYPE);
assert transformComponent != null;
WeatherTracker weatherTrackerComponent = (WeatherTracker)archetypeChunk.getComponent(index, WEATHER_TRACKER_COMPONENT_TYPE);
assert weatherTrackerComponent != null;
float transitionSeconds = weatherTrackerComponent.consumeFirstSendForWorld() ? 0.5F : 10.0F;
weatherTrackerComponent.updateWeather(playerRefComponent, weatherResource, transformComponent, transitionSeconds, commandBuffer);
}
static {
QUERY = Archetype.of(PLAYER_REF_COMPONENT_TYPE, TRANSFORM_COMPONENT_TYPE, WEATHER_TRACKER_COMPONENT_TYPE);
}
}
public static class InvalidateWeatherAfterTeleport extends RefChangeSystem<EntityStore, Teleport> {
@Nonnull
private static final Query<EntityStore> QUERY = WeatherTracker.getComponentType();
@Nonnull
private static final Set<Dependency<EntityStore>> DEPENDENCIES;
public InvalidateWeatherAfterTeleport() {
}
@Nonnull
public ComponentType<EntityStore, Teleport> componentType() {
return Teleport.getComponentType();
}
public void onComponentAdded(@Nonnull Ref<EntityStore> ref, @Nonnull Teleport component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
WeatherTracker weatherTrackerComponent = (WeatherTracker)commandBuffer.getComponent(ref, WeatherTracker.getComponentType());
assert weatherTrackerComponent != null;
weatherTrackerComponent.clear();
}
public void onComponentSet(@Nonnull Ref<EntityStore> ref, @Nullable Teleport oldComponent, @Nonnull Teleport newComponent, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
}
public void onComponentRemoved(@Nonnull Ref<EntityStore> ref, @Nonnull Teleport component, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
}
@Nullable
public Query<EntityStore> getQuery() {
return QUERY;
}
@Nonnull
public Set<Dependency<EntityStore>> getDependencies() {
return DEPENDENCIES;
}
static {
DEPENDENCIES = Set.of(new SystemDependency(Order.AFTER, TeleportSystems.PlayerMoveSystem.class));
}
}
}