package com.hypixel.hytale.builtin.mounts.interactions;
import com.hypixel.hytale.builtin.mounts.minecart.MinecartComponent;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.codec.codecs.map.EnumMapCodec;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.protocol.InteractionType;
import com.hypixel.hytale.protocol.RailConfig;
import com.hypixel.hytale.protocol.RailPoint;
import com.hypixel.hytale.server.core.asset.type.blockhitbox.BlockBoundingBoxes;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.server.core.entity.InteractionContext;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.server.core.modules.entity.component.Interactable;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.interaction.Interactions;
import com.hypixel.hytale.server.core.modules.interaction.interaction.CooldownHandler;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.RootInteraction;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.SimpleBlockInteraction;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import java.util.Collections;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class SpawnMinecartInteraction extends SimpleBlockInteraction {
public static final BuilderCodec<SpawnMinecartInteraction> CODEC;
private String modelId;
private Map<InteractionType, String> cartInteractions = Collections.emptyMap();
public SpawnMinecartInteraction() {
}
protected void interactWithBlock(@Nonnull World world, @Nonnull CommandBuffer<EntityStore> commandBuffer, @Nonnull InteractionType type, @Nonnull InteractionContext context, @Nullable ItemStack itemInHand, @Nonnull Vector3i targetBlock, @Nonnull CooldownHandler cooldownHandler) {
Ref<EntityStore> ref = context.getEntity();
Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
Vector3d targetPosition = targetBlock.toVector3d();
targetPosition.add(0.5, 0.5, 0.5);
Vector3f rotation = new Vector3f();
HeadRotation headRotation = (HeadRotation)commandBuffer.getComponent(ref, HeadRotation.getComponentType());
if (headRotation != null) {
rotation.setYaw(headRotation.getRotation().getYaw());
}
WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(targetBlock.x, targetBlock.z));
if (chunk != null) {
BlockType block = chunk.getBlockType(targetBlock);
int blockRotation = chunk.getRotationIndex(targetBlock.x, targetBlock.y, targetBlock.z);
RailConfig railConfig = block.getRailConfig(blockRotation);
if (railConfig != null) {
alignToRail(targetBlock, targetPosition, rotation, rotation.getYaw(), railConfig);
} else {
BlockBoundingBoxes.RotatedVariantBoxes bounding = ((BlockBoundingBoxes)BlockBoundingBoxes.getAssetMap().getAsset(block.getHitboxTypeIndex())).get(blockRotation);
targetPosition.add(0.0, bounding.getBoundingBox().max.y - 0.5, 0.0);
}
holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(targetPosition, rotation));
holder.ensureComponent(UUIDComponent.getComponentType());
ModelAsset modelAsset = (ModelAsset)ModelAsset.getAssetMap().getAsset(this.modelId);
if (modelAsset == null) {
modelAsset = ModelAsset.DEBUG;
}
Model model = Model.createRandomScaleModel(modelAsset);
holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference()));
holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
holder.addComponent(BoundingBox.getComponentType(), new BoundingBox(model.getBoundingBox()));
holder.ensureComponent(Interactable.getComponentType());
holder.addComponent(Interactions.getComponentType(), new Interactions(this.cartInteractions));
holder.putComponent(MinecartComponent.getComponentType(), new MinecartComponent(context.getHeldItem() != null ? context.getHeldItem().getItemId() : null));
commandBuffer.addEntity(holder, AddReason.SPAWN);
}
}
protected void simulateInteractWithBlock(@Nonnull InteractionType type, @Nonnull InteractionContext context, @Nullable ItemStack itemInHand, @Nonnull World world, @Nonnull Vector3i targetBlock) {
}
private static void alignToRail(@Nonnull Vector3i targetBlock, @Nonnull Vector3d target, @Nonnull Vector3f rotation, float yaw, @Nonnull RailConfig config) {
RailPoint[] points = config.points;
double smallestDistance = 1.7976931348623157E308;
double ox = target.x;
double oy = target.y;
double oz = target.z;
Vector3d facingDir = new Vector3d();
facingDir.assign((double)yaw, 0.0);
for(int index = 0; index < points.length - 1; ++index) {
RailPoint p = points[index];
RailPoint p2 = points[index + 1];
Vector3d point = new Vector3d((double)((float)targetBlock.x + p.point.x), (double)((float)targetBlock.y + p.point.y), (double)((float)targetBlock.z + p.point.z));
Vector3d point2 = new Vector3d((double)((float)targetBlock.x + p2.point.x), (double)((float)targetBlock.y + p2.point.y), (double)((float)targetBlock.z + p2.point.z));
Vector3d dir = point2.clone().subtract(point);
double maxLength = dir.length();
dir.normalize();
Vector3d toPoint = target.clone().subtract(point);
double distance = dir.dot(toPoint);
Vector3d pointOnLine = point.clone();
pointOnLine.addScaled(dir, Math.min(maxLength, Math.max(0.0, distance)));
double pointDist = pointOnLine.distanceSquaredTo(target);
if (pointDist >= 0.0 && pointDist <= 0.800000011920929 && pointDist < smallestDistance) {
ox = pointOnLine.x;
oy = pointOnLine.y;
oz = pointOnLine.z;
smallestDistance = pointDist;
if (facingDir.dot(dir) < 0.0) {
dir.scale(-1.0);
}
float newYaw = (float)(Math.atan2(dir.x, dir.z) + 3.141592653589793);
float newPitch = (float)Math.asin(dir.y);
rotation.setYaw(newYaw);
rotation.setPitch(newPitch);
}
}
if (!(smallestDistance >= 1.7976931348623157E308)) {
target.assign(ox, oy, oz);
}
}
static {
CODEC = ((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)BuilderCodec.builder(SpawnMinecartInteraction.class, SpawnMinecartInteraction::new, SimpleBlockInteraction.CODEC).documentation("Spawns a minecart at the target block")).appendInherited(new KeyedCodec("Model", Codec.STRING), (o, v) -> o.modelId = v, (o) -> o.modelId, (o, p) -> o.modelId = p.modelId).addValidator(ModelAsset.VALIDATOR_CACHE.getValidator()).add()).appendInherited(new KeyedCodec("CartInteractions", new EnumMapCodec(InteractionType.class, RootInteraction.CHILD_ASSET_CODEC)), (o, v) -> o.cartInteractions = v, (o) -> o.cartInteractions, (o, p) -> o.cartInteractions = p.cartInteractions).addValidatorLate(() -> RootInteraction.VALIDATOR_CACHE.getMapValueValidator().late()).add()).build();
}
}