All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.minestom.server.entity.ExperienceOrb Maven / Gradle / Ivy

There is a newer version: 7320437640
Show newest version
package net.minestom.server.entity;

import net.minestom.server.coordinate.Vec;
import net.minestom.server.thread.Acquirable;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

import java.util.Comparator;

public class ExperienceOrb extends Entity {

    private short experienceCount;
    private Player target;
    private long lastTargetUpdateTick;

    public ExperienceOrb(short experienceCount) {
        super(EntityType.EXPERIENCE_ORB);
        setBoundingBox(0.5f, 0.5f, 0.5f);
        //todo vanilla sets random velocity here?
        this.experienceCount = experienceCount;
    }

    @Override
    public void update(long time) {

        // TODO slide toward nearest player

        //todo water movement
        if (hasNoGravity()) {
            setVelocity(getVelocity().add(0, -0.3f, 0));
        }

        //todo lava

        double d = 8.0;
        if (lastTargetUpdateTick < time - 20 + getEntityId() % 100) {
            if (target == null || target.getPosition().distanceSquared(getPosition()) > 64) {
                this.target = getClosestPlayer(this, 8);
            }

            lastTargetUpdateTick = time;
        }

        if (target != null && target.getGameMode() == GameMode.SPECTATOR) {
            target = null;
        }

        if (target != null) {
            final var pos = getPosition();
            final var targetPos = target.getPosition();
            final Vec toTarget = new Vec(targetPos.x() - pos.x(), targetPos.y() + (target.getEyeHeight() / 2) - pos.y(), targetPos.z() - pos.z());
            double e = toTarget.length(); //could really be lengthSquared
            if (e < 8) {
                double f = 1 - (e / 8);
                setVelocity(getVelocity().add(toTarget.normalize().mul(f * f * 0.1)));
            }
        }

        // Move should be called here
        float g = 0.98f;
        if (this.onGround) {
//            g = 2f;
            g = 0.6f * 0.98f;
        }
        // apply slipperiness

        setVelocity(getVelocity().mul(new Vec(g, 0.98f, g)));
        if (isOnGround()) {
            setVelocity(getVelocity().mul(new Vec(1, -0.9f, 1)));
        }
    }

    @Override
    public void spawn() {

    }

    /**
     * Gets the experience count.
     *
     * @return the experience count
     */
    public short getExperienceCount() {
        return experienceCount;
    }

    /**
     * Changes the experience count.
     *
     * @param experienceCount the new experience count
     */
    public void setExperienceCount(short experienceCount) {
        // Remove the entity in order to respawn it with the correct experience count
        getViewers().forEach(this::removeViewer);

        this.experienceCount = experienceCount;

        getViewers().forEach(this::addViewer);
    }

    private Player getClosestPlayer(Entity entity, float maxDistance) {
        Player closest = entity.getInstance()
                .getPlayers()
                .stream()
                .min(Comparator.comparingDouble(a -> a.getDistanceSquared(entity)))
                .orElse(null);
        if (closest == null) return null;
        if (closest.getDistanceSquared(entity) > maxDistance * maxDistance) return null;
        return closest;
    }

    @ApiStatus.Experimental
    @SuppressWarnings("unchecked")
    @Override
    public @NotNull Acquirable acquirable() {
        return (Acquirable) super.acquirable();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy