after working with npc on spigot 1.20.1 nms I decided to try to write npcManager on 1.21.1 paperweight, but already 2 hours I sit and can not do something working, after a bunch of promt chat gpt I came to the forum.
The current npc class looks like this:
For context, its npcManager:
and Skin class
I apologize if I wrote a complete nonsense in NpcBase, I have rewritten this code 1000 times
The current npc class looks like this:
Java:
package ru.zaralx.evoSurvival.utils.npc;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.network.Connection;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ClientInformation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.CommonListenerCookie;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.server.players.PlayerList;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import ru.zaralx.evoSurvival.EvoSurvival;
import java.util.UUID;
@Getter
public abstract class NpcBase {
protected final UUID uuid;
protected Location location;
@Setter protected String displayName;
@Setter protected Skin skin;
protected ServerPlayer npcEntity;
public NpcBase(Location location, String displayName, Skin skin) {
this.uuid = UUID.randomUUID();
this.location = location;
this.displayName = displayName;
this.skin = skin;
}
public void spawn() {
GameProfile profile = new GameProfile(uuid, displayName);
profile.getProperties().put("textures", new Property("textures", skin.getTexture(), skin.getSignature()));
MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer();
ServerLevel world = ((CraftWorld) location.getWorld()).getHandle();
npcEntity = new ServerPlayer(server, world, profile, ClientInformation.createDefault());
npcEntity.setPos(location.getX(), location.getY(), location.getZ());
PlayerList playerList = server.getPlayerList();
Connection connection = new Connection(null);
CommonListenerCookie cookie = CommonListenerCookie.createInitial(profile, true);
playerList.placeNewPlayer(connection, npcEntity, cookie);
showToNearbyPlayers();
startLookingAtPlayers();
}
public void remove() {
if (npcEntity != null) {
PlayerList playerList = ((CraftServer) Bukkit.getServer()).getHandle();
playerList.remove(npcEntity);
}
}
public void showToNearbyPlayers() {
for (Player player : Bukkit.getOnlinePlayers()) {
if (player.getLocation().distance(location) <= 64) {
showToPlayer(player);
}
}
}
protected void showToPlayer(Player player) {
ServerGamePacketListenerImpl connection = ((CraftPlayer) player).getHandle().connection;
connection.send(new ClientboundPlayerInfoUpdatePacket(
ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER,
npcEntity
));
// Cannot resolve symbol 'ClientboundAddPlayerPacket'
connection.send(new ClientboundAddPlayerPacket(npcEntity));
}
private void startLookingAtPlayers() {
new BukkitRunnable() {
@Override
public void run() {
Player nearest = getNearestPlayer();
if (nearest != null) {
npcEntity.setYRot(nearest.getLocation().getYaw());
npcEntity.setXRot(nearest.getLocation().getPitch());
}
}
}.runTaskTimer(EvoSurvival.getInstance(), 0L, 10L);
}
private Player getNearestPlayer() {
Player nearest = null;
double minDistance = Double.MAX_VALUE;
for (Player player : Bukkit.getOnlinePlayers()) {
double distance = player.getLocation().distance(location);
if (distance < minDistance) {
minDistance = distance;
nearest = player;
}
}
return nearest;
}
}
For context, its npcManager:
Java:
package ru.zaralx.evoSurvival.utils.npc;
import java.util.HashMap;
import java.util.Map;
public class NpcManager {
private final Map<Integer, NpcBase> npcMap = new HashMap<>();
public void addNpc(NpcBase npc) {
npcMap.put(npc.getNpcEntity().getId(), npc);
}
public void removeNpc(NpcBase npc) {
npcMap.remove(npc.getNpcEntity().getId());
}
public void removeAllNpc() {
for (NpcBase npc : npcMap.values()) {
npc.remove();
}
npcMap.clear();
}
public NpcBase getNpc(Integer id) {
return npcMap.get(id);
}
}
Java:
package ru.zaralx.evoSurvival.utils.npc;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
public class Skin {
private String signature = "";
private String texture = "";
public Skin(String texture, String signature) {
this.signature = signature;
this.texture = texture;
}
public Skin(String nickname) {
getSkin(nickname);
}
private void getSkin(String nickname) {
try {
URL mojangUrl = new URL("https://api.mojang.com/users/profiles/minecraft/" + nickname);
BufferedReader reader = new BufferedReader(new InputStreamReader(mojangUrl.openStream()));
MojangProfile profile = new Gson().fromJson(reader, MojangProfile.class);
reader.close();
URL skinUrl = new URL("https://sessionserver.mojang.com/session/minecraft/profile/"+profile.getId()+"?unsigned=false");
BufferedReader skinReader = new BufferedReader(new InputStreamReader(skinUrl.openStream()));
JsonObject skinJson = new Gson().fromJson(skinReader, JsonObject.class);
skinReader.close();
JsonArray properties = skinJson.getAsJsonArray("properties");
if (properties != null && !properties.isEmpty()) {
JsonObject property = properties.get(0).getAsJsonObject();
String value = property.get("value").getAsString();
String signature = property.get("signature").getAsString();
this.texture = value;
this.signature = signature;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public String getSignature() {
return signature;
}
public String getTexture() {
return texture;
}
private static class MojangProfile {
private String id;
private String name;
public String getId() {
return id;
}
}
}
I apologize if I wrote a complete nonsense in NpcBase, I have rewritten this code 1000 times