• Es freut uns dass du in unser Minecraft Forum gefunden hast. Hier kannst du mit über 130.000 Minecraft Fans über Minecraft diskutieren, Fragen stellen und anderen helfen. In diesem Minecraft Forum kannst du auch nach Teammitgliedern, Administratoren, Moderatoren , Supporter oder Sponsoren suchen. Gerne kannst du im Offtopic Bereich unseres Minecraft Forums auch über nicht Minecraft spezifische Themen reden. Wir hoffen dir gefällt es in unserem Minecraft Forum!

Spigot UUID eines Spielers Serverseitig ändern & Spieler neu laden

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
Hallo,
ich möchte einen NickSystem schreiben, wo ich den Namen, Skin und die UUID des Spielers ändern kann. Ich habe es bereits geschafft den Namen und den Skin des Spielers zu ändern. Doch die UUID ändert sich nicht. Den Namen habe ich geändert, indem ich im GameProfile des Spielers den Field "name" auf die gewünschte Name geändert habe. Genauso habe ich es auch mit der UUID versucht. Ich habe im GameProfile des Spielers deb Field "id" auf die gewünschte UUID geändert ( UUID.randomUUID(); ). Das ganze klappt auch, wenn ich das ganze im PlayerLoginEvent mache. Deshalb denke ich das der Fehler beim neu laden des Spielers ist. Ich hoffe ihr könnt mir dabei behilflich sein. Der Plugin ist übrigens auf der 1.16.4.

nick Methode:
    public static void nickPlayer(Player player, String name) {
        GameProfile gameProfile = ((CraftPlayer) player).getHandle().getProfile();
        UUID uuid = UUID.randomUUID();
        try {
            Field field1 = gameProfile.getClass().getDeclaredField("id");
            Field field2 = gameProfile.getClass().getDeclaredField("name");
            field1.setAccessible(true);
            field2.setAccessible(true);
            field1.set(gameProfile, uuid);
            field2.set(gameProfile, name);
            field1.setAccessible(false);
            field2.setAccessible(false);
            player.setDisplayName(name);
        } catch(NoSuchFieldException | IllegalAcces***ception e) {
            e.printStackTrace();
        }
        gameProfile.getProperties().clear();
        Skin skin = new Skin(Bukkit.getOfflinePlayer(name).getUniqueId().toString().replace("-", ""));
        gameProfile.getProperties().put("textures", new Property("textures", skin.getSkinValue(), skin.getSkinSignatur()));
        if(skin.getSkinName() != null) {
            gameProfile.getProperties().put(skin.getSkinName(), new Property(skin.getSkinName(), skin.getSkinValue(), skin.getSkinSignatur()));
        }
    }

    public static void reloadPlayer(Player player) {
        CraftPlayer craftPlayer = ((CraftPlayer) player);
        EntityPlayer entityPlayer = craftPlayer.getHandle();
        PacketPlayOutEntityDestroy packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(craftPlayer.getEntityId());
        PacketPlayOutPlayerInfo packetPlayOutPlayerInfoRemove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entityPlayer);
        PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, entityPlayer);
        PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
        Bukkit.getScheduler().scheduleSyncDelayedTask(NickAPI.getInstance(), new Runnable() {
            @Override
            public void run() {
                for(Player on : Bukkit.getOnlinePlayers()) {
                    on.hidePlayer(NickAPI.getInstance(), player);
                }
                Bukkit.getScheduler().scheduleSyncDelayedTask(NickAPI.getInstance(), new Runnable() {
                    @Override
                    public void run() {
                        for(Player on : Bukkit.getOnlinePlayers()) {
                            on.showPlayer(NickAPI.getInstance(), player);
                        }
                        sendNickPacket(packetPlayOutEntityDestroy);
                        sendNickPacket(packetPlayOutPlayerInfoRemove);
                        for(Player on : Bukkit.getOnlinePlayers()) {
                            if(on != player) {
                                sendPacket(packetPlayOutPlayerInfoAdd, on);
                                sendPacket(packetPlayOutNamedEntitySpawn, on);
                            }
                        }
                        player.updateInventory();
                    }
                }, 15);
            }
        }, 1);
    }
 
Zuletzt bearbeitet:

Chrisliebär❤️

