2020-04-24 03:25:58 +02:00
|
|
|
package net.minestom.server.entity;
|
2019-08-31 07:54:53 +02:00
|
|
|
|
2020-10-31 01:38:57 +01:00
|
|
|
import net.minestom.server.instance.Instance;
|
2020-04-24 03:25:58 +02:00
|
|
|
import net.minestom.server.network.packet.server.play.SpawnExperienceOrbPacket;
|
|
|
|
import net.minestom.server.network.player.PlayerConnection;
|
2020-10-31 01:38:57 +01:00
|
|
|
import net.minestom.server.utils.Position;
|
2020-12-31 19:50:26 +01:00
|
|
|
import net.minestom.server.utils.Vector;
|
2020-10-24 10:46:23 +02:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
2020-10-31 01:38:57 +01:00
|
|
|
import org.jetbrains.annotations.Nullable;
|
2019-08-31 07:54:53 +02:00
|
|
|
|
2021-01-25 13:47:13 +01:00
|
|
|
import java.util.Comparator;
|
|
|
|
|
2019-08-31 07:54:53 +02:00
|
|
|
public class ExperienceOrb extends Entity {
|
|
|
|
|
|
|
|
private short experienceCount;
|
2020-12-31 19:50:26 +01:00
|
|
|
private Player target;
|
|
|
|
private long lastTargetUpdateTick;
|
|
|
|
|
2019-08-31 07:54:53 +02:00
|
|
|
|
2020-10-31 01:38:57 +01:00
|
|
|
public ExperienceOrb(short experienceCount, @NotNull Position spawnPosition) {
|
|
|
|
super(EntityType.EXPERIENCE_ORB, spawnPosition);
|
2020-12-06 01:36:37 +01:00
|
|
|
setGravity(0.02f, 0.04f, 1.96f);
|
2019-08-31 07:54:53 +02:00
|
|
|
setBoundingBox(0.5f, 0.5f, 0.5f);
|
2020-12-31 19:50:26 +01:00
|
|
|
//todo vanilla sets random velocity here?
|
2019-08-31 07:54:53 +02:00
|
|
|
this.experienceCount = experienceCount;
|
|
|
|
}
|
|
|
|
|
2020-10-31 01:38:57 +01:00
|
|
|
public ExperienceOrb(short experienceCount, @NotNull Position spawnPosition, @Nullable Instance instance) {
|
|
|
|
this(experienceCount, spawnPosition);
|
|
|
|
|
|
|
|
if (instance != null) {
|
|
|
|
setInstance(instance);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-31 07:54:53 +02:00
|
|
|
@Override
|
2020-06-01 00:51:31 +02:00
|
|
|
public void update(long time) {
|
2020-12-31 19:50:26 +01:00
|
|
|
|
2019-08-31 07:54:53 +02:00
|
|
|
// TODO slide toward nearest player
|
2020-12-31 19:50:26 +01:00
|
|
|
|
|
|
|
//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().getDistanceSquared(getPosition()) > 64) {
|
|
|
|
this.target = getClosestPlayer(this, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
lastTargetUpdateTick = time;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target != null && target.getGameMode() == GameMode.SPECTATOR) {
|
|
|
|
target = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target != null) {
|
|
|
|
Position pos = getPosition();
|
|
|
|
Position targetPos = target.getPosition();
|
|
|
|
Vector toTarget = new Vector(targetPos.getX() - pos.getX(), targetPos.getY() + (target.getEyeHeight() / 2) - pos.getY(), targetPos.getZ() - pos.getZ());
|
|
|
|
double e = toTarget.length(); //could really be lengthSquared
|
|
|
|
if (e < 8) {
|
|
|
|
double f = 1 - (e / 8);
|
|
|
|
setVelocity(getVelocity().add(toTarget.normalize().multiply(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().multiply(new Vector(g, 0.98f, g)));
|
|
|
|
if (isOnGround())
|
|
|
|
setVelocity(getVelocity().multiply(new Vector(1, -0.9f, 1)));
|
2019-08-31 07:54:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void spawn() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-10-24 10:46:23 +02:00
|
|
|
public boolean addViewer(@NotNull Player player) {
|
2020-08-03 06:36:42 +02:00
|
|
|
final boolean result = super.addViewer(player); // Add player to viewers list
|
|
|
|
if (!result)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
final PlayerConnection playerConnection = player.getPlayerConnection();
|
2019-08-31 07:54:53 +02:00
|
|
|
|
|
|
|
SpawnExperienceOrbPacket experienceOrbPacket = new SpawnExperienceOrbPacket();
|
|
|
|
experienceOrbPacket.entityId = getEntityId();
|
|
|
|
experienceOrbPacket.position = getPosition();
|
|
|
|
experienceOrbPacket.expCount = experienceCount;
|
2020-05-24 20:21:17 +02:00
|
|
|
|
2019-08-31 07:54:53 +02:00
|
|
|
playerConnection.sendPacket(experienceOrbPacket);
|
2020-05-24 20:21:17 +02:00
|
|
|
playerConnection.sendPacket(getVelocityPacket());
|
|
|
|
|
2020-09-24 01:50:25 +02:00
|
|
|
return true;
|
2019-08-31 07:54:53 +02:00
|
|
|
}
|
|
|
|
|
2020-05-24 20:21:17 +02:00
|
|
|
/**
|
2020-10-15 21:16:31 +02:00
|
|
|
* Gets the experience count.
|
2020-08-03 06:36:42 +02:00
|
|
|
*
|
|
|
|
* @return the experience count
|
2020-05-24 20:21:17 +02:00
|
|
|
*/
|
2019-08-31 07:54:53 +02:00
|
|
|
public short getExperienceCount() {
|
|
|
|
return experienceCount;
|
|
|
|
}
|
|
|
|
|
2020-05-24 20:21:17 +02:00
|
|
|
/**
|
2020-10-15 21:16:31 +02:00
|
|
|
* Changes the experience count.
|
2020-08-03 06:36:42 +02:00
|
|
|
*
|
|
|
|
* @param experienceCount the new experience count
|
2020-05-24 20:21:17 +02:00
|
|
|
*/
|
2019-08-31 07:54:53 +02:00
|
|
|
public void setExperienceCount(short experienceCount) {
|
2020-05-24 20:21:17 +02:00
|
|
|
// Remove the entity in order to respawn it with the correct experience count
|
2020-09-24 01:50:25 +02:00
|
|
|
getViewers().forEach(this::removeViewer);
|
2020-05-24 20:21:17 +02:00
|
|
|
|
2019-08-31 07:54:53 +02:00
|
|
|
this.experienceCount = experienceCount;
|
2020-05-24 20:21:17 +02:00
|
|
|
|
2020-09-24 01:50:25 +02:00
|
|
|
getViewers().forEach(this::addViewer);
|
2019-08-31 07:54:53 +02:00
|
|
|
}
|
2020-12-31 19:50:26 +01:00
|
|
|
|
|
|
|
private Player getClosestPlayer(Entity entity, float maxDistance) {
|
|
|
|
Player closest = entity.getInstance()
|
|
|
|
.getPlayers()
|
|
|
|
.stream()
|
2021-01-25 13:47:13 +01:00
|
|
|
.min(Comparator.comparingDouble(a -> a.getDistance(entity)))
|
2020-12-31 19:50:26 +01:00
|
|
|
.orElse(null);
|
|
|
|
if (closest == null) return null;
|
|
|
|
if (closest.getDistance(entity) > maxDistance) return null;
|
|
|
|
return closest;
|
|
|
|
}
|
2019-08-31 07:54:53 +02:00
|
|
|
}
|