diff --git a/pom.xml b/pom.xml index 816e349..44c58cb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.smallaswater RsNPC - 2.4.2 + 2.4.3-SNAPSHOT RsNPC RsNPC -- NPC plugin for Nukkit diff --git a/src/main/java/com/smallaswater/npc/RsNPC.java b/src/main/java/com/smallaswater/npc/RsNPC.java index f041184..617f488 100644 --- a/src/main/java/com/smallaswater/npc/RsNPC.java +++ b/src/main/java/com/smallaswater/npc/RsNPC.java @@ -101,8 +101,6 @@ public void onLoad() { @Override public void onEnable() { - this.loadLanguage(); - switch (GameCoreDownload.checkAndDownload()) { case 1: Server.getInstance().getPluginManager().disablePlugin(this); @@ -114,6 +112,8 @@ public void onEnable() { break; } + this.loadLanguage(); + try { if (Server.getInstance().getPluginManager().getPlugin("AutoUpData") != null) { if (AutoData.defaultUpDataByMaven(this, this.getFile(), "com.smallaswater", "RsNPC", null)) { @@ -224,6 +224,7 @@ private void loadNpcs() { * 加载内置皮肤 */ private void loadPrivateSkins() { + this.skins.put("private_steve", DEFAULT_SKIN); String[] skins = { "阳", "糖菲_slim", "玉茗_slim" }; for (String skinName : skins) { try { diff --git a/src/main/java/com/smallaswater/npc/command/sub/CreateSubCommand.java b/src/main/java/com/smallaswater/npc/command/sub/CreateSubCommand.java index b5ed46c..1dd1340 100644 --- a/src/main/java/com/smallaswater/npc/command/sub/CreateSubCommand.java +++ b/src/main/java/com/smallaswater/npc/command/sub/CreateSubCommand.java @@ -65,11 +65,9 @@ public boolean execute(CommandSender sender, String label, String[] args) { } this.rsNPC.getNpcs().put(name, rsNpcConfig); rsNpcConfig.checkEntity(); - //玄学解决首次生成不显示的问题 - Server.getInstance().getScheduler().scheduleDelayedTask(this.rsNPC, () -> { - rsNpcConfig.getEntityRsNpc().close(); - rsNpcConfig.checkEntity(); - }, 20); + //修复首次生成不显示的问题 通过重复生成实体解决nk未能及时发送PlayerListPacket的问题 + Server.getInstance().getScheduler().scheduleDelayedTask(this.rsNPC, () -> rsNpcConfig.getEntityRsNpc().close(), 20); + Server.getInstance().getScheduler().scheduleDelayedTask(this.rsNPC, rsNpcConfig::checkEntity, 40); sender.sendMessage(this.rsNPC.getLanguage().translateString("tips.npcCreateSuccess", name)); } else { sender.sendMessage(this.rsNPC.getLanguage().translateString("tips.nameRequired")); diff --git a/src/main/java/com/smallaswater/npc/data/RsNpcConfig.java b/src/main/java/com/smallaswater/npc/data/RsNpcConfig.java index 9e88743..f63b9bf 100644 --- a/src/main/java/com/smallaswater/npc/data/RsNpcConfig.java +++ b/src/main/java/com/smallaswater/npc/data/RsNpcConfig.java @@ -17,7 +17,6 @@ import com.smallaswater.npc.utils.Utils; import com.smallaswater.npc.utils.exception.RsNpcConfigLoadException; import com.smallaswater.npc.utils.exception.RsNpcLoadException; -import com.smallaswater.npc.variable.VariableManage; import lombok.Getter; import lombok.NonNull; import lombok.Setter; @@ -164,7 +163,7 @@ public RsNpcConfig(@NonNull String name, @NonNull Config config) throws RsNpcCon } try { - this.skinName = config.getString("皮肤", "默认"); + this.skinName = config.getString("皮肤", "private_steve"); if (!RsNPC.getInstance().getSkins().containsKey(this.skinName)) { RsNPC.getInstance().getLogger().warning("NPC: " + this.name + " 皮肤: " + this.skinName + " 不存在!已切换为默认皮肤!"); } @@ -386,7 +385,7 @@ public void checkEntity() { if (!this.lookAtThePlayer) { this.entityRsNpc.setRotation(this.location.yaw, this.location.pitch); } - this.entityRsNpc.setNameTag(VariableManage.stringReplace(null, this.showName, this)); + this.entityRsNpc.setNameTag(this.showName /*VariableManage.stringReplace(null, this.showName, this)*/); } } diff --git a/src/main/java/com/smallaswater/npc/entitys/EntityRsNPC.java b/src/main/java/com/smallaswater/npc/entitys/EntityRsNPC.java index 649cf13..ca53112 100644 --- a/src/main/java/com/smallaswater/npc/entitys/EntityRsNPC.java +++ b/src/main/java/com/smallaswater/npc/entitys/EntityRsNPC.java @@ -6,26 +6,28 @@ import cn.nukkit.Server; import cn.nukkit.block.BlockLiquid; import cn.nukkit.entity.EntityHuman; +import cn.nukkit.entity.data.EntityMetadata; +import cn.nukkit.entity.data.Skin; import cn.nukkit.level.Level; import cn.nukkit.level.format.FullChunk; import cn.nukkit.math.Vector3; import cn.nukkit.nbt.tag.CompoundTag; -import cn.nukkit.network.protocol.EmotePacket; -import cn.nukkit.network.protocol.ProtocolInfo; -import cn.nukkit.network.protocol.RemoveEntityPacket; -import cn.nukkit.network.protocol.SetEntityLinkPacket; +import cn.nukkit.network.protocol.*; import com.smallaswater.npc.RsNPC; import com.smallaswater.npc.data.RsNpcConfig; import com.smallaswater.npc.route.Node; import com.smallaswater.npc.route.RouteFinder; +import com.smallaswater.npc.variable.VariableManage; import lombok.Getter; import lombok.NonNull; import lombok.Setter; +import java.util.HashSet; import java.util.LinkedList; public class EntityRsNPC extends EntityHuman { + @Getter private final RsNpcConfig config; private int emoteSecond = 0; private int nextRouteIndex = 0; @@ -70,14 +72,9 @@ public EntityRsNPC(@NonNull FullChunk chunk, @NonNull CompoundTag nbt, RsNpcConf this.dataProperties.putFloat(EntityUtils.getEntityField("DATA_BOUNDING_BOX_HEIGHT", DATA_BOUNDING_BOX_HEIGHT), this.getHeight()); this.dataProperties.putFloat(EntityUtils.getEntityField("DATA_BOUNDING_BOX_WIDTH", DATA_BOUNDING_BOX_WIDTH), this.getWidth()); this.dataProperties.putInt(EntityUtils.getEntityField("DATA_HEALTH", DATA_HEALTH), (int) this.getHealth()); - this.sendData(this.getViewers().values().toArray(new Player[0])); } } - public RsNpcConfig getConfig() { - return this.config; - } - @Override public float getWidth() { if (this.config != null && this.config.isEnableCustomCollisionSize()) { @@ -273,11 +270,13 @@ public void addMovement(double x, double y, double z, double yaw, double pitch, public void spawnTo(Player player) { if (this.getNetworkId() == -1) { super.spawnTo(player); + this.sendData(player); } if (!this.hasSpawned.containsKey(player.getLoaderId()) && this.chunk != null && player.usedChunks.containsKey(Level.chunkHash(this.chunk.getX(), this.chunk.getZ()))) { this.hasSpawned.put(player.getLoaderId(), player); player.dataPacket(this.createAddEntityPacket()); + this.sendData(player); } if (this.riding != null) { this.riding.spawnTo(player); @@ -303,4 +302,51 @@ public void despawnFrom(Player player) { this.hasSpawned.remove(player.getLoaderId()); } } + + @Override + public void setSkin(Skin skin) { + Skin oldSkin = this.getSkin(); + super.setSkin(skin); + this.sendSkin(oldSkin); + } + + protected void sendSkin(Skin oldSkin) { + PlayerSkinPacket packet = new PlayerSkinPacket(); + packet.skin = this.getSkin(); + packet.newSkinName = this.getSkin().getSkinId(); + packet.oldSkinName = oldSkin != null ? oldSkin.getSkinId() : "old"; + packet.uuid = this.getUniqueId(); + HashSet players = new HashSet<>(this.getViewers().values()); + if (!players.isEmpty()) { + Server.broadcastPacket(players, packet); + } + } + + @Override + public void sendData(Player player, EntityMetadata data) { + SetEntityDataPacket pk = new SetEntityDataPacket(); + pk.eid = this.getId(); + pk.metadata = data == null ? this.dataProperties : data; + pk.metadata.putString( + EntityUtils.getEntityField("DATA_NAMETAG", DATA_NAMETAG), + VariableManage.stringReplace(player, this.getNameTag(), this.getConfig()) + ); + player.dataPacket(pk); + } + + @Override + public void sendData(Player[] players, EntityMetadata data) { + SetEntityDataPacket pk = new SetEntityDataPacket(); + pk.eid = this.getId(); + pk.metadata = data == null ? this.dataProperties : data; + + for(Player player : players) { + SetEntityDataPacket clone = (SetEntityDataPacket) pk.clone(); + clone.metadata.putString( + EntityUtils.getEntityField("DATA_NAMETAG", DATA_NAMETAG), + VariableManage.stringReplace(player, this.getNameTag(), this.getConfig()) + ); + player.dataPacket(clone); + } + } } \ No newline at end of file diff --git a/src/main/java/com/smallaswater/npc/entitys/EntityRsNPCCustomEntity.java b/src/main/java/com/smallaswater/npc/entitys/EntityRsNPCCustomEntity.java index 1f628a8..6627b80 100644 --- a/src/main/java/com/smallaswater/npc/entitys/EntityRsNPCCustomEntity.java +++ b/src/main/java/com/smallaswater/npc/entitys/EntityRsNPCCustomEntity.java @@ -4,6 +4,7 @@ import cn.lanink.gamecore.utils.EntityUtils; import cn.nukkit.Player; import cn.nukkit.entity.data.IntEntityData; +import cn.nukkit.entity.data.Skin; import cn.nukkit.level.Level; import cn.nukkit.level.format.FullChunk; import cn.nukkit.nbt.tag.CompoundTag; @@ -12,6 +13,7 @@ import cn.nukkit.network.protocol.SetEntityLinkPacket; import cn.nukkit.network.protocol.types.EntityLink; import com.smallaswater.npc.data.RsNpcConfig; +import com.smallaswater.npc.variable.VariableManage; import lombok.NonNull; import static cn.nukkit.network.protocol.SetEntityLinkPacket.TYPE_PASSENGER; @@ -79,7 +81,7 @@ public void addMovement(double x, double y, double z, double yaw, double pitch, public void spawnTo(Player player) { if (!this.hasSpawned.containsKey(player.getLoaderId()) && this.chunk != null && player.usedChunks.containsKey(Level.chunkHash(this.chunk.getX(), this.chunk.getZ()))) { this.hasSpawned.put(player.getLoaderId(), player); - player.dataPacket(createAddEntityPacket()); + player.dataPacket(createAddEntityPacket(player)); } if (this.riding != null) { @@ -121,4 +123,18 @@ public DataPacket createAddEntityPacket() { return addEntity; } + public DataPacket createAddEntityPacket(Player player) { + AddEntityPacket pk = (AddEntityPacket) this.createAddEntityPacket(); + pk.metadata.putString( + EntityUtils.getEntityField("DATA_NAMETAG", DATA_NAMETAG), + VariableManage.stringReplace(player, this.getNameTag(), this.getConfig()) + ); + return pk; + } + + @Override + public void setSkin(Skin skin) { + this.skin = skin; + } + } diff --git a/src/main/java/com/smallaswater/npc/utils/FormHelper.java b/src/main/java/com/smallaswater/npc/utils/FormHelper.java index cda7f2d..18a94b0 100644 --- a/src/main/java/com/smallaswater/npc/utils/FormHelper.java +++ b/src/main/java/com/smallaswater/npc/utils/FormHelper.java @@ -134,7 +134,7 @@ public static void sendAdminNpc(@NotNull Player player, @NotNull RsNpcConfig rsN "\n显示名称一直可见: " + toAdminNpcBooleanShowText(rsNpcConfig.isNameTagAlwaysVisible()) + "\n坐标:\n x: " + NukkitMath.round(rsNpcConfig.getLocation().getX(), 2) + "\n y: " + NukkitMath.round(rsNpcConfig.getLocation().getY(), 2) + - "\n z: " + NukkitMath.round(rsNpcConfig.getLocation().getZ(), 2) + "" + + "\n z: " + NukkitMath.round(rsNpcConfig.getLocation().getZ(), 2) + "\n yaw: " + NukkitMath.round(rsNpcConfig.getLocation().getYaw(), 3) + "\n 世界: " + rsNpcConfig.getLocation().getLevel().getName() + "\n物品:\n 手持: " + hand.getId() + ":" + hand.getDamage() + @@ -233,7 +233,7 @@ public static void sendAdminNpcConfig(@NotNull Player player, @NotNull RsNpcConf custom.onResponded((formResponseCustom, cp) -> { try { String showName = formResponseCustom.getInputResponse(0); - if ("".equals(showName.trim())) { + if (showName.trim().isEmpty()) { cp.sendMessage(language.translateString("gui.adminNPCConfig.responded.showNameNull")); return; } @@ -324,7 +324,7 @@ public static void sendAdminNpcConfigEmote(@NotNull Player player, @NotNull RsNp rsNpcConfig.getEmoteIDs().clear(); String[] emoteIDs = formResponseCustom.getInputResponse(2).split(";"); for (String id : emoteIDs) { - if (!"".equals(id.trim())) { + if (!id.trim().isEmpty()) { rsNpcConfig.getEmoteIDs().add(id); } } @@ -393,7 +393,7 @@ public static void sendAdminNpcConfigCommandAdd(@NotNull Player player, @NotNull custom.onResponded((formResponseCustom, cp) -> { String cmd = formResponseCustom.getInputResponse(1).replace("&", ""); - if ("".equals(cmd.trim())) { + if (cmd.trim().isEmpty()) { cp.sendMessage("命令不能为空!"); return; } @@ -483,7 +483,7 @@ public static void sendAdminNpcConfigMessageAdd(@NotNull Player player, @NotNull custom.onResponded((formResponseCustom, cp) -> { String message = formResponseCustom.getInputResponse(1); - if ("".equals(message.trim())) { + if (message.trim().isEmpty()) { cp.sendMessage(language.translateString("gui.adminNPCConfigMessageAdd.responded.messageNull")); return; } diff --git a/src/main/resources/Npc.yml b/src/main/resources/Npc.yml index 8de77a8..b26309a 100644 --- a/src/main/resources/Npc.yml +++ b/src/main/resources/Npc.yml @@ -14,7 +14,7 @@ nameTagAlwaysVisible: true 胸部: "" 腿部: "" 脚部: "" -皮肤: "默认" +皮肤: "private_steve" 实体NetworkId: -1 实体大小: 1.0 看向玩家: true diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c8e9047..e570bed 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: RsNPC main: com.smallaswater.npc.RsNPC -version: "2.4.2" +version: "2.4.3-SNAPSHOT" api: - "1.0.9" - "1.0.11"