nur echt mit ❤️
Moderator
Registriert
19 Mai 2014
Beiträge
1.675
Diamanten
830
Was genau meinst du denn mit "die UUID ändert sich nicht"? Wenn der Skin des Spielers sich ändert, dann sollte auch seine UUID neu gesetzt worden sein. Natürlich nur visuell und nur auf den anderen Clients. Für den Spieler selbst wird er immer die selbe UUID behalten und es ist auch etwas problematisch, wenn andere Clients eine neue UUID sehen, da Plugins und der Server natürlich weiterhin mit der korrekten UUID arbeiten.
 

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
Was genau meinst du denn mit "die UUID ändert sich nicht"? Wenn der Skin des Spielers sich ändert, dann sollte auch seine UUID neu gesetzt worden sein. Natürlich nur visuell und nur auf den anderen Clients. Für den Spieler selbst wird er immer die selbe UUID behalten und es ist auch etwas problematisch, wenn andere Clients eine neue UUID sehen, da Plugins und der Server natürlich weiterhin mit der korrekten UUID arbeiten.

Der Skin ändert sich nur für andere Spieler, nicht für sich selbst. Ich habe einen Befehl gemacht, wo der Plugin mit der Methode: player.getUniqueId(); , die UUID des Spielers sendet. Wie gesagt, wenn ich das im PlayerLoginEvent mache dann wird die UUID auch geändert, doch wenn ich es nach dem Login mache klappt es nicht, weshalb ich den Spieler ja neu laden muss. Und ich denke das dort das Problem liegt... Aber ich weiß nicht was ich beim neu laden falsch mache. Die UUID soll natürlich Serverseitig geändert werden.
 

Chrisliebär❤️

nur echt mit ❤️
Moderator
Registriert
19 Mai 2014
Beiträge
1.675
Diamanten
830
Was du willst ist unmöglich und wird zu massiven Problemen mit anderen Plugins kommen. Du kannst nicht einfach die UUID ändern und erwarten, dass andere Plugins nicht sofort explodieren. Ohne dass der Spieler sich neu einloggt geht das überhaupt nicht. Aber statt das Rad neu zu erfinden, könntest du einfach das selbe Protokoll nutzen, welches auch BungeeCord nutzt. Damit lässt sich die UUID des Spielers nämlich einfach beim Verbindungsaufbau setzen. Oder du baust die Funktionalität in BungeeCord ein. Alles andere ist eine absolut schreckliche Idee.

Dass du den Skin für den Spieler selbst ändern kannst, kann ich mir eigentlich nicht vorstellen. Der Client sollte keine Möglichkeit haben seine eigene UUID zu ändern.
 

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
Was du willst ist unmöglich und wird zu massiven Problemen mit anderen Plugins kommen. Du kannst nicht einfach die UUID ändern und erwarten, dass andere Plugins nicht sofort explodieren. Ohne dass der Spieler sich neu einloggt geht das überhaupt nicht. Aber statt das Rad neu zu erfinden, könntest du einfach das selbe Protokoll nutzen, welches auch BungeeCord nutzt. Damit lässt sich die UUID des Spielers nämlich einfach beim Verbindungsaufbau setzen. Oder du baust die Funktionalität in BungeeCord ein. Alles andere ist eine absolut schreckliche Idee.

Dass du den Skin für den Spieler selbst ändern kannst, kann ich mir eigentlich nicht vorstellen. Der Client sollte keine Möglichkeit haben seine eigene UUID zu ändern.

Es sind sowieso alle Plugins selber programmiert und wir können die Plugins deshalb darauf anpassen. Also sollte es den Plugins nichts ausmachen das die UUID geändert wird. Wie gesagt beim PlayerLoginEvent geht das ja, aber da ich das in meinem NickSystem einbauen möchte sollte die UUID nach den Eingabe vom Befehl geändert werden. Und ich habe in einigen Forumbeiträgen gesehen das wenn man die Packets sendet, die ich auch in meiner reloadPlayer Methode eingebaut habe, soll der Spieler neu geladen werden... Doch das klappt bei mir nicht...
 

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
Wozu willst du überhaupt die UUID verändern, das ergibt in meinen Augen überhaupt keinen Sinn.

Ich will die UUID verändert, damit die Spieler nicht herausfinden können das der Spieler genickt ist bzw. wer der genickte Spieler wirklich ist. Denn es gibt ja LabyMod addons, womit man das herausfinden kann...
 

Ativendus

Kuhfänger
Registriert
7 Dezember 2016
Beiträge
78
Diamanten
352
Ich würde sagen die Anzahl von Spielern die ihre eigenen Clients programmieren oder die Anzahl von Clients, die sowas können oder die Anzahl an Leuten, die sowas unbedingt wollen ist sehr gering und eigentlich zu vernachlässigen. Gerade bei einem etwas kleineren Server wird dieser Fall nicht vorkommen.
 

Chrisliebär❤️

