package com.hypixel.hytale.builtin.deployables.config;
import com.hypixel.hytale.builtin.deployables.component.DeployableComponent;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.core.modules.entity.DespawnComponent;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.damage.DamageCause;
import com.hypixel.hytale.server.core.modules.time.TimeResource;
import com.hypixel.hytale.server.core.modules.time.WorldTimeResource;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.core.util.TargetUtil;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
public class DeployableTrapConfig extends DeployableAoeConfig {
public static final BuilderCodec<DeployableTrapConfig> CODEC;
protected float fuzeDuration = 0.0F;
protected float activeDuration = 1.0F;
protected boolean destroyOnTriggered = false;
protected DeployableTrapConfig() {
}
public void tick(@Nonnull DeployableComponent deployableComponent, float dt, int index, @Nonnull ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull Store<EntityStore> store, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
Vector3d pos = ((TransformComponent)archetypeChunk.getComponent(index, TransformComponent.getComponentType())).getPosition();
World world = ((EntityStore)store.getExternalData()).getWorld();
Ref<EntityStore> entityRef = archetypeChunk.getReferenceTo(index);
if (!deployableComponent.getOwner().isValid()) {
world.execute(() -> {
if (entityRef.isValid()) {
DespawnComponent despawn = (DespawnComponent)store.ensureAndGetComponent(entityRef, DespawnComponent.getComponentType());
WorldTimeResource timeManager = (WorldTimeResource)commandBuffer.getResource(WorldTimeResource.getResourceType());
despawn.setDespawn(timeManager.getGameTime());
}
});
} else {
float radius = this.getRadius(store, deployableComponent.getSpawnInstant());
this.handleDebugGraphics(world, deployableComponent.getDebugColor(), pos, radius * 2.0F);
switch (deployableComponent.getFlag(DeployableComponent.DeployableFlag.STATE)) {
case 0:
deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 1);
break;
case 1:
deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 2);
playAnimation(store, entityRef, this, "Grow");
break;
case 2:
if (radius >= this.endRadius) {
deployableComponent.setFlag(DeployableComponent.DeployableFlag.STATE, 3);
playAnimation(store, entityRef, this, "Looping");
}
}
Ref<EntityStore> trapRef = archetypeChunk.getReferenceTo(index);
deployableComponent.setTimeSinceLastAttack(deployableComponent.getTimeSinceLastAttack() + dt);
if (deployableComponent.getTimeSinceLastAttack() > this.damageInterval && this.isLive(store, deployableComponent)) {
deployableComponent.setTimeSinceLastAttack(0.0F);
this.handleDetection(store, commandBuffer, trapRef, deployableComponent, pos, radius, DamageCause.PHYSICAL);
}
}
}
protected void handleDetection(final Store<EntityStore> store, final CommandBuffer<EntityStore> commandBuffer, final Ref<EntityStore> deployableRef, final DeployableComponent deployableComponent, Vector3d position, float radius, final DamageCause damageCause) {
World world = ((EntityStore)store.getExternalData()).getWorld();
<undefinedtype> consumer = new Consumer<Ref<EntityStore>>() {
public void accept(Ref<EntityStore> entityStoreRef) {
if (entityStoreRef != deployableRef) {
if (store.getComponent(entityStoreRef, DeployableComponent.getComponentType()) == null) {
DeployableTrapConfig.this.attackTarget(entityStoreRef, deployableRef, damageCause, commandBuffer);
if (DeployableTrapConfig.this.destroyOnTriggered && deployableComponent.getFlag(DeployableComponent.DeployableFlag.TRIGGERED) == 0) {
DeployableTrapConfig.this.onTriggered(store, deployableRef);
deployableComponent.setFlag(DeployableComponent.DeployableFlag.TRIGGERED, 1);
}
DeployableTrapConfig.this.applyEffectToTarget(store, entityStoreRef);
}
}
}
};
switch (this.shape) {
case Sphere:
for(Ref<EntityStore> targetRef : TargetUtil.getAllEntitiesInSphere(position, (double)radius, store)) {
consumer.accept(targetRef);
}
break;
case Cylinder:
for(Ref<EntityStore> targetRef : TargetUtil.getAllEntitiesInCylinder(position, (double)radius, (double)this.height, store)) {
consumer.accept(targetRef);
}
}
}
protected boolean isLive(@Nonnull Store<EntityStore> store, @Nonnull DeployableComponent comp) {
if (comp.getFlag(DeployableComponent.DeployableFlag.LIVE) == 1) {
return true;
} else if (this.fuzeDuration == 0.0F) {
comp.setFlag(DeployableComponent.DeployableFlag.LIVE, 1);
return true;
} else {
Instant now = ((TimeResource)store.getResource(TimeResource.getResourceType())).getNow();
Instant spawnTime = comp.getSpawnInstant();
float timeDiff = (float)Duration.between(spawnTime, now).toMillis() / 1000.0F;
if (timeDiff >= this.fuzeDuration) {
comp.setFlag(DeployableComponent.DeployableFlag.LIVE, 1);
return true;
} else {
return false;
}
}
}
protected void onTriggered(@Nonnull Store<EntityStore> store, @Nonnull Ref<EntityStore> ref) {
Instant now = ((TimeResource)store.getResource(TimeResource.getResourceType())).getNow();
DespawnComponent despawnComponent = (DespawnComponent)store.getComponent(ref, DespawnComponent.getComponentType());
despawnComponent.setDespawn(now.plus((long)this.activeDuration, ChronoUnit.SECONDS));
}
public String toString() {
return "DeployableTrapConfig{}" + super.toString();
}
static {
CODEC = ((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)BuilderCodec.builder(DeployableTrapConfig.class, DeployableTrapConfig::new, DeployableAoeConfig.CODEC).appendInherited(new KeyedCodec("FuzeDuration", Codec.FLOAT), (o, i) -> o.fuzeDuration = i, (o) -> o.fuzeDuration, (o, p) -> o.fuzeDuration = p.fuzeDuration).documentation("The time it will take for the trap to become active").add()).appendInherited(new KeyedCodec("ActiveDuration", Codec.FLOAT), (o, i) -> o.activeDuration = i, (o) -> o.activeDuration, (o, p) -> o.activeDuration = p.activeDuration).documentation("The time the trap will stay alive after getting triggered").add()).appendInherited(new KeyedCodec("DestroyOnTriggered", Codec.BOOLEAN), (o, i) -> o.destroyOnTriggered = i, (o) -> o.destroyOnTriggered, (o, p) -> o.destroyOnTriggered = p.destroyOnTriggered).documentation("Whether the trap will disappear when it's triggered by a players").add()).build();
}
}