feat: add FakePlayer on Disconnect
This commit is contained in:
parent
fa18a203b1
commit
780e7dc597
4 changed files with 173 additions and 19 deletions
|
@ -21,18 +21,23 @@ import de.cliffbreak.varo.listeners.PlayerClientOptionsChangeListener;
|
||||||
import de.cliffbreak.varo.listeners.PlayerDeathListener;
|
import de.cliffbreak.varo.listeners.PlayerDeathListener;
|
||||||
import de.cliffbreak.varo.listeners.PlayerJoinQuitListener;
|
import de.cliffbreak.varo.listeners.PlayerJoinQuitListener;
|
||||||
import de.cliffbreak.varo.listeners.PlayerPreLoginListener;
|
import de.cliffbreak.varo.listeners.PlayerPreLoginListener;
|
||||||
|
import de.cliffbreak.varo.managers.NPCManager;
|
||||||
|
|
||||||
public class Varo extends JavaPlugin {
|
public class Varo extends JavaPlugin {
|
||||||
|
|
||||||
public File configurationFile = new File("plugins/CliffbreakVaro", "config.yml");
|
public File configurationFile = new File("plugins/CliffbreakVaro", "config.yml");
|
||||||
public FileConfiguration config = YamlConfiguration.loadConfiguration(this.configurationFile);
|
public FileConfiguration config = YamlConfiguration.loadConfiguration(this.configurationFile);
|
||||||
public PlayerCache playerCache = new PlayerCache(this);
|
public NPCManager npcManager;
|
||||||
|
public PlayerCache playerCache;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
|
||||||
getLogger().info("CliffbreakVaro is starting...");
|
getLogger().info("CliffbreakVaro is starting...");
|
||||||
|
|
||||||
|
this.npcManager = new NPCManager(this);
|
||||||
|
this.playerCache = new PlayerCache(this);
|
||||||
|
|
||||||
// this.config.addDefault("Varo.Start", "TODO: StartDate");
|
// this.config.addDefault("Varo.Start", "TODO: StartDate");
|
||||||
this.config.addDefault("Varo.Bans", new ArrayList<String>());
|
this.config.addDefault("Varo.Bans", new ArrayList<String>());
|
||||||
this.config.options().copyDefaults(true);
|
this.config.options().copyDefaults(true);
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
package de.cliffbreak.varo.commands;
|
package de.cliffbreak.varo.commands;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import com.destroystokyo.paper.Title;
|
import com.destroystokyo.paper.Title;
|
||||||
|
@ -23,6 +19,7 @@ import org.json.simple.parser.ParseException;
|
||||||
|
|
||||||
import de.cliffbreak.varo.Varo;
|
import de.cliffbreak.varo.Varo;
|
||||||
import de.cliffbreak.varo.uitls.MessageUtils;
|
import de.cliffbreak.varo.uitls.MessageUtils;
|
||||||
|
import de.cliffbreak.varo.uitls.WebUtils;
|
||||||
|
|
||||||
public class VaroCommand implements CommandExecutor {
|
public class VaroCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
@ -41,23 +38,13 @@ public class VaroCommand implements CommandExecutor {
|
||||||
if (args.length == 2 && args[0].equals("unban")) {
|
if (args.length == 2 && args[0].equals("unban")) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final ArrayList<String> bans = (ArrayList<String>) this.plugin.config.get("Varo.Bans");
|
final ArrayList<String> bans = (ArrayList<String>) this.plugin.config.get("Varo.Bans");
|
||||||
String url = "https://api.mojang.com/users/profiles/minecraft/" + args[1];
|
|
||||||
try {
|
try {
|
||||||
HttpURLConnection connection = ((HttpURLConnection) (new URL(url)).openConnection());
|
String result = WebUtils.GET("https://api.mojang.com/users/profiles/minecraft/" + args[1]);
|
||||||
connection.setRequestMethod("GET");
|
if (result.isEmpty()) {
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
||||||
String inputLine;
|
|
||||||
StringBuffer content = new StringBuffer();
|
|
||||||
while ((inputLine = in.readLine()) != null) {
|
|
||||||
content.append(inputLine);
|
|
||||||
}
|
|
||||||
in.close();
|
|
||||||
connection.disconnect();
|
|
||||||
if (content.toString().isEmpty()) {
|
|
||||||
sender.sendMessage("§c§lFehler: §r§cDer Spieler wurde nicht gefunden.");
|
sender.sendMessage("§c§lFehler: §r§cDer Spieler wurde nicht gefunden.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
JSONObject uuidObject = (JSONObject) JSONValue.parseWithException(content.toString());
|
JSONObject uuidObject = (JSONObject) JSONValue.parseWithException(result);
|
||||||
if (!bans.contains(uuidObject.get("id").toString())) {
|
if (!bans.contains(uuidObject.get("id").toString())) {
|
||||||
sender.sendMessage("§c§lFehler: §r§cDer Spieler ist nicht gebannt.");
|
sender.sendMessage("§c§lFehler: §r§cDer Spieler ist nicht gebannt.");
|
||||||
return true;
|
return true;
|
||||||
|
@ -66,7 +53,7 @@ public class VaroCommand implements CommandExecutor {
|
||||||
this.plugin.config.set("Varo.Bans", bans);
|
this.plugin.config.set("Varo.Bans", bans);
|
||||||
this.plugin.saveConfiguration();
|
this.plugin.saveConfiguration();
|
||||||
sender.sendMessage("§a§lErfolg: §r§aDer Spieler ist nun nicht mehr gebannt.");
|
sender.sendMessage("§a§lErfolg: §r§aDer Spieler ist nun nicht mehr gebannt.");
|
||||||
} catch (ParseException | IOException e) {
|
} catch (IOException | ParseException e) {
|
||||||
sender.sendMessage(
|
sender.sendMessage(
|
||||||
"§c§lFehler:§r§c beim Verbinden mit der Mojang-API ist ein Fehler aufgetreten. Eventuell sind die Mojang Server down.");
|
"§c§lFehler:§r§c beim Verbinden mit der Mojang-API ist ein Fehler aufgetreten. Eventuell sind die Mojang Server down.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -94,11 +81,30 @@ public class VaroCommand implements CommandExecutor {
|
||||||
sender.sendMessage(MessageUtils.getRichTextComponent("§9" + "Team 08", ""));
|
sender.sendMessage(MessageUtils.getRichTextComponent("§9" + "Team 08", ""));
|
||||||
sender.sendMessage(MessageUtils.getRichTextComponent("§d" + "Team 09", ""));
|
sender.sendMessage(MessageUtils.getRichTextComponent("§d" + "Team 09", ""));
|
||||||
sender.sendMessage(MessageUtils.getRichTextComponent("§5" + "Team 10", ""));
|
sender.sendMessage(MessageUtils.getRichTextComponent("§5" + "Team 10", ""));
|
||||||
|
} else if (args.length == 1 && args[0].equals("test")) {
|
||||||
|
if (sender instanceof Player) {
|
||||||
|
try {
|
||||||
|
plugin.npcManager.createClone((Player) sender, false);
|
||||||
|
} catch (IOException e) {
|
||||||
|
sender.sendMessage(
|
||||||
|
"§c§lFehler:§r§c beim Verbinden mit der Mojang-API ist ein Fehler aufgetreten. Eventuell sind die Mojang Server down.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.sendMessage("§c§lFehler:§r§c Dieses Kommando kann nur durch einen Spieler ausgeführt werden.");
|
||||||
|
}
|
||||||
|
} else if (args.length == 1 && args[0].equals("testremove")) {
|
||||||
|
if (sender instanceof Player) {
|
||||||
|
plugin.npcManager.removeClone(((Player) sender));
|
||||||
|
} else {
|
||||||
|
sender.sendMessage("§c§lFehler:§r§c Dieses Kommando kann nur durch einen Spieler ausgeführt werden.");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage("\n§6========== §b§lCliffbreak.de VARO §r§6============\n ");
|
sender.sendMessage("\n§6========== §b§lCliffbreak.de VARO §r§6============\n ");
|
||||||
sender.sendMessage("§a/varo start: §rStarte das Varo Projekt!");
|
sender.sendMessage("§a/varo start: §rStarte das Varo Projekt!");
|
||||||
sender.sendMessage("§a/varo unban [Spieler]: §rSpieler wieder auf den Server lassen");
|
sender.sendMessage("§a/varo unban [Spieler]: §rSpieler wieder auf den Server lassen");
|
||||||
sender.sendMessage("§a/varo teamcolors: §rZeige verfügbare Team-Farben an");
|
sender.sendMessage("§a/varo teamcolors: §rZeige verfügbare Team-Farben an");
|
||||||
|
sender.sendMessage("§a/varo test: §rSpawne einen Klon");
|
||||||
|
sender.sendMessage("§a/varo testremove: §rLösche den Klon");
|
||||||
sender.sendMessage("\n§6==========================================");
|
sender.sendMessage("\n§6==========================================");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package de.cliffbreak.varo.listeners;
|
package de.cliffbreak.varo.listeners;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
||||||
|
@ -26,6 +27,11 @@ public class PlayerJoinQuitListener implements Listener {
|
||||||
@EventHandler()
|
@EventHandler()
|
||||||
public void onPlayerQuit(final PlayerQuitEvent e) {
|
public void onPlayerQuit(final PlayerQuitEvent e) {
|
||||||
e.setQuitMessage(null);
|
e.setQuitMessage(null);
|
||||||
|
try {
|
||||||
|
plugin.npcManager.createClone(e.getPlayer(), true);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
Bukkit.broadcast(
|
Bukkit.broadcast(
|
||||||
MessageUtils.getRichTextComponent(e.getPlayer().getName(), "§f hat den Server verlassen.", true));
|
MessageUtils.getRichTextComponent(e.getPlayer().getName(), "§f hat den Server verlassen.", true));
|
||||||
}
|
}
|
||||||
|
@ -33,6 +39,8 @@ public class PlayerJoinQuitListener implements Listener {
|
||||||
@EventHandler()
|
@EventHandler()
|
||||||
public void onPlayerJoin(final PlayerJoinEvent e) {
|
public void onPlayerJoin(final PlayerJoinEvent e) {
|
||||||
e.setJoinMessage(null);
|
e.setJoinMessage(null);
|
||||||
|
plugin.npcManager.removeClone(e.getPlayer());
|
||||||
|
plugin.npcManager.syncClones(e.getPlayer());
|
||||||
Bukkit.broadcast(
|
Bukkit.broadcast(
|
||||||
MessageUtils.getRichTextComponent(e.getPlayer().getName(), "§f hat den Server betreten.", true));
|
MessageUtils.getRichTextComponent(e.getPlayer().getName(), "§f hat den Server betreten.", true));
|
||||||
e.getPlayer().sendMessage("\n§7§l#### §9Cliffbreak.de - §lVaro §r§9Changelog §7§l####\n \n"
|
e.getPlayer().sendMessage("\n§7§l#### §9Cliffbreak.de - §lVaro §r§9Changelog §7§l####\n \n"
|
||||||
|
@ -40,6 +48,8 @@ public class PlayerJoinQuitListener implements Listener {
|
||||||
|
|
||||||
final Stack<String> changes = new Stack<String>();
|
final Stack<String> changes = new Stack<String>();
|
||||||
|
|
||||||
|
changes.push(" §7• §r§lADD: §rAdd a FakePlayer if Player is logged out");
|
||||||
|
changes.push(" §7• §r§lADD: §rAdd /varo test && /varo testremove");
|
||||||
changes.push(" §7• §r§lFIX: §r/varo Command is only usable by Server Operators now");
|
changes.push(" §7• §r§lFIX: §r/varo Command is only usable by Server Operators now");
|
||||||
changes.push(" §7• §r§lADD: §rDisallow special Items (Enchanted Golden Apple, Fishing Rod, Totem of Undying)");
|
changes.push(" §7• §r§lADD: §rDisallow special Items (Enchanted Golden Apple, Fishing Rod, Totem of Undying)");
|
||||||
changes.push(" §7• §r§lADD: §rUse Vanilla Hearts");
|
changes.push(" §7• §r§lADD: §rUse Vanilla Hearts");
|
||||||
|
|
133
varo/src/main/java/de/cliffbreak/varo/managers/NPCManager.java
Normal file
133
varo/src/main/java/de/cliffbreak/varo/managers/NPCManager.java
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
package de.cliffbreak.varo.managers;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import com.mojang.authlib.properties.Property;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.craftbukkit.v1_15_R1.CraftServer;
|
||||||
|
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
|
||||||
|
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.scoreboard.Scoreboard;
|
||||||
|
import org.bukkit.scoreboard.Team;
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import org.json.simple.JSONValue;
|
||||||
|
import org.json.simple.parser.ParseException;
|
||||||
|
|
||||||
|
import de.cliffbreak.varo.Varo;
|
||||||
|
import de.cliffbreak.varo.uitls.WebUtils;
|
||||||
|
import net.minecraft.server.v1_15_R1.DataWatcherObject;
|
||||||
|
import net.minecraft.server.v1_15_R1.DataWatcherRegistry;
|
||||||
|
import net.minecraft.server.v1_15_R1.EntityPlayer;
|
||||||
|
import net.minecraft.server.v1_15_R1.MinecraftServer;
|
||||||
|
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityDestroy;
|
||||||
|
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityHeadRotation;
|
||||||
|
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityMetadata;
|
||||||
|
import net.minecraft.server.v1_15_R1.PacketPlayOutNamedEntitySpawn;
|
||||||
|
import net.minecraft.server.v1_15_R1.PacketPlayOutPlayerInfo;
|
||||||
|
import net.minecraft.server.v1_15_R1.PlayerConnection;
|
||||||
|
import net.minecraft.server.v1_15_R1.PlayerInteractManager;
|
||||||
|
import net.minecraft.server.v1_15_R1.WorldServer;
|
||||||
|
import net.minecraft.server.v1_15_R1.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
|
||||||
|
|
||||||
|
public class NPCManager {
|
||||||
|
|
||||||
|
private final Varo plugin;
|
||||||
|
private final ArrayList<EntityPlayer> players = new ArrayList<EntityPlayer>();
|
||||||
|
private Scoreboard scoreboard;
|
||||||
|
private Team afkTeam;
|
||||||
|
|
||||||
|
public NPCManager(final Varo plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.scoreboard = Bukkit.getScoreboardManager().getMainScoreboard();
|
||||||
|
if (scoreboard.getTeam("afk") == null) {
|
||||||
|
|
||||||
|
this.afkTeam = scoreboard.registerNewTeam("afk");
|
||||||
|
} else {
|
||||||
|
this.afkTeam = scoreboard.getTeam("afk");
|
||||||
|
}
|
||||||
|
this.afkTeam.setPrefix("§8§l[AFK] ");
|
||||||
|
this.afkTeam.setColor(ChatColor.GRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createClone(final Player player, final boolean shouldHaveAFKPrefix) throws IOException {
|
||||||
|
final Location location = player.getLocation();
|
||||||
|
final MinecraftServer nmsServer = ((CraftServer) Bukkit.getServer()).getServer();
|
||||||
|
final WorldServer nmsWorld = ((CraftWorld) player.getWorld()).getHandle();
|
||||||
|
final GameProfile gameProfile = new GameProfile(player.getUniqueId(), player.getName());
|
||||||
|
try {
|
||||||
|
final String result = WebUtils.GET("https://sessionserver.mojang.com/session/minecraft/profile/"
|
||||||
|
+ player.getUniqueId().toString().replace("-", "") + "?unsigned=false");
|
||||||
|
final JSONObject resultObject = (JSONObject) JSONValue.parseWithException(result);
|
||||||
|
final JSONObject properties = (JSONObject) ((JSONArray) resultObject.get("properties")).get(0);
|
||||||
|
|
||||||
|
gameProfile.getProperties().put("textures", new Property("textures", properties.get("value").toString(),
|
||||||
|
properties.get("signature").toString()));
|
||||||
|
} catch (IOException | ParseException e) {
|
||||||
|
plugin.getLogger().info(e.getMessage());
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
final EntityPlayer npc = new EntityPlayer(nmsServer, nmsWorld, gameProfile,
|
||||||
|
new PlayerInteractManager(nmsWorld));
|
||||||
|
|
||||||
|
npc.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||||
|
|
||||||
|
if (shouldHaveAFKPrefix) {
|
||||||
|
this.afkTeam.addEntry(npc.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
players.add(npc);
|
||||||
|
|
||||||
|
for (Player connectionPlayer : Bukkit.getOnlinePlayers()) {
|
||||||
|
final PlayerConnection connection = ((CraftPlayer) connectionPlayer).getHandle().playerConnection;
|
||||||
|
connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, npc));
|
||||||
|
connection.sendPacket(new PacketPlayOutNamedEntitySpawn(npc));
|
||||||
|
connection.sendPacket(
|
||||||
|
new PacketPlayOutEntityHeadRotation(npc, (byte) ((location.getYaw() * 256.0F) / 360.0F)));
|
||||||
|
npc.getDataWatcher().set(new DataWatcherObject<>(16, DataWatcherRegistry.a),
|
||||||
|
(byte) plugin.playerCache.getSkinParts(player.getUniqueId().toString().replace("-", "")));
|
||||||
|
npc.getDataWatcher().set(new DataWatcherObject<>(17, DataWatcherRegistry.a),
|
||||||
|
plugin.playerCache.getMainHandAsByte(player.getUniqueId().toString().replace("-", "")));
|
||||||
|
connection.sendPacket(new PacketPlayOutEntityMetadata(npc.getId(), npc.getDataWatcher(), true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syncClones(Player player) {
|
||||||
|
for (EntityPlayer npc : this.players) {
|
||||||
|
final PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection;
|
||||||
|
connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, npc));
|
||||||
|
connection.sendPacket(new PacketPlayOutNamedEntitySpawn(npc));
|
||||||
|
connection.sendPacket(new PacketPlayOutEntityHeadRotation(npc, (byte) ((npc.yaw * 256.0F) / 360.0F)));
|
||||||
|
npc.getDataWatcher().set(new DataWatcherObject<>(16, DataWatcherRegistry.a),
|
||||||
|
(byte) plugin.playerCache.getSkinParts(player.getUniqueId().toString().replace("-", "")));
|
||||||
|
npc.getDataWatcher().set(new DataWatcherObject<>(17, DataWatcherRegistry.a),
|
||||||
|
plugin.playerCache.getMainHandAsByte(player.getUniqueId().toString().replace("-", "")));
|
||||||
|
connection.sendPacket(new PacketPlayOutEntityMetadata(npc.getId(), npc.getDataWatcher(), true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeClone(Player player) {
|
||||||
|
this.afkTeam.removeEntry(player.getName());
|
||||||
|
for (int i = 0; i < this.players.size(); i++) {
|
||||||
|
EntityPlayer npc = this.players.get(i);
|
||||||
|
if (npc.getUniqueID().equals(player.getUniqueId())) {
|
||||||
|
final WorldServer nmsWorld = ((CraftWorld) player.getWorld()).getHandle();
|
||||||
|
nmsWorld.removeEntity(npc);
|
||||||
|
|
||||||
|
for (Player connectionPlayer : Bukkit.getOnlinePlayers()) {
|
||||||
|
final PlayerConnection connection = ((CraftPlayer) connectionPlayer).getHandle().playerConnection;
|
||||||
|
connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, npc));
|
||||||
|
connection.sendPacket(new PacketPlayOutEntityDestroy(npc.getId()));
|
||||||
|
}
|
||||||
|
this.players.remove(npc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue