package com.hypixel.hytale.server.spawning.interactions;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.codec.validation.Validators;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.spatial.SpatialResource;
import com.hypixel.hytale.math.random.RandomExtra;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.protocol.InteractionType;
import com.hypixel.hytale.server.core.entity.InteractionContext;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.interaction.interaction.CooldownHandler;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.SimpleInstantInteraction;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.spawning.SpawningPlugin;
import com.hypixel.hytale.server.spawning.assets.spawnmarker.config.SpawnMarker;
import com.hypixel.hytale.server.spawning.spawnmarkers.SpawnMarkerEntity;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import javax.annotation.Nonnull;
public class TriggerSpawnMarkersInteraction extends SimpleInstantInteraction {
public static final BuilderCodec<TriggerSpawnMarkersInteraction> CODEC;
private String markerType;
private double range = 10.0;
private double rangeSquared;
private int count;
public TriggerSpawnMarkersInteraction() {
}
protected void firstRun(@Nonnull InteractionType type, @Nonnull InteractionContext context, @Nonnull CooldownHandler cooldownHandler) {
CommandBuffer<EntityStore> commandBuffer = context.getCommandBuffer();
Ref<EntityStore> self = context.getEntity();
Vector3d position = ((TransformComponent)commandBuffer.getComponent(self, TransformComponent.getComponentType())).getPosition();
SpatialResource<Ref<EntityStore>, EntityStore> spatialResource = (SpatialResource)commandBuffer.getResource(SpawningPlugin.get().getSpawnMarkerSpatialResource());
ObjectArrayList<Ref<EntityStore>> spawners = new ObjectArrayList<Ref<EntityStore>>();
spatialResource.getSpatialStructure().collect(position, (double)((int)this.range + 1), spawners);
if (this.count == 0) {
for(int i = 0; i < spawners.size(); ++i) {
Ref<EntityStore> spawnMarkerRef = this.filterMarker(spawners.get(i), position, commandBuffer);
if (spawnMarkerRef != null) {
SpawnMarkerEntity spawnMarkerEntityComponent = (SpawnMarkerEntity)commandBuffer.getComponent(spawnMarkerRef, SpawnMarkerEntity.getComponentType());
assert spawnMarkerEntityComponent != null;
commandBuffer.run((store) -> spawnMarkerEntityComponent.trigger(spawnMarkerRef, store));
}
}
} else {
ObjectArrayList<Ref<EntityStore>> triggerList = new ObjectArrayList<Ref<EntityStore>>();
RandomExtra.reservoirSample(spawners, (reference, _this, _commandBuffer) -> _this.filterMarker(reference, position, _commandBuffer), this.count, triggerList, this, commandBuffer);
for(int i = 0; i < triggerList.size(); ++i) {
Ref<EntityStore> spawnMarkerRef = triggerList.get(i);
SpawnMarkerEntity spawnMarkerEntityComponent = (SpawnMarkerEntity)commandBuffer.getComponent(spawnMarkerRef, SpawnMarkerEntity.getComponentType());
assert spawnMarkerEntityComponent != null;
commandBuffer.run((store) -> spawnMarkerEntityComponent.trigger(spawnMarkerRef, store));
}
}
}
protected Ref<EntityStore> filterMarker(@Nonnull Ref<EntityStore> targetRef, @Nonnull Vector3d position, @Nonnull CommandBuffer<EntityStore> commandBuffer) {
if (!targetRef.isValid()) {
return null;
} else {
TransformComponent targetTransformComponent = (TransformComponent)commandBuffer.getComponent(targetRef, TransformComponent.getComponentType());
assert targetTransformComponent != null;
Vector3d targetPosition = targetTransformComponent.getPosition();
SpawnMarkerEntity targetMarkerEntityComponent = (SpawnMarkerEntity)commandBuffer.getComponent(targetRef, SpawnMarkerEntity.getComponentType());
return targetMarkerEntityComponent == null || !targetMarkerEntityComponent.isManualTrigger() || !(position.distanceSquaredTo(targetPosition) <= this.rangeSquared) || this.markerType != null && !this.markerType.equals(targetMarkerEntityComponent.getSpawnMarkerId()) ? null : targetRef;
}
}
static {
CODEC = ((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)BuilderCodec.builder(TriggerSpawnMarkersInteraction.class, TriggerSpawnMarkersInteraction::new, SimpleInstantInteraction.CODEC).appendInherited(new KeyedCodec("MarkerType", Codec.STRING), (o, v) -> o.markerType = v, (o) -> o.markerType, (o, p) -> o.markerType = p.markerType).addValidator(SpawnMarker.VALIDATOR_CACHE.getValidator()).documentation("The manual spawn marker type to trigger. If omitted, will trigger all manual spawners.").add()).appendInherited(new KeyedCodec("Range", Codec.DOUBLE), (o, v) -> o.range = v, (o) -> o.range, (o, p) -> o.range = p.range).addValidator(Validators.greaterThan(0.0)).documentation("Range within which to trigger spawn markers.").add()).appendInherited(new KeyedCodec("Count", Codec.INTEGER), (o, v) -> o.count = v, (o) -> o.count, (o, p) -> o.count = p.count).addValidator(Validators.greaterThanOrEqual(0)).documentation("Max number of spawn markers to activate. Set to 0 to activate all spawn markers.").add()).afterDecode((i) -> i.rangeSquared = i.range * i.range)).build();
}
}