diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 00000000..e08a013b
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GETTERS_AND_SETTERS
+ KEEP
+
+
+ OVERRIDDEN_METHODS
+ KEEP
+
+
+ DEPENDENT_METHODS
+ BREADTH_FIRST
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 8fb7db0b..1fff01b8 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -12,6 +12,7 @@
diff --git a/.idea/modules/common/HMCCosmetics.common.test.iml b/.idea/modules/common/HMCCosmetics.common.test.iml
new file mode 100644
index 00000000..c163761f
--- /dev/null
+++ b/.idea/modules/common/HMCCosmetics.common.test.iml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 9a13f5e6..658ff7f3 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -102,5 +102,9 @@ bukkit {
default = BukkitPluginDescription.Permission.Default.OP
description = "Permission to set other users' cosmetics."
}
+ register("hmccosmetics.cmd.wardrobe") {
+ default = BukkitPluginDescription.Permission.Default.OP
+ description = "Permission to view the wardrobe"
+ }
}
}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 47f1ba50..99d0a73a 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1 +1,2 @@
-rootProject.name = "HMCCosmetics"
\ No newline at end of file
+rootProject.name = "HMCCosmetics"
+include("common")
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java b/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java
index b1e00dbe..c3eabf9c 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/HMCCosmetics.java
@@ -15,12 +15,14 @@ import io.github.fisher2911.hmccosmetics.hook.item.ItemsAdderHook;
import io.github.fisher2911.hmccosmetics.listener.ClickListener;
import io.github.fisher2911.hmccosmetics.listener.CosmeticFixListener;
import io.github.fisher2911.hmccosmetics.listener.JoinListener;
+import io.github.fisher2911.hmccosmetics.listener.PlayerShiftListener;
import io.github.fisher2911.hmccosmetics.listener.RespawnListener;
import io.github.fisher2911.hmccosmetics.listener.TeleportListener;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Translation;
import io.github.fisher2911.hmccosmetics.user.UserManager;
+
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.SQLException;
@@ -28,6 +30,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
+
import me.mattstudios.mf.base.CommandManager;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
@@ -105,7 +108,8 @@ public class HMCCosmetics extends JavaPlugin {
new ClickListener(this),
new TeleportListener(this),
new RespawnListener(this),
- new CosmeticFixListener(this)
+ new CosmeticFixListener(this),
+ new PlayerShiftListener(this)
).
forEach(
listener -> this.getServer().getPluginManager()
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.java b/src/main/java/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.java
index 2a1bbd91..53ba7623 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/command/CosmeticsCommand.java
@@ -9,6 +9,7 @@ import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
+import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import io.github.fisher2911.hmccosmetics.util.StringUtils;
import java.util.Map;
@@ -191,6 +192,31 @@ public class CosmeticsCommand extends CommandBase {
}
}
+ @SubCommand("wardrobe")
+ @Permission(io.github.fisher2911.hmccosmetics.message.Permission.VIEW_WARDROBE)
+ public void openWardrobe(final Player player) {
+ final Optional optionalUser = this.plugin.getUserManager().get(player.getUniqueId());
+ if (optionalUser.isEmpty()) return;
+
+ final User user = optionalUser.get();
+
+ final Wardrobe wardrobe = user.getWardrobe();
+ if (wardrobe.isActive()) {
+ this.messageHandler.sendMessage(
+ player,
+ Messages.WARDROBE_ALREADY_OPEN
+ );
+ return;
+ }
+
+ wardrobe.setActive(true);
+ Bukkit.getScheduler().runTaskAsynchronously(
+ this.plugin,
+ () -> wardrobe.spawnFakePlayer(player)
+ );
+ this.cosmeticsMenu.openDefault(player);
+ }
+
private void setDyeColor(final String dyeColor, final ArmorItem armorItem, final CommandSender sender) {
try {
final java.awt.Color awtColor = java.awt.Color.decode(dyeColor);
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/database/Database.java b/src/main/java/io/github/fisher2911/hmccosmetics/database/Database.java
index bf28b548..5dc8fd8e 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/database/Database.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/Database.java
@@ -11,11 +11,14 @@ import io.github.fisher2911.hmccosmetics.database.dao.UserDAO;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.user.User;
+
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
+
+import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import org.bukkit.Bukkit;
public class Database {
@@ -25,7 +28,7 @@ public class Database {
final Dao armorItemDao;
private final ConnectionSource dataSource;
private final DatabaseType databaseType;
- AtomicInteger ARMOR_STAND_ID = new AtomicInteger(Integer.MAX_VALUE);
+ AtomicInteger FAKE_ENTITY_ID = new AtomicInteger(Integer.MAX_VALUE);
String TABLE_NAME = "user";
String PLAYER_UUID_COLUMN = "uuid";
String BACKPACK_COLUMN = "backpack";
@@ -67,7 +70,8 @@ public class Database {
}
public void loadUser(final UUID uuid, final Consumer onComplete) {
- final int armorStandId = ARMOR_STAND_ID.getAndDecrement();
+ final int armorStandId = FAKE_ENTITY_ID.getAndDecrement();
+ final Wardrobe wardrobe = this.newWardrobe();
Threads.getInstance().execute(
() -> {
try {
@@ -80,8 +84,11 @@ public class Database {
final List armorItems = this.armorItemDao.queryForEq("uuid",
uuid.toString());
- final User actualUser = user.toUser(this.plugin.getCosmeticManager(),
- armorItems, armorStandId);
+ final User actualUser = user.toUser(
+ this.plugin.getCosmeticManager(),
+ armorItems,
+ wardrobe,
+ armorStandId);
Bukkit.getScheduler().runTask(this.plugin,
() -> {
this.plugin.getUserManager().add(
@@ -96,7 +103,7 @@ public class Database {
}
});
- final User user = new User(uuid, PlayerArmor.empty(), armorStandId);
+ final User user = new User(uuid, PlayerArmor.empty(), wardrobe, armorStandId);
this.plugin.getUserManager().add(user);
onComplete.accept(user);
@@ -149,4 +156,13 @@ public class Database {
return armorItemDao;
}
+ public Wardrobe newWardrobe() {
+ return new Wardrobe(
+ UUID.randomUUID(),
+ PlayerArmor.empty(),
+ FAKE_ENTITY_ID.getAndDecrement(),
+ FAKE_ENTITY_ID.getAndDecrement(),
+ false
+ );
+ }
}
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseConverter.java b/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseConverter.java
index fed19f51..e2036b31 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseConverter.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/DatabaseConverter.java
@@ -4,6 +4,7 @@ import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.user.User;
+
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
@@ -16,6 +17,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
+
import org.bukkit.configuration.file.YamlConfiguration;
public class DatabaseConverter {
@@ -85,11 +87,12 @@ public class DatabaseConverter {
while (results.next()) {
final PlayerArmor playerArmor = PlayerArmor.empty();
- final User user = new User
- (UUID.fromString(results.getString(1)),
- playerArmor,
- this.database.ARMOR_STAND_ID.getAndDecrement()
- );
+ final User user = new User(
+ UUID.fromString(results.getString(1)),
+ playerArmor,
+ this.database.newWardrobe(),
+ this.database.FAKE_ENTITY_ID.getAndDecrement()
+ );
final String backpackId = results.getString(2);
final String hatId = results.getString(3);
final int hatDye = results.getInt(4);
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/UserDAO.java b/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/UserDAO.java
index d6535891..7d7e39ac 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/UserDAO.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/database/dao/UserDAO.java
@@ -6,6 +6,8 @@ import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.user.User;
+import io.github.fisher2911.hmccosmetics.user.Wardrobe;
+
import java.util.List;
import java.util.Objects;
import java.util.UUID;
@@ -27,7 +29,10 @@ public class UserDAO {
this.uuid = uuid;
}
- public User toUser(final CosmeticManager cosmeticManager, final List armorItems,
+ public User toUser(
+ final CosmeticManager cosmeticManager,
+ final List armorItems,
+ final Wardrobe wardrobe,
final int armorStandId) {
final PlayerArmor playerArmor = PlayerArmor.empty();
@@ -39,7 +44,7 @@ public class UserDAO {
playerArmor.setItem(armorItem);
}
- return new User(this.uuid, playerArmor, armorStandId);
+ return new User(this.uuid, playerArmor, wardrobe, armorStandId);
}
@Override
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/listener/ClickListener.java b/src/main/java/io/github/fisher2911/hmccosmetics/listener/ClickListener.java
index 684df993..519f1a7b 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/listener/ClickListener.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/listener/ClickListener.java
@@ -19,8 +19,6 @@ public class ClickListener implements Listener {
private final HMCCosmetics plugin;
private final UserManager userManager;
- private final List equipmentSlots = List.of(39, 40);
-
public ClickListener(final HMCCosmetics plugin) {
this.plugin = plugin;
this.userManager = this.plugin.getUserManager();
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/listener/JoinListener.java b/src/main/java/io/github/fisher2911/hmccosmetics/listener/JoinListener.java
index e9136e21..a2c0c169 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/listener/JoinListener.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/listener/JoinListener.java
@@ -2,7 +2,9 @@ package io.github.fisher2911.hmccosmetics.listener;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.database.Database;
+import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
+import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -10,6 +12,8 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
+import java.util.Optional;
+
public class JoinListener implements Listener {
private final HMCCosmetics plugin;
@@ -33,6 +37,17 @@ public class JoinListener implements Listener {
@EventHandler
public void onQuit(final PlayerQuitEvent event) {
final Player player = event.getPlayer();
+ final Optional optionalUser = this.userManager.get(player.getUniqueId());
+ optionalUser.ifPresent(user -> {
+ final Wardrobe wardrobe = user.getWardrobe();
+
+ if (wardrobe.isActive()) {
+ Bukkit.getScheduler().runTaskAsynchronously(
+ this.plugin,
+ () -> wardrobe.despawnFakePlayer(player)
+ );
+ }
+ });
this.userManager.remove(player.getUniqueId());
}
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/listener/PlayerShiftListener.java b/src/main/java/io/github/fisher2911/hmccosmetics/listener/PlayerShiftListener.java
new file mode 100644
index 00000000..f9228307
--- /dev/null
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/listener/PlayerShiftListener.java
@@ -0,0 +1,43 @@
+package io.github.fisher2911.hmccosmetics.listener;
+
+import io.github.fisher2911.hmccosmetics.HMCCosmetics;
+import io.github.fisher2911.hmccosmetics.message.Messages;
+import io.github.fisher2911.hmccosmetics.user.User;
+import io.github.fisher2911.hmccosmetics.user.UserManager;
+import io.github.fisher2911.hmccosmetics.user.Wardrobe;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerToggleSneakEvent;
+
+import java.util.Optional;
+
+public class PlayerShiftListener implements Listener {
+
+ private final HMCCosmetics plugin;
+ private final UserManager userManager;
+
+ public PlayerShiftListener(final HMCCosmetics plugin) {
+ this.plugin = plugin;
+ this.userManager = this.plugin.getUserManager();
+ }
+
+ @EventHandler
+ public void onPlayerShift(final PlayerToggleSneakEvent event) {
+ final Player player = event.getPlayer();
+ final Optional userOptional = this.userManager.get(player.getUniqueId());
+
+ if (userOptional.isEmpty()) return;
+
+ final User user = userOptional.get();
+ final Wardrobe wardrobe = user.getWardrobe();
+
+ if (!wardrobe.isActive()) return;
+
+ wardrobe.setActive(false);
+ this.plugin.getMessageHandler().sendMessage(
+ player,
+ Messages.CLOSED_WARDROBE
+ );
+ }
+}
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/message/Messages.java b/src/main/java/io/github/fisher2911/hmccosmetics/message/Messages.java
index a03aaa3f..ff54bebd 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/message/Messages.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/message/Messages.java
@@ -50,6 +50,13 @@ public class Messages {
""");
+ public static final Message OPENED_WARDROBE =
+ new Message("opened-wardrobe", ChatColor.GREEN + "Viewing wardrobe!");
+ public static final Message CLOSED_WARDROBE =
+ new Message("closed-wardrobe", ChatColor.GREEN + "Closing wardrobe!");
+ public static final Message WARDROBE_ALREADY_OPEN =
+ new Message("wardrobe-already-open", ChatColor.RED + "The wardrobe is already open!");
+
public static final Message SET_OTHER_BACKPACK = new Message(
"set-other-backpack", ChatColor.GREEN + "You have set the backpack of " +
Placeholder.PLAYER + " to " + Placeholder.TYPE + "."
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/message/Permission.java b/src/main/java/io/github/fisher2911/hmccosmetics/message/Permission.java
index 17cfd0ff..fcde6639 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/message/Permission.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/message/Permission.java
@@ -7,5 +7,6 @@ public class Permission {
public static final String RELOAD_COMMAND = "hmccosmetics.cmd.reload";
public static final String HELP_COMMAND = "hmccosmetics.cmd.help";
public static final String SET_COSMETIC_COMMAND = "hmccosmetics.cmd.set";
+ public static final String VIEW_WARDROBE = "hmccosmetics.cmd.wardrobe";
}
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/packet/PacketManager.java b/src/main/java/io/github/fisher2911/hmccosmetics/packet/PacketManager.java
index d9e97b78..d2d90c87 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/packet/PacketManager.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/packet/PacketManager.java
@@ -4,21 +4,45 @@ import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.MinecraftKey;
import com.comphenix.protocol.wrappers.Pair;
-import java.lang.reflect.InvocationTargetException;
-import java.util.List;
-import java.util.UUID;
+import com.comphenix.protocol.wrappers.PlayerInfoData;
+import com.comphenix.protocol.wrappers.WrappedChatComponent;
+import com.comphenix.protocol.wrappers.WrappedGameProfile;
+import com.mojang.authlib.GameProfile;
+import io.github.fisher2911.hmccosmetics.playerpackets.PlayerPackets;
+import io.github.fisher2911.hmccosmetics.playerpackets.PlayerPackets_1_17_R1;
+import io.github.fisher2911.hmccosmetics.playerpackets.PlayerPackets_1_18_R1;
import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.IntArrayList;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
public class PacketManager {
+ private static final PlayerPackets playerPackets;
+
+ static {
+ final String version = Bukkit.getVersion();
+ if (version.contains("1.17")) {
+ playerPackets = new PlayerPackets_1_17_R1();
+ } /*else if (version.contains("1.18")) {
+ playerPackets = new PlayerPackets_1_18_R1();
+ }*/ else {
+ playerPackets = null;
+ }
+ }
+
public static PacketContainer getEntitySpawnPacket(final Location location, final int entityId,
final EntityType entityType) {
final PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
@@ -91,8 +115,6 @@ public class PacketManager {
final float pitch,
final EnumWrappers.SoundCategory soundCategory
) {
-// final Location location = player.getLocation();
-
final var manager = ProtocolLibrary.getProtocolManager();
final var packet = manager.createPacket(PacketType.Play.Server.CUSTOM_SOUND_EFFECT);
@@ -119,6 +141,16 @@ public class PacketManager {
return packet;
}
+ public static PacketContainer[] getFakePlayerPacket(final Location location, Player player, final UUID uuid, final int entityId) throws IllegalStateException {
+ if (playerPackets == null) throw new IllegalStateException("This cannot be used in version: " + Bukkit.getVersion());
+ return playerPackets.getSpawnPacket(location, player, uuid, entityId);
+ }
+
+ public static PacketContainer getRemovePlayerPacket(final Player player, final UUID uuid, final int entityId) {
+ if (playerPackets == null) throw new IllegalStateException("This cannot be used in version: " + Bukkit.getVersion());
+ return playerPackets.getRemovePacket(player, uuid, entityId);
+ }
+
public static void sendPacket(final Player to, final PacketContainer... packets) {
final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
try {
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/playerpackets/PlayerPackets.java b/src/main/java/io/github/fisher2911/hmccosmetics/playerpackets/PlayerPackets.java
new file mode 100644
index 00000000..890b7bcc
--- /dev/null
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/playerpackets/PlayerPackets.java
@@ -0,0 +1,14 @@
+package io.github.fisher2911.hmccosmetics.playerpackets;
+
+import com.comphenix.protocol.events.PacketContainer;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+import java.util.UUID;
+
+public interface PlayerPackets {
+
+ PacketContainer[] getSpawnPacket(final Location location, final Player player, final UUID uuid, final int entityId);
+ PacketContainer getRemovePacket(final Player player, final UUID uuid, final int entityId);
+
+}
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/playerpackets/PlayerPackets_1_17_R1.java b/src/main/java/io/github/fisher2911/hmccosmetics/playerpackets/PlayerPackets_1_17_R1.java
new file mode 100644
index 00000000..9151beb1
--- /dev/null
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/playerpackets/PlayerPackets_1_17_R1.java
@@ -0,0 +1,87 @@
+package io.github.fisher2911.hmccosmetics.playerpackets;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.reflect.StructureModifier;
+import com.comphenix.protocol.wrappers.EnumWrappers;
+import com.comphenix.protocol.wrappers.PlayerInfoData;
+import com.comphenix.protocol.wrappers.WrappedChatComponent;
+import com.comphenix.protocol.wrappers.WrappedGameProfile;
+import com.mojang.authlib.GameProfile;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+public class PlayerPackets_1_17_R1 implements PlayerPackets {
+
+ public PacketContainer[] getSpawnPacket(final Location location, final Player player, final UUID uuid, final int entityId) {
+ final PacketContainer playerInfoPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
+ final StructureModifier action = playerInfoPacket.getPlayerInfoAction();
+ final StructureModifier> infoData = playerInfoPacket.getPlayerInfoDataLists();
+
+ final List playerInfoData = new ArrayList<>();
+
+ final GameProfile profile = this.getCopyProfile(player, uuid);
+
+ playerInfoData.add(new PlayerInfoData(WrappedGameProfile
+ .fromHandle(profile),
+ 0,
+ EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
+ WrappedChatComponent.fromText("")));
+
+ action.write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
+ infoData.write(0, playerInfoData);
+
+ final PacketContainer spawnPacket = new PacketContainer(PacketType.Play.Server.NAMED_ENTITY_SPAWN);
+ spawnPacket.getUUIDs().write(0, uuid);
+ spawnPacket.getIntegers().write(0, entityId);
+ spawnPacket.getDoubles().
+ write(0, location.getX()).
+ write(1, location.getY()).
+ write(2, location.getZ());
+
+ return new PacketContainer[]{playerInfoPacket, spawnPacket};
+ }
+
+ public PacketContainer getRemovePacket(final Player player, final UUID uuid, final int entityId) {
+ final PacketContainer playerPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
+ playerPacket.getIntegers().write(0, entityId);
+ final StructureModifier action = playerPacket.getPlayerInfoAction();
+ final StructureModifier> infoData = playerPacket.getPlayerInfoDataLists();
+
+ final List playerInfoData = new ArrayList<>();
+
+ final GameProfile profile = this.getCopyProfile(player, uuid);
+
+ playerInfoData.add(new PlayerInfoData(WrappedGameProfile
+ .fromHandle(profile),
+ 0,
+ EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
+ WrappedChatComponent.fromText(profile.getName())));
+
+ action.write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
+ infoData.write(0, playerInfoData);
+
+ return playerPacket;
+ }
+
+ private GameProfile getCopyProfile(final Player player, final UUID uuid) {
+ final GameProfile playerProfile = ((CraftPlayer) player).getProfile();
+ final GameProfile profile = new GameProfile(
+ uuid,
+ player.getDisplayName());
+
+ for (final var entry : playerProfile.getProperties().entries()) {
+ profile.getProperties().put(entry.getKey(), entry.getValue());
+ }
+
+ return profile;
+ }
+
+}
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/playerpackets/PlayerPackets_1_18_R1.java b/src/main/java/io/github/fisher2911/hmccosmetics/playerpackets/PlayerPackets_1_18_R1.java
new file mode 100644
index 00000000..4851670a
--- /dev/null
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/playerpackets/PlayerPackets_1_18_R1.java
@@ -0,0 +1,87 @@
+package io.github.fisher2911.hmccosmetics.playerpackets;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.reflect.StructureModifier;
+import com.comphenix.protocol.wrappers.EnumWrappers;
+import com.comphenix.protocol.wrappers.PlayerInfoData;
+import com.comphenix.protocol.wrappers.WrappedChatComponent;
+import com.comphenix.protocol.wrappers.WrappedGameProfile;
+import com.mojang.authlib.GameProfile;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+//import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class PlayerPackets_1_18_R1 implements PlayerPackets {
+
+ public PacketContainer[] getSpawnPacket(final Location location, final Player player, final UUID uuid, final int entityId) {
+ final PacketContainer playerInfoPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
+ final StructureModifier action = playerInfoPacket.getPlayerInfoAction();
+ final StructureModifier> infoData = playerInfoPacket.getPlayerInfoDataLists();
+
+ final List playerInfoData = new ArrayList<>();
+
+ final GameProfile profile = this.getCopyProfile(player, uuid);
+
+ playerInfoData.add(new PlayerInfoData(WrappedGameProfile
+ .fromHandle(profile),
+ 0,
+ EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
+ WrappedChatComponent.fromText("")));
+
+ action.write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
+ infoData.write(0, playerInfoData);
+
+ final PacketContainer spawnPacket = new PacketContainer(PacketType.Play.Server.NAMED_ENTITY_SPAWN);
+ spawnPacket.getUUIDs().write(0, uuid);
+ spawnPacket.getIntegers().write(0, entityId);
+ spawnPacket.getDoubles().
+ write(0, location.getX()).
+ write(1, location.getY()).
+ write(2, location.getZ());
+
+ return new PacketContainer[]{playerInfoPacket, spawnPacket};
+ }
+
+ public PacketContainer getRemovePacket(final Player player, final UUID uuid, final int entityId) {
+ final PacketContainer playerPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
+ playerPacket.getIntegers().write(0, entityId);
+ final StructureModifier action = playerPacket.getPlayerInfoAction();
+ final StructureModifier> infoData = playerPacket.getPlayerInfoDataLists();
+
+ final List playerInfoData = new ArrayList<>();
+
+ final GameProfile profile = this.getCopyProfile(player, uuid);
+
+ playerInfoData.add(new PlayerInfoData(WrappedGameProfile
+ .fromHandle(profile),
+ 0,
+ EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
+ WrappedChatComponent.fromText(profile.getName())));
+
+ action.write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
+ infoData.write(0, playerInfoData);
+
+ return playerPacket;
+ }
+
+ private GameProfile getCopyProfile(final Player player, final UUID uuid) {
+ final GameProfile playerProfile = ((CraftPlayer) player).getProfile();
+ final GameProfile profile = new GameProfile(
+ uuid,
+ player.getDisplayName());
+
+ for (final var entry : playerProfile.getProperties().entries()) {
+ profile.getProperties().put(entry.getKey(), entry.getValue());
+ }
+
+ return profile;
+ }
+
+}
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/user/Equipment.java b/src/main/java/io/github/fisher2911/hmccosmetics/user/Equipment.java
new file mode 100644
index 00000000..10e107fc
--- /dev/null
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/user/Equipment.java
@@ -0,0 +1,35 @@
+package io.github.fisher2911.hmccosmetics.user;
+
+import org.bukkit.inventory.EntityEquipment;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+public class Equipment {
+
+ private static final EquipmentSlot[] VALUES = EquipmentSlot.values();
+ private final Map equipment = new EnumMap<>(EquipmentSlot.class);
+
+ public Equipment() {
+ }
+
+ public static Equipment fromEntityEquipment(final EntityEquipment entityEquipment) {
+ final Equipment equipment = new Equipment();
+ for (final EquipmentSlot slot : VALUES) {
+ equipment.setItem(slot, entityEquipment.getItem(slot));
+ }
+ return equipment;
+ }
+
+ @Nullable
+ public ItemStack getItem(final EquipmentSlot slot) {
+ return this.equipment.get(slot);
+ }
+
+ public void setItem(final EquipmentSlot slot, @Nullable final ItemStack itemStack) {
+ this.equipment.put(slot, itemStack);
+ }
+}
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java b/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java
index deaae76b..2f38f60c 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/user/User.java
@@ -27,12 +27,21 @@ public class User {
private final UUID uuid;
private final PlayerArmor playerArmor;
+ private Wardrobe wardrobe;
+
private ArmorItem lastSetItem = ArmorItem.empty(ArmorItem.Type.HAT);
private boolean hasArmorStand;
private final int armorStandId;
- public User(final UUID uuid, final PlayerArmor playerArmor, final int armorStandId) {
+ public User(final UUID uuid, final PlayerArmor playerArmor, final Wardrobe wardrobe, final int armorStandId) {
+ this.uuid = uuid;
+ this.playerArmor = playerArmor;
+ this.wardrobe = wardrobe;
+ this.armorStandId = armorStandId;
+ }
+
+ protected User(final UUID uuid, final PlayerArmor playerArmor, final int armorStandId) {
this.uuid = uuid;
this.playerArmor = playerArmor;
this.armorStandId = armorStandId;
@@ -50,6 +59,10 @@ public class User {
return playerArmor;
}
+ public Wardrobe getWardrobe() {
+ return wardrobe;
+ }
+
protected void setPlayerArmor(final PlayerArmor playerArmor) {
for (final ArmorItem armorItem : playerArmor.getArmorItems()) {
this.playerArmor.setItem(armorItem);
@@ -162,4 +175,16 @@ public class User {
public ArmorItem getLastSetItem() {
return lastSetItem;
}
+
+ public int getEntityId() {
+ final Player player = this.getPlayer();
+ if (player == null) return -1;
+ return player.getEntityId();
+ }
+
+ public boolean hasPermissionToUse(final ArmorItem armorItem) {
+ final Player player = this.getPlayer();
+ if (player == null) return false;
+ return player.hasPermission(armorItem.getPermission());
+ }
}
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java b/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java
index 91701d7e..c6dab9cc 100644
--- a/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/user/UserManager.java
@@ -125,8 +125,11 @@ public class UserManager {
public void updateCosmetics(final User user, final boolean ignoreRestrictions, final Player other) {
final Player player = user.getPlayer();
+ final Equipment equipment;
if (player == null) {
- return;
+ equipment = new Equipment();
+ } else {
+ equipment = Equipment.fromEntityEquipment(player.getEquipment());
}
final PlayerArmor playerArmor = user.getPlayerArmor();
@@ -134,28 +137,27 @@ public class UserManager {
final List> equipmentList = new ArrayList<>();
equipmentList.add(
- new Pair<>(EnumWrappers.ItemSlot.HEAD, this.getCosmeticItem(player, playerArmor.getHat(), EquipmentSlot.HEAD, ignoreRestrictions))
+ new Pair<>(EnumWrappers.ItemSlot.HEAD, this.getCosmeticItem(equipment, playerArmor.getHat(), EquipmentSlot.HEAD, ignoreRestrictions))
);
equipmentList.add(
- new Pair<>(EnumWrappers.ItemSlot.OFFHAND, this.getCosmeticItem(player, playerArmor.getOffHand(), EquipmentSlot.OFF_HAND, ignoreRestrictions))
+ new Pair<>(EnumWrappers.ItemSlot.OFFHAND, this.getCosmeticItem(equipment, playerArmor.getOffHand(), EquipmentSlot.OFF_HAND, ignoreRestrictions))
);
PacketManager.sendPacket(
other,
PacketManager.getEquipmentPacket(
equipmentList,
- player.getEntityId()
+ user.getEntityId()
)
);
}
private ItemStack getCosmeticItem(
- final Player player,
+ final Equipment equipment,
final ArmorItem armorItem,
final EquipmentSlot slot,
final boolean ignoreRestrictions) {
final CosmeticSettings cosmeticSettings = this.settings.getCosmeticSettings();
- final EntityEquipment equipment = player.getEquipment();
final Map placeholders = Map.of(Placeholder.ALLOWED, "true",
Placeholder.ENABLED, "true");
@@ -180,17 +182,24 @@ public class UserManager {
}
public void setItem(final User user, final ArmorItem armorItem) {
- ArmorItem previous = user.getPlayerArmor().getItem(armorItem.getType());
+ final Wardrobe wardrobe = user.getWardrobe();
+ final User setUser;
+ if (wardrobe.isActive()) {
+ setUser = wardrobe;
+ } else {
+ setUser = user;
+ }
+ ArmorItem previous = setUser.getPlayerArmor().getItem(armorItem.getType());
final CosmeticChangeEvent event =
- new CosmeticChangeEvent(new CosmeticItem(armorItem.copy()), new CosmeticItem(previous.copy()), user);
+ new CosmeticChangeEvent(new CosmeticItem(armorItem.copy()), new CosmeticItem(previous.copy()), setUser);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) return;
- user.setItem(event.getCosmeticItem().getArmorItem());
+ setUser.setItem(event.getCosmeticItem().getArmorItem());
Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> {
switch (armorItem.getType()) {
- case HAT, OFF_HAND -> this.updateCosmetics(user);
+ case HAT, OFF_HAND -> this.updateCosmetics(setUser);
}
});
}
diff --git a/src/main/java/io/github/fisher2911/hmccosmetics/user/Wardrobe.java b/src/main/java/io/github/fisher2911/hmccosmetics/user/Wardrobe.java
new file mode 100644
index 00000000..1b97fcdc
--- /dev/null
+++ b/src/main/java/io/github/fisher2911/hmccosmetics/user/Wardrobe.java
@@ -0,0 +1,48 @@
+package io.github.fisher2911.hmccosmetics.user;
+
+import com.mojang.authlib.GameProfile;
+import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
+import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
+import io.github.fisher2911.hmccosmetics.packet.PacketManager;
+import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+
+import java.util.UUID;
+
+public class Wardrobe extends User {
+
+ private final int entityId;
+ private boolean active;
+
+ public Wardrobe(
+ final UUID uuid,
+ final PlayerArmor playerArmor,
+ final int armorStandId,
+ final int entityId,
+ final boolean active) {
+ super(uuid, playerArmor, armorStandId);
+ this.entityId = entityId;
+ this.active = active;
+ }
+
+ public void spawnFakePlayer(final Player viewer) {
+ PacketManager.sendPacket(viewer, PacketManager.getFakePlayerPacket(viewer.getLocation(), viewer, this.getUuid(), this.entityId));
+ }
+
+ public void despawnFakePlayer(final Player viewer) {
+ PacketManager.sendPacket(viewer, PacketManager.getRemovePlayerPacket(viewer, this.getUuid(), this.entityId));
+ }
+
+ @Override
+ public boolean hasPermissionToUse(final ArmorItem armorItem) {
+ return true;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setActive(final boolean active) {
+ this.active = active;
+ }
+}