nur echt mit ❤️
Moderator
Registriert
19 Mai 2014
Beiträge
1.675
Diamanten
830
Und ich habe in einigen Forumbeiträgen gesehen das wenn man die Packets sendet, die ich auch in meiner reloadPlayer Methode eingebaut habe, soll der Spieler neu geladen werden... Doch das klappt bei mir nicht...
Die dürften alle annehmen, dass du lediglich den Spieler für alle anderen Clients modifizieren möchtest. Niemand wäre wahnsinnig genug um tatsächlich im laufenden Betrieb die UUID eines bereits verbundenen Spielers auf dem Server zu ändern. Das wird explodieren!

Wenn du allerdings ohnehin alle Plugins selbst schreibst, kannst du die Verwandlung auch einfach direkt an deinen Pluginschnittstellen umsetzen und lediglich die von dir bereits verwendeten Möglichkeiten nutzen.
 

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
Ich habe es so gemacht das ich den Packet "PacketPlayOutNamedEntitySpawn" an alle Spielern (außer den Spieler der genickt sein soll selbst) sende. Dabei ändere ich die UUID im Packet so das die UUID nur für die Spieler geändert wird und für die Plugins gleich bleibt. Dann bekomme ich ja auch keine Probleme mit den Plugins. Den Namen ändere ich im GameProfile und den Skin ändere ich auch noch. Da ich die Änderung der UUID´s mit Packets mache muss ich jeden Spieler der den Server neu betretet den Packet nochmal (natürlich auch wieder mit der geänderten UUID). Also ich speichere die genickten Spieler in einer ArrayList und den sende den Spielern die den Server betreten für alle genickten Spieler einen Packet mit der geänderten UUID. Ich verwende dabei immer eine Random UUID (UUID.randomUUID). Doch das ganze geht bei mir aufgrund eines Fehlers die ich mache nicht. Ich habe bei mir den Fehler nicht gefunden und wollte fragen, ob ihr da einen findet. Ich habe es im folgenden Code das so geregelt das jeder Spieler der den Server betretet automatisch genickt wird. In der Config gibt es eine Liste mit verschiedenen Namen und da wird ein zufälliger Name genommen und der Spieler bekommt dann den Skin und Namen des Spielers die per Zufall dran genommen wurde (UUID ist wie gesagt random). Wenn ich den Server betrete sehe ich jeden Spieler genickt der bereits drauf war, jedoch werden für mich die Spieler die nach mir den Server für mich und den anderen die vor ihm schon drauf waren nicht genickt.
Sry für den langen Text, ich hoffe ihr nehmt euch trotzdem die Zeit und hilft mir dabei, danke schonmal für eure Antworten!

NickPlayer Klasse:
package de.traymc.nickapi.utils;

import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import de.traymc.nickapi.main.NickAPI;
import net.minecraft.server.v1_16_R3.EntityPlayer;
import net.minecraft.server.v1_16_R3.PacketPlayOutNamedEntitySpawn;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;

public class NickPlayer extends Reflections {

    public static List<String> nicknames = new ArrayList<>();
    public static List<UUID> nickedPlayers = new ArrayList<>();

    Player player;

    public NickPlayer(Player player) {
        this.player = player;
    }

    public void addAutoNickPlayer() {

    }

    public void autoNickPlayer() {
        String tempname = "null";
        {
            List<String> onlinePlayerNames = new ArrayList<>();
            for(Player on : Bukkit.getOnlinePlayers()) {
                onlinePlayerNames.add(on.getName());
            }
            while(tempname == "null" || onlinePlayerNames.contains(tempname)) {
                Random random = new Random();
                int randomNumber = random.nextInt(nicknames.size());
                tempname = nicknames.get(randomNumber);
            }
        }
        String name = tempname;
        UUID uuid = UUID.randomUUID();
        CraftPlayer craftPlayer = ((CraftPlayer) player);
        EntityPlayer entityPlayer = craftPlayer.getHandle();
        GameProfile gameProfile = entityPlayer.getProfile();
        Bukkit.getScheduler().scheduleSyncDelayedTask(NickAPI.getInstance(), new Runnable() {
            @Override
            public void run() {
                PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
                setValue(packetPlayOutNamedEntitySpawn, "b", uuid);
                sendNickPacket(packetPlayOutNamedEntitySpawn, player);
                setValue(gameProfile, "name", name);
                player.setDisplayName(name);
                Bukkit.getScheduler().scheduleSyncDelayedTask(NickAPI.getInstance(), new Runnable() {
                    @Override
                    public void run() {
                        gameProfile.getProperties().clear();
                        Skin skin = new Skin(Bukkit.getOfflinePlayer(name).getUniqueId().toString().replace("-", ""));
                        gameProfile.getProperties().put("textures", new Property("textures", skin.getSkinValue(), skin.getSkinSignatur()));
                        if(skin.getSkinName() != null) {
                            gameProfile.getProperties().put(skin.getSkinName(), new Property(skin.getSkinName(), skin.getSkinValue(), skin.getSkinSignatur()));
                        }
                        if(!nickedPlayers.contains(player.getUniqueId())) {
                            nickedPlayers.add(player.getUniqueId());
                        }
                    }
                }, 4);
            }
        }, 7);
    }

