Started work on #20
This commit is contained in:
parent
a91ee58547
commit
96028d2ca1
|
@ -5,9 +5,12 @@
|
|||
package net.jitse.npclib.api;
|
||||
|
||||
import net.jitse.npclib.api.skin.Skin;
|
||||
import net.jitse.npclib.api.state.NPCSlot;
|
||||
import net.jitse.npclib.api.state.NPCState;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public interface NPC {
|
||||
|
||||
|
@ -88,4 +91,21 @@ public interface NPC {
|
|||
* Requires {@link NPC#create} to be used first.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Toggle a state of the NPC.
|
||||
*
|
||||
* @param state The state to be toggled.
|
||||
* @return Object instance.
|
||||
*/
|
||||
NPC toggleState(NPCState state);
|
||||
|
||||
/**
|
||||
* Change the item in the inventory of the NPC.
|
||||
*
|
||||
* @param slot The slot to set the item of.
|
||||
* @param item The item to set.
|
||||
* @return Object instance.
|
||||
*/
|
||||
NPC setItem(NPCSlot slot, ItemStack item);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package net.jitse.npclib.api.state;
|
||||
|
||||
public enum NPCSlot {
|
||||
|
||||
HELMET(4),
|
||||
CHESTPLATE(3),
|
||||
LEGGINGS(2),
|
||||
BOOTS(1),
|
||||
IN_HAND(0);
|
||||
|
||||
int slot;
|
||||
|
||||
NPCSlot(int slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public int getSlot() {
|
||||
return slot;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package net.jitse.npclib.api.state;
|
||||
|
||||
public enum NPCState {
|
||||
|
||||
ON_FIRE((byte) 1),
|
||||
CROUCHED((byte) 2),
|
||||
INVISIBLE((byte) 32);
|
||||
|
||||
private byte b;
|
||||
|
||||
NPCState(byte b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public byte getByte() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public static byte getMasked(final NPCState... status) {
|
||||
byte b = 0;
|
||||
for (NPCState s : status) b |= s.getByte();
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
package net.jitse.npclib.internal;
|
||||
|
||||
import net.jitse.npclib.api.state.NPCSlot;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
|
@ -16,4 +17,13 @@ interface PacketHandler {
|
|||
void sendShowPackets(Player player);
|
||||
|
||||
void sendHidePackets(Player player);
|
||||
|
||||
void sendMetadataPacket(Player player);
|
||||
|
||||
void sendEquipmentPacket(Player player, NPCSlot slot);
|
||||
|
||||
default void sendEquipmentPackets(Player player) {
|
||||
for (NPCSlot slot : NPCSlot.values())
|
||||
sendEquipmentPacket(player, slot);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,13 @@ import net.jitse.npclib.api.NPC;
|
|||
import net.jitse.npclib.api.events.NPCHideEvent;
|
||||
import net.jitse.npclib.api.events.NPCShowEvent;
|
||||
import net.jitse.npclib.api.skin.Skin;
|
||||
import net.jitse.npclib.api.state.NPCSlot;
|
||||
import net.jitse.npclib.api.state.NPCState;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
|
@ -32,11 +35,14 @@ public abstract class SimpleNPC implements NPC, PacketHandler {
|
|||
private final Set<UUID> autoHidden = new HashSet<>();
|
||||
|
||||
protected double cosFOV = Math.cos(Math.toRadians(60));
|
||||
protected NPCState[] activeStates = new NPCState[]{};
|
||||
|
||||
protected NPCLib instance;
|
||||
protected Location location;
|
||||
protected Skin skin;
|
||||
|
||||
protected ItemStack helmet, chestplate, leggings, boots, inHand;
|
||||
|
||||
public SimpleNPC(NPCLib instance, List<String> lines) {
|
||||
this.instance = instance;
|
||||
this.lines = lines == null ? Collections.emptyList() : lines;
|
||||
|
@ -153,6 +159,8 @@ public abstract class SimpleNPC implements NPC, PacketHandler {
|
|||
|
||||
if (auto) {
|
||||
sendShowPackets(player);
|
||||
sendMetadataPacket(player);
|
||||
sendEquipmentPackets(player);
|
||||
} else {
|
||||
if (isShown(player)) {
|
||||
throw new RuntimeException("Cannot call show method twice.");
|
||||
|
@ -167,6 +175,8 @@ public abstract class SimpleNPC implements NPC, PacketHandler {
|
|||
if (player.getWorld().equals(location.getWorld()) && player.getLocation().distance(location)
|
||||
<= instance.getAutoHideDistance()) {
|
||||
sendShowPackets(player);
|
||||
sendMetadataPacket(player);
|
||||
sendEquipmentPackets(player);
|
||||
} else {
|
||||
autoHidden.add(player.getUniqueId());
|
||||
}
|
||||
|
@ -207,4 +217,82 @@ public abstract class SimpleNPC implements NPC, PacketHandler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NPC toggleState(NPCState state) {
|
||||
int inActiveStatesIndex = -1;
|
||||
if (activeStates.length == 0) { // If there're no active states, this is the first to be toggled (on).
|
||||
activeStates = new NPCState[]{state};
|
||||
} else { // Otherwise, there have been states that were toggled, check if we need to toggle something off.
|
||||
for (int i = 0; i < activeStates.length; i++) {
|
||||
if (activeStates[i] == state) { // If the state is to be toggled off, save the index so we can remove it.
|
||||
inActiveStatesIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inActiveStatesIndex > -1) { // If there's a state to be toggled of, create a new array with all items but the one to be toggled off.
|
||||
NPCState[] newArr = new NPCState[activeStates.length - 1];
|
||||
for (int i = 0; i < newArr.length; i++) {
|
||||
if (inActiveStatesIndex == i) {
|
||||
continue;
|
||||
} else if (i < inActiveStatesIndex) {
|
||||
newArr[i] = activeStates[i];
|
||||
} else {
|
||||
newArr[i] = activeStates[i + 1];
|
||||
}
|
||||
}
|
||||
activeStates = newArr;
|
||||
} else { // Else, we need to add a state by appending our state to the array.
|
||||
NPCState[] newArr = new NPCState[activeStates.length + 1];
|
||||
System.arraycopy(activeStates, 0, newArr, 0, activeStates.length);
|
||||
newArr[activeStates.length] = state;
|
||||
activeStates = newArr;
|
||||
}
|
||||
}
|
||||
|
||||
// Send a new metadata packet to all players that can see the NPC.
|
||||
for (UUID shownUuid : shown) {
|
||||
Player player = Bukkit.getPlayer(shownUuid);
|
||||
if (player != null && isShown(player)) {
|
||||
sendMetadataPacket(player);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NPC setItem(NPCSlot slot, ItemStack item) {
|
||||
if (slot == null) {
|
||||
throw new NullPointerException("Slot cannot be null");
|
||||
}
|
||||
|
||||
switch (slot) {
|
||||
case HELMET:
|
||||
this.helmet = item;
|
||||
break;
|
||||
case CHESTPLATE:
|
||||
this.chestplate = item;
|
||||
break;
|
||||
case LEGGINGS:
|
||||
this.leggings = item;
|
||||
break;
|
||||
case BOOTS:
|
||||
this.boots = item;
|
||||
break;
|
||||
case IN_HAND:
|
||||
this.inHand = item;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Entered an invalid inventory slot");
|
||||
}
|
||||
|
||||
for (UUID shownUuid : shown) {
|
||||
Player player = Bukkit.getPlayer(shownUuid);
|
||||
if (player != null && isShown(player)) {
|
||||
sendEquipmentPacket(player, slot);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.util.Objects;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Jitse Boonstras
|
||||
* @author Jitse Boonstra
|
||||
*/
|
||||
public class ChunkListener implements Listener {
|
||||
|
||||
|
@ -35,7 +35,7 @@ public class ChunkListener implements Listener {
|
|||
Chunk chunk = event.getChunk();
|
||||
|
||||
for (SimpleNPC npc : NPCManager.getAllNPCs()) {
|
||||
if (!isSameChunk(npc.getLocation(), chunk))
|
||||
if (npc.getLocation() == null || !isSameChunk(npc.getLocation(), chunk))
|
||||
continue; // We aren't unloading the chunk with the NPC in it.
|
||||
|
||||
// We found an NPC in the chunk being unloaded. Time to hide this NPC from all players.
|
||||
|
|
20
nms/pom.xml
20
nms/pom.xml
|
@ -15,16 +15,16 @@
|
|||
|
||||
<modules>
|
||||
<module>v1_8_R1</module>
|
||||
<module>v1_8_R2</module>
|
||||
<module>v1_8_R3</module>
|
||||
<module>v1_9_R1</module>
|
||||
<module>v1_9_R2</module>
|
||||
<module>v1_10_R1</module>
|
||||
<module>v1_11_R1</module>
|
||||
<module>v1_12_R1</module>
|
||||
<module>v1_13_R1</module>
|
||||
<module>v1_13_R2</module>
|
||||
<module>v1_14_R1</module>
|
||||
<!-- <module>v1_8_R2</module>-->
|
||||
<!-- <module>v1_8_R3</module>-->
|
||||
<!-- <module>v1_9_R1</module>-->
|
||||
<!-- <module>v1_9_R2</module>-->
|
||||
<!-- <module>v1_10_R1</module>-->
|
||||
<!-- <module>v1_11_R1</module>-->
|
||||
<!-- <module>v1_12_R1</module>-->
|
||||
<!-- <module>v1_13_R1</module>-->
|
||||
<!-- <module>v1_13_R2</module>-->
|
||||
<!-- <module>v1_14_R1</module>-->
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
package net.jitse.npclib.nms.v1_8_R1;
|
||||
|
||||
import net.jitse.npclib.NPCLib;
|
||||
import net.jitse.npclib.api.state.NPCSlot;
|
||||
import net.jitse.npclib.hologram.Hologram;
|
||||
import net.jitse.npclib.internal.MinecraftVersion;
|
||||
import net.jitse.npclib.internal.SimpleNPC;
|
||||
import net.jitse.npclib.nms.v1_8_R1.packets.PacketPlayOutEntityHeadRotationWrapper;
|
||||
import net.jitse.npclib.nms.v1_8_R1.packets.PacketPlayOutNamedEntitySpawnWrapper;
|
||||
import net.jitse.npclib.nms.v1_8_R1.packets.PacketPlayOutPlayerInfoWrapper;
|
||||
import net.jitse.npclib.nms.v1_8_R1.packets.PacketPlayOutScoreboardTeamWrapper;
|
||||
import net.jitse.npclib.nms.v1_8_R1.packets.*;
|
||||
import net.minecraft.server.v1_8_R1.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_8_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -97,4 +97,41 @@ public class NPC_v1_8_R1 extends SimpleNPC {
|
|||
|
||||
hologram.destroy(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMetadataPacket(Player player) {
|
||||
PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
|
||||
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadataWrapper().create(activeStates, entityId);
|
||||
|
||||
playerConnection.sendPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendEquipmentPacket(Player player, NPCSlot slot) {
|
||||
PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
|
||||
|
||||
ItemStack item;
|
||||
switch (slot) {
|
||||
case HELMET:
|
||||
item = helmet;
|
||||
break;
|
||||
case CHESTPLATE:
|
||||
item = chestplate;
|
||||
break;
|
||||
case LEGGINGS:
|
||||
item = leggings;
|
||||
break;
|
||||
case BOOTS:
|
||||
item = boots;
|
||||
break;
|
||||
case IN_HAND:
|
||||
item = inHand;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Slot is not recognized");
|
||||
}
|
||||
|
||||
PacketPlayOutEntityEquipment packet = new PacketPlayOutEntityEquipment(entityId, slot.getSlot(), CraftItemStack.asNMSCopy(item));
|
||||
playerConnection.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package net.jitse.npclib.nms.v1_8_R1.packets;
|
||||
|
||||
import net.jitse.npclib.api.state.NPCState;
|
||||
import net.minecraft.server.v1_8_R1.DataWatcher;
|
||||
import net.minecraft.server.v1_8_R1.PacketPlayOutEntityMetadata;
|
||||
|
||||
public class PacketPlayOutEntityMetadataWrapper {
|
||||
|
||||
public PacketPlayOutEntityMetadata create(NPCState[] activateStates, int entityId) {
|
||||
DataWatcher dataWatcher = new DataWatcher(null);
|
||||
byte masked = NPCState.getMasked(activateStates);
|
||||
dataWatcher.a(0, masked);
|
||||
|
||||
return new PacketPlayOutEntityMetadata(entityId, dataWatcher, true);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue