Added Player#setSkin and PlayerSkinInitEvent to modify it at initialization

This commit is contained in:
Felix Cravic 2020-05-30 19:47:47 +02:00
parent 1343a66681
commit 7ce6f7ada1
7 changed files with 274 additions and 70 deletions

View File

@ -4,6 +4,7 @@ import fr.themode.demo.entity.ChickenCreature;
import fr.themode.demo.generator.ChunkGeneratorDemo;
import fr.themode.demo.generator.NoiseTestGenerator;
import net.minestom.server.MinecraftServer;
import net.minestom.server.attribute.Attribute;
import net.minestom.server.benchmark.BenchmarkManager;
import net.minestom.server.benchmark.ThreadResult;
import net.minestom.server.entity.*;
@ -39,6 +40,11 @@ import java.util.UUID;
public class PlayerInit {
private static String textures = "ewogICJ0aW1lc3RhbXAiIDogMTU5MDg1NTI3NjIwNCwKICAicHJvZmlsZUlkIiA6ICI0NTY2ZTY5ZmM5MDc0OGVlOGQ3MWQ3YmE1YWEwMGQyMCIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaGlua29mZGVhdGgiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzRkMWUwOGIwYmI3ZTlmNTkwYWYyNzc1ODEyNWJiZWQxNzc4YWM2Y2VmNzI5YWVkZmNiOTYxM2U5OTExYWU3NSIKICAgIH0sCiAgICAiQ0FQRSIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjBjYzA4ODQwNzAwNDQ3MzIyZDk1M2EwMmI5NjVmMWQ2NWExM2E2MDNiZjY0YjE3YzgwM2MyMTQ0NmZlMTYzNSIKICAgIH0KICB9Cn0=";
private static String signature = "rCVVwVpLF9ovy+Hm4cOXOLSPOMjNo5WoBfHo9K2OcTUPqcZJ1P/1k4lAnQkChD/Ri11iJ84PejWJzDkHMXM8196Wh+jf12d2GJVhca9/SRLms0cFJjdZZjs72+82AdX0OtO3+qzwKRHzHoEYb+ZVZLfgx37ZKKo4DD3IKmaSnwEjOVJ4BOhnsXLmcNW37kdZUmv2/hlg7ZuWZaayWPhadCYEMnkpVtDIpnpzAeV9EcRfg/ysQoynO2v6WEW0RtnfFEczMN6vXtfiuC8UqyA2SK9aiLnBgpGaehDfFIq/0dpo2uFilVDS/Il6uQ1JSwq7yNT5lNF+i1AlH9SGf1VVy5mT9ShmkVmRxCXX5cSNLXZD0acsNNJb/GAuDHuXpE32GsfgKxWAXMHLw0GnbADbFDfdl5nQyQTDS7FRfUjsFpF8a8Z83muFXaty2WLFy1zxy2JEkI/q+ltLaEG6mQbWI2zhOS7ARvK0OmPz4lDYVInfrwL93AIdMUg2Re817hsapkN6Dm1ND+iirvayR90gqQ9C9J0dMMBlSyTSoKBQeLsi8qETS+7LuhvletPTDFolnTIvP8hj2bWLmQ7LfXJ2arJCUw86YEavVYuF0gYrBuKcEYTC4DA0kO4yLj63gwEgOj9dEigCgyqUcenzmZBffSZ365/QF0cGrG7HC7HmF0w=";
private static PlayerSkin skin = new PlayerSkin(textures, signature);
private static volatile InstanceContainer instanceContainer;
private static volatile InstanceContainer netherTest;
@ -95,16 +101,15 @@ public class PlayerInit {
benchmarkMessage += "&e" + MathUtils.round(result.getCpuPercentage(), 2) + "% CPU ";
benchmarkMessage += "&c" + MathUtils.round(result.getUserPercentage(), 2) + "% USER ";
benchmarkMessage += "&d" + MathUtils.round(result.getBlockedPercentage(), 2) + "% BLOCKED ";
benchmarkMessage += "&a" + MathUtils.round(result.getWaitedPercentage(), 2) + "% WAITED ";
benchmarkMessage += "\n";
}
// if (benchmarkMessage.length() > 0)
// System.out.println(benchmarkMessage);
for (Player player : connectionManager.getOnlinePlayers()) {
player.sendHeaderFooter("RAM USAGE: " + ramUsage + " MB", benchmarkMessage, '&');
}
}
}, new UpdateOption(5, TimeUnit.TICK));
}, new UpdateOption(10, TimeUnit.TICK));
connectionManager.addPacketConsumer((player, packetController, packet) -> {
// Listen to all received packet
@ -150,6 +155,7 @@ public class PlayerInit {
ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
chickenCreature.setInstance(player.getInstance());
chickenCreature.setAttribute(Attribute.MOVEMENT_SPEED, 0.4f);
/*FakePlayer fakePlayer = new FakePlayer(UUID.randomUUID(), "test");
fakePlayer.addEventCallback(EntityDeathEvent.class, e -> {
@ -211,6 +217,10 @@ public class PlayerInit {
scoreboard.setTitle("test");*/
});
player.addEventCallback(PlayerSkinInitEvent.class, event -> {
event.setSkin(skin);
});
player.addEventCallback(PlayerSpawnEvent.class, event -> {
player.setGameMode(GameMode.CREATIVE);
player.teleport(new Position(0, 41f, 0));
@ -224,9 +234,10 @@ public class PlayerInit {
item.setEnchantment(Enchantment.SHARPNESS, (short) 50);
player.getInventory().addItemStack(item);
inventory.addItemStack(item.clone());
player.openInventory(inventory);
//player.getInventory().addItemStack(new ItemStack(Material.STONE, (byte) 100));
player.getInventory().addItemStack(new ItemStack(Material.STONE, (byte) 100));
Instance instance = player.getInstance();
WorldBorder worldBorder = instance.getWorldBorder();
@ -301,7 +312,7 @@ public class PlayerInit {
public static ResponseDataConsumer getResponseDataConsumer() {
return (playerConnection, responseData) -> {
responseData.setMaxPlayer(100);
responseData.setMaxPlayer(0);
responseData.setOnline(MinecraftServer.getConnectionManager().getOnlinePlayers().size());
responseData.addPlayer("A name", UUID.randomUUID());
responseData.addPlayer("Could be some message", UUID.randomUUID());

View File

@ -53,19 +53,7 @@ public abstract class EntityCreature extends LivingEntity {
super.update();
// Path finding
if (blockPositions != null) {
if (targetPosition != null) {
float distance = getPosition().getDistance(targetPosition);
//System.out.println("test: "+distance);
if (distance < 0.7f) {
setNextPathPosition();
//System.out.println("END TARGET");
} else {
moveTowards(targetPosition, getAttributeValue(Attribute.MOVEMENT_SPEED));
//System.out.println("MOVE TOWARD " + targetPosition);
}
}
}
pathProgress();
}
@ -250,7 +238,7 @@ public abstract class EntityCreature extends LivingEntity {
public void jump(float height) {
// FIXME magic value
Vector velocity = new Vector(0, height * 10, 0);
Vector velocity = new Vector(0, height * 5, 0);
setVelocity(velocity);
}
@ -281,7 +269,7 @@ public abstract class EntityCreature extends LivingEntity {
}
/**
* Used to move the entity toward {@code direction} in the axis X and Z
* Used to move the entity toward {@code direction} in the X and Z axis
* Gravity is still applied but the entity will not attempt to jump
*
* @param direction the targeted position
@ -304,11 +292,27 @@ public abstract class EntityCreature extends LivingEntity {
}
this.targetPosition = blockPosition.toPosition();//.add(0.5f, 0, 0.5f);
// FIXME: jump support
if (blockPosition.getY() > getPosition().getY())
jump(1);
}
private void pathProgress() {
if (blockPositions != null) {
if (targetPosition != null) {
float distance = getPosition().getDistance(targetPosition);
//System.out.println("test: "+distance);
if (distance < 1f) {
setNextPathPosition();
pathProgress();
//System.out.println("END TARGET");
} else {
moveTowards(targetPosition, getAttributeValue(Attribute.MOVEMENT_SPEED));
//System.out.println("MOVE TOWARD " + targetPosition);
}
}
}
}
private ItemStack getEquipmentItem(ItemStack itemStack, ArmorEquipEvent.ArmorSlot armorSlot) {
itemStack = ItemStackUtils.notNull(itemStack);

View File

@ -62,6 +62,7 @@ public class Player extends LivingEntity {
private int latency;
private String displayName;
private PlayerSkin skin;
private Dimension dimension;
private GameMode gameMode;
@ -165,6 +166,11 @@ public class Player extends LivingEntity {
*/
protected void init() {
// Init player (register events)
for (Consumer<Player> playerInitialization : MinecraftServer.getConnectionManager().getPlayerInitializations()) {
playerInitialization.accept(this);
}
// TODO complete login sequence with optionals packets
JoinGamePacket joinGamePacket = new JoinGamePacket();
joinGamePacket.entityId = getEntityId();
@ -189,21 +195,13 @@ public class Player extends LivingEntity {
spawnPositionPacket.z = 0;
playerConnection.sendPacket(spawnPositionPacket);
// Add player to list
String jsonDisplayName = displayName != null ? Chat.toJsonString(Chat.fromLegacyText(displayName)) : null;
String property = "";
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.ADD_PLAYER);
PlayerInfoPacket.AddPlayer addPlayer = new PlayerInfoPacket.AddPlayer(getUuid(), getUsername(), getGameMode(), getLatency());
addPlayer.displayName = jsonDisplayName;
PlayerInfoPacket.AddPlayer.Property prop = new PlayerInfoPacket.AddPlayer.Property("textures", property);
addPlayer.properties.add(prop);
playerInfoPacket.playerInfos.add(addPlayer);
playerConnection.sendPacket(playerInfoPacket);
// Init player
for (Consumer<Player> playerInitialization : MinecraftServer.getConnectionManager().getPlayerInitializations()) {
playerInitialization.accept(this);
}
// Add player to list with spawning skin
PlayerSkinInitEvent skinInitEvent = new PlayerSkinInitEvent(this);
callEvent(PlayerSkinInitEvent.class, skinInitEvent);
this.skin = skinInitEvent.getSkin();
final String textures = skin == null ? "" : skin.getTextures();
final String signature = skin == null ? null : skin.getSignature();
playerConnection.sendPacket(getAddPlayerToList(textures, signature));
// Commands start
{
@ -245,6 +243,7 @@ public class Player extends LivingEntity {
playerConnection.sendPacket(getPropertiesPacket()); // Send default properties
refreshHealth(); // Heal and send health packet
refreshAbilities(); // Send abilities packet
getInventory().update();
}
/**
@ -493,33 +492,7 @@ public class Player extends LivingEntity {
return false;
PlayerConnection viewerConnection = player.getPlayerConnection();
String property = "eyJ0aW1lc3RhbXAiOjE1NjU0ODMwODQwOTYsInByb2ZpbGVJZCI6ImFiNzBlY2I0MjM0NjRjMTRhNTJkN2EwOTE1MDdjMjRlIiwicHJvZmlsZU5hbWUiOiJUaGVNb2RlOTExIiwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2RkOTE2NzJiNTE0MmJhN2Y3MjA2ZTRjN2IwOTBkNzhlM2Y1ZDc2NDdiNWFmZDIyNjFhZDk4OGM0MWI2ZjcwYTEifX19";
SpawnPlayerPacket spawnPlayerPacket = new SpawnPlayerPacket();
spawnPlayerPacket.entityId = getEntityId();
spawnPlayerPacket.playerUuid = getUuid();
spawnPlayerPacket.position = getPosition();
PlayerInfoPacket pInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.ADD_PLAYER);
PlayerInfoPacket.AddPlayer addP = new PlayerInfoPacket.AddPlayer(getUuid(), getUsername(), getGameMode(), 10);
PlayerInfoPacket.AddPlayer.Property p = new PlayerInfoPacket.AddPlayer.Property("textures", property);//new PlayerInfoPacket.AddPlayer.Property("textures", properties.get(onlinePlayer.getUsername()));
addP.properties.add(p);
pInfoPacket.playerInfos.add(addP);
viewerConnection.sendPacket(pInfoPacket);
viewerConnection.sendPacket(spawnPlayerPacket);
viewerConnection.sendPacket(getVelocityPacket());
viewerConnection.sendPacket(getMetadataPacket());
// Equipments synchronization
syncEquipments();
if (hasPassenger()) {
viewerConnection.sendPacket(getPassengersPacket());
}
// Team
if (team != null)
viewerConnection.sendPacket(team.getTeamsCreationPacket());
showPlayer(viewerConnection);
return result;
}
@ -530,9 +503,7 @@ public class Player extends LivingEntity {
boolean result = super.removeViewer(player);
PlayerConnection viewerConnection = player.getPlayerConnection();
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER);
playerInfoPacket.playerInfos.add(new PlayerInfoPacket.RemovePlayer(getUuid()));
viewerConnection.sendPacket(playerInfoPacket);
viewerConnection.sendPacket(getRemovePlayerToList());
// Team
if (team != null && team.getPlayers().size() == 1) // If team only contains "this" player
@ -893,6 +864,66 @@ public class Player extends LivingEntity {
sendPacketToViewersAndSelf(infoPacket);
}
/**
* Get the player skin
*
* @return the player skin object,
* null means that the player has his {@link #getUuid()} default skin
*/
public PlayerSkin getSkin() {
return skin;
}
/**
* Change the player skin
*
* @param skin the player skin, null to reset it to his {@link #getUuid()} default skin
*/
public synchronized void setSkin(PlayerSkin skin) {
this.skin = skin;
final String textures = skin == null ? "" : skin.getTextures();
final String signature = skin == null ? null : skin.getSignature();
DestroyEntitiesPacket destroyEntitiesPacket = new DestroyEntitiesPacket();
destroyEntitiesPacket.entityIds = new int[]{getEntityId()};
PlayerInfoPacket removePlayerPacket = getRemovePlayerToList();
PlayerInfoPacket addPlayerPacket = getAddPlayerToList(textures, signature);
RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.dimension = getDimension();
respawnPacket.gameMode = getGameMode();
respawnPacket.levelType = getLevelType();
playerConnection.sendPacket(removePlayerPacket);
playerConnection.sendPacket(destroyEntitiesPacket);
playerConnection.sendPacket(respawnPacket);
playerConnection.sendPacket(addPlayerPacket);
for (Player viewer : getViewers()) {
PlayerConnection connection = viewer.getPlayerConnection();
connection.sendPacket(removePlayerPacket);
connection.sendPacket(destroyEntitiesPacket);
showPlayer(connection);
}
getInventory().update();
teleport(getPosition());
}
/**
* Used to update the internal skin field
*
* @param skin the player skin
* @see #setSkin(PlayerSkin) instead
*/
protected void refreshSkin(PlayerSkin skin) {
this.skin = skin;
}
/**
* Get if the player has the respawn screen enabled or disabled
*
@ -1820,6 +1851,78 @@ public class Player extends LivingEntity {
return lastKeepAlive;
}
/**
* Get the packet to add the player from tab-list
*
* @param textures the textures value
* @param signature the textures signature
* @return a {@link PlayerInfoPacket} to add the player
*/
protected PlayerInfoPacket getAddPlayerToList(String textures, String signature) {
String jsonDisplayName = displayName != null ? Chat.toJsonString(Chat.fromLegacyText(displayName)) : null;
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.ADD_PLAYER);
PlayerInfoPacket.AddPlayer addPlayer =
new PlayerInfoPacket.AddPlayer(getUuid(), getUsername(), getGameMode(), getLatency());
addPlayer.displayName = jsonDisplayName;
PlayerInfoPacket.AddPlayer.Property prop =
new PlayerInfoPacket.AddPlayer.Property("textures", textures, signature);
addPlayer.properties.add(prop);
playerInfoPacket.playerInfos.add(addPlayer);
return playerInfoPacket;
}
/**
* Get the packet to remove the player from tab-list
*
* @return a {@link PlayerInfoPacket} to add the player
*/
protected PlayerInfoPacket getRemovePlayerToList() {
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER);
PlayerInfoPacket.RemovePlayer removePlayer =
new PlayerInfoPacket.RemovePlayer(getUuid());
playerInfoPacket.playerInfos.add(removePlayer);
return playerInfoPacket;
}
/**
* Send all the related packet to have the player sent to another with related data
* (create player, spawn position, velocity, metadata, equipments, passengers, team)
* <p>
* WARNING: this does not sync the player, please use {@link #addViewer(Player)}
*
* @param connection the connection to show the player to
*/
protected void showPlayer(PlayerConnection connection) {
SpawnPlayerPacket spawnPlayerPacket = new SpawnPlayerPacket();
spawnPlayerPacket.entityId = getEntityId();
spawnPlayerPacket.playerUuid = getUuid();
spawnPlayerPacket.position = getPosition();
final String textures = skin == null ? "" : skin.getTextures();
final String signature = skin == null ? null : skin.getSignature();
connection.sendPacket(getAddPlayerToList(textures, signature));
connection.sendPacket(spawnPlayerPacket);
connection.sendPacket(getVelocityPacket());
connection.sendPacket(getMetadataPacket());
// Equipments synchronization
syncEquipments();
if (hasPassenger()) {
connection.sendPacket(getPassengersPacket());
}
// Team
if (team != null)
connection.sendPacket(team.getTeamsCreationPacket());
}
@Override
public ItemStack getItemInMainHand() {
return inventory.getItemInMainHand();

View File

@ -0,0 +1,28 @@
package net.minestom.server.entity;
public class PlayerSkin {
private String textures;
private String signature;
public PlayerSkin(String textures, String signature) {
this.textures = textures;
this.signature = signature;
}
public String getTextures() {
return textures;
}
public void setTextures(String textures) {
this.textures = textures;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
}

View File

@ -3,16 +3,32 @@ package net.minestom.server.event.player;
import net.minestom.server.event.Event;
import net.minestom.server.instance.Instance;
/**
* Called at player login, used to define his spawn instance
* <p>
* WARNING: defining the spawning instance is MANDATORY
*/
public class PlayerLoginEvent extends Event {
private Instance spawningInstance;
/**
* Get the spawning instance of the player
* <p>
* WARNING: this must NOT be null, otherwise the player cannot spawn
*
* @return the spawning instance
*/
public Instance getSpawningInstance() {
return spawningInstance;
}
/**
* Change the spawning instance
*
* @param instance the new spawning instance
*/
public void setSpawningInstance(Instance instance) {
this.spawningInstance = instance;
}
}

View File

@ -0,0 +1,45 @@
package net.minestom.server.event.player;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.PlayerSkin;
import net.minestom.server.event.Event;
/**
* Called at the player connection to initialize his skin
*/
public class PlayerSkinInitEvent extends Event {
private Player player;
private PlayerSkin skin;
public PlayerSkinInitEvent(Player player) {
this.player = player;
}
/**
* Get the player whose the skin is getting initialized
*
* @return
*/
public Player getPlayer() {
return player;
}
/**
* Get the spawning skin of the player
*
* @return the player skin, or null if not any
*/
public PlayerSkin getSkin() {
return skin;
}
/**
* Set the spawning skin of the player
*
* @param skin the new player skin
*/
public void setSkin(PlayerSkin skin) {
this.skin = skin;
}
}

View File

@ -17,9 +17,6 @@ public class LoginStartPacket implements ClientPreplayPacket {
public void process(PlayerConnection connection, ConnectionManager connectionManager) {
// TODO send encryption request OR directly login success
// TODO: Skin
//UUID adam = UUID.fromString("58ffa9d8-aee1-4587-8b79-41b754f6f238");
//UUID mode = UUID.fromString("ab70ecb4-2346-4c14-a52d-7a091507c24e");
UUID playerUuid = connectionManager.getPlayerConnectionUuid(connection);
LoginSuccessPacket successPacket = new LoginSuccessPacket(playerUuid, username);