9
0
mirror of https://github.com/HibiscusMC/HMCCosmetics.git synced 2025-12-19 15:09:19 +00:00

Added wardrobe (Need to fix imports)

This commit is contained in:
HeroBrineGoat
2022-02-02 16:12:28 -05:00
parent 1ba07b87cf
commit a07eec4ddc
23 changed files with 533 additions and 32 deletions

36
.idea/codeStyles/Project.xml generated Normal file
View File

@@ -0,0 +1,36 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="FORMATTER_TAGS_ENABLED" value="true" />
<JavaCodeStyleSettings>
<option name="GENERATE_FINAL_LOCALS" value="true" />
<option name="GENERATE_FINAL_PARAMETERS" value="true" />
<option name="REPLACE_NULL_CHECK" value="false" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999999999" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999999" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="JAVA">
<arrangement>
<groups>
<group>
<type>GETTERS_AND_SETTERS</type>
<order>KEEP</order>
</group>
<group>
<type>OVERRIDDEN_METHODS</type>
<order>KEEP</order>
</group>
<group>
<type>DEPENDENT_METHODS</type>
<order>BREADTH_FIRST</order>
</group>
</groups>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

1
.idea/gradle.xml generated
View File

@@ -12,6 +12,7 @@
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/common" />
</set>
</option>
</GradleProjectSettings>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="TestModuleProperties" production-module="HMCCosmetics.common.main" />
</module>

View File

@@ -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"
}
}
}

View File

@@ -1 +1,2 @@
rootProject.name = "HMCCosmetics"
rootProject.name = "HMCCosmetics"
include("common")

View File

@@ -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()

View File

@@ -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<User> 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);

View File

@@ -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, UUID> 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<User> 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<ArmorItemDAO> 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
);
}
}

View File

@@ -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);

View File

@@ -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<ArmorItemDAO> armorItems,
public User toUser(
final CosmeticManager cosmeticManager,
final List<ArmorItemDAO> 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

View File

@@ -19,8 +19,6 @@ public class ClickListener implements Listener {
private final HMCCosmetics plugin;
private final UserManager userManager;
private final List<Integer> equipmentSlots = List.of(39, 40);
public ClickListener(final HMCCosmetics plugin) {
this.plugin = plugin;
this.userManager = this.plugin.getUserManager();

View File

@@ -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<User> 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());
}

View File

@@ -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<User> 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
);
}
}

View File

@@ -50,6 +50,13 @@ public class Messages {
<st> </st>""");
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 + "."

View File

@@ -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";
}

View File

@@ -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 {

View File

@@ -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);
}

View File

@@ -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<EnumWrappers.PlayerInfoAction> action = playerInfoPacket.getPlayerInfoAction();
final StructureModifier<List<PlayerInfoData>> infoData = playerInfoPacket.getPlayerInfoDataLists();
final List<PlayerInfoData> 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<EnumWrappers.PlayerInfoAction> action = playerPacket.getPlayerInfoAction();
final StructureModifier<List<PlayerInfoData>> infoData = playerPacket.getPlayerInfoDataLists();
final List<PlayerInfoData> 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;
}
}

View File

@@ -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<EnumWrappers.PlayerInfoAction> action = playerInfoPacket.getPlayerInfoAction();
final StructureModifier<List<PlayerInfoData>> infoData = playerInfoPacket.getPlayerInfoDataLists();
final List<PlayerInfoData> 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<EnumWrappers.PlayerInfoAction> action = playerPacket.getPlayerInfoAction();
final StructureModifier<List<PlayerInfoData>> infoData = playerPacket.getPlayerInfoDataLists();
final List<PlayerInfoData> 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;
}
}

View File

@@ -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<EquipmentSlot, ItemStack> 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);
}
}

View File

@@ -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());
}
}

View File

@@ -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<Pair<EnumWrappers.ItemSlot, ItemStack>> 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<String, String> 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);
}
});
}

View File

@@ -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;
}
}