-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
397 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
src/main/java/de/luuuuuis/privateserver/spigot/events/NPCListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package de.luuuuuis.privateserver.spigot.events; | ||
|
||
import de.luuuuuis.privateserver.spigot.PrivateServer; | ||
import de.luuuuuis.privateserver.spigot.util.reflections.NMSUtils; | ||
import de.luuuuuis.privateserver.spigot.util.reflections.Reflections; | ||
import net.jitse.npclib.api.NPC; | ||
import net.jitse.npclib.api.events.NPCInteractEvent; | ||
import net.jitse.npclib.api.skin.Skin; | ||
import net.jitse.npclib.internal.NPCBase; | ||
import net.minecraft.server.v1_8_R3.PacketPlayOutEntity; | ||
import org.bukkit.Location; | ||
import org.bukkit.entity.Player; | ||
import org.bukkit.event.EventHandler; | ||
import org.bukkit.event.Listener; | ||
import org.bukkit.event.player.PlayerJoinEvent; | ||
import org.bukkit.event.player.PlayerQuitEvent; | ||
import org.bukkit.scheduler.BukkitRunnable; | ||
import org.bukkit.util.NumberConversions; | ||
import org.bukkit.util.Vector; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
public class NPCListener implements Listener { | ||
|
||
private final PrivateServer privateServer; | ||
private final Map<Player, NPC> npcs = new HashMap<>(); | ||
|
||
public NPCListener(PrivateServer privateServer) { | ||
this.privateServer = privateServer; | ||
} | ||
|
||
@EventHandler | ||
public void onJoin(PlayerJoinEvent e) { | ||
Player p = e.getPlayer(); | ||
|
||
Location location = new Location(p.getWorld(), p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ()); | ||
NPC npc = privateServer.getNpcLib().createNPC(Collections.singletonList("§aPrivate Server")); | ||
npc.setLocation(location); | ||
|
||
Objects.requireNonNull(NMSUtils.getProfile(p)).getProperties().get("textures").stream() | ||
.findFirst().ifPresent(playerProperty -> npc.setSkin(new Skin(playerProperty.getValue(), playerProperty.getSignature()))); | ||
|
||
npc.create(); | ||
npc.show(p); | ||
|
||
npcs.put(p, npc); | ||
|
||
// Sets head rotation for the npc if the player is in a range of 15 blocks | ||
// Author: @yanjulang | ||
new BukkitRunnable() { | ||
|
||
@Override | ||
public void run() { | ||
if (!p.isOnline()) { | ||
cancel(); | ||
return; | ||
} | ||
|
||
if (npc.getLocation().getWorld() == p.getWorld() && p.getLocation().distance(npc.getLocation()) < 15) { | ||
Vector look = p.getLocation().toVector().add(new Vector(0, 1, 0)).subtract(npc.getLocation().toVector().add(new Vector(0, 1.54, 0))); | ||
float[] rots = vecToRots(look); | ||
|
||
if (rots[0] > 180) { | ||
rots[0] -= 360; | ||
} | ||
|
||
Object packet = null; | ||
try { | ||
packet = Objects.requireNonNull(NMSUtils.getNMSClass("PacketPlayOutEntityHeadRotation")).getConstructor().newInstance(); | ||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException instantiationException) { | ||
instantiationException.printStackTrace(); | ||
} | ||
|
||
Reflections.setValue(packet, "a", ((NPCBase) npc).getEntityId()); | ||
Reflections.setValue(packet, "b", toAngle(rots[0])); | ||
NMSUtils.sendPacket(p, packet); | ||
NMSUtils.sendPacket(p, new PacketPlayOutEntity.PacketPlayOutEntityLook(((NPCBase) npc).getEntityId(), toAngle(rots[0]), toAngle(rots[1]), true)); | ||
} | ||
} | ||
|
||
private float[] vecToRots(Vector vector) { | ||
double x = vector.getX(); | ||
double z = vector.getZ(); | ||
if (x == 0.0D && z == 0.0D) { | ||
return new float[]{0f, (float) (vector.getY() > 0.0D ? -90 : 90)}; | ||
} else { | ||
double theta = Math.atan2(-x, z); | ||
float yaw = (float) Math.toDegrees((theta + 6.283185307179586D) % 6.283185307179586D); | ||
double x2 = NumberConversions.square(x); | ||
double z2 = NumberConversions.square(z); | ||
double xz = Math.sqrt(x2 + z2); | ||
float pitch = (float) Math.toDegrees(Math.atan(-vector.getY() / xz)); | ||
return new float[]{yaw, pitch}; | ||
} | ||
} | ||
|
||
public byte toAngle(float value) { | ||
return (byte) ((int) (value * 256.0F / 360.0F)); | ||
} | ||
}.runTaskTimerAsynchronously(privateServer, 0, 2); | ||
|
||
} | ||
|
||
@EventHandler | ||
public void onQuit(PlayerQuitEvent e) { | ||
Player p = e.getPlayer(); | ||
|
||
NPC npc = npcs.get(p); | ||
npc.destroy(); | ||
|
||
npcs.remove(p); | ||
} | ||
|
||
@EventHandler | ||
public void onInteract(NPCInteractEvent e) { | ||
NPC npc = npcs.get(e.getWhoClicked()); | ||
|
||
if (e.getNPC().equals(npc)) { | ||
|
||
} | ||
|
||
} | ||
} |
102 changes: 102 additions & 0 deletions
102
src/main/java/de/luuuuuis/privateserver/spigot/util/reflections/NMSUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package de.luuuuuis.privateserver.spigot.util.reflections; | ||
|
||
import com.mojang.authlib.GameProfile; | ||
import org.bukkit.Bukkit; | ||
import org.bukkit.entity.Player; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
import java.util.Objects; | ||
|
||
public class NMSUtils { | ||
|
||
/** | ||
* Send a packet to a player without using direct nms imports | ||
* | ||
* @param player to send the packet to | ||
* @param packet to send | ||
*/ | ||
public static void sendPacket(Player player, Object packet) { | ||
try { | ||
Object handle = player.getClass().getMethod("getHandle").invoke(player); | ||
Object connection = handle.getClass().getField("playerConnection").get(handle); | ||
connection.getClass().getMethod("sendPacket", getNMSClass("Packet")).invoke(connection, packet); | ||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | ||
| SecurityException | NoSuchFieldException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
|
||
/** | ||
* Get an NMS Class by its Name | ||
* Class Path: Net.Ninecraft.Server.<VersionString>.ClassName | ||
* | ||
* @param name of the Class | ||
* @return Class | ||
*/ | ||
public static Class<?> getNMSClass(String name) { | ||
String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; | ||
try { | ||
return Class.forName("net.minecraft.server." + version + "." + name); | ||
} catch (ClassNotFoundException e) { | ||
e.printStackTrace(); | ||
return null; | ||
} | ||
} | ||
|
||
/** | ||
* Get an CraftBukkit Class by its Name | ||
* Class Path: org.bukkit.craftbukkit.<VersionString>.ClassName | ||
* | ||
* @param name of the Class | ||
* @return Class | ||
*/ | ||
public static Class<?> getCraftBukkitClass(String name) { | ||
String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; | ||
try { | ||
return Class.forName("org.bukkit.craftbukkit." + version + "." + name); | ||
} catch (ClassNotFoundException e) { | ||
e.printStackTrace(); | ||
return null; | ||
} | ||
} | ||
|
||
/** | ||
* Get the NMS Version String from Bukkit.getServer() - package | ||
* | ||
* @return String | ||
*/ | ||
public static String getVersion() { | ||
return Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; | ||
} | ||
|
||
/** | ||
* Get the {@link GameProfile} from a player | ||
* | ||
* @param player to get the GameProfile from | ||
* @return GameProfile | ||
*/ | ||
public static GameProfile getProfile(Player player) { | ||
try { | ||
return (GameProfile) Objects.requireNonNull(NMSUtils.getHandle(player)).getClass().getMethod("getProfile").invoke(NMSUtils.getHandle(player)); | ||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | ||
| SecurityException e) { | ||
e.printStackTrace(); | ||
return null; | ||
} | ||
} | ||
|
||
/** | ||
* Get an NMS - EntityPlayer - Object by a org.bukkit.Player - Object | ||
* | ||
* @param player (Bukkit Player) | ||
* @return NMS EntityPlayer Object | ||
*/ | ||
public static Object getHandle(Player player) { | ||
try { | ||
return player.getClass().getMethod("getHandle").invoke(player); | ||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | ||
| SecurityException e) { | ||
return null; | ||
} | ||
} | ||
} |
Oops, something went wrong.