    public boolean isEnableNick() {
        return true;
    }

    public boolean isNicked() {
        return true;
    }

    public String getRealName() {
        return Bukkit.getOfflinePlayer(player.getUniqueId()).getName();
    }
}

Reflections Klasse:
package de.traymc.nickapi.utils;

import net.minecraft.server.v1_16_R3.Packet;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;

import java.lang.reflect.Field;

public class Reflections {

    public void sendPacket(Packet packet, Player player) {
        ((CraftPlayer) Bukkit.getPlayer(player.getUniqueId())).getHandle().playerConnection.sendPacket(packet);
    }

    public void sendNickPacket(Packet packet, Player player) {
        for(Player on : Bukkit.getOnlinePlayers()) {
            if(!on.getUniqueId().equals(player.getUniqueId())) {
                sendPacket(packet, on);
            }
        }
    }

    public void setValue(Object obj, String name, Object value) {
        try {
            Field field = obj.getClass().getDeclaredField(name);
            field.setAccessible(true);
            field.set(obj, value);
            field.setAccessible(false);
        } catch(NoSuchFieldException | IllegalAcces***ception e) {
            e.printStackTrace();
        }
    }
}

PlayerJoinQuitListener:
package de.traymc.nickapi.listeners;

import com.mojang.authlib.GameProfile;
import de.traymc.nickapi.main.NickAPI;
import de.traymc.nickapi.main.Unnick_CMD;
import de.traymc.nickapi.utils.NickPlayer;
import de.traymc.nickapi.utils.Reflections;
import net.minecraft.server.v1_16_R3.EntityPlayer;
import net.minecraft.server.v1_16_R3.PacketPlayOutNamedEntitySpawn;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
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 java.util.UUID;

public class PlayerJoinQuitListener extends Reflections implements Listener {

    @EventHandler
    public void onJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        NickPlayer nickPlayer = new NickPlayer(player);
        if(nickPlayer.isEnableNick()) { //diese Methode gibt derzeit noch automatisch true zurück
            nickPlayer.autoNickPlayer();
            Bukkit.getScheduler().scheduleSyncDelayedTask(NickAPI.getInstance(), new Runnable() {
                @Override
                public void run() {
                    player.sendMessage(Unnick_CMD.prefix + "§aDu heißt diese Runde: §a§l" + player.getName() + "§a!");
                }
            }, 10);
        }
        for(UUID packetPlayerUUID : NickPlayer.nickedPlayers) {
            if(!packetPlayerUUID.equals(player.getUniqueId())) {
                nickPlayerForJoiner(Bukkit.getPlayer(packetPlayerUUID), player);
            }
        }
    }

    @EventHandler
    public void onQuit(PlayerQuitEvent event) {
        Player player = event.getPlayer();
        if(NickPlayer.nickedPlayers.contains(player.getUniqueId())) {
            NickPlayer.nickedPlayers.remove(player.getUniqueId());
        }
    }

    public void nickPlayerForJoiner(Player nickPlayer, Player joiner) {
        UUID uuid = UUID.randomUUID();
        Player player = Bukkit.getPlayer(nickPlayer.getUniqueId());
        CraftPlayer craftPlayer = ((CraftPlayer) player);
        EntityPlayer entityPlayer = craftPlayer.getHandle();

        PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
        setValue(packetPlayOutNamedEntitySpawn, "b", new GameProfile(uuid, player.getName()).getId());
        sendPacket(packetPlayOutNamedEntitySpawn, Bukkit.getPlayer(joiner.getUniqueId()));
    }
}
 

Chrisliebär❤️

nur echt mit ❤️
Moderator
Registriert
19 Mai 2014
Beiträge
1.675
Diamanten
830
Der Code sieht nicht aus, als ob du wirklich wüsstest, was du tust. Ich würde daher sagen, dass dein Vorhaben doch über dem liegt, was du momentan sicher realisieren kannst. Du kannst nicht einfach irgendwelche Pakete an den Client schicken und glauben, dass das dann funktioniert. Der Server und der Client verwalten über das Netzwerk einen gemeinsamen Zustand über die Spielwelt. Die Bukkit API lässt einen zwar glauben, dass man schon nichts kaputt machen kann, aber das liegt nur an der beschränkten API von Bukkit.

