feat: added Human entity
This commit is contained in:
parent
ba36b2ab1d
commit
f082b3b9f6
138
api/src/main/java/ru/dragonestia/msb3/api/entity/Human.java
Normal file
138
api/src/main/java/ru/dragonestia/msb3/api/entity/Human.java
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package ru.dragonestia.msb3.api.entity;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
|
import net.minestom.server.MinecraftServer;
|
||||||
|
import net.minestom.server.coordinate.Point;
|
||||||
|
import net.minestom.server.coordinate.Pos;
|
||||||
|
import net.minestom.server.coordinate.Vec;
|
||||||
|
import net.minestom.server.entity.*;
|
||||||
|
import net.minestom.server.entity.attribute.Attribute;
|
||||||
|
import net.minestom.server.entity.metadata.display.AbstractDisplayMeta;
|
||||||
|
import net.minestom.server.entity.metadata.display.TextDisplayMeta;
|
||||||
|
import net.minestom.server.instance.Instance;
|
||||||
|
import net.minestom.server.network.packet.server.play.PlayerInfoRemovePacket;
|
||||||
|
import net.minestom.server.network.packet.server.play.PlayerInfoUpdatePacket;
|
||||||
|
import net.minestom.server.network.packet.server.play.TeamsPacket;
|
||||||
|
import net.minestom.server.scoreboard.Team;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class Human extends EntityCreature {
|
||||||
|
|
||||||
|
private static final AtomicInteger freeId = new AtomicInteger(0);
|
||||||
|
private static final Map<String, Team> npcTeams = new ConcurrentHashMap<>();
|
||||||
|
private static final Point displayNamePositionOffset = new Vec(0, 2, 0);
|
||||||
|
|
||||||
|
@Getter private Component name;
|
||||||
|
private final String username;
|
||||||
|
@Getter private final PlayerSkin skin;
|
||||||
|
private final NamedTextColor teamColor;
|
||||||
|
private final PlayerInfoUpdatePacket createPacket;
|
||||||
|
private final PlayerInfoRemovePacket removePacket;
|
||||||
|
private final Team team;
|
||||||
|
private Entity displayNameEntity;
|
||||||
|
|
||||||
|
public Human(String name, PlayerSkin skin) {
|
||||||
|
this(Component.text(name, NamedTextColor.YELLOW), skin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Human(Component name, PlayerSkin skin) {
|
||||||
|
this(name, skin, NamedTextColor.YELLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Human(Component name, PlayerSkin skin, NamedTextColor teamColor) {
|
||||||
|
super(EntityType.PLAYER);
|
||||||
|
this.name = name;
|
||||||
|
this.username = "Human_" + freeId.incrementAndGet();
|
||||||
|
this.skin = skin;
|
||||||
|
this.teamColor = teamColor;
|
||||||
|
this.createPacket = getCreatePacket();
|
||||||
|
this.removePacket = new PlayerInfoRemovePacket(getUuid());
|
||||||
|
this.team = pickTeam();
|
||||||
|
|
||||||
|
getEntityMeta().setCustomNameVisible(false);
|
||||||
|
setBoundingBox(0.6, 1.8, 0.6);
|
||||||
|
getAttribute(Attribute.MOVEMENT_SPEED).setBaseValue(0.2F);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayerInfoUpdatePacket getCreatePacket() {
|
||||||
|
var properties = List.of(new PlayerInfoUpdatePacket.Property("textures", skin.textures(), skin.signature()));
|
||||||
|
return new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.ADD_PLAYER,
|
||||||
|
new PlayerInfoUpdatePacket.Entry(getUuid(), username, properties, false, 0, GameMode.CREATIVE, name, null, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> setInstance(@NotNull Instance instance, @NotNull Pos spawnPosition) {
|
||||||
|
return super.setInstance(instance, spawnPosition)
|
||||||
|
.thenRun(this::getDisplayNameEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull CompletableFuture<Void> teleport(@NotNull Pos position, @NotNull Vec velocity, long @Nullable [] chunks, int flags, boolean shouldConfirm) {
|
||||||
|
return super.teleport(position, velocity, chunks, flags, shouldConfirm)
|
||||||
|
.thenRun(() -> getDisplayNameEntity().teleport(position.add(displayNamePositionOffset), chunks, flags, shouldConfirm));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshPosition(@NotNull Pos newPosition, boolean ignoreView, boolean sendPackets) {
|
||||||
|
super.refreshPosition(newPosition, ignoreView, sendPackets);
|
||||||
|
getDisplayNameEntity().refreshPosition(newPosition.add(displayNamePositionOffset), ignoreView, sendPackets);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void remove(boolean permanent) {
|
||||||
|
super.remove(permanent);
|
||||||
|
if (displayNameEntity != null) displayNameEntity.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateNewViewer(@NotNull Player player) {
|
||||||
|
player.sendPacket(createPacket);
|
||||||
|
super.updateNewViewer(player);
|
||||||
|
player.sendPacket(new TeamsPacket(team.getTeamName(), new TeamsPacket.AddEntitiesToTeamAction(List.of(username))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateOldViewer(@NotNull Player player) {
|
||||||
|
player.sendPacket(removePacket);
|
||||||
|
super.updateOldViewer(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Team pickTeam() {
|
||||||
|
return npcTeams.computeIfAbsent(teamColor.asHexString(), $ -> MinecraftServer.getTeamManager()
|
||||||
|
.createBuilder("NPC_r%s_g%s_b%s".formatted(teamColor.red(), teamColor.green(), teamColor.blue()))
|
||||||
|
.collisionRule(TeamsPacket.CollisionRule.ALWAYS)
|
||||||
|
.teamColor(teamColor)
|
||||||
|
.nameTagVisibility(TeamsPacket.NameTagVisibility.NEVER)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized Entity getDisplayNameEntity() {
|
||||||
|
if (displayNameEntity == null) {
|
||||||
|
displayNameEntity = new Entity(EntityType.TEXT_DISPLAY);
|
||||||
|
var meta = (TextDisplayMeta) displayNameEntity.getEntityMeta();
|
||||||
|
meta.setText(name);
|
||||||
|
meta.setHasNoGravity(true);
|
||||||
|
meta.setBillboardRenderConstraints(AbstractDisplayMeta.BillboardConstraints.VERTICAL);
|
||||||
|
displayNameEntity.setInstance(instance, getPosition().add(displayNamePositionOffset));
|
||||||
|
}
|
||||||
|
return displayNameEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(Component name) {
|
||||||
|
this.name = name;
|
||||||
|
if (displayNameEntity != null) {
|
||||||
|
var meta = (TextDisplayMeta) displayNameEntity.getEntityMeta();
|
||||||
|
meta.setText(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user