package com.hypixel.hytale.server.npc.movement.controllers.builders;
import com.google.gson.JsonElement;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.npc.asset.builder.BuilderDescriptorState;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import com.hypixel.hytale.server.npc.asset.builder.validators.DoubleRangeValidator;
import com.hypixel.hytale.server.npc.asset.builder.validators.DoubleSingleValidator;
import com.hypixel.hytale.server.npc.asset.builder.validators.RelationalOperator;
import com.hypixel.hytale.server.npc.movement.controllers.MotionController;
import com.hypixel.hytale.server.npc.movement.controllers.MotionControllerDive;
import com.hypixel.hytale.server.spawning.SpawnTestResult;
import com.hypixel.hytale.server.spawning.SpawningContext;
import javax.annotation.Nonnull;
public class BuilderMotionControllerDive extends BuilderMotionControllerBase {
private double minHorizontalSpeed;
private double maxVerticalSpeed;
private double acceleration;
private double gravity;
private double maxFallSpeed;
private double maxSinkSpeed;
private double maxRotationSpeed;
private float maxMoveTurnAngle;
private double minDiveDepth;
private double maxDiveDepth;
private double minWaterDepth;
private double maxWaterDepth;
private double minDepthAboveGround;
private double minDepthBelowSurface;
private double swimDepth;
private double sinkRatio;
private double fastDiveThreshold;
private double desiredDepthWeight;
public BuilderMotionControllerDive() {
}
@Nonnull
public String getShortDescription() {
return "Provide diving abilities for NPC";
}
@Nonnull
public String getLongDescription() {
return this.getShortDescription();
}
@Nonnull
public BuilderDescriptorState getBuilderDescriptorState() {
return BuilderDescriptorState.WorkInProgress;
}
@Nonnull
public MotionControllerDive build(@Nonnull BuilderSupport builderSupport) {
return new MotionControllerDive(builderSupport, this);
}
@Nonnull
public BuilderMotionControllerDive readConfig(@Nonnull JsonElement data) {
this.getDouble(data, "MaxSwimSpeed", this.maxHorizontalSpeed, 3.0, DoubleSingleValidator.greater0(), BuilderDescriptorState.Stable, "Maximum horizontal speed", (String)null);
this.getDouble(data, "MaxDiveSpeed", (v) -> this.maxVerticalSpeed = v, 8.0, DoubleSingleValidator.greater0(), BuilderDescriptorState.Stable, "Maximum vertical speed", (String)null);
this.getDouble(data, "MaxFallSpeed", (v) -> this.maxFallSpeed = v, 10.0, DoubleSingleValidator.greater0(), BuilderDescriptorState.Stable, "Terminal velocity falling in air", (String)null);
this.getDouble(data, "MaxSinkSpeed", (v) -> this.maxSinkSpeed = v, 4.0, DoubleSingleValidator.greater0(), BuilderDescriptorState.Stable, "Terminal velocity sinking in water", (String)null);
this.getDouble(data, "Gravity", (v) -> this.gravity = v, 10.0, DoubleSingleValidator.greater0(), BuilderDescriptorState.Stable, "Gravity", (String)null);
this.getDouble(data, "Acceleration", (v) -> this.acceleration = v, 3.0, DoubleSingleValidator.greater0(), BuilderDescriptorState.Stable, "Acceleration", (String)null);
this.getDouble(data, "MaxRotationSpeed", (v) -> this.maxRotationSpeed = v, 360.0, DoubleSingleValidator.greater0(), BuilderDescriptorState.Stable, "Maximum rotational speed in degrees", (String)null);
this.getFloat(data, "MaxSwimTurnAngle", (v) -> this.maxMoveTurnAngle = v, 90.0F, DoubleRangeValidator.between(0.0, 180.0), BuilderDescriptorState.WorkInProgress, "Maximum angle NPC can walk without explicit turning in degrees", (String)null);
this.validateDoubleRelation("MinSwimSpeed", this.minHorizontalSpeed, RelationalOperator.LessEqual, this.maxHorizontalSpeed);
this.getDouble(data, "FastSwimThreshold", (v) -> this.fastDiveThreshold = v, 0.6, DoubleRangeValidator.between01(), BuilderDescriptorState.WorkInProgress, "Relative threshold when fast swimming animation should be used", (String)null);
this.getDouble(data, "SwimDepth", (v) -> this.swimDepth = v, 0.4, DoubleRangeValidator.between(-1.0, 1.0), BuilderDescriptorState.WorkInProgress, "Minimum height NPC needs to be submerged to be able to swim", "0 is at eye height, -1 is bottom of bounding box, +1 top of bounding box. other values between -1 and +1 scale linear");
this.getDouble(data, "SinkRatio", (v) -> this.sinkRatio = v, 1.0, DoubleSingleValidator.greaterEqual0(), BuilderDescriptorState.WorkInProgress, "Relative sink or climb speed while wandering", (String)null);
this.getDouble(data, "MinDiveDepth", (v) -> this.minDiveDepth = v, 0.0, DoubleSingleValidator.greaterEqual0(), BuilderDescriptorState.Unknown, (String)null, (String)null);
this.getDouble(data, "MaxDiveDepth", (v) -> this.maxDiveDepth = v, 1.7976931348623157E308, DoubleSingleValidator.greater0(), BuilderDescriptorState.WorkInProgress, "Maximum dive depth below surface desired", (String)null);
this.getDouble(data, "MinDepthAboveGround", (v) -> this.minDepthAboveGround = v, 1.0, DoubleSingleValidator.greaterEqual0(), BuilderDescriptorState.WorkInProgress, "Minimum distance from ground desired", (String)null);
this.getDouble(data, "MinDepthBelowSurface", (v) -> this.minDepthBelowSurface = v, 1.0, DoubleSingleValidator.greaterEqual0(), BuilderDescriptorState.WorkInProgress, "Minimum distance from water surface desired", (String)null);
this.getDouble(data, "MinWaterDepth", (v) -> this.minWaterDepth = v, 1.0, DoubleSingleValidator.greaterEqual0(), BuilderDescriptorState.Unknown, (String)null, (String)null);
this.getDouble(data, "MaxWaterDepth", (v) -> this.maxWaterDepth = v, 0.0, DoubleSingleValidator.greaterEqual0(), BuilderDescriptorState.Unknown, (String)null, (String)null);
this.getDouble(data, "DesiredDepthWeight", (v) -> this.desiredDepthWeight = v, 0.0, DoubleRangeValidator.between(0.0, 1.0), BuilderDescriptorState.Stable, "How much this NPC prefers being within the desired height range", "How much this NPC prefers being within the desired height range. 0 means it doesn't care much, 1 means it will do its best to get there fast.");
return this;
}
@Nonnull
public Class<MotionController> category() {
return MotionController.class;
}
public double getMinHorizontalSpeed() {
return this.minHorizontalSpeed;
}
public double getAcceleration() {
return this.acceleration;
}
public double getMaxVerticalSpeed() {
return this.maxVerticalSpeed;
}
public double getGravity() {
return this.gravity;
}
public double getMaxFallSpeed() {
return this.maxFallSpeed;
}
public double getMaxSinkSpeed() {
return this.maxSinkSpeed;
}
public float getMaxMoveTurnAngle() {
return 0.017453292F * this.maxMoveTurnAngle;
}
public double getMaxRotationSpeed() {
return this.maxRotationSpeed * 0.01745329238474369;
}
public double getMinDiveDepth() {
return this.minDiveDepth;
}
public double getMaxDiveDepth() {
return this.maxDiveDepth;
}
public double getMinWaterDepth() {
return this.minWaterDepth;
}
public double getMaxWaterDepth() {
return this.maxWaterDepth;
}
public double getMinDepthAboveGround() {
return this.minDepthAboveGround;
}
public double getMinDepthBelowSurface() {
return this.minDepthBelowSurface;
}
public double getSwimDepth() {
return this.swimDepth;
}
public double getSinkRatio() {
return this.sinkRatio;
}
public double getFastDiveThreshold() {
return this.fastDiveThreshold;
}
public double getDesiredDepthWeight() {
return this.desiredDepthWeight;
}
@Nonnull
public SpawnTestResult canSpawn(@Nonnull SpawningContext context) {
Model model = context.getModel();
double swimDepth = model == null ? 0.5 : MotionControllerDive.relativeSwimDepthToHeight(this.getSwimDepth(), model.getBoundingBox(), model.getEyeHeight());
if (!context.isInWater((float)swimDepth)) {
return SpawnTestResult.FAIL_NO_POSITION;
} else {
return context.validatePosition(20) ? SpawnTestResult.TEST_OK : SpawnTestResult.FAIL_INVALID_POSITION;
}
}
@Nonnull
public Class<? extends MotionController> getClassType() {
return MotionControllerDive.class;
}
}