Sobald du in das Netzwerk eingreifst, bist du Mittelsmann zwischen Client und Server und alles was du dort tust muss konsistent mit dem Protokoll sein, damit Server und Client weiterhin konsistent kommunizieren. Das tust du bisher an fast keiner einzigen Stelle. Übrigens stimmt es nicht, dass du die UUID auf dem Server änderst, wie du behauptet hast, du verschickst aktuell lediglich eigene Pakete. Was dir glaub überhaupt nicht bewusst ist, ist die Tatsache, dass du auch die Pakete des Servers abfangen musst.

Wenn der Server Spieler Foobar spawnt, dann musst du das Paket abfangen und die UUID dort ebenfalls austauschen. Das seh ich aktuell gar nicht und dafür nutzt man, aus gutem Grund, ProtoclLib, denn das ist ziemlich aufwändig. Das selbe Problem tritt auf, wenn ein Spieler in die Reichweite des Clients kommt, auch dann musst du das Spawn Paket abfangen und umschreiben, und nicht einfach ein zusätzliches schicken.

Der Grund, warum das vermutlich aktuell so funktioniert ist einfach, weil die die Spieler spawnst bevor der Server dazu eine Chance hat und daher ignoriert der Client das eigentlich Paket des Servers. Der Server weiß davon natürlich auch nichts, wenn der Spieler nicht in Sichtweite ist, bekommt er keine Positionsupdates, wird aktuell aber trotzdem gespawnt, was übrigens auch dafür sorgt, dass der Client den Spieler trotzdem rendert. Wenn du genug Spieler hast, ist das eine absolute Katastrophe.

Ich seh da leider keine Möglichkeit dir bei deinem Problem zu helfen, da dir scheinbar nicht bewusst ist, wie so ein Netzwerkprotokoll funktioniert und wieso du da nicht einfach irgendwelche Pakete verschicken kannst. Dass das bisher trotzdem funktioniert hat ist nur Beweis, wie komplex die Probleme sind, die du im Netzwerkcode anrichten kannst.
 

Malfrador

Threadripper
Registriert
16 Juni 2013
Beiträge
1.473
Diamanten
396
Minecraft
Malfrador
Nur als kleine Anmerkung:
1. Nicht nur ProtocolLib, sondern auch PacketWrapper machen die Arbeit mit Paketen deutlich leichter.
2. Ein Spieler wird nicht korrekt sichtbar sein, wenn seine UUID nicht in der Playerlist ist. Du musst den Fake-Spieler also auch zu dieser hinzufügen. Danach kann er natürlich wieder versteckt werden.

Zu deinem Vorgehen:
Anstatt neue Entities zu spawnen, fange doch einfach die Entity-Spawn-Pakete der versteckten Spieler ab & modifiziere diese. Das ist deutlich sauberer und weniger aufwendig. ProtocolLib bietet auch dafür die entsprechenden Tools.
 

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
Nur als kleine Anmerkung:
1. Nicht nur ProtocolLib, sondern auch PacketWrapper machen die Arbeit mit Paketen deutlich leichter.
2. Ein Spieler wird nicht korrekt sichtbar sein, wenn seine UUID nicht in der Playerlist ist. Du musst den Fake-Spieler also auch zu dieser hinzufügen. Danach kann er natürlich wieder versteckt werden.

Zu deinem Vorgehen:
Anstatt neue Entities zu spawnen, fange doch einfach die Entity-Spawn-Pakete der versteckten Spieler ab & modifiziere diese. Das ist deutlich sauberer und weniger aufwendig. ProtocolLib bietet auch dafür die entsprechenden Tools.

Wie kann ich die UUID in die PlayerList hinzufügen?
 

Malfrador

Threadripper
Registriert
16 Juni 2013
Beiträge
1.473
Diamanten
396
Minecraft
Malfrador
Wie kann ich die UUID in die PlayerList hinzufügen?
In dem du das entsprechende Packet sendest. Das Packet muss vor dem Spawn des Spielers gesendet werden - der Client stellt keine Spieler dar, die nicht in der Playerlist sind.

Mit ProtocolLib & PacketWrapper geht das in ein paar Zeilen
Java:
WrapperPlayServerPlayerInfo info = new WrapperPlayServerPlayerInfo();
info.setAction(EnumWrappers.PlayerInfoAction.ADD_PLAYER);
// Test1 wäre der Name des Spielers, wird aber nirgendwo angezeigt. Test2 wird tatsächlich angezeigt in der Tablist.
// 1 ist der Ping. Und ein Gamemode braucht auch jeder "Spieler".
// Sobald der Spieler gespawnt ist, sollte man ihn wieder aus der Tablist/PlayerInfo entfernen.
PlayerInfoData data = new PlayerInfoData(new WrappedGameProfile(uuid, "Test1"), 1, EnumWrappers.NativeGameMode.SURVIVAL, WrappedChatComponent.fromText("Test2"));
List<PlayerInfoData> dataList = new ArrayList<>();
dataList.add(data);
info.setData(dataList);
try {
// player -> Spieler an den das Packet gesendet werden soll. manager ist ProtocolLib's ProtocolManager.
    manager.sendServerPacket(player, info.getHandle());
} catch (InvocationTargetException e) {
    e.printStackTrace();
}
 

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
In dem du das entsprechende Packet sendest. Das Packet muss vor dem Spawn des Spielers gesendet werden - der Client stellt keine Spieler dar, die nicht in der Playerlist sind.

Mit ProtocolLib & PacketWrapper geht das in ein paar Zeilen
Java:
WrapperPlayServerPlayerInfo info = new WrapperPlayServerPlayerInfo();
info.setAction(EnumWrappers.PlayerInfoAction.ADD_PLAYER);
// Test1 wäre der Name des Spielers, wird aber nirgendwo angezeigt. Test2 wird tatsächlich angezeigt in der Tablist.
// 1 ist der Ping. Und ein Gamemode braucht auch jeder "Spieler".
// Sobald der Spieler gespawnt ist, sollte man ihn wieder aus der Tablist/PlayerInfo entfernen.
PlayerInfoData data = new PlayerInfoData(new WrappedGameProfile(uuid, "Test1"), 1, EnumWrappers.NativeGameMode.SURVIVAL, WrappedChatComponent.fromText("Test2"));
List<PlayerInfoData> dataList = new ArrayList<>();
dataList.add(data);
info.setData(dataList);
try {
// player -> Spieler an den das Packet gesendet werden soll. manager ist ProtocolLib's ProtocolManager.
    manager.sendServerPacket(player, info.getHandle());
} catch (InvocationTargetException e) {
    e.printStackTrace();
}

Ich habe die sendPacket Methode überschrieben, doch irgendwie bringt das nichts, obwohl das eigentlich gehen muss, denn ich habe mithilfe von Netty Injections gekuckt, ob der Packet gesendet wird und habe festgestellt das das Packet "PacketPlayOutNamedEntitySpawn" mit der gefälschten UUID gesendet wird, doch erstend werden die Spieler nicht genickt und zweitens werden die Spieler unsichtbar...

CustinPlayerConnection Klasse:
package de.traymc.nickapi.utils;

import net.minecraft.server.v1_16_R3.EntityPlayer;
import net.minecraft.server.v1_16_R3.MinecraftServer;
import net.minecraft.server.v1_16_R3.NetworkManager;
import net.minecraft.server.v1_16_R3.Packet;
import net.minecraft.server.v1_16_R3.PacketPlayOutNamedEntitySpawn;
import net.minecraft.server.v1_16_R3.PlayerConnection;
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;

import java.util.UUID;

public class CustomPlayerConnection extends PlayerConnection {


    public CustomPlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) {
        super(minecraftserver, networkmanager, entityplayer);
    }

    public CustomPlayerConnection(EntityPlayer entityPlayer) {
        this(entityPlayer.server, entityPlayer.playerConnection.networkManager, entityPlayer);
    }

    public CustomPlayerConnection(Player player) {
        this(getNMSPlayer(player));
    }


    public static EntityPlayer getNMSPlayer(Player player) {
        return ((CraftPlayer) player).getHandle();
    }

    @Override
    public void sendPacket(Packet packet) {
        if(packet instanceof PacketPlayOutNamedEntitySpawn) {
            PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn = (PacketPlayOutNamedEntitySpawn) packet;
            Reflections reflections = new Reflections();
            UUID playeruuid = (UUID) reflections.getValue(packetPlayOutNamedEntitySpawn, "b");
            if(NickPlayer.nickedPlayers.containsKey(playeruuid)) {
                UUID uuid = UUID.randomUUID();
                reflections.setValue(packetPlayOutNamedEntitySpawn, "b", uuid);
                super.sendPacket(packetPlayOutNamedEntitySpawn);
            } else {
                super.sendPacket(packet);
            }
        } else {
            super.sendPacket(packet);
        }
    }
}

PlayerJoinQuitListener Klasse:
package de.traymc.nickapi.listeners;

import de.traymc.nickapi.main.NickAPI;
import de.traymc.nickapi.main.Unnick_CMD;
import de.traymc.nickapi.utils.CustomPlayerConnection;
import de.traymc.nickapi.utils.NickPlayer;
import de.traymc.nickapi.utils.Reflections;
import org.bukkit.Bukkit;
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;

public class PlayerJoinQuitListener extends Reflections implements Listener {


    @EventHandler
    public void onJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        NickPlayer nickPlayer = new NickPlayer(player);
        CustomPlayerConnection pc = new CustomPlayerConnection(player);
        CustomPlayerConnection.getNMSPlayer(player).playerConnection = pc;
        if(nickPlayer.isEnableNick()) { //gibt auto. true zurück
            String name = nickPlayer.getRandomName();
            nickPlayer.nickPlayer(name);
            Bukkit.getScheduler().scheduleSyncDelayedTask(NickAPI.getInstance(), new Runnable() {
                @Override
                public void run() {
                    player.sendMessage(Unnick_CMD.prefix + "§aDu heißt diese Runde: §a§l" + player.getName() + "§a!");
                }
            }, 7);
        }
    }

    @EventHandler
    public void onQuit(PlayerQuitEvent event) {
        Player player = event.getPlayer();
        if(NickPlayer.nickedPlayers.containsKey(player.getUniqueId())) {
            NickPlayer.nickedPlayers.remove(player.getUniqueId());
        }
    }
}

NickPlayer Klasse:
package de.traymc.nickapi.utils;

import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import de.traymc.nickapi.listeners.PacketReader;
import de.traymc.nickapi.main.NickAPI;
import net.minecraft.server.v1_16_R3.EntityPlayer;
import net.minecraft.server.v1_16_R3.PacketPlayOutNamedEntitySpawn;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.UUID;

public class NickPlayer extends Reflections {

    public static List<String> nicknames = new ArrayList<>();
    public static HashMap<UUID, PacketReader> packetReaders = new HashMap<>();
    public static HashMap<UUID, String> nickedPlayers = new HashMap<>();
    Player player;

    public NickPlayer(Player player) {
        this.player = player;
    }

    public void enableAutoNickForPlayer() {

    }

    public String getRandomName() {
        String tempname = "null";
        {
            List<String> onlinePlayerNames = new ArrayList<>();
            for(Player on : Bukkit.getOnlinePlayers()) {
                onlinePlayerNames.add(on.getName());
            }
            while(tempname == "null" || onlinePlayerNames.contains(tempname)) {
                Random random = new Random();
                int randomNumber = random.nextInt(NickPlayer.nicknames.size());
                tempname = NickPlayer.nicknames.get(randomNumber);
            }
        }
        String name = tempname;
        return name;
    }

    public void nickPlayer(String name) {
        /*
        Bukkit.getScheduler().scheduleSyncDelayedTask(NickAPI.getInstance(), new Runnable() {
            @Override
            public void run() {
                CraftPlayer craftPlayer = ((CraftPlayer) player);
                EntityPlayer entityPlayer = craftPlayer.getHandle();
                GameProfile gameProfile = entityPlayer.getProfile();
                setValue(gameProfile, "name", name);
                player.setDisplayName(name);
                gameProfile.getProperties().clear();
                Skin skin = new Skin(Bukkit.getOfflinePlayer(name).getUniqueId().toString().replace("-", ""));
                gameProfile.getProperties().put("textures", new Property("textures", skin.getSkinValue(), skin.getSkinSignatur()));
                if(skin.getSkinName() != null) {
                    gameProfile.getProperties().put(skin.getSkinName(), new Property(skin.getSkinName(), skin.getSkinValue(), skin.getSkinSignatur()));
                }
            }
        }, 5);
         */
        nickedPlayers.put(player.getUniqueId(), name);
    }

    public boolean isEnableNick() {
        return true;
    }

    public boolean isNicked() {
        return true;
    }

    public String getRealName() {
        return Bukkit.getOfflinePlayer(player.getUniqueId()).getName();
    }
}
 

Malfrador

Threadripper
Registriert
16 Juni 2013
Beiträge
1.473
Diamanten
396
Minecraft
Malfrador
Wenn du irgendwelchen unnötig komplizierten NMS-Stuff tust, kann ich dir leider auch nicht helfen. Da bist du auf dich alleine gestellt, das tut niemand freiwillig. Insbesondere NettyInjections klingen nach einer ultra schlechten Idee, die dir die gesamte Client-/Server-Kommunikation kaputtmachen werden.

Generell scheint es mir so, als sei das ein Projekt eindeutig über deinem aktuellen Skilllevel und du solltest mit etwas leichterem anfangen, oder zumindest APIs nutzen die die Arbeit erleichtern anstatt pures NMS.
 

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
Wenn du irgendwelchen unnötig komplizierten NMS-Stuff tust, kann ich dir leider auch nicht helfen. Da bist du auf dich alleine gestellt, das tut niemand freiwillig. Insbesondere NettyInjections klingen nach einer ultra schlechten Idee, die dir die gesamte Client-/Server-Kommunikation kaputtmachen werden.

Generell scheint es mir so, als sei das ein Projekt eindeutig über deinem aktuellen Skilllevel und du solltest mit etwas leichterem anfangen, oder zumindest APIs nutzen die die Arbeit erleichtern anstatt pures NMS.

Du meinst ich soll die Client-/Server-Kommunikation nicht kaputt machen und gleichzeitig meinst du das ich soll die Packets abfangen. Wenn ich Netty-Injections nutzen würde dann würde ich das nutzen, um die Packets abzufangen und zu modifizieren. Abgesehen davon habe ich gesagt das ich Netty Injections nur genutzt habe um zu testen ob das Packet auch wirklich modifiziert gesendet wird und für nichts anderes.

Wenn du schon meinst das mein Ansatz unnötig kompliziert ist kennst du doch sicher einen besseren und leichteren? Dieser Forum ist ja nicht unbedingt dazu da um Fehler zu finden sondern auch da damit man generellen bei den Vorgehensweisen behilflich ist? Aber ich verstehe trotzdem nicht was am überschreiben einer sendPacket Methode so kompliziert sein soll. Wie du gesagt hast soll ich die Packets bevor sie vom Spieler verarbeitet werden modifziert werden richtig? Genau das mache ich bei meiner sendPacket Methode. Da störe ich ja wie du meinst nichts an der Client-Server Modifikation, sondern modifiziere die UUID bevor der Server es sendet. Ein besserer Ansatz fällt mir da nicht ein.

Ich finde es generell voll dumm zu sagen das man etwas leichteres machen soll. Man lernt wenn man etwas schwierigeres macht. Wenn ich was leichtes mache lerne ich daraus nicht... Klar würde ich das verstehen wenn du mir das nicht sagen würdest wenn ich die Grundlagen und so nicht kenne, aber sonst kann man trotzdem versuchen den Leuten zu erklären was sie falsch machen. Wenn sie das nicht verstehen, verstehen sie das eben nicht. Das wollte ich nur mal erwähnen, da ich das oft im Forum sehe, denn ein Forum ist nicht dazu da, um den Skill level einer Person zu bewerten sondern einer Person zu helfen, aber trotzdem sehe ich sowas fast in jedem Beitrag als Antwort...
 

Chrisliebär❤️

nur echt mit ❤️
Moderator
Registriert
19 Mai 2014
Beiträge
1.675
Diamanten
830
Wenn du schon meinst das mein Ansatz unnötig kompliziert ist kennst du doch sicher einen besseren und leichteren?
Wir haben die jetzt beide mehrfach ProtocolLib empfohlen. Niemand fummelt von Hand in den NMS Klassen rum, weil das ein undokumentierter Haufen voll mit Obfuscatetem Müll ist. ProtocolLib besteht aus mehreren Schichten von Code, der sich ziemlich intelligent durch zur Laufzeit die Klasseninformationen besorgt, die du dir sonst durch das wälzen von nacktem Code selbst erschließen musst. Wenn du Reverse Engeneering lernen willst, klar, macht weiter so, das ist der korrekt Weg. Aber mir scheint du bist an einer Problemlösung interessiert und willst nur fertig werden, dann nutz ProtocolLib.

Ich finde es generell voll dumm zu sagen das man etwas leichteres machen soll. Man lernt wenn man etwas schwierigeres macht. Wenn ich was leichtes mache lerne ich daraus nicht...
Nutz ProtocolLib, du lernst genug.

Plugin findest du hier: https://www.spigotmc.org/resources/protocollib.1997/
Quellcode hier: https://github.com/dmulloy2/ProtocolLib/
Wrapperklassen, inklusive ihre Funktionsweise, hier: https://github.com/dmulloy2/PacketWrapper

Wrapperklassen find ich persönlich unschön, aber ich guck trotzdem rein, weil man direkt sieht, wie man das Zeugs benutzt. Da du aber bereits den Aufbau der NMS Packets verstanden hast, solltest du relativ schmerzlos mit ProtocolLibs StructureModifier zum Ziel kommen. Den NMS Code kannst du als Referenz trotzdem offen haben, das macht ebenfalls jeder so.

Es macht deutlich mehr Sinn, zu verstehen, wie ProtocolLib arbeitet, als Mojangs Gammelcode zu lesen.
 
Oben