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

Changed to use PacketEvents

This commit is contained in:
Fisher2911
2022-03-18 17:14:30 -04:00
parent 6653ac6edc
commit 67e3dbfcf5
53 changed files with 1410 additions and 4218 deletions

View File

@@ -7,7 +7,7 @@ repositories {
maven("https://papermc.io/repo/repository/maven-public/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://jitpack.io")
maven("https://repo.dmulloy2.net/repository/public/")
// maven("https://repo.dmulloy2.net/repository/public/")
}
dependencies {
@@ -15,5 +15,5 @@ dependencies {
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:22.0.0")
compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
// compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
}

View File

@@ -1,9 +0,0 @@
package io.github.fisher2911.nms;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
public class ArmorStandPackets_1_16_R3 {
}

View File

@@ -1,8 +0,0 @@
package io.github.fisher2911.nms;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
public class DestroyPacket_1_16_R3 {
}

View File

@@ -1,139 +1,120 @@
package io.github.fisher2911.nms;
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.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import org.bukkit.GameMode;
import org.bukkit.Location;
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.UUID;
public class PacketHelper_1_16_R3 implements PacketHelper {
@Override
public PacketContainer getPlayerSpawnPacket(final Location location, UUID uuid, final int entityId) {
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());
spawnPacket.getBytes().write(0, (byte)(((location.getYaw() * 256.0F) / 360.0F)));
return spawnPacket;
}
@Override
public PacketContainer getPlayerInfoPacket(final Player player, final UUID uuid) {
final GameProfile profile = this.getCopyProfile(player, uuid);
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<>();
playerInfoData.add(new PlayerInfoData(WrappedGameProfile
.fromHandle(profile),
0,
EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
WrappedChatComponent.fromText(profile.getName())));
action.write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
infoData.write(0, playerInfoData);
return playerInfoPacket;
}
@Override
public PacketContainer getPlayerRemovePacket(final Player player, final UUID uuid, final int entityId) {
final PacketContainer playerPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
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("")));
action.write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
infoData.write(0, playerInfoData);
return playerPacket;
}
@Override
public PacketContainer getPlayerOverlayPacket(final int entityId) {
final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
WrappedDataWatcher metaData = new WrappedDataWatcher();
final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(16, byteSerializer), mask);
metaContainer.getIntegers().write(0, entityId);
metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
return metaContainer;
}
private GameProfile getCopyProfile(final Player player, final UUID uuid) {
final GameProfile playerProfile = ((CraftPlayer) player).getProfile();
final GameProfile profile = new GameProfile(
uuid,
player.getDisplayName()
);
profile.getProperties().removeAll("textures");
Property textureProperty = playerProfile.getProperties().get("textures").iterator().next();
String texture = textureProperty.getValue();
String signature = textureProperty.getSignature();
profile.getProperties().put("textures", new Property("textures", texture, signature));
return profile;
}
@Override
public PacketContainer getArmorStandMeta(final int armorStandId) {
final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
WrappedDataWatcher metaData = new WrappedDataWatcher();
final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, byteSerializer), (byte) (0x20));
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(14, byteSerializer), (byte) (0x10));
metaContainer.getIntegers().write(0, armorStandId);
metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
return metaContainer;
}
@Override
public PacketContainer getDestroyPacket(final int entityId) {
final PacketContainer destroyPacket = new PacketContainer(
PacketType.Play.Server.ENTITY_DESTROY);
destroyPacket.getIntegerArrays().write(0, new int[]{entityId});
return destroyPacket;
}
// @Override
// public PacketContainer getPlayerSpawnPacket(final Location location, UUID uuid, final int entityId) {
// 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());
// spawnPacket.getBytes().write(0, (byte)(((location.getYaw() * 256.0F) / 360.0F)));
//
// return spawnPacket;
// }
//
// @Override
// public PacketContainer getPlayerInfoPacket(final Player player, final UUID uuid) {
// final GameProfile profile = this.getCopyProfile(player, uuid);
// 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<>();
//
// playerInfoData.add(new PlayerInfoData(WrappedGameProfile
// .fromHandle(profile),
// 0,
// EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
// WrappedChatComponent.fromText(profile.getName())));
//
// action.write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
// infoData.write(0, playerInfoData);
//
// return playerInfoPacket;
// }
//
// @Override
// public PacketContainer getPlayerRemovePacket(final Player player, final UUID uuid, final int entityId) {
// final PacketContainer playerPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
// 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("")));
//
// action.write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
// infoData.write(0, playerInfoData);
//
// return playerPacket;
// }
//
// @Override
// public PacketContainer getPlayerOverlayPacket(final int entityId) {
// final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
//
// WrappedDataWatcher metaData = new WrappedDataWatcher();
//
// final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
//
// final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
//
// metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(16, byteSerializer), mask);
//
// metaContainer.getIntegers().write(0, entityId);
// metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
// return metaContainer;
// }
//
// private GameProfile getCopyProfile(final Player player, final UUID uuid) {
// final GameProfile playerProfile = ((CraftPlayer) player).getProfile();
// final GameProfile profile = new GameProfile(
// uuid,
// player.getDisplayName()
// );
//
// profile.getProperties().removeAll("textures");
// Property textureProperty = playerProfile.getProperties().get("textures").iterator().next();
// String texture = textureProperty.getValue();
// String signature = textureProperty.getSignature();
// profile.getProperties().put("textures", new Property("textures", texture, signature));
//
// return profile;
// }
//
// @Override
// public PacketContainer getArmorStandMeta(final int armorStandId) {
// final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
//
// WrappedDataWatcher metaData = new WrappedDataWatcher();
//
// final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
//
// metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, byteSerializer), (byte) (0x20));
// metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(14, byteSerializer), (byte) (0x10));
//
// metaContainer.getIntegers().write(0, armorStandId);
// metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
// return metaContainer;
// }
//
// @Override
// public PacketContainer getDestroyPacket(final int entityId) {
// final PacketContainer destroyPacket = new PacketContainer(
// PacketType.Play.Server.ENTITY_DESTROY);
// destroyPacket.getIntegerArrays().write(0, new int[]{entityId});
//
// return destroyPacket;
// }
}

View File

@@ -11,7 +11,7 @@ repositories {
maven("https://papermc.io/repo/repository/maven-public/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://jitpack.io")
maven("https://repo.dmulloy2.net/repository/public/")
// maven("https://repo.dmulloy2.net/repository/public/")
}
dependencies {
@@ -19,5 +19,5 @@ dependencies {
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot:1.17-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:22.0.0")
compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
// compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
}

View File

@@ -1,140 +1,120 @@
package io.github.fisher2911.nms;
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.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.IntArrayList;
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 PacketHelper_1_17_R1 implements PacketHelper {
@Override
public PacketContainer getPlayerSpawnPacket(final Location location, UUID uuid, final int entityId) {
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());
spawnPacket.getBytes().write(0, (byte)(((location.getYaw() * 256.0F) / 360.0F)));
return spawnPacket;
}
@Override
public PacketContainer getPlayerInfoPacket(final Player player, final UUID uuid) {
final GameProfile profile = this.getCopyProfile(player, uuid);
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<>();
playerInfoData.add(new PlayerInfoData(WrappedGameProfile
.fromHandle(profile),
0,
EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
WrappedChatComponent.fromText(profile.getName())));
action.write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
infoData.write(0, playerInfoData);
return playerInfoPacket;
}
@Override
public PacketContainer getPlayerRemovePacket(final Player player, final UUID uuid, final int entityId) {
final PacketContainer playerPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
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("")));
action.write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
infoData.write(0, playerInfoData);
return playerPacket;
}
@Override
public PacketContainer getPlayerOverlayPacket(final int entityId) {
final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
WrappedDataWatcher metaData = new WrappedDataWatcher();
final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(17, byteSerializer), mask);
metaContainer.getIntegers().write(0, entityId);
metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
return metaContainer;
}
private GameProfile getCopyProfile(final Player player, final UUID uuid) {
final GameProfile playerProfile = ((CraftPlayer) player).getProfile();
final GameProfile profile = new GameProfile(
uuid,
player.getDisplayName()
);
profile.getProperties().removeAll("textures");
Property textureProperty = playerProfile.getProperties().get("textures").iterator().next();
String texture = textureProperty.getValue();
String signature = textureProperty.getSignature();
profile.getProperties().put("textures", new Property("textures", texture, signature));
return profile;
}
@Override
public PacketContainer getArmorStandMeta(final int armorStandId) {
final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
WrappedDataWatcher metaData = new WrappedDataWatcher();
final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, byteSerializer), (byte) (0x20));
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, byteSerializer), (byte) (0x10));
metaContainer.getIntegers().write(0, armorStandId);
metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
return metaContainer;
}
@Override
public PacketContainer getDestroyPacket(final int entityId) {
final PacketContainer destroyPacket = new PacketContainer(
PacketType.Play.Server.ENTITY_DESTROY);
destroyPacket.getModifier().write(0, new IntArrayList(new int[]{entityId}));
return destroyPacket;
}
// @Override
// public PacketContainer getPlayerSpawnPacket(final Location location, UUID uuid, final int entityId) {
// 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());
// spawnPacket.getBytes().write(0, (byte)(((location.getYaw() * 256.0F) / 360.0F)));
//
// return spawnPacket;
// }
//
// @Override
// public PacketContainer getPlayerInfoPacket(final Player player, final UUID uuid) {
// final GameProfile profile = this.getCopyProfile(player, uuid);
// 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<>();
//
// playerInfoData.add(new PlayerInfoData(WrappedGameProfile
// .fromHandle(profile),
// 0,
// EnumWrappers.NativeGameMode.fromBukkit(GameMode.CREATIVE),
// WrappedChatComponent.fromText(profile.getName())));
//
// action.write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
// infoData.write(0, playerInfoData);
//
// return playerInfoPacket;
// }
//
// @Override
// public PacketContainer getPlayerRemovePacket(final Player player, final UUID uuid, final int entityId) {
// final PacketContainer playerPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
// 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("")));
//
// action.write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
// infoData.write(0, playerInfoData);
//
// return playerPacket;
// }
//
// @Override
// public PacketContainer getPlayerOverlayPacket(final int entityId) {
// final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
//
// WrappedDataWatcher metaData = new WrappedDataWatcher();
//
// final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
//
// final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
//
// metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(17, byteSerializer), mask);
//
// metaContainer.getIntegers().write(0, entityId);
// metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
// return metaContainer;
// }
//
// private GameProfile getCopyProfile(final Player player, final UUID uuid) {
// final GameProfile playerProfile = ((CraftPlayer) player).getProfile();
// final GameProfile profile = new GameProfile(
// uuid,
// player.getDisplayName()
// );
//
// profile.getProperties().removeAll("textures");
// Property textureProperty = playerProfile.getProperties().get("textures").iterator().next();
// String texture = textureProperty.getValue();
// String signature = textureProperty.getSignature();
// profile.getProperties().put("textures", new Property("textures", texture, signature));
//
// return profile;
// }
//
// @Override
// public PacketContainer getArmorStandMeta(final int armorStandId) {
// final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
//
// WrappedDataWatcher metaData = new WrappedDataWatcher();
//
// final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
//
// metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, byteSerializer), (byte) (0x20));
// metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, byteSerializer), (byte) (0x10));
//
// metaContainer.getIntegers().write(0, armorStandId);
// metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
// return metaContainer;
// }
//
// @Override
// public PacketContainer getDestroyPacket(final int entityId) {
// final PacketContainer destroyPacket = new PacketContainer(
// PacketType.Play.Server.ENTITY_DESTROY);
// destroyPacket.getModifier().write(0, new IntArrayList(new int[]{entityId}));
//
// return destroyPacket;
// }
}

View File

@@ -11,7 +11,7 @@ repositories {
maven("https://papermc.io/repo/repository/maven-public/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://jitpack.io")
maven("https://repo.dmulloy2.net/repository/public/")
// maven("https://repo.dmulloy2.net/repository/public/")
}
dependencies {
@@ -19,5 +19,5 @@ dependencies {
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot:1.18-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:22.0.0")
compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
// compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
}

View File

@@ -1,139 +1,119 @@
package io.github.fisher2911.nms;
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.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class PacketHelper_1_18_R1 implements PacketHelper {
@Override
public PacketContainer getPlayerSpawnPacket(final Location location, UUID uuid, final int entityId) {
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());
spawnPacket.getBytes().write(0, (byte)(((location.getYaw() * 256.0F) / 360.0F)));
return spawnPacket;
}
@Override
public PacketContainer getPlayerInfoPacket(final Player player, final UUID uuid) {
final GameProfile profile = this.getCopyProfile(player, uuid);
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<>();
playerInfoData.add(new PlayerInfoData(WrappedGameProfile
.fromHandle(profile),
0,
EnumWrappers.NativeGameMode.fromBukkit(GameMode.SURVIVAL),
WrappedChatComponent.fromText(profile.getName())));
action.write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
infoData.write(0, playerInfoData);
return playerInfoPacket;
}
@Override
public PacketContainer getPlayerRemovePacket(final Player player, final UUID uuid, final int entityId) {
final PacketContainer playerPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
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("")));
action.write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
infoData.write(0, playerInfoData);
return playerPacket;
}
@Override
public PacketContainer getPlayerOverlayPacket(final int entityId) {
final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
WrappedDataWatcher metaData = new WrappedDataWatcher();
final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(17, byteSerializer), mask);
metaContainer.getIntegers().write(0, entityId);
metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
return metaContainer;
}
private GameProfile getCopyProfile(final Player player, final UUID uuid) {
final GameProfile playerProfile = ((CraftPlayer) player).getProfile();
final GameProfile profile = new GameProfile(
uuid,
player.getDisplayName()
);
profile.getProperties().removeAll("textures");
Property textureProperty = playerProfile.getProperties().get("textures").iterator().next();
String texture = textureProperty.getValue();
String signature = textureProperty.getSignature();
profile.getProperties().put("textures", new Property("textures", texture, signature));
return profile;
}
@Override
public PacketContainer getArmorStandMeta(final int armorStandId) {
final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
WrappedDataWatcher metaData = new WrappedDataWatcher();
final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, byteSerializer), (byte) (0x20));
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, byteSerializer), (byte) (0x10));
metaContainer.getIntegers().write(0, armorStandId);
metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
return metaContainer;
}
@Override
public PacketContainer getDestroyPacket(final int entityId) {
final PacketContainer destroyPacket = new PacketContainer(
PacketType.Play.Server.ENTITY_DESTROY);
destroyPacket.getModifier().write(0, new IntArrayList(new int[]{entityId}));
return destroyPacket;
}
// @Override
// public PacketContainer getPlayerSpawnPacket(final Location location, UUID uuid, final int entityId) {
// 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());
// spawnPacket.getBytes().write(0, (byte)(((location.getYaw() * 256.0F) / 360.0F)));
//
// return spawnPacket;
// }
//
// @Override
// public PacketContainer getPlayerInfoPacket(final Player player, final UUID uuid) {
// final GameProfile profile = this.getCopyProfile(player, uuid);
// 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<>();
//
// playerInfoData.add(new PlayerInfoData(WrappedGameProfile
// .fromHandle(profile),
// 0,
// EnumWrappers.NativeGameMode.fromBukkit(GameMode.SURVIVAL),
// WrappedChatComponent.fromText(profile.getName())));
//
// action.write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER);
// infoData.write(0, playerInfoData);
//
// return playerInfoPacket;
// }
//
// @Override
// public PacketContainer getPlayerRemovePacket(final Player player, final UUID uuid, final int entityId) {
// final PacketContainer playerPacket = new PacketContainer(PacketType.Play.Server.PLAYER_INFO);
// 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("")));
//
// action.write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
// infoData.write(0, playerInfoData);
//
// return playerPacket;
// }
//
// @Override
// public PacketContainer getPlayerOverlayPacket(final int entityId) {
// final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
//
// WrappedDataWatcher metaData = new WrappedDataWatcher();
//
// final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
//
// final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
//
// metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(17, byteSerializer), mask);
//
// metaContainer.getIntegers().write(0, entityId);
// metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
// return metaContainer;
// }
//
// private GameProfile getCopyProfile(final Player player, final UUID uuid) {
// final GameProfile playerProfile = ((CraftPlayer) player).getProfile();
// final GameProfile profile = new GameProfile(
// uuid,
// player.getDisplayName()
// );
//
// profile.getProperties().removeAll("textures");
// Property textureProperty = playerProfile.getProperties().get("textures").iterator().next();
// String texture = textureProperty.getValue();
// String signature = textureProperty.getSignature();
// profile.getProperties().put("textures", new Property("textures", texture, signature));
//
// return profile;
// }
//
// @Override
// public PacketContainer getArmorStandMeta(final int armorStandId) {
// final PacketContainer metaContainer = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
//
// WrappedDataWatcher metaData = new WrappedDataWatcher();
//
// final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
//
// metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, byteSerializer), (byte) (0x20));
// metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, byteSerializer), (byte) (0x10));
//
// metaContainer.getIntegers().write(0, armorStandId);
// metaContainer.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
// return metaContainer;
// }
//
// @Override
// public PacketContainer getDestroyPacket(final int entityId) {
// final PacketContainer destroyPacket = new PacketContainer(
// PacketType.Play.Server.ENTITY_DESTROY);
// destroyPacket.getModifier().write(0, new IntArrayList(new int[]{entityId}));
//
// return destroyPacket;
// }
}

View File

@@ -1,112 +1,3 @@
//import net.minecrell.pluginyml.bukkit.BukkitPluginDescription
//
plugins {
id("java")
}
// id("com.github.johnrengelman.shadow") version "7.1.1"
// id("net.minecrell.plugin-yml.bukkit") version "0.5.1"
//}
//
//group = "io.github.fisher2911"
//version = "1.7.1"
//description = "Intuitive, easy-to-use cosmetics plugin, designed for servers using resource packs.\n"
//
//repositories {
// mavenCentral()
// maven("https://papermc.io/repo/repository/maven-public/")
// maven("https://repo.mattstudios.me/artifactory/public/")
// maven("https://jitpack.io")
// maven("https://repo.dmulloy2.net/repository/public/")
// maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
// maven("https://mvnrepository.com/artifact/com.zaxxer/HikariCP")
// maven("https://repo.jeff-media.de/maven2/")
// maven("https://oss.sonatype.org/content/repositories/snapshots")
//}
//
//dependencies {
// compileOnly("com.mojang:authlib:1.5.25")
// compileOnly("org.spigotmc:spigot:1.17-R0.1-SNAPSHOT")
// compileOnly("org.jetbrains:annotations:22.0.0")
// compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
// compileOnly("me.clip:placeholderapi:2.11.1")
// compileOnly("com.github.oraxen:oraxen:-SNAPSHOT")
// compileOnly("com.github.LoneDev6:API-ItemsAdder:2.5.4")
// implementation("net.kyori:adventure-api:4.9.3")
// implementation("net.kyori:adventure-text-minimessage:4.10.0-SNAPSHOT")
// implementation("net.kyori:adventure-platform-bukkit:4.0.1")
// implementation("dev.triumphteam:triumph-gui:3.1.1")
// implementation("me.mattstudios.utils:matt-framework:1.4.6")
// implementation("org.spongepowered:configurate-yaml:4.1.2")
// implementation("org.bstats:bstats-bukkit:2.2.1")
// implementation("com.zaxxer:HikariCP:5.0.0")
// implementation("com.j256.ormlite:ormlite-jdbc:6.1")
// implementation("com.j256.ormlite:ormlite-core:6.1")
//}
//
//tasks {
// build {
// dependsOn(shadowJar)
// }
//
// compileJava {
// options.encoding = Charsets.UTF_8.name()
// options.release.set(16)
// }
//
// shadowJar {
// relocate("dev.triumphteam.gui", "io.github.fisher2911.hmccosmetics.gui")
// relocate("me.mattstudios.mf", "io.github.fisher2911.hmccosmetics.mf")
// relocate("net.kyori.adventure.text.minimessage", "io.github.fisher2911.hmccosmetics.adventure.minimessage")
// relocate("net.kyori.adventure.platform", "io.github.fisher2911.hmccosmetics.adventure.platform")
// relocate("org.spongepowered.configurate", "io.github.fisher2911.hmccosmetics.configurate")
// relocate("org.bstats", "io.github.fisher2911.hmccosmetics.bstats")
// relocate("com.zaxxer.hikaricp", "io.github.fisher2911.hmccosmetics.hikaricp")
// relocate("com.j256.ormlite", "io.github.fisher2911.hmccosmetics.ormlite")
// archiveFileName.set("HMCCosmetics.jar")
// }
//
// javadoc {
// options.encoding = Charsets.UTF_8.name()
// }
//
// processResources {
// filteringCharset = Charsets.UTF_8.name()
// }
//}
//
//java {
// toolchain.languageVersion.set(JavaLanguageVersion.of(16))
//}
//
//bukkit {
// load = BukkitPluginDescription.PluginLoadOrder.STARTUP
// main = "io.github.fisher2911.hmccosmetics.HMCCosmetics"
// apiVersion = "1.17"
// name = "HMCCosmetics"
// authors = listOf("MasterOfTheFish")
// softDepend = listOf("Multiverse", "PlaceholderAPI", "Oraxen", "ItemsAdder")
// depend = listOf("ProtocolLib")
// permissions {
// register("hmccosmetics.cmd.default") {
// default = BukkitPluginDescription.Permission.Default.OP
// description = "Permission to execute the default command."
// }
// register("hmccosmetics.cmd.dye") {
// default = BukkitPluginDescription.Permission.Default.OP
// description = "Permission to dye armor."
// }
// register("hmccosmetics.cmd.reload") {
// default = BukkitPluginDescription.Permission.Default.OP
// description = "Permission to use the reload command."
// }
// register("hmccosmetics.cmd.set") {
// 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

@@ -22,22 +22,24 @@ repositories {
maven("https://repo.jeff-media.de/maven2/")
maven("https://repo.citizensnpcs.co")
maven("https://mvn.lumine.io/repository/maven-public")
maven("https://jitpack.io/")
}
dependencies {
implementation(project(":1.16"))
implementation(project(":1.17"))
implementation(project(":1.18"))
implementation(project(":nms"))
// implementation(project(":1.16"))
// implementation(project(":1.17"))
// implementation(project(":1.18"))
// implementation(project(":nms"))
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:22.0.0")
compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
// compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
compileOnly("me.clip:placeholderapi:2.11.1")
compileOnly("com.github.oraxen:oraxen:-SNAPSHOT")
compileOnly("com.github.LoneDev6:API-ItemsAdder:2.5.4")
compileOnly("net.citizensnpcs:citizens-main:2.0.29-SNAPSHOT")
compileOnly("com.ticxo.modelengine:api:R2.4.1:")
implementation("com.github.retrooper.packetevents:spigot:2.0-SNAPSHOT")
implementation("net.kyori:adventure-api:4.10.0")
implementation ("net.kyori:adventure-text-minimessage:4.10.0-SNAPSHOT")
implementation("net.kyori:adventure-platform-bukkit:4.0.1")
@@ -68,6 +70,7 @@ tasks {
relocate("org.bstats", "io.github.fisher2911.hmccosmetics.bstats")
relocate("com.zaxxer.hikaricp", "io.github.fisher2911.hmccosmetics.hikaricp")
relocate("com.j256.ormlite", "io.github.fisher2911.hmccosmetics.ormlite")
relocate("com.github.retrooper.packetevents", "io.github.fisher2911.hmccosmetics.packetevents")
archiveFileName.set("HMCCosmetics.jar")
dependencies {
@@ -100,8 +103,8 @@ bukkit {
apiVersion = "1.16"
name = "HMCCosmetics"
authors = listOf("MasterOfTheFish")
softDepend = listOf("Multiverse", "PlaceholderAPI", "Oraxen", "ItemsAdder", "Citizens", "ModelEngine")
depend = listOf("ProtocolLib")
softDepend = listOf("Multiverse", "PlaceholderAPI", "Oraxen", "ItemsAdder", "Citizens", "ModelEngine", "packetevents")
// depend = listOf("ProtocolLib")
permissions {
register("hmccosmetics.cmd.default") {
default = BukkitPluginDescription.Permission.Default.OP

View File

@@ -1,7 +1,6 @@
package io.github.fisher2911.hmccosmetics;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.github.retrooper.packetevents.PacketEvents;
import io.github.fisher2911.hmccosmetics.command.CosmeticsCommand;
import io.github.fisher2911.hmccosmetics.concurrent.Threads;
import io.github.fisher2911.hmccosmetics.config.Settings;
@@ -12,8 +11,8 @@ import io.github.fisher2911.hmccosmetics.database.DatabaseFactory;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.gui.Token;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.item.ItemsAdderHook;
import io.github.fisher2911.hmccosmetics.listener.ClickListener;
import io.github.fisher2911.hmccosmetics.listener.CosmeticFixListener;
@@ -28,6 +27,13 @@ import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Translation;
import io.github.fisher2911.hmccosmetics.task.TaskManager;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
import me.mattstudios.mf.base.CommandManager;
import me.mattstudios.mf.base.CompletionHandler;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -38,18 +44,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import me.mattstudios.mf.base.CommandManager;
import me.mattstudios.mf.base.CompletionHandler;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
public class HMCCosmetics extends JavaPlugin {
public static final Path PLUGIN_FOLDER = Paths.get("plugins", "HMCCosmetics");
private ProtocolManager protocolManager;
private TaskManager taskManager;
private Settings settings;
private UserManager userManager;
@@ -62,12 +60,18 @@ public class HMCCosmetics extends JavaPlugin {
private BukkitTask saveTask;
@Override
public void onLoad() {
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
PacketEvents.getAPI().getSettings().debug(true);
PacketEvents.getAPI().load();
}
@Override
public void onEnable() {
PacketEvents.getAPI().init();
final int pluginId = 13873;
final Metrics metrics = new Metrics(this, pluginId);
this.protocolManager = ProtocolLibrary.getProtocolManager();
this.taskManager = new TaskManager(this);
this.taskManager.start();
this.settings = new Settings(this);
@@ -106,6 +110,7 @@ public class HMCCosmetics extends JavaPlugin {
@Override
public void onDisable() {
PacketEvents.getAPI().terminate();
this.saveTask.cancel();
this.database.saveAll();
this.messageHandler.close();
@@ -237,10 +242,6 @@ public class HMCCosmetics extends JavaPlugin {
return cosmeticsMenu;
}
public ProtocolManager getProtocolManager() {
return protocolManager;
}
public Database getDatabase() {
return database;
}

View File

@@ -1,111 +0,0 @@
package io.github.fisher2911.hmccosmetics.api;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import java.util.ArrayList;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
/**
* Wrapper for ArmorItem used internally for convenience and safety
*/
public class CosmeticItem {
private final ArmorItem armorItem;
public CosmeticItem(final ArmorItem armorItem) {
this.armorItem = armorItem;
}
/**
* @param itemStack the {@link org.bukkit.inventory.ItemStack} display item
* @param id the id of the item
* @param type the cosmetic item type
* @param dyeable whether the item can be dyed
* @param rgb from Bukkit's {@link Color#asRGB()}
*/
public CosmeticItem(
final ItemStack itemStack,
final String name,
final String id,
final ItemStack locked,
final ItemStack applied,
final String permission,
final ArmorItem.Type type,
final boolean dyeable,
final int rgb) {
this.armorItem = new ArmorItem(itemStack, name, id, locked, applied, permission, type, dyeable, rgb);
}
/**
* @param material the {@link org.bukkit.Material} display item
* @param id the id of the item
* @param type the cosmetic item type
* @param dyeable whether the item can be dyed
* @param rgb from Bukkit's {@link Color#asRGB()}
*/
public CosmeticItem(
final Material material,
final String name,
final String id,
final Material locked,
final Material applied,
final String permission,
final ArmorItem.Type type,
final boolean dyeable,
final int rgb
) {
this.armorItem = new ArmorItem(material, name, id, new ItemStack(locked), new ItemStack(applied), permission, type, dyeable, rgb);
}
/**
* @param itemStack the {@link org.bukkit.inventory.ItemStack} display item
* @param id the id of the item
* @param type the cosmetic item type
*/
public CosmeticItem(final ItemStack itemStack, final String name, final String id, final ItemStack locked, final ItemStack applied, final ArmorItem.Type type) {
this(itemStack, name, id, locked, applied, "", type, false, -1);
}
/**
* @param material the {@link org.bukkit.Material} display item
* @param id the id of the item
* @param type the cosmetic item type
*/
public CosmeticItem(final Material material, final Material locked, final Material applied, final String name, final String id, final ArmorItem.Type type) {
this(material, name, id, locked, applied, "", type, false, -1);
}
public ItemStack getItemStack(final ArmorItem.Status status) {
return this.armorItem.getItemStack(status);
}
public ItemStack getItemStack() {
return this.armorItem.getItemStack();
}
public String getId() {
return this.armorItem.getId();
}
public ArmorItem.Type getType() {
return this.armorItem.getType();
}
public boolean isDyeable() {
return this.armorItem.isDyeable();
}
public int getColor() {
return this.armorItem.getDye();
}
public ArmorItem getArmorItem() {
return this.armorItem;
}
}

View File

@@ -1,79 +0,0 @@
package io.github.fisher2911.hmccosmetics.api;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import java.util.Optional;
import java.util.UUID;
import org.jetbrains.annotations.Nullable;
public class HMCCosmeticsAPI {
private static final HMCCosmetics plugin;
static {
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
}
/**
* This will attempt to get the {@link io.github.fisher2911.hmccosmetics.api.CosmeticItem} that
* the user is wearing. It returns an empty {@link io.github.fisher2911.hmccosmetics.api.CosmeticItem}
* if the user is not found, or if the user is not wearing a cosmetic
*
* @param uuid the uuid of the user
* @param type the type of cosmetic being retrieved
* @return the current cosmetic of the player
*/
public static CosmeticItem getUserCurrentItem(final UUID uuid, final ArmorItem.Type type) {
final Optional<User> userOptional = plugin.getUserManager().get(uuid);
if (userOptional.isEmpty()) {
return new CosmeticItem(ArmorItem.empty(type));
}
return new CosmeticItem(userOptional.get().getPlayerArmor().getItem(type));
}
/**
* @param uuid the uuid of the user whose cosmetic is being set
* @param cosmeticItem the cosmetic being set
* @return true if the cosmetic was set, or else false
*/
public static boolean setCosmeticItem(final UUID uuid, final CosmeticItem cosmeticItem) {
final UserManager userManager = plugin.getUserManager();
final Optional<User> userOptional = userManager.get(uuid);
if (userOptional.isEmpty()) {
return false;
}
userManager.setItem(userOptional.get(), cosmeticItem.getArmorItem());
return true;
}
/**
* @param id the id of the cosmetic item being retrieved
* @return null if the cosmetic was not found, or a copy of the cosmetic item
*/
@Nullable
public static CosmeticItem getCosmeticFromId(final String id) {
final ArmorItem armorItem = plugin.getCosmeticManager().getArmorItem(id);
if (armorItem == null) {
return null;
}
return new CosmeticItem(armorItem.copy());
}
/**
* @param uuid the uuid of the user whose armor stand id is being retrieved
* @return the armor stand id, or -1 if the user is not found
*/
public static int getUserArmorStandId(final UUID uuid) {
final Optional<User> userOptional = plugin.getUserManager().get(uuid);
if (userOptional.isEmpty()) {
return -1;
}
return userOptional.get().getArmorStandId();
}
}

View File

@@ -1,36 +0,0 @@
package io.github.fisher2911.hmccosmetics.api.event;
import io.github.fisher2911.hmccosmetics.api.CosmeticItem;
import io.github.fisher2911.hmccosmetics.user.BaseUser;
import io.github.fisher2911.hmccosmetics.user.User;
/**
* Called when a user changes their equipped cosmetic
*/
public class CosmeticChangeEvent extends CosmeticItemEvent {
private final BaseUser user;
private CosmeticItem removed;
public CosmeticChangeEvent(
final CosmeticItem cosmeticItem,
final CosmeticItem removed,
final BaseUser user) {
super(cosmeticItem);
this.removed = removed;
this.user = user;
}
public BaseUser getUser() {
return user;
}
public CosmeticItem getRemoved() {
return removed;
}
public void setRemoved(final CosmeticItem removed) {
this.removed = removed;
}
}

View File

@@ -1,47 +0,0 @@
package io.github.fisher2911.hmccosmetics.api.event;
import io.github.fisher2911.hmccosmetics.api.CosmeticItem;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public abstract class CosmeticItemEvent extends Event implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
private CosmeticItem cosmeticItem;
private boolean cancelled;
public CosmeticItemEvent(final CosmeticItem cosmeticItem) {
this.cosmeticItem = cosmeticItem;
this.cancelled = false;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
public CosmeticItem getCosmeticItem() {
return this.cosmeticItem;
}
public void setCosmeticItem(final CosmeticItem cosmeticItem) {
this.cosmeticItem = cosmeticItem;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(final boolean cancelled) {
this.cancelled = cancelled;
}
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
}

View File

@@ -1,454 +0,0 @@
package io.github.fisher2911.hmccosmetics.command;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.config.WardrobeSettings;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.gui.Token;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.message.Message;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.task.TaskChain;
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 me.mattstudios.mf.annotations.Command;
import me.mattstudios.mf.annotations.Completion;
import me.mattstudios.mf.annotations.Default;
import me.mattstudios.mf.annotations.Permission;
import me.mattstudios.mf.annotations.SubCommand;
import me.mattstudios.mf.base.CommandBase;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
@Command("cosmetics")
public class CosmeticsCommand extends CommandBase {
private final HMCCosmetics plugin;
private final UserManager userManager;
private final MessageHandler messageHandler;
private final CosmeticsMenu cosmeticsMenu;
private final CosmeticManager cosmeticManager;
private final Settings settings;
private final CosmeticSettings cosmeticSettings;
public CosmeticsCommand(final HMCCosmetics plugin) {
this.plugin = plugin;
this.userManager = this.plugin.getUserManager();
this.messageHandler = this.plugin.getMessageHandler();
this.cosmeticsMenu = this.plugin.getCosmeticsMenu();
this.cosmeticManager = this.plugin.getCosmeticManager();
this.settings = this.plugin.getSettings();
this.cosmeticSettings = this.settings.getCosmeticSettings();
}
@Default
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DEFAULT_COMMAND)
public void defaultCommand(final Player player) {
this.defaultCommand(player, this.cosmeticSettings.getDefaultMenu());
}
@SubCommand("menu")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DEFAULT_COMMAND)
public void defaultCommand(final Player player, @Completion("#menus") @me.mattstudios.mf.annotations.Optional String menu) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
if (menu == null) menu = this.cosmeticSettings.getDefaultMenu();
if (optionalUser.isEmpty()) {
this.cosmeticsMenu.openMenu(menu, player);
return;
}
final User user = optionalUser.get();
final Wardrobe wardrobe = user.getWardrobe();
if (wardrobe.isActive() &&
!this.settings.getWardrobeSettings().inDistanceOfWardrobe(wardrobe.getCurrentLocation(), player.getLocation())) {
wardrobe.setActive(false);
wardrobe.despawnFakePlayer(player, userManager);
this.messageHandler.sendMessage(
player,
Messages.CLOSED_WARDROBE
);
}
this.cosmeticsMenu.openMenu(menu, player);
}
@SubCommand("reload")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.RELOAD_COMMAND)
public void reloadCommand(final CommandSender sender) {
Bukkit.getScheduler().runTaskAsynchronously(
this.plugin,
() -> {
this.plugin.reload();
this.messageHandler.sendMessage(
sender,
Messages.RELOADED
);
}
);
}
@SubCommand("dye")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DYE_COMMAND)
public void dyeArmor(
final Player player,
@Completion("#types") String typeString,
final @me.mattstudios.mf.annotations.Optional String dyeColor
) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) {
return;
}
try {
final ArmorItem.Type type = ArmorItem.Type.valueOf(typeString.toUpperCase());
final User user = optionalUser.get();
if (dyeColor == null) {
this.cosmeticsMenu.openDyeSelectorGui(user, type);
return;
}
final ArmorItem armorItem = user.getPlayerArmor().getItem(type);
this.setDyeColor(dyeColor, armorItem, player);
this.userManager.setItem(user, armorItem);
this.messageHandler.sendMessage(
player,
Messages.SET_DYE_COLOR,
Map.of(Placeholder.ITEM, StringUtils.formatArmorItemType(typeString))
);
} catch (final IllegalArgumentException exception) {
this.messageHandler.sendMessage(
player,
Messages.INVALID_TYPE);
}
}
@SubCommand("help") // WORK IN PROGRESS (WIP)
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.HELP_COMMAND)
public void helpCommand(final CommandSender sender) {
this.messageHandler.sendMessage(
sender,
Messages.HELP_COMMAND
);
}
@SubCommand("add")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.SET_COSMETIC_COMMAND)
public void setCommand(
final CommandSender sender,
@Completion("#players") final Player player,
@Completion("#ids") final String id,
final @me.mattstudios.mf.annotations.Optional String dyeColor
) {
final Optional<User> userOptional = this.userManager.get(player.getUniqueId());
if (userOptional.isEmpty()) {
this.messageHandler.sendMessage(
sender,
Messages.INVALID_USER
);
return;
}
final User user = userOptional.get();
final ArmorItem armorItem = this.plugin.getCosmeticManager().getArmorItem(id);
if (armorItem == null) {
this.messageHandler.sendMessage(
sender,
Messages.ITEM_NOT_FOUND
);
return;
}
if (dyeColor != null) {
this.setDyeColor(dyeColor, armorItem, player);
}
final Message setMessage = Messages.getSetMessage(armorItem.getType());
final Message setOtherMessage = Messages.getSetOtherMessage(armorItem.getType());
this.userManager.setItem(user, armorItem);
this.messageHandler.sendMessage(
player,
setMessage
);
this.messageHandler.sendMessage(
sender,
setOtherMessage,
Map.of(Placeholder.PLAYER, player.getName(),
Placeholder.TYPE, id)
);
}
@SubCommand("remove")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.SET_COSMETIC_COMMAND)
public void removeCommand(final CommandSender sender,
@Completion("#players") final Player player, @Completion("#types") String typeString) {
final Optional<User> userOptional = this.userManager.get(player.getUniqueId());
if (userOptional.isEmpty()) {
this.messageHandler.sendMessage(
sender,
Messages.INVALID_USER
);
return;
}
final User user = userOptional.get();
try {
final ArmorItem.Type type = ArmorItem.Type.valueOf(typeString.toUpperCase());
final Message setOtherMessage = Messages.getSetOtherMessage(type);
this.userManager.removeItem(user, type);
this.messageHandler.sendMessage(
sender,
setOtherMessage,
Map.of(Placeholder.PLAYER, player.getName(),
Placeholder.TYPE, "none")
);
} catch (final IllegalArgumentException exception) {
this.messageHandler.sendMessage(player, Messages.INVALID_TYPE);
}
}
@SubCommand("wardrobe")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.WARDROBE)
public void openWardrobe(Player player, @me.mattstudios.mf.annotations.Optional final Player other) {
if (other != null) {
if (!player.hasPermission(io.github.fisher2911.hmccosmetics.message.Permission.OPEN_OTHER_WARDROBE)) {
this.messageHandler.sendMessage(
player,
Messages.NO_PERMISSION
);
return;
}
this.messageHandler.sendMessage(
player,
Messages.OPENED_OTHER_WARDROBE,
Map.of(Placeholder.PLAYER, other.getName())
);
player = other;
}
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;
}
final WardrobeSettings settings = this.settings.getWardrobeSettings();
final boolean inDistanceOfStatic = settings.inDistanceOfStatic(player.getLocation());
if (!settings.isPortable() && !inDistanceOfStatic) {
this.messageHandler.sendMessage(
player,
Messages.NOT_NEAR_WARDROBE
);
return;
}
if (settings.isPortable() && !inDistanceOfStatic) {
if (!player.hasPermission(io.github.fisher2911.hmccosmetics.message.Permission.PORTABLE_WARDROBE)) {
this.messageHandler.sendMessage(
player,
Messages.CANNOT_USE_PORTABLE_WARDROBE
);
return;
}
wardrobe.setCurrentLocation(null);
}
wardrobe.setActive(true);
settings.playOpenSound(player);
final Player finalPlayer = player;
new TaskChain(this.plugin).
chain(() -> {
wardrobe.spawnFakePlayer(finalPlayer);
}, true).
chain(() -> {
// this.cosmeticsMenu.openDefault(finalPlayer);
this.messageHandler.sendMessage(
finalPlayer,
Messages.OPENED_WARDROBE
);
}).execute();
}
public static final String NPC_APPLY = "apply";
public static final String NPC_REMOVE = "remove";
@SubCommand("npc")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.SET_COSMETIC_COMMAND)
public void applyNpc(
final CommandSender sender,
@Completion("#npc-args") final String arg,
@Completion("#npcs") final Integer npcId,
@Completion("#types") final String typeStr,
@me.mattstudios.mf.annotations.Optional @Completion("#ids") final String itemId
) {
final CitizensHook citizensHook = HookManager.getInstance().getCitizensHook();
if (citizensHook == null) {
this.messageHandler.sendMessage(
sender,
Messages.HOOK_NOT_ENABLED,
Map.of(Placeholder.TYPE, "Citizens")
);
return;
}
if (npcId == null) {
this.messageHandler.sendMessage(
sender,
new Message("illegal-npc-id", "<red>" + "Invalid NPC id specified: " + npcId)
);
return;
}
final ArmorItem armorItem = this.plugin.getCosmeticManager().getArmorItem(itemId);
if (armorItem == null) {
this.messageHandler.sendMessage(
sender,
Messages.ITEM_NOT_FOUND
);
return;
}
switch (arg.toLowerCase(Locale.ROOT)) {
case NPC_APPLY -> {
this.setNpcCosmetic(citizensHook, sender, npcId, armorItem);
}
case NPC_REMOVE -> {
try {
final ArmorItem.Type type = ArmorItem.Type.valueOf(typeStr);
this.setNpcCosmetic(citizensHook, sender, npcId, ArmorItem.empty(type, "none"));
} catch (final IllegalArgumentException exception) {
this.messageHandler.sendMessage(
sender,
Messages.INVALID_TYPE,
Map.of(Placeholder.TYPE, typeStr)
);
}
}
}
}
@SubCommand("hide")
public void hide(final Player player) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
if (user.isHidden()) {
user.setHidden(false);
this.messageHandler.sendMessage(
player,
Messages.SHOWN_COSMETICS
);
return;
}
user.setHidden(true);
this.messageHandler.sendMessage(
player,
Messages.HID_COSMETICS
);
}
@SubCommand("token")
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.GIVE_TOKEN)
public void token(
final CommandSender sender,
@Completion("#tokens") final String tokenId,
@Completion("#players") @me.mattstudios.mf.annotations.Optional Player giveTo) {
if (!(sender instanceof Player) && giveTo == null) {
this.messageHandler.sendMessage(
sender,
Messages.MUST_BE_PLAYER
);
return;
}
if (giveTo == null) {
giveTo = ((Player) sender);
}
final Token token = this.cosmeticManager.getToken(tokenId);
if (token == null) {
this.messageHandler.sendMessage(
sender,
Messages.ITEM_NOT_FOUND
);
return;
}
giveTo.getInventory().addItem(token.getItemStack().clone());
final String tokenName = token.getArmorItem().getName();
this.messageHandler.sendMessage(
sender,
Messages.GAVE_TOKEN,
Map.of(Placeholder.ID, tokenName,
Placeholder.PLAYER, giveTo.getDisplayName())
);
this.messageHandler.sendMessage(
giveTo,
Messages.RECEIVED_TOKEN,
Map.of(Placeholder.ID, tokenName)
);
}
private void setNpcCosmetic(final CitizensHook hook, final CommandSender sender, final int npcId, final ArmorItem item) {
final boolean isSet = hook.setNpcCosmetic(npcId, item);
if (!isSet) {
this.messageHandler.sendMessage(
sender,
Messages.NPC_NOT_FOUND,
Map.of(Placeholder.ID, String.valueOf(npcId))
);
return;
}
this.messageHandler.sendMessage(
sender,
Messages.SET_NPC_COSMETIC,
Map.of(Placeholder.TYPE, item.getType().toString(),
Placeholder.ITEM, item.getId(),
Placeholder.ID, String.valueOf(npcId))
);
}
private void setDyeColor(final String dyeColor, final ArmorItem armorItem, final CommandSender sender) {
try {
final java.awt.Color awtColor = java.awt.Color.decode(dyeColor);
Color color = Color.fromRGB(awtColor.getRed(), awtColor.getGreen(), awtColor.getBlue());
armorItem.setDye(color.asRGB());
} catch (final NumberFormatException exception) {
this.messageHandler.sendMessage(
sender,
Messages.INVALID_COLOR,
Map.of(Placeholder.ITEM, dyeColor)
);
}
}
}

View File

@@ -1,32 +0,0 @@
package io.github.fisher2911.hmccosmetics.concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Threads {
private static final Threads INSTANCE;
static {
INSTANCE = new Threads();
}
private final ExecutorService service;
private Threads() {
this.service = Executors.newFixedThreadPool(1);
}
public static Threads getInstance() {
return INSTANCE;
}
public void execute(final Runnable runnable) {
this.service.execute(runnable);
}
public void onDisable() {
this.service.shutdownNow().forEach(Runnable::run);
}
}

View File

@@ -1,281 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.message.Message;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
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.util.Utils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class ActionSerializer implements TypeSerializer<List<CosmeticGuiAction>> {
public static final ActionSerializer INSTANCE = new ActionSerializer();
private static final HMCCosmetics plugin;
private static final String OPEN_MENU = "open-menu";
private static final String SET_ITEMS = "set-items";
private static final String REMOVE_COSMETICS = "remove-cosmetics";
private static final String SET_COSMETICS = "set-cosmetics";
private static final String SEND_MESSAGE = "send-message";
private static final String SEND_MESSAGES = "send-messages";
private static final String SEND_COMMAND = "send-command";
private static final String SEND_COMMANDS = "send-commands";
private static final String SOUND = "sound";
static {
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
}
private ActionSerializer() {
}
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path)
throws SerializationException {
if (!source.hasChild(path)) {
throw new SerializationException(
"Required field " + Arrays.toString(path) + " was not present in node");
}
return source.node(path);
}
@Override
public List<CosmeticGuiAction> deserialize(final Type type, final ConfigurationNode source) {
return this.deserialize(type, new ArrayList<>(), source, CosmeticGuiAction.When.ALL);
}
private List<CosmeticGuiAction> deserialize(
final Type type,
final List<CosmeticGuiAction> consumers,
final ConfigurationNode source,
final CosmeticGuiAction.When when) {
final var children = source.childrenMap();
for (final var entry : children.entrySet()) {
final String clickType = entry.getKey().toString();
try {
final CosmeticGuiAction.When nextWhen = CosmeticGuiAction.When.valueOf(clickType.toUpperCase());
this.deserialize(type, consumers, entry.getValue(), nextWhen);
} catch (final IllegalArgumentException exception) {
consumers.add(this.parseAction(entry.getValue(), clickType.toUpperCase(Locale.ROOT), when));
}
}
return consumers;
}
private CosmeticGuiAction parseAction(
final ConfigurationNode node,
final String clickType,
final CosmeticGuiAction.When when
) {
final ConfigurationNode openMenuNode = node.node(OPEN_MENU);
final ConfigurationNode setItemsNode = node.node(SET_ITEMS);
final ConfigurationNode removeItemsNode = node.node(REMOVE_COSMETICS);
final ConfigurationNode setCosmeticsNode = node.node(SET_COSMETICS);
final ConfigurationNode soundNode = node.node(SOUND);
final String openMenu = openMenuNode.getString();
final List<ArmorItem.Type> removeCosmeticTypes = this.loadRemoveTypes(removeItemsNode);
final List<String> setCosmetics = this.loadSetCosmetics(setCosmeticsNode);
final ClickType click = Utils.stringToEnum(clickType, ClickType.class, ClickType.UNKNOWN);
final Map<Integer, GuiItem> setItems = this.loadSetItems(setItemsNode);
final Consumer<Player> messageConsumer = this.loadMessages(node, plugin);
final SoundData soundData = this.loadSoundData(soundNode);
return new CosmeticGuiAction(
when,
event -> {
if (click != ClickType.UNKNOWN && event.getClick() != click) return;
if (!(event.getWhoClicked() instanceof final Player player)) return;
if (soundData != null) {
soundData.play(player);
}
if (openMenu != null) plugin.getCosmeticsMenu().openMenu(openMenu, event.getWhoClicked());
messageConsumer.accept(player);
final UserManager userManager = plugin.getUserManager();
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
final CosmeticManager cosmeticManager = plugin.getCosmeticManager();
for (final String id : setCosmetics) {
final ArmorItem armorItem = cosmeticManager.getArmorItem(id);
if (armorItem == null) continue;
userManager.setItem(user, armorItem);
}
for (final ArmorItem.Type type : removeCosmeticTypes) {
userManager.removeItem(user, type);
}
final CosmeticGui gui = user.getOpenGui();
if (gui != null) {
for (final var entry : setItems.entrySet()) {
final GuiItem item = entry.getValue();
gui.updateItem(entry.getKey(), item, user, player);
}
}
}
);
}
private Map<Integer, GuiItem> loadSetItems(final ConfigurationNode node) {
if (node.virtual()) return Collections.emptyMap();
final Map<Integer, GuiItem> setItems = new HashMap<>();
try {
for (final var entry : node.childrenMap().entrySet()) {
if (!(entry.getKey() instanceof final Integer slot)) continue;
final var key = entry.getValue();
final GuiItem guiItem = ArmorItemSerializer.INSTANCE.deserialize(GuiItem.class, key);
if (guiItem == null) continue;
setItems.put(slot, guiItem);
}
} catch (final SerializationException exception) {
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().severe(
"Error loading set-items"
);
return Collections.emptyMap();
}
return setItems;
}
private static final String CONSOLE = "console";
private static final String PLAYER = "player";
private Consumer<Player> loadMessages(final ConfigurationNode source, final HMCCosmetics plugin) {
final ConfigurationNode messageNode = source.node(SEND_MESSAGE);
final ConfigurationNode messagesNode = source.node(SEND_MESSAGES);
final ConfigurationNode commandNode = source.node(SEND_COMMAND);
final ConfigurationNode commandsNode = source.node(SEND_COMMANDS);
final List<String> messages = new ArrayList<>();
final List<String> commands = new ArrayList<>();
final String message = messageNode.getString();
if (message != null) messages.add(message);
final String command = commandNode.getString();
if (command != null) commands.add(command);
for (final var node : messagesNode.childrenList()) {
final String listMessage = node.getString();
if (listMessage == null) continue;
messages.add(listMessage);
}
for (final var node : commandsNode.childrenList()) {
final String commandMessage = node.getString();
if (commandMessage == null) continue;
commands.add(commandMessage);
}
return player -> {
final String playerName = player.getName();
final Map<String, String> placeholders = Map.of(Placeholder.PLAYER, playerName);
final MessageHandler messageHandler = plugin.getMessageHandler();
for (final String sendMessage : messages) {
messageHandler.sendMessage(
player,
new Message("", sendMessage),
placeholders
);
}
for (final String sendCommand : commands) {
final String[] parts = sendCommand.split(":");
if (parts.length < 2) {
Bukkit.dispatchCommand(
Bukkit.getConsoleSender(),
sendCommand.replace(Placeholder.PLAYER, playerName)
);
continue;
}
final String sender = parts[0];
final String commandToSend = parts[1];
if (sender.equalsIgnoreCase(CONSOLE)) {
Bukkit.dispatchCommand(
Bukkit.getConsoleSender(),
commandToSend.replace(Placeholder.PLAYER, playerName)
);
continue;
}
player.chat("/" + commandToSend.replace(Placeholder.PLAYER, playerName));
}
};
}
private List<ArmorItem.Type> loadRemoveTypes(final ConfigurationNode node) {
try {
final List<String> typeStrings = node.getList(String.class);
if (typeStrings == null) return new ArrayList<>();
return typeStrings.stream().map(
string -> {
try {
return ArmorItem.Type.valueOf(string.toUpperCase(Locale.ROOT));
} catch (final IllegalArgumentException exception) {
plugin.getLogger().severe(string + " is not a valid cosmetic type.");
}
return null;
}
).
filter(type -> type != null).
collect(Collectors.toList());
} catch (final SerializationException exception) {
exception.printStackTrace();
}
return new ArrayList<>();
}
private SoundData loadSoundData(final ConfigurationNode node) {
try {
return SoundSerializer.INSTANCE.deserialize(SoundData.class, node);
} catch (final ConfigurateException exception) {
return null;
}
}
private List<String> loadSetCosmetics(final ConfigurationNode node) {
try {
return node.getList(String.class);
} catch (final ConfigurateException exception) {
return new ArrayList<>();
}
}
@Override
public void serialize(final Type type, @Nullable final List<CosmeticGuiAction> obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -1,150 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.BalloonItem;
import io.github.fisher2911.hmccosmetics.gui.WrappedGuiItem;
import io.github.fisher2911.hmccosmetics.util.StringUtils;
import io.github.fisher2911.hmccosmetics.util.Utils;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
public class ArmorItemSerializer implements TypeSerializer<WrappedGuiItem> {
public static final ArmorItemSerializer INSTANCE = new ArmorItemSerializer();
private ArmorItemSerializer() {
}
private static final String NAME = "name";
private static final String LOCKED_LORE = "locked-lore";
private static final String APPLIED_LORE = "applied-lore";
private static final String LOCKED_ITEM = "locked-item";
private static final String APPLIED_ITEM = "applied-item";
private static final String PERMISSION = "permission";
private static final String TYPE = "type";
private static final String ACTION = "action";
private static final String ID = "id";
private static final String DYEABLE = "dyeable";
private static final String BALLOON_MODEL_ID = "balloon";
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path)
throws SerializationException {
if (!source.hasChild(path)) {
throw new SerializationException(
"Required field " + Arrays.toString(path) + " was not present in node");
}
return source.node(path);
}
@Override
public WrappedGuiItem deserialize(final Type type, final ConfigurationNode source)
throws SerializationException {
final ConfigurationNode nameNode = source.node(NAME);
final ConfigurationNode lockedLoreNode = source.node(LOCKED_LORE);
final ConfigurationNode appliedLoreNode = source.node(APPLIED_LORE);
final ConfigurationNode lockedItemNode = source.node(LOCKED_ITEM);
final ConfigurationNode appliedItemNode = source.node(APPLIED_ITEM);
final ConfigurationNode permissionNode = source.node(PERMISSION);
final ConfigurationNode typeNode = source.node(TYPE);
final ConfigurationNode actionNode = source.node(ACTION);
final ConfigurationNode idNode = source.node(ID);
final ConfigurationNode dyeableNode = source.node(DYEABLE);
final ConfigurationNode balloonModelIdNode = source.node(BALLOON_MODEL_ID);
final ItemStack itemStack = Utils.replaceIfNull(
ItemSerializer.INSTANCE.deserialize(ItemStack.class, source),
new ItemStack(Material.AIR)
);
ItemStack lockedItem = ItemSerializer.INSTANCE.deserialize(ItemStack.class, lockedItemNode);
if (lockedItem == null) {
final List<String> lockedLore = Utils.replaceIfNull(lockedLoreNode.getList(String.class),
new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
lockedItem = ItemBuilder.from(itemStack.clone()).lore(lockedLore).build();
}
ItemStack appliedItem = ItemSerializer.INSTANCE.deserialize(ItemStack.class, appliedItemNode);
if (appliedItem == null) {
final List<String> appliedLore = Utils.replaceIfNull(appliedLoreNode.getList(String.class),
new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
appliedItem = ItemBuilder.from(itemStack.clone()).lore(appliedLore).build();
}
final boolean dyeable = dyeableNode.getBoolean();
final List<CosmeticGuiAction> actions = ActionSerializer.INSTANCE.deserialize(GuiAction.class, actionNode);
try {
final ArmorItem.Type cosmeticType = ArmorItem.Type.valueOf(
Utils.replaceIfNull(
typeNode.getString(), ""
).toUpperCase(Locale.ROOT)
);
final String permission = permissionNode.getString();
if (cosmeticType == ArmorItem.Type.BALLOON) {
return new BalloonItem(
itemStack,
actions,
Utils.replaceIfNull(nameNode.getString(), ""),
Utils.replaceIfNull(idNode.getString(), ""),
lockedItem,
appliedItem,
permission,
cosmeticType,
dyeable,
-1,
balloonModelIdNode.getString()
);
}
return new ArmorItem(
itemStack,
actions,
Utils.replaceIfNull(nameNode.getString(), ""),
Utils.replaceIfNull(idNode.getString(), ""),
lockedItem,
appliedItem,
permission,
cosmeticType,
dyeable,
-1
);
} catch (final IllegalArgumentException exception) {
final GuiItem guiItem = dev.triumphteam.gui.builder.item.ItemBuilder.from(itemStack).asGuiItem();
final GuiAction<InventoryClickEvent> guiAction = event -> {
for (final CosmeticGuiAction action : actions) {
action.execute(event, CosmeticGuiAction.When.ALL);
}
};
guiItem.setAction(guiAction);
return new WrappedGuiItem(guiItem, guiAction);
}
}
@Override
public void serialize(final Type type, @Nullable final WrappedGuiItem obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -1,28 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import org.bukkit.event.inventory.InventoryClickEvent;
import java.util.function.Consumer;
public class CosmeticGuiAction {
private final When when;
private final Consumer<InventoryClickEvent> consumer;
public CosmeticGuiAction(final When when, final Consumer<InventoryClickEvent> consumer) {
this.when = when;
this.consumer = consumer;
}
public void execute(final InventoryClickEvent event, final When when) {
if (this.when != When.ALL && this.when != when) return;
consumer.accept(event);
}
public enum When {
EQUIP,
REMOVE,
ALL
}
}

View File

@@ -1,124 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.util.Utils;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.util.Vector;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
@ConfigSerializable
public class CosmeticSettings {
private static final String DEFAULT_MENU = "default-menu";
private static final String COSMETIC_SETTINGS_PATH = "cosmetic-settings";
private static final String REQUIRE_EMPTY_HELMET_PATH = "require-empty-helmet";
private static final String REQUIRE_EMPTY_OFF_HAND_PATH = "require-empty-off-hand";
private static final String REQUIRE_EMPTY_CHEST_PLATE_PATH = "require-empty-chest-plate";
private static final String REQUIRE_EMPTY_PANTS_PATH = "require-empty-pants";
private static final String REQUIRE_EMPTY_BOOTS_PATH = "require-empty-boots";
private static final String BALLOON_OFFSET = "balloon-offset";
private static final transient String LOOK_DOWN_PITCH_PATH = "look-down-backpack-remove";
private static final String VIEW_DISTANCE_PATH = "view-distance";
private String defaultMenu;
private boolean requireEmptyHelmet;
private boolean requireEmptyOffHand;
private boolean requireEmptyChestPlate;
private boolean requireEmptyPants;
private boolean requireEmptyBoots;
private int lookDownPitch;
private int viewDistance;
private Vector balloonOffset;
public void load(final FileConfiguration config) {
this.defaultMenu = Utils.replaceIf(config.getString(DEFAULT_MENU), CosmeticsMenu.DEFAULT_MAIN_MENU, null, "");
this.requireEmptyHelmet = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_HELMET_PATH);
this.requireEmptyOffHand = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_OFF_HAND_PATH);
this.requireEmptyChestPlate = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_CHEST_PLATE_PATH);
this.requireEmptyPants = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_PANTS_PATH);
this.requireEmptyBoots = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_BOOTS_PATH);
this.lookDownPitch = config.getInt(COSMETIC_SETTINGS_PATH + "." + LOOK_DOWN_PITCH_PATH);
this.viewDistance = config.getInt(COSMETIC_SETTINGS_PATH + "." + VIEW_DISTANCE_PATH);
final var balloonSection = config.getConfigurationSection(COSMETIC_SETTINGS_PATH + "." + BALLOON_OFFSET);
if (balloonSection != null) {
this.balloonOffset = loadVector(balloonSection);
}
}
private Vector loadVector(final ConfigurationSection section) {
return new Vector(section.getDouble("x"), section.getDouble("y"), section.getDouble("z"));
}
public boolean isRequireEmptyHelmet() {
return requireEmptyHelmet;
}
public void setRequireEmptyHelmet(final boolean requireEmptyHelmet) {
this.requireEmptyHelmet = requireEmptyHelmet;
}
public boolean isRequireEmptyOffHand() {
return requireEmptyOffHand;
}
public void setRequireEmptyOffHand(final boolean requireEmptyOffHand) {
this.requireEmptyOffHand = requireEmptyOffHand;
}
public boolean isRequireEmptyChestPlate() {
return requireEmptyChestPlate;
}
public void setRequireEmptyChestPlate(final boolean requireEmptyChestPlate) {
this.requireEmptyChestPlate = requireEmptyChestPlate;
}
public boolean isRequireEmptyPants() {
return requireEmptyPants;
}
public void setRequireEmptyPants(final boolean requireEmptyPants) {
this.requireEmptyPants = requireEmptyPants;
}
public boolean isRequireEmptyBoots() {
return requireEmptyBoots;
}
public void setRequireEmptyBoots(final boolean requireEmptyBoots) {
this.requireEmptyBoots = requireEmptyBoots;
}
public Vector getBalloonOffset() {
return balloonOffset;
}
public int getLookDownPitch() {
return lookDownPitch;
}
public int getViewDistance() {
return viewDistance;
}
public String getDefaultMenu() {
return defaultMenu;
}
public boolean requireEmpty(final EquipmentSlot slot) {
return switch (slot) {
case OFF_HAND -> this.isRequireEmptyOffHand();
case HEAD -> this.isRequireEmptyHelmet();
case CHEST -> this.isRequireEmptyChestPlate();
case LEGS -> this.isRequireEmptyPants();
case FEET -> this.isRequireEmptyBoots();
default -> false;
};
}
}

View File

@@ -1,133 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.ColorItem;
import io.github.fisher2911.hmccosmetics.gui.DyeSelectorGui;
import io.github.fisher2911.hmccosmetics.gui.WrappedGuiItem;
import org.bukkit.Color;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class DyeGuiSerializer implements TypeSerializer<DyeSelectorGui> {
public static final DyeGuiSerializer INSTANCE = new DyeGuiSerializer();
private static final HMCCosmetics plugin;
private static final String TITLE = "title";
private static final String ROWS = "rows";
private static final String ITEMS = "items";
private static final String COSMETICS_SLOTS = "cosmetics-slots";
private static final String SET_COLOR = "set-color";
private static final String RED = "red";
private static final String GREEN = "green";
private static final String BLUE = "blue";
static {
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
}
private DyeGuiSerializer() {
}
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path)
throws SerializationException {
if (!source.hasChild(path)) {
throw new SerializationException(
"Required field " + Arrays.toString(path) + " was not present in node");
}
return source.node(path);
}
@Override
public DyeSelectorGui deserialize(final Type type, final ConfigurationNode source)
throws SerializationException {
final ConfigurationNode titleNode = this.nonVirtualNode(source, TITLE);
final ConfigurationNode rowsNode = this.nonVirtualNode(source, ROWS);
final ConfigurationNode itemsNode = source.node(ITEMS);
final ConfigurationNode cosmeticSlotsNode = source.node(COSMETICS_SLOTS);
final Map<Integer, GuiItem> guiItemMap = new HashMap<>();
final var itemMap = itemsNode.childrenMap();
final var cosmeticSlotsMap = cosmeticSlotsNode.childrenMap();
for (final var entry : itemMap.entrySet()) {
if (!(entry.getKey() instanceof final Integer slot)) {
continue;
}
final var node = entry.getValue();
final WrappedGuiItem guiItem = ArmorItemSerializer.INSTANCE.deserialize(
GuiItem.class,
node
);
final ConfigurationNode colorNode = node.node(SET_COLOR);
if (colorNode.virtual()) {
guiItemMap.put(slot, guiItem);
continue;
}
final int red = colorNode.node(RED).getInt();
final int green = colorNode.node(GREEN).getInt();
final int blue = colorNode.node(BLUE).getInt();
guiItemMap.put(slot,
new ColorItem(guiItem.getItemStack(), guiItem.getAction(), Color.fromRGB(red, green, blue))
);
}
final BiMap<Integer, ArmorItem.Type> cosmeticSlots = HashBiMap.create();
int selectedCosmetic = -1;
for (final var entry : cosmeticSlotsMap.entrySet()) {
if (!(entry.getKey() instanceof final Integer slot)) {
continue;
}
selectedCosmetic = selectedCosmetic == -1 ? slot : selectedCosmetic;
final var node = entry.getValue();
final String typeStr = node.getString();
try {
final ArmorItem.Type itemType = ArmorItem.Type.valueOf(typeStr);
cosmeticSlots.put(slot, itemType);
} catch (final IllegalArgumentException | NullPointerException exception) {
plugin.getLogger().severe(typeStr + " is not a valid ArmorItem type in DyeGui!");
}
}
String title = titleNode.getString();
if (title == null) {
title = "";
}
return new DyeSelectorGui(
plugin,
title,
rowsNode.getInt(),
guiItemMap,
cosmeticSlots,
selectedCosmetic);
}
@Override
public void serialize(final Type type, @Nullable final DyeSelectorGui obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -1,78 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.message.Adventure;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
public class GuiSerializer implements TypeSerializer<CosmeticGui> {
public static final GuiSerializer INSTANCE = new GuiSerializer();
private static final HMCCosmetics plugin;
private static final String TITLE = "title";
private static final String ROWS = "rows";
private static final String ITEMS = "items";
static {
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
}
private GuiSerializer() {
}
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path)
throws SerializationException {
if (!source.hasChild(path)) {
throw new SerializationException(
"Required field " + Arrays.toString(path) + " was not present in node");
}
return source.node(path);
}
@Override
public CosmeticGui deserialize(final Type type, final ConfigurationNode source)
throws SerializationException {
final ConfigurationNode titleNode = this.nonVirtualNode(source, TITLE);
final ConfigurationNode rowsNode = this.nonVirtualNode(source, ROWS);
final ConfigurationNode itemsNode = source.node(ITEMS);
final var childrenMap = itemsNode.childrenMap();
final Map<Integer, GuiItem> guiItemMap = new HashMap<>();
for (final var entry : childrenMap.entrySet()) {
if (!(entry.getKey() instanceof final Integer slot)) continue;
final GuiItem guiItem = ArmorItemSerializer.INSTANCE.deserialize(
GuiItem.class,
entry.getValue()
);
guiItemMap.put(slot, guiItem);
}
String title = titleNode.getString();
if (title == null) {
title = "";
}
return new CosmeticGui(plugin,
title,
rowsNode.getInt(),
guiItemMap);
}
@Override
public void serialize(final Type type, @Nullable final CosmeticGui obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -1,191 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.gui.WrappedGuiItem;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.util.Keys;
import io.github.fisher2911.hmccosmetics.util.StringUtils;
import io.github.fisher2911.hmccosmetics.util.Utils;
import io.github.fisher2911.hmccosmetics.util.builder.ColorBuilder;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import io.github.fisher2911.hmccosmetics.util.builder.SkullBuilder;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer;
import org.bukkit.Registry;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class ItemSerializer implements TypeSerializer<ItemStack> {
public static final ItemSerializer INSTANCE = new ItemSerializer();
private static final String MATERIAL = "material";
private static final String AMOUNT = "amount";
private static final String NAME = "name";
private static final String UNBREAKABLE = "unbreakable";
private static final String GLOWING = "glowing";
private static final String LORE = "lore";
private static final String MODEL_DATA = "model-data";
private static final String ENCHANTS = "enchants";
private static final String ITEM_FLAGS = "item-flags";
private static final String TEXTURE = "texture";
private static final String OWNER = "owner";
private static final String COLOR = "color";
private static final String RED = "red";
private static final String GREEN = "green";
private static final String BLUE = "blue";
private ItemSerializer() {
}
@Override
public ItemStack deserialize(final Type type, final ConfigurationNode source)
throws SerializationException {
final ConfigurationNode materialNode = source.node(MATERIAL);
final ConfigurationNode amountNode = source.node(AMOUNT);
final ConfigurationNode nameNode = source.node(NAME);
final ConfigurationNode unbreakableNode = source.node(UNBREAKABLE);
final ConfigurationNode glowingNode = source.node(GLOWING);
final ConfigurationNode loreNode = source.node(LORE);
final ConfigurationNode modelDataNode = source.node(MODEL_DATA);
final ConfigurationNode enchantsNode = source.node(ENCHANTS);
final ConfigurationNode itemFlagsNode = source.node(ITEM_FLAGS);
final ConfigurationNode textureNode = source.node(TEXTURE);
final ConfigurationNode ownerNode = source.node(OWNER);
final ConfigurationNode colorNode = source.node(COLOR);
final ConfigurationNode redNode = colorNode.node(RED);
final ConfigurationNode greenNode = colorNode.node(GREEN);
final ConfigurationNode blueNode = colorNode.node(BLUE);
final String materialString = Utils.replaceIfNull(materialNode.getString(), "");
final int amount = amountNode.getInt();
ItemStack itemStack;
try {
itemStack = new ItemStack(Material.valueOf(materialString.toUpperCase()), amount);
} catch (final IllegalArgumentException exception) {
itemStack = HookManager.getInstance().getItemHooks().getItemStack(materialString);
if (itemStack == null) {
return null;
}
}
final String name = StringUtils.parseStringToString(Utils.replaceIfNull(nameNode.getString(), ""));
final boolean unbreakable = unbreakableNode.getBoolean();
final boolean glowing = glowingNode.getBoolean();
final List<String> lore = Utils.replaceIfNull(loreNode.getList(String.class),
new ArrayList<String>()).
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
final int modelData = modelDataNode.getInt();
final Set<ItemFlag> itemFlags = Utils.replaceIfNull(itemFlagsNode.getList(String.class),
new ArrayList<String>()).
stream().map(flag -> {
try {
return ItemFlag.valueOf(flag.toUpperCase());
} catch (final Exception ignored) {
return null;
}
}).collect(Collectors.toSet());
final String texture = textureNode.getString();
final String owner = ownerNode.getString();
final Color color;
if (colorNode.virtual()) {
color = null;
} else {
color = Color.fromRGB(redNode.getInt(), greenNode.getInt(), blueNode.getInt());
}
final Map<Enchantment, Integer> enchantments =
Utils.replaceIfNull(enchantsNode.getList(String.class),
new ArrayList<String>()).
stream().
collect(Collectors.toMap(enchantmentString -> {
if (!enchantmentString.contains(":")) {
return null;
}
final NamespacedKey namespacedKey = NamespacedKey.minecraft(
enchantmentString.
split(":")[0].
toLowerCase());
return Registry.ENCHANTMENT.get(namespacedKey);
}, enchantmentString -> {
if (!enchantmentString.contains(":")) {
return 0;
}
try {
return Integer.parseInt(enchantmentString.split(":")[1]);
} catch (final NumberFormatException exception) {
return 0;
}
}));
final ItemBuilder itemBuilder;
if (itemStack.getType() == Material.PLAYER_HEAD) {
itemBuilder = SkullBuilder.create();
if (texture != null) {
((SkullBuilder) itemBuilder).texture(texture);
} else if (owner != null) {
final OfflinePlayer player = Bukkit.getOfflinePlayer(owner);
((SkullBuilder) itemBuilder).owner(player);
}
} else if (ColorBuilder.canBeColored(itemStack)) {
itemBuilder = ColorBuilder.from(itemStack);
if (color != null) {
((ColorBuilder) itemBuilder).color(color);
}
} else {
itemBuilder = ItemBuilder.from(itemStack);
}
if (itemStack.getItemMeta() != null && !itemStack.getItemMeta().hasCustomModelData()) {
itemBuilder.modelData(modelData);
}
if (!lore.isEmpty()) itemBuilder.lore(lore);
if (!name.isBlank()) itemBuilder.name(name);
itemStack = itemBuilder.
amount(amount).
unbreakable(unbreakable).
glow(glowing).
enchants(enchantments, true).
itemFlags(itemFlags).
build();
Keys.setKey(itemStack);
return itemStack;
}
@Override
public void serialize(final Type type, @Nullable final ItemStack obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -1,46 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class LocationSerializer implements TypeSerializer<Location> {
public static final LocationSerializer INSTANCE = new LocationSerializer();
private static final String WORLD = "world";
private static final String X = "x";
private static final String Y = "y";
private static final String Z = "z";
private static final String PITCH = "pitch";
private static final String YAW = "yaw";
private LocationSerializer() {}
@Override
@Nullable
public Location deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
final World world = Bukkit.getWorld(source.node(WORLD).getString());
if (world == null) return null;
return new Location(
world,
source.node(X).getDouble(),
source.node(Y).getDouble(),
source.node(Z).getDouble(),
source.node(YAW).getFloat(),
source.node(PITCH).getFloat()
);
}
@Override
public void serialize(final Type type, @Nullable final Location obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -1,31 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
public class Settings {
private final HMCCosmetics plugin;
private final CosmeticSettings cosmeticSettings;
private final WardrobeSettings wardrobeSettings;
public Settings(final HMCCosmetics plugin) {
this.plugin = plugin;
this.cosmeticSettings = new CosmeticSettings();
this.wardrobeSettings = new WardrobeSettings(this.plugin);
}
public void load() {
this.plugin.saveDefaultConfig();
this.plugin.reloadConfig();
this.cosmeticSettings.load(this.plugin.getConfig());
this.wardrobeSettings.load();
}
public CosmeticSettings getCosmeticSettings() {
return cosmeticSettings;
}
public WardrobeSettings getWardrobeSettings() {
return wardrobeSettings;
}
}

View File

@@ -1,61 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.MinecraftKey;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import org.bukkit.entity.Player;
public class SoundData {
private final String name;
private final EnumWrappers.SoundCategory soundCategory;
private final float volume;
private final float pitch;
public SoundData(final String name, final EnumWrappers.SoundCategory soundCategory, final float volume, final float pitch) {
this.name = name;
this.soundCategory = soundCategory;
this.volume = volume;
this.pitch = pitch;
}
public String getName() {
return name;
}
public float getVolume() {
return volume;
}
public float getPitch() {
return pitch;
}
public EnumWrappers.SoundCategory getSoundCategory() {
return soundCategory;
}
public void play(final Player player) {
final PacketContainer soundPacket = PacketManager.getSoundPacket(
player,
player.getLocation(),
this.getKey(this.name),
this.volume,
this.pitch,
this.soundCategory
);
PacketManager.sendPacket(player, soundPacket);
}
private MinecraftKey getKey(final String string) {
if (!string.contains(":")) {
return new MinecraftKey(string);
}
final String[] parts = string.split(":");
return new MinecraftKey(parts[0], parts[1]);
}
}

View File

@@ -1,53 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import com.comphenix.protocol.wrappers.EnumWrappers;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class SoundSerializer implements TypeSerializer<SoundData> {
public static final SoundSerializer INSTANCE = new SoundSerializer();
private SoundSerializer() {}
private static final String SOUND_NAME = "name";
private static final String SOUND_VOLUME = "volume";
private static final String SOUND_PITCH = "pitch";
private static final String SOUND_CATEGORY = "category";
@Override
public SoundData deserialize(final Type type, final ConfigurationNode node) throws SerializationException {
final ConfigurationNode soundNameNode = node.node(SOUND_NAME);
final ConfigurationNode volumeNode = node.node(SOUND_VOLUME);
final ConfigurationNode pitchNode = node.node(SOUND_PITCH);
final ConfigurationNode categoryNode = node.node(SOUND_CATEGORY);
final SoundData soundData;
final String soundName = soundNameNode.getString();
final String category = categoryNode.getString();
final int volume = volumeNode.getInt();
final int pitch = pitchNode.getInt();
if (soundName == null || category == null) {
soundData = null;
} else {
soundData = new SoundData(
soundName,
EnumWrappers.SoundCategory.valueOf(category),
volume,
pitch
);
}
return soundData;
}
@Override
public void serialize(final Type type, @Nullable final SoundData obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -1,37 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.gui.TokenGui;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type;
public class TokenGuiSerializer implements TypeSerializer<TokenGui> {
public static final TokenGuiSerializer INSTANCE = new TokenGuiSerializer();
private static final String TOKEN_SLOT = "token-slot";
private static final String COSMETIC_SLOT = "cosmetic-slot";
private TokenGuiSerializer() {}
@Override
public TokenGui deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
final CosmeticGui cosmeticGui = GuiSerializer.INSTANCE.deserialize(CosmeticGui.class, source);
final ConfigurationNode tokenSlotNode = source.node(TOKEN_SLOT);
final ConfigurationNode cosmeticSlotNode = source.node(COSMETIC_SLOT);
return new TokenGui(
cosmeticGui,
tokenSlotNode.getInt(),
cosmeticSlotNode.getInt()
);
}
@Override
public void serialize(final Type type, @Nullable final TokenGui obj, final ConfigurationNode node) throws SerializationException {
}
}

View File

@@ -1,59 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.Token;
import org.bukkit.inventory.ItemStack;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.nio.file.Path;
import java.util.List;
public class TokenLoader {
private static final String FILE_NAME = "tokens.yml";
private static final String TOKEN_PATH = "tokens";
private static final String ID_PATH = "id";
private static final String COMMANDS_PATH = "commands";
private final HMCCosmetics plugin;
private final CosmeticManager cosmeticManager;
public TokenLoader(final HMCCosmetics plugin) {
this.plugin = plugin;
this.cosmeticManager = this.plugin.getCosmeticManager();
}
public void load() {
final Path path = Path.of(this.plugin.getDataFolder().getPath(), FILE_NAME);
final File file = path.toFile();
if (!file.exists()) {
this.plugin.saveResource(FILE_NAME, false);
}
final YamlConfigurationLoader loader = YamlConfigurationLoader.
builder().
defaultOptions(opts -> opts.serializers(build -> build.register(ItemStack.class, ItemSerializer.INSTANCE))).
path(path).
build();
try {
final ConfigurationNode source = loader.load().node(TOKEN_PATH);
for (final var entry : source.childrenMap().entrySet()) {
final var node = entry.getValue();
final String id = node.node(ID_PATH).getString();
final ItemStack itemStack = node.get(ItemStack.class);
final ArmorItem armorItem = this.cosmeticManager.getArmorItem(id);
if (armorItem == null) {
this.plugin.getLogger().severe("Could not find armor item for token: " + id + " with id: " + id);
continue;
}
final List<String> commands = node.node(COMMANDS_PATH).getList(String.class);
this.cosmeticManager.addToken(new Token(itemStack, armorItem, commands));
}
} catch (final ConfigurateException exception) {
this.plugin.getLogger().severe("Error loading tokens!");
}
}
}

View File

@@ -1,165 +0,0 @@
package io.github.fisher2911.hmccosmetics.config;
import com.comphenix.protocol.events.PacketListener;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.gui.DyeSelectorGui;
import io.github.fisher2911.hmccosmetics.gui.WrappedGuiItem;
import io.github.fisher2911.hmccosmetics.util.Utils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
import java.io.File;
import java.nio.file.Path;
public class WardrobeSettings {
private static final String WARDROBE_PATH = "wardrobe";
private static final String DISABLE_ON_DAMAGE_PATH = "disable-on-damage";
private static final String DISPLAY_RADIUS_PATH = "display-radius";
private static final String PORTABLE_PATH = "portable";
private static final String ALWAYS_DISPLAY_PATH = "always-display";
private static final String STATIC_RADIUS_PATH = "static-radius";
private static final String ROTATION_SPEED_PATH = "rotation-speed";
private static final String SPAWN_DELAY_PATH = "spawn-delay";
private static final String DESPAWN_DELAY_PATH = "despawn-delay";
private static final String APPLY_COSMETICS_ON_CLOSE = "apply-cosmetics-on-close";
private static final String OPEN_SOUND = "open-sound";
private static final String CLOSE_SOUND = "close-sound";
private static final String STATIC_LOCATION_PATH = "wardrobe-location";
private static final String VIEWER_LOCATION_PATH = "viewer-location";
private static final String LEAVE_LOCATION_PATH = "leave-location";
private final HMCCosmetics plugin;
private boolean disableOnDamage;
private int displayRadius;
private boolean portable;
private boolean alwaysDisplay;
private int staticRadius;
private int rotationSpeed;
private int spawnDelay;
private int despawnDelay;
private boolean applyCosmeticsOnClose;
private SoundData openSound;
private SoundData closeSound;
private Location wardrobeLocation;
private Location viewerLocation;
private Location leaveLocation;
public WardrobeSettings(final HMCCosmetics plugin) {
this.plugin = plugin;
}
public void load() {
final File file = Path.of(this.plugin.getDataFolder().getPath(), "config.yml").toFile();
final YamlConfigurationLoader loader = YamlConfigurationLoader.
builder().
path(file.toPath()).
defaultOptions(opts ->
opts.serializers(build -> {
build.register(SoundData.class, SoundSerializer.INSTANCE);
build.register(Location.class, LocationSerializer.INSTANCE);
}))
.build();
try {
final var source = loader.load().node(WARDROBE_PATH);
this.disableOnDamage = source.node(DISABLE_ON_DAMAGE_PATH).getBoolean();
this.displayRadius = source.node(DISPLAY_RADIUS_PATH).getInt();
this.portable = source.node(PORTABLE_PATH).getBoolean();
this.staticRadius = source.node(STATIC_RADIUS_PATH).getInt();
this.alwaysDisplay = source.node(ALWAYS_DISPLAY_PATH).getBoolean();
this.rotationSpeed = source.node(ROTATION_SPEED_PATH).getInt();
this.spawnDelay = source.node(SPAWN_DELAY_PATH).getInt();
this.despawnDelay = source.node(DESPAWN_DELAY_PATH).getInt();
this.applyCosmeticsOnClose = source.node(APPLY_COSMETICS_ON_CLOSE).getBoolean();
this.openSound = source.node(OPEN_SOUND).get(SoundData.class);
this.closeSound = source.node(CLOSE_SOUND).get(SoundData.class);
this.wardrobeLocation = source.node(STATIC_LOCATION_PATH).get(Location.class);
this.viewerLocation = source.node(VIEWER_LOCATION_PATH).get(Location.class);
this.leaveLocation = Utils.replaceIfNull(source.node(LEAVE_LOCATION_PATH).get(Location.class), this.viewerLocation);
} catch (final ConfigurateException exception) {
this.plugin.getLogger().severe("Error loading wardrobe settings");
}
}
public boolean getDisableOnDamage() {
return disableOnDamage;
}
public int getDisplayRadius() {
return displayRadius;
}
public boolean isPortable() {
return portable;
}
public boolean isAlwaysDisplay() {
return alwaysDisplay;
}
public int getStaticRadius() {
return staticRadius;
}
public int getRotationSpeed() {
return rotationSpeed;
}
public int getSpawnDelay() {
return spawnDelay;
}
public int getDespawnDelay() {
return despawnDelay;
}
public boolean isApplyCosmeticsOnClose() {
return applyCosmeticsOnClose;
}
public Location getWardrobeLocation() {
return this.wardrobeLocation.clone();
}
public Location getViewerLocation() {
return viewerLocation;
}
public Location getLeaveLocation() {
return leaveLocation;
}
public void playOpenSound(final Player player) {
if (this.openSound == null) return;
this.openSound.play(player);
}
public void playCloseSound(final Player player) {
if (this.closeSound == null) return;
this.closeSound.play(player);
}
public boolean inDistanceOfWardrobe(final Location wardrobeLocation, final Location playerLocation) {
if (this.displayRadius == -1) return true;
if (!wardrobeLocation.getWorld().equals(playerLocation.getWorld())) return false;
return playerLocation.distanceSquared(wardrobeLocation) <= this.displayRadius * this.displayRadius;
}
public boolean inDistanceOfStatic(final Location location) {
if (this.wardrobeLocation == null) return false;
if (this.staticRadius == -1) return false;
if (!this.wardrobeLocation.getWorld().equals(location.getWorld())) return false;
return this.wardrobeLocation.distanceSquared(location) <= this.staticRadius * this.staticRadius;
}
}

View File

@@ -1,71 +0,0 @@
package io.github.fisher2911.hmccosmetics.cosmetic;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.Token;
import io.github.fisher2911.hmccosmetics.util.Keys;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Map;
public class CosmeticManager {
private final Map<String, Token> tokenMap;
private final Map<String, ArmorItem> armorItemMap;
public CosmeticManager(final Map<String, Token> tokenMap, final Map<String, ArmorItem> armorItemMap) {
this.tokenMap = tokenMap;
this.armorItemMap = armorItemMap;
}
@Nullable
public ArmorItem getArmorItem(final String id) {
return this.armorItemMap.get(id);
}
public void addArmorItem(final ArmorItem armorItem) {
this.armorItemMap.put(armorItem.getId(), armorItem);
}
public Collection<ArmorItem> getAllArmorItems() {
return this.armorItemMap.values();
}
public Map<String, ArmorItem> getArmorItemMap() {
return armorItemMap;
}
@Nullable
public Token getToken(final String id) {
return this.tokenMap.get(id);
}
public void addToken(final Token token) {
this.tokenMap.put(token.getId(), token);
}
public Collection<Token> getAllTokens() {
return this.tokenMap.values();
}
public Map<String, Token> getTokenMap() {
return this.tokenMap;
}
@Nullable
public Token getToken(final ItemStack itemStack) {
final String id = Keys.getValue(itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING);
if (id == null) return null;
return this.tokenMap.get(id);
}
public boolean isToken(final ItemStack itemStack) {
return Keys.hasKey(itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING);
}
public void clearTokens() {
this.tokenMap.clear();
}
}

View File

@@ -6,9 +6,9 @@ import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.concurrent.Threads;
import io.github.fisher2911.hmccosmetics.database.dao.ArmorItemDAO;
import io.github.fisher2911.hmccosmetics.database.dao.CitizenDAO;
import io.github.fisher2911.hmccosmetics.database.dao.UserDAO;
import io.github.fisher2911.hmccosmetics.dao.ArmorItemDAO;
import io.github.fisher2911.hmccosmetics.dao.CitizenDAO;
import io.github.fisher2911.hmccosmetics.dao.UserDAO;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.user.EntityIds;
@@ -20,11 +20,8 @@ import org.bukkit.entity.Entity;
import java.sql.SQLException;
import java.util.List;
import java.util.Random;
import java.util.SplittableRandom;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public class Database {

View File

@@ -1,122 +0,0 @@
package io.github.fisher2911.hmccosmetics.database.dao;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import java.util.Objects;
import org.jetbrains.annotations.Nullable;
@DatabaseTable(tableName = "armor_items")
public class ArmorItemDAO {
@DatabaseField(columnName = "uuid", useGetSet = true, uniqueCombo = true)
private String uuid;
@DatabaseField
private String id;
@DatabaseField(id = true, useGetSet = true, columnName = "artificial_id")
private String artificialId;
@DatabaseField(uniqueCombo = true)
private String type;
@DatabaseField(columnName = "color")
private int rgbDye;
public ArmorItemDAO(final String id, final String type, final int rgbDye) {
this.id = id;
this.artificialId = this.getArtificialId();
this.type = type;
this.rgbDye = rgbDye;
}
public ArmorItemDAO() {
}
public static ArmorItemDAO fromArmorItem(final ArmorItem armorItem) {
return new ArmorItemDAO(armorItem.getId(), armorItem.getType().toString(), armorItem.getDye());
}
@Nullable
public ArmorItem toArmorItem(final CosmeticManager cosmeticManager) {
final ArmorItem armorItem = cosmeticManager.getArmorItem(this.id);
if (armorItem == null) {
return null;
}
final ArmorItem copy = armorItem.copy();
copy.setDye(this.rgbDye);
return copy;
}
public String getUuid() {
return uuid;
}
public void setUuid(final String uuid) {
this.uuid = uuid;
}
/**
* ORMLite does not allow more than one primary key (WHYYYY???????????)
*
* @return
*/
public String getArtificialId() {
return this.uuid + "-" + this.type;
}
public void setArtificialId(final String artificialId) {
this.artificialId = artificialId;
}
public void setId(final String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(final String type) {
this.type = type;
}
public int getRgbDye() {
return rgbDye;
}
public void setRgbDye(final int rgbDye) {
this.rgbDye = rgbDye;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final ArmorItemDAO that = (ArmorItemDAO) o;
return Objects.equals(getUuid(), that.getUuid()) && Objects.equals(getType(),
that.getType());
}
@Override
public int hashCode() {
return Objects.hash(getUuid(), getType());
}
@Override
public String toString() {
return "ArmorItemDAO{" +
"uuid='" + uuid + '\'' +
", id='" + id + '\'' +
", type='" + type + '\'' +
", rgbDye=" + rgbDye +
'}';
}
}

View File

@@ -1,63 +0,0 @@
package io.github.fisher2911.hmccosmetics.database.dao;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
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.EntityIds;
import io.github.fisher2911.hmccosmetics.user.NPCUser;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
@DatabaseTable(tableName = "citizen")
public class CitizenDAO {
@DatabaseField(id = true)
private int citizensId;
public CitizenDAO() {
}
public CitizenDAO(final int citizensId) {
this.citizensId = citizensId;
}
public void setCitizensId(final int citizensId) {
this.citizensId = citizensId;
}
@Nullable
public NPCUser toUser(
final CosmeticManager cosmeticManager,
final EntityIds entityIds,
final List<ArmorItemDAO> armorItems
) {
final PlayerArmor playerArmor = PlayerArmor.empty();
for (final ArmorItemDAO armorItemDao : armorItems) {
final ArmorItem armorItem = armorItemDao.toArmorItem(cosmeticManager);
if (armorItem == null) {
continue;
}
playerArmor.setItem(armorItem);
}
return new NPCUser(this.citizensId, playerArmor, entityIds);
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final CitizenDAO that = (CitizenDAO) o;
return citizensId == that.citizensId;
}
@Override
public int hashCode() {
return Objects.hash(citizensId);
}
}

View File

@@ -1,78 +0,0 @@
package io.github.fisher2911.hmccosmetics.database.dao;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
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.EntityIds;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
@DatabaseTable(tableName = "user")
public class UserDAO {
@DatabaseField(id = true)
private UUID uuid;
public UserDAO() {
}
public UserDAO(final UUID uuid) {
this.uuid = uuid;
}
public void setUuid(final UUID uuid) {
this.uuid = uuid;
}
@Nullable
public User toUser(
final CosmeticManager cosmeticManager,
final EntityIds entityIds,
final List<ArmorItemDAO> armorItems,
final Wardrobe wardrobe
) {
final PlayerArmor playerArmor = PlayerArmor.empty();
for (final ArmorItemDAO armorItemDao : armorItems) {
final ArmorItem armorItem = armorItemDao.toArmorItem(cosmeticManager);
if (armorItem == null) {
continue;
}
playerArmor.setItem(armorItem);
}
return new User(this.uuid, playerArmor, wardrobe, entityIds);
}
@Override
public String toString() {
return "UserDAO{" +
"uuid=" + uuid +
'}';
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final UserDAO userDAO = (UserDAO) o;
return Objects.equals(uuid, userDAO.uuid);
}
@Override
public int hashCode() {
return Objects.hash(uuid);
}
}

View File

@@ -1,13 +1,8 @@
package io.github.fisher2911.hmccosmetics.gui;
import com.comphenix.protocol.wrappers.EnumWrappers;
import dev.triumphteam.gui.components.GuiAction;
import io.github.fisher2911.hmccosmetics.config.CosmeticGuiAction;
import io.github.fisher2911.hmccosmetics.util.builder.ColorBuilder;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
@@ -16,6 +11,9 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class ArmorItem extends WrappedGuiItem {
private final String name;
@@ -338,13 +336,13 @@ public class ArmorItem extends WrappedGuiItem {
}
@Nullable
public static Type fromWrapper(EnumWrappers.ItemSlot slot) {
public static Type fromWrapper(EquipmentSlot slot) {
return switch (slot) {
case HEAD -> Type.HAT;
case CHEST -> Type.CHEST_PLATE;
case LEGS -> Type.PANTS;
case FEET -> Type.BOOTS;
case OFFHAND -> Type.OFF_HAND;
case OFF_HAND -> Type.OFF_HAND;
default -> null;
};
}

View File

@@ -1,34 +1,14 @@
package io.github.fisher2911.hmccosmetics.listener;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.user.Equipment;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.bukkit.BanList;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
public class ClickListener implements Listener {
@@ -77,86 +57,86 @@ public class ClickListener implements Listener {
this.userManager = this.plugin.getUserManager();
}
@EventHandler
public void onArmorSlotClick(final InventoryClickEvent event) {
final int slot = event.getSlot();
if (!(event.getWhoClicked() instanceof final Player player)) return;
if (slot >= 36 && slot <= 40) {
this.fixInventory(player);
}
}
@EventHandler
public void onBlockClick(final PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
final Player player = event.getPlayer();
final Block block = event.getClickedBlock();
if (block != null && block.getType().isInteractable() && !player.isSneaking()) return;
final ItemStack clickedWith = event.getItem();
if (clickedWith == null) return;
this.checkFix(player, -1, clickedWith);
}
@EventHandler
public void onShiftClick(final InventoryClickEvent event) {
if (event.getClick() != ClickType.SHIFT_LEFT &&
event.getClick() != ClickType.SHIFT_RIGHT) return;
if (!(event.getWhoClicked() instanceof final Player player)) return;
final ItemStack clicked = event.getCurrentItem();
if (clicked == null) return;
this.checkFix(player, -1, clicked);
}
@EventHandler
public void onCosmeticClick(final InventoryDragEvent event) {
final HumanEntity player = event.getWhoClicked();
if (!(player instanceof Player)) {
return;
}
// this.fixInventory((Player) player);
}
@EventHandler
public void onInventoryClose(final InventoryCloseEvent event) {
final HumanEntity player = event.getPlayer();
this.userManager.get(player.getUniqueId()).ifPresent(this::doRunnable);
}
private void fixInventory(final Player player) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) {
return;
}
this.doRunnable(optionalUser.get());
}
private void doRunnable(final User user) {
Bukkit.getScheduler().runTaskLaterAsynchronously(
this.plugin, () -> this.userManager.updateCosmetics(user),
1);
}
private void checkFix(final Player player, final int clickedSlot, final ItemStack itemStack) {
final EquipmentSlot slot = this.getArmorSlot(itemStack.getType());
if (slot == null) return;
final ItemStack wearing = player.getEquipment().getItem(slot);
if (wearing == null) return;
if (wearing.getType() == Material.AIR || (clickedSlot >= 39 && clickedSlot <= 40)) {
this.fixInventory(player);
}
}
@Nullable
private EquipmentSlot getArmorSlot(final Material material) {
for (final EquipmentSlot slot : EquipmentSlot.values()) {
final Set<Material> armorItems = ARMOR_ITEMS.get(slot);
if (armorItems == null) continue;
if (material == null) continue;
if (armorItems.contains(material)) return slot;
}
return null;
}
// @EventHandler
// public void onArmorSlotClick(final InventoryClickEvent event) {
// final int slot = event.getSlot();
// if (!(event.getWhoClicked() instanceof final Player player)) return;
// if (slot >= 36 && slot <= 40) {
// this.fixInventory(player);
// }
// }
//
// @EventHandler
// public void onBlockClick(final PlayerInteractEvent event) {
// if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
// final Player player = event.getPlayer();
// final Block block = event.getClickedBlock();
// if (block != null && block.getType().isInteractable() && !player.isSneaking()) return;
// final ItemStack clickedWith = event.getItem();
// if (clickedWith == null) return;
// this.checkFix(player, -1, clickedWith);
// }
//
// @EventHandler
// public void onShiftClick(final InventoryClickEvent event) {
// if (event.getClick() != ClickType.SHIFT_LEFT &&
// event.getClick() != ClickType.SHIFT_RIGHT) return;
// if (!(event.getWhoClicked() instanceof final Player player)) return;
// final ItemStack clicked = event.getCurrentItem();
// if (clicked == null) return;
// this.checkFix(player, -1, clicked);
// }
//
// @EventHandler
// public void onCosmeticClick(final InventoryDragEvent event) {
// final HumanEntity player = event.getWhoClicked();
// if (!(player instanceof Player)) {
// return;
// }
//// this.fixInventory((Player) player);
// }
//
// @EventHandler
// public void onInventoryClose(final InventoryCloseEvent event) {
// final HumanEntity player = event.getPlayer();
// this.userManager.get(player.getUniqueId()).ifPresent(this::doRunnable);
// }
//
// private void fixInventory(final Player player) {
// final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
//
// if (optionalUser.isEmpty()) {
// return;
// }
//
// this.doRunnable(optionalUser.get());
// }
//
// private void doRunnable(final User user) {
// Bukkit.getScheduler().runTaskLaterAsynchronously(
// this.plugin, () -> this.userManager.updateCosmetics(user),
// 1);
// }
//
// private void checkFix(final Player player, final int clickedSlot, final ItemStack itemStack) {
// final EquipmentSlot slot = this.getArmorSlot(itemStack.getType());
// if (slot == null) return;
// final ItemStack wearing = player.getEquipment().getItem(slot);
// if (wearing == null) return;
// if (wearing.getType() == Material.AIR || (clickedSlot >= 39 && clickedSlot <= 40)) {
// this.fixInventory(player);
// }
// }
//
// @Nullable
// private EquipmentSlot getArmorSlot(final Material material) {
// for (final EquipmentSlot slot : EquipmentSlot.values()) {
// final Set<Material> armorItems = ARMOR_ITEMS.get(slot);
// if (armorItems == null) continue;
// if (material == null) continue;
// if (armorItems.contains(material)) return slot;
// }
// return null;
// }
}

View File

@@ -1,46 +1,346 @@
package io.github.fisher2911.hmccosmetics.listener;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientClickWindow;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerWindowItems;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.message.Translation;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import io.github.fisher2911.hmccosmetics.task.DelayedTask;
import io.github.fisher2911.hmccosmetics.task.TaskManager;
import io.github.fisher2911.hmccosmetics.user.Equipment;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import io.github.fisher2911.hmccosmetics.util.Utils;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import io.github.retrooper.packetevents.util.SpigotDataHelper;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.spigotmc.event.entity.EntityMountEvent;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class CosmeticFixListener implements Listener {
private final HMCCosmetics plugin;
private final UserManager userManager;
private final CosmeticSettings settings;
private final TaskManager taskManager;
public CosmeticFixListener(final HMCCosmetics plugin) {
this.plugin = plugin;
this.userManager = this.plugin.getUserManager();
this.settings = this.plugin.getSettings().getCosmeticSettings();
this.taskManager = this.plugin.getTaskManager();
this.registerPacketListeners();
}
final Map<EquipmentSlot, Set<Material>> ARMOR_ITEMS = Map.of(
EquipmentSlot.HEAD, EnumSet.of(
Material.LEATHER_HELMET,
Material.CHAINMAIL_HELMET,
Material.IRON_HELMET,
Material.GOLDEN_HELMET,
Material.DIAMOND_HELMET,
Material.NETHERITE_HELMET,
Material.TURTLE_HELMET
),
EquipmentSlot.CHEST, EnumSet.of(
Material.LEATHER_CHESTPLATE,
Material.CHAINMAIL_CHESTPLATE,
Material.IRON_CHESTPLATE,
Material.GOLDEN_CHESTPLATE,
Material.DIAMOND_CHESTPLATE,
Material.NETHERITE_CHESTPLATE,
Material.ELYTRA
),
EquipmentSlot.LEGS, EnumSet.of(
Material.LEATHER_LEGGINGS,
Material.CHAINMAIL_LEGGINGS,
Material.IRON_LEGGINGS,
Material.GOLDEN_LEGGINGS,
Material.DIAMOND_LEGGINGS,
Material.NETHERITE_LEGGINGS
),
EquipmentSlot.FEET, EnumSet.of(
Material.LEATHER_BOOTS,
Material.CHAINMAIL_BOOTS,
Material.IRON_BOOTS,
Material.GOLDEN_BOOTS,
Material.DIAMOND_BOOTS,
Material.NETHERITE_BOOTS
)
);
public void registerPacketListeners() {
this.registerMenuChangeListener();
this.registerInventoryClickListener();
}
private void registerClickAirListener() {
// PacketEvents.getAPI().getEventManager().registerListener(
// new PacketListener() {
// @Override
// public void onPacketReceive(PacketReceiveEvent event) {
//
// }
// }.asAbstract(PacketListenerPriority.HIGHEST, false, true)
// );
// ProtocolLibrary.getProtocolManager().addPacketListener(
// new PacketAdapter(this.plugin, ListenerPriority.MONITOR, PacketType.Play.Client.BLOCK_PLACE) {
// @Override
// public void onPacketReceiving(PacketEvent event) {
// final Player player = event.getPlayer();
// final Optional<User> optionalUser = CosmeticFixListener.this.userManager.get(player.getUniqueId());
// if (optionalUser.isEmpty()) return;
// final ItemStack inHand = player.getInventory().getItemInMainHand();
// if (inHand == null || inHand.getType() == Material.AIR) return;
// final EquipmentSlot slot = getArmorSlot(inHand.getType());
// if (slot == null) {
// return;
// }
// final ArmorItem.Type type = ArmorItem.Type.fromEquipmentSlot(slot);
// if (type == null) {
// return;
// }
// final User user = optionalUser.get();
// final Location location = player.getLocation();
// taskManager.submit(() -> {
// final EntityEquipment entityEquipment = player.getEquipment();
// final Equipment equipment;
// if (entityEquipment == null) {
// equipment = Equipment.fromEntityEquipment(player.getEquipment());
// } else {
// equipment = new Equipment();
// }
// equipment.setItem(
// slot,
// getCosmeticItem(
// user.getPlayerArmor().getItem(type),
// inHand,
// ArmorItem.Status.APPLIED,
// slot
// )
// );
// final List<Pair<EnumWrappers.ItemSlot, ItemStack>> items = getItemList(player, user, equipment, Set.of(type));
// for (final Player p : Bukkit.getOnlinePlayers()) {
// if (!settings.isInViewDistance(location, p.getLocation())) continue;
// sendUpdatePacket(
// user.getEntityId(),
// p,
// items
// );
// }
// });
// }
// }
// );
}
@EventHandler
public void onEntityMount(final EntityMountEvent event) {
if (!(event.getEntity() instanceof final Player player)) {
return;
public void onShiftClick(final InventoryClickEvent event) {
if (event.getClick() != ClickType.SHIFT_LEFT && event.getClick() != ClickType.SHIFT_RIGHT) return;
if (!(event.getWhoClicked() instanceof final Player player)) return;
final int clickedSlot = event.getSlot();
final ItemStack clicked = event.getCurrentItem();
if (clicked == null) return;
final EquipmentSlot slot = this.getArmorSlot(clicked.getType());
if (slot == null) return;
final Optional<User> user = this.userManager.get(player.getUniqueId());
if (user.isEmpty()) return;
final ArmorItem.Type type = ArmorItem.Type.fromWrapper(slot);
if (type == null) return;
final EntityEquipment equipment = player.getEquipment();
final ItemStack current;
if (equipment == null) {
current = new ItemStack(Material.AIR);
} else {
current = equipment.getItem(slot);
}
this.fixCosmetics(player);
updateOnClick(
player,
slot,
user.get(),
type,
current
);
}
@EventHandler
private void registerInventoryClickListener() {
PacketEvents.getAPI().getEventManager().registerListener(
new PacketListenerAbstract() {
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() != PacketType.Play.Client.CLICK_WINDOW) return;
final WrapperPlayClientClickWindow packet = new WrapperPlayClientClickWindow(event);
if (packet.getWindowId() != 0) return;
if (!(event.getPlayer() instanceof final Player player)) return;
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
int slotClicked = packet.getSlot();
final WrapperPlayClientClickWindow.WindowClickType clickType = packet.getWindowClickType();
EquipmentSlot slot = getPacketArmorSlot(slotClicked);
if (slot == null) return;
final EntityEquipment entityEquipment = player.getEquipment();
if (entityEquipment == null) return;
final ItemStack current = Utils.replaceIfNull(entityEquipment.getItem(slot), new ItemStack(Material.AIR));
final ArmorItem.Type type = ArmorItem.Type.fromEquipmentSlot(slot);
if (type == null) return;
updateOnClick(
player,
slot,
user,
type,
current
);
}
}
);
}
private void updateOnClick(final Player player, final EquipmentSlot slot, final User user, final ArmorItem.Type type, final ItemStack current) {
taskManager.submit(() -> {
final Location location = player.getLocation();
final Equipment equipment = Equipment.fromEntityEquipment(player.getEquipment());
final ItemStack cosmetic = getCosmeticItem(
user.getPlayerArmor().getItem(type),
current,
ArmorItem.Status.APPLIED,
slot
);
if (cosmetic != null && cosmetic.getType() != Material.AIR) equipment.setItem(slot, cosmetic);
final List<com.github.retrooper.packetevents.protocol.player.Equipment> items =
getItemList(user, equipment, Set.of(type));
for (final Player other : Bukkit.getOnlinePlayers()) {
if (!settings.isInViewDistance(location, other.getLocation())) continue;
sendUpdatePacket(
user.getEntityId(),
other,
items
);
}
});
}
private void registerMenuChangeListener() {
PacketEvents.getAPI().getEventManager().registerListener(
new PacketListenerAbstract() {
@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() != PacketType.Play.Server.WINDOW_ITEMS) return;
final WrapperPlayServerWindowItems packet = new WrapperPlayServerWindowItems(event);
if (!(event.getPlayer() instanceof final Player player)) return;
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
if (packet.getWindowId() != 0) return;
final List<com.github.retrooper.packetevents.protocol.item.ItemStack> itemStacks = packet.getItems();
final int size = itemStacks.size();
final PlayerArmor playerArmor = user.getPlayerArmor();
for (final ArmorItem armorItem : playerArmor.getArmorItems()) {
final ArmorItem.Type type = armorItem.getType();
final EquipmentSlot slot = type.getSlot();
if (slot == null) continue;
final int packetSlot = getPacketArmorSlot(slot);
if (packetSlot == -1) continue;
if (packetSlot >= size) continue;
final ItemStack current = SpigotDataHelper.toBukkitItemStack(itemStacks.get(packetSlot));
final com.github.retrooper.packetevents.protocol.item.ItemStack setTo =
SpigotDataHelper.fromBukkitItemStack(getCosmeticItem(
armorItem,
current,
ArmorItem.Status.APPLIED,
slot
));
itemStacks.set(packetSlot, setTo);
}
packet.setItems(itemStacks);
}
}
);
}
// @EventHandler
// public void onBlockClick(final PlayerInteractEvent event) {
// if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
// final Player player = event.getPlayer();
// final Block block = event.getClickedBlock();
// if (block != null && block.getType().isInteractable() && !player.isSneaking()) return;
// final ItemStack clickedWith = event.getItem();
// if (clickedWith == null) return;
// this.checkFix(player, -1, clickedWith);
// }
private int getPacketArmorSlot(final EquipmentSlot slot) {
return switch (slot) {
case HEAD -> 5;
case CHEST -> 6;
case LEGS -> 7;
case FEET -> 8;
case OFF_HAND -> 45;
default -> -1;
};
}
@Nullable
public EquipmentSlot getPacketArmorSlot(final int slot) {
return switch (slot) {
case 5 -> EquipmentSlot.HEAD;
case 6 -> EquipmentSlot.CHEST;
case 7 -> EquipmentSlot.LEGS;
case 8 -> EquipmentSlot.FEET;
case 45 -> EquipmentSlot.OFF_HAND;
default -> null;
};
}
// @EventHandler
// public void onEntityMount(final EntityMountEvent event) {
// if (!(event.getEntity() instanceof final Player player)) {
// return;
// }
// this.fixCosmetics(player);
// }
//
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onOffhandSwap(final PlayerSwapHandItemsEvent event) {
final ItemStack offHand = event.getOffHandItem();
if (offHand != null && offHand.getType() != Material.AIR) {
return;
}
this.fixCosmetics(event.getPlayer());
final Player player = event.getPlayer();
this.fixOffHand(player, new ItemStack(Material.AIR));
}
@EventHandler(ignoreCancelled = true)
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onBlockPlace(final BlockPlaceEvent event) {
if (event.getHand() != EquipmentSlot.OFF_HAND) {
return;
@@ -51,7 +351,60 @@ public class CosmeticFixListener implements Listener {
return;
}
this.fixCosmetics(event.getPlayer());
this.fixOffHand(event.getPlayer(), new ItemStack(Material.AIR));
}
private void fixOffHand(final Player player, final ItemStack current) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
final ArmorItem.Type type = ArmorItem.Type.OFF_HAND;
final ArmorItem armorItem = user.getPlayerArmor().getItem(type);
this.taskManager.submit(new DelayedTask(() -> this.sendUpdatePacket(
player.getEntityId(),
player,
armorItem,
current,
type
), 1));
}
private List<com.github.retrooper.packetevents.protocol.player.Equipment> getItemList(
final User user,
final Equipment equipment,
final Set<ArmorItem.Type> ignored
) {
final PlayerArmor armor = user.getPlayerArmor();
final List<com.github.retrooper.packetevents.protocol.player.Equipment> items = new ArrayList<>();
for (final ArmorItem.Type type : ArmorItem.Type.values()) {
final EquipmentSlot slot = type.getSlot();
if (slot == null) continue;
if (ignored.contains(type)) {
items.add(this.getEquipment(equipment.getItem(slot), slot));
continue;
}
final ItemStack wearing = Utils.replaceIfNull(equipment.getItem(slot), new ItemStack(Material.AIR));
final ItemStack itemStack = this.getCosmeticItem(
armor.getItem(type),
wearing,
ArmorItem.Status.APPLIED,
slot
);
if (itemStack.getType() != Material.AIR) items.add(this.getEquipment(itemStack, slot));
}
return items;
}
@Nullable
private EquipmentSlot getArmorSlot(final Material material) {
for (final EquipmentSlot slot : EquipmentSlot.values()) {
final Set<Material> armorItems = ARMOR_ITEMS.get(slot);
if (armorItems == null) continue;
if (material == null) continue;
if (armorItems.contains(material)) return slot;
}
return null;
}
private void fixCosmetics(final Player player) {
@@ -59,4 +412,67 @@ public class CosmeticFixListener implements Listener {
() -> this.userManager.updateCosmetics(player.getUniqueId()), 2);
}
private void sendUpdatePacket(
final int entityId,
final Player other,
final ArmorItem armorItem,
final ItemStack wearing,
final ArmorItem.Type type) {
final EquipmentSlot slot = type.getSlot();
final ItemStack itemStack = this.getCosmeticItem(armorItem, wearing, ArmorItem.Status.APPLIED, slot);
final List<com.github.retrooper.packetevents.protocol.player.Equipment> itemList = new ArrayList<>();
itemList.add(this.getEquipment(itemStack, slot));
this.sendUpdatePacket(entityId, other, itemList);
}
private void sendUpdatePacket(
final int entityId,
final Player other,
List<com.github.retrooper.packetevents.protocol.player.Equipment> items) {
PacketManager.sendEquipmentPacket(
items,
entityId,
other
);
}
private com.github.retrooper.packetevents.protocol.player.Equipment getEquipment(
final ItemStack itemStack,
final EquipmentSlot slot
) {
return new com.github.retrooper.packetevents.protocol.player.Equipment(
PacketManager.fromBukkitSlot(slot),
SpigotDataHelper.fromBukkitItemStack(itemStack)
);
}
private ItemStack getCosmeticItem(
final ArmorItem armorItem,
final ItemStack wearing,
final ArmorItem.Status status,
final EquipmentSlot slot
) {
final Map<String, String> placeholders = Map.of(Placeholder.ALLOWED, Translation.TRUE,
Placeholder.ENABLED, Translation.TRUE);
if (armorItem.isEmpty()) return wearing;
ItemStack itemStack = ItemBuilder.from(armorItem.getItemStack(status)).
namePlaceholders(placeholders).
lorePlaceholders(placeholders).
build();
if (wearing == null) return itemStack;
final boolean isAir = wearing.getType().isAir();
final boolean requireEmpty = settings.requireEmpty(slot);
if (!isAir && requireEmpty) {
return wearing;
}
return itemStack;
}
}

View File

@@ -1,252 +1,467 @@
package io.github.fisher2911.hmccosmetics.packet;
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.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.MinecraftKey;
import com.comphenix.protocol.wrappers.Pair;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import io.github.fisher2911.nms.PacketHelper;
import io.github.fisher2911.nms.PacketHelper_1_16_R3;
import io.github.fisher2911.nms.PacketHelper_1_17_R1;
import io.github.fisher2911.nms.PacketHelper_1_18_R1;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.player.Equipment;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerAttachEntity;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEquipment;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityHeadLook;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityRelativeMove;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityRotation;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityTeleport;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfo;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPassengers;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnLivingEntity;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnPlayer;
import io.github.retrooper.packetevents.util.SpigotDataHelper;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
public class PacketManager {
//
// private static final PacketHelper PACKET_HELPER;
//
// static {
// final String version = Bukkit.getVersion();
// if (version.contains("1.16")) {
// PACKET_HELPER = new PacketHelper_1_16_R3();
// } else if (version.contains("1.17")) {
// PACKET_HELPER = new PacketHelper_1_17_R1();
// } else if (version.contains("1.18")) {
// PACKET_HELPER = new PacketHelper_1_18_R1();
// } else {
// PACKET_HELPER = null;
// }
// }
private static final PacketHelper PACKET_HELPER;
public static void sendArmorStandMetaContainer(final int armorStandId, final Collection<? extends Player> sendTo) {
sendArmorStandMetaContainer(armorStandId, sendTo.toArray(new Player[0]));
}
static {
final String version = Bukkit.getVersion();
if (version.contains("1.16")) {
PACKET_HELPER = new PacketHelper_1_16_R3();
} else if (version.contains("1.17")) {
PACKET_HELPER = new PacketHelper_1_17_R1();
} else if (version.contains("1.18")) {
PACKET_HELPER = new PacketHelper_1_18_R1();
} else {
PACKET_HELPER = null;
public static void sendArmorStandMetaContainer(final int armorStandId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerEntityMetadata(
armorStandId,
List.of(
new EntityData(0, EntityDataTypes.BYTE, (byte) 0x20),
new EntityData(15, EntityDataTypes.BYTE, (byte) 0x10)
)
));
}
}
public static PacketContainer getArmorStandMetaContainer(final int armorStandId) {
if (PACKET_HELPER == null)
throw new IllegalStateException("This cannot be used in version: " + Bukkit.getVersion());
return PACKET_HELPER.getArmorStandMeta(armorStandId);
}
public static PacketContainer getEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType) {
return getEntitySpawnPacket(location, entityId, entityType, UUID.randomUUID());
}
public static PacketContainer getEntitySpawnPacket(
public static void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final UUID uuid) {
final PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
// Entity ID
packet.getIntegers().write(0, entityId);
// Entity Type
// packet.getIntegers().write(6, 78);
// Set location
packet.getDoubles().write(0, location.getX());
packet.getDoubles().write(1, location.getY());
packet.getDoubles().write(2, location.getZ());
// Set yaw pitch
packet.getIntegers().write(4, (int) location.getPitch());
packet.getIntegers().write(5, (int) location.getYaw());
// Set UUID
packet.getUUIDs().write(0, uuid);
packet.getEntityTypeModifier().write(0, entityType);
return packet;
final Collection<? extends Player> sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, sendTo.toArray(new Player[0]));
}
public static PacketContainer getInvisibilityPacket(final int entityId) {
final PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
packet.getIntegers().write(0, entityId);
WrappedDataWatcher metaData = new WrappedDataWatcher();
final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, byteSerializer), (byte) (0x20));
packet.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
return packet;
}
public static PacketContainer getTeleportPacket(final int entityId, final Location location) {
final PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
packet.getIntegers().write(0, entityId);
packet.getDoubles().write(0, location.getX()).write(1, location.getY()).write(2, location.getZ());
return packet;
}
public static PacketContainer getMovePacket(final int entityId, final Location from, final Location to) {
final PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE);
final short x = (short) ((to.getX() * 32 - from.getX() * 32) * 128);
final short y = (short) ((to.getY() * 32 - from.getY() * 32) * 128);
final short z = (short) ((to.getZ() * 32 - from.getZ() * 32) * 128);
packet.getIntegers().write(0, entityId);
packet.getShorts().write(0, x).write(1, y).write(2, y);
return packet;
}
public static PacketContainer getLeashPacket(final int balloonId, final int entityId) {
final PacketContainer packet = new PacketContainer(PacketType.Play.Server.ATTACH_ENTITY);
packet.getIntegers().write(0, balloonId).write(1, entityId);
return packet;
}
public static PacketContainer getEquipmentPacket(
final List<Pair<EnumWrappers.ItemSlot, ItemStack>> equipmentList,
final int entityId
) {
final PacketContainer armorPacket = new PacketContainer(
PacketType.Play.Server.ENTITY_EQUIPMENT);
armorPacket.getIntegers().write(0, entityId);
try {
armorPacket.getSlotStackPairLists().write(0, equipmentList);
// for some reason ProtocolLib throws an error the first time this is called
} catch (final NullPointerException ignored) {}
return armorPacket;
}
public static PacketContainer getRotationPacket(final int entityId, final Location location) {
final PacketContainer rotationPacket = new PacketContainer(
PacketType.Play.Server.ENTITY_HEAD_ROTATION);
rotationPacket.getIntegers().write(0, entityId);
rotationPacket.getBytes().write(0, (byte) (location.getYaw() * 256 / 360));
return rotationPacket;
}
public static PacketContainer getLookPacket(final int entityId, final Location location) {
final PacketContainer rotationPacket = new PacketContainer(
PacketType.Play.Server.ENTITY_LOOK);
rotationPacket.getIntegers().write(0, entityId);
rotationPacket.getBytes().write(0, (byte) (location.getYaw() * 256 / 360));
// rotationPacket.getBytes().write(1, (byte) (location.getPitch() * 256 / 360));
return rotationPacket;
}
public static PacketContainer getRidingPacket(final int mountId, final int passengerId) {
final PacketContainer ridingPacket = new PacketContainer(PacketType.Play.Server.MOUNT);
ridingPacket.
getIntegers().
write(0, mountId);
ridingPacket.getIntegerArrays().write(0, new int[]{passengerId});
return ridingPacket;
}
public static PacketContainer getEntityDestroyPacket(final int entityId) {
return PACKET_HELPER.getDestroyPacket(entityId);
}
public static PacketContainer getSoundPacket(
final Player player,
public static void sendEntitySpawnPacket(
final Location location,
final MinecraftKey name,
final float volume,
final float pitch,
final EnumWrappers.SoundCategory soundCategory
final int entityId,
final EntityType entityType,
final Player... sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, UUID.randomUUID());
}
public static void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final UUID uuid,
final Collection<? extends Player> sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, uuid, sendTo.toArray(new Player[0]));
}
public static void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final UUID uuid,
final Player... sendTo) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerSpawnLivingEntity(
entityId,
uuid,
entityType,
new Vector3d(location.getX(), location.getY(), location.getZ()),
location.getYaw(),
location.getPitch(),
0f,
Vector3d.zero(),
Collections.emptyList()
));
}
}
public static void sendInvisibilityPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendInvisibilityPacket(entityId, sendTo.toArray(new Player[0]));
}
public static void sendInvisibilityPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerEntityMetadata(
entityId,
List.of(new EntityData(0, EntityDataTypes.BYTE, (byte) 0x20))
));
}
}
public static void sendTeleportPacket(
final int entityId,
final Location location,
boolean onGround,
final Collection<? extends Player> sendTo
) {
final var manager = ProtocolLibrary.getProtocolManager();
final var packet = manager.createPacket(PacketType.Play.Server.CUSTOM_SOUND_EFFECT);
packet.getMinecraftKeys()
.write(
0,
name
);
packet.getSoundCategories()
.write(0, EnumWrappers.SoundCategory.valueOf(soundCategory.name()));
packet.getIntegers()
.write(0, location.getBlockX() * 8)
.write(
1, location.getBlockY() * 8
)
.write(2, location.getBlockZ() * 8);
packet.getFloat()
.write(0, volume)
.write(1, pitch);
return packet;
sendTeleportPacket(entityId, location, onGround, sendTo.toArray(new Player[0]));
}
public static PacketContainer getFakePlayerSpawnPacket(final Location location, final UUID uuid, final int entityId) throws IllegalStateException {
if (PACKET_HELPER == null)
throw new IllegalStateException("This cannot be used in version: " + Bukkit.getVersion());
return PACKET_HELPER.getPlayerSpawnPacket(location, uuid, entityId);
}
public static PacketContainer getFakePlayerInfoPacket(final Player player, final UUID uuid) throws IllegalStateException {
if (PACKET_HELPER == null)
throw new IllegalStateException("This cannot be used in version: " + Bukkit.getVersion());
return PACKET_HELPER.getPlayerInfoPacket(player, uuid);
}
public static PacketContainer getPlayerOverlayPacket(final int playerId) throws IllegalStateException {
if (PACKET_HELPER == null)
throw new IllegalStateException("This cannot be used in version: " + Bukkit.getVersion());
return PACKET_HELPER.getPlayerOverlayPacket(playerId);
}
public static PacketContainer getRemovePlayerPacket(final Player player, final UUID uuid, final int entityId) {
if (PACKET_HELPER == null)
throw new IllegalStateException("This cannot be used in version: " + Bukkit.getVersion());
return PACKET_HELPER.getPlayerRemovePacket(player, uuid, entityId);
}
public static PacketContainer getSpectatePacket(final int entityId) {
final PacketContainer packetContainer = new PacketContainer(PacketType.Play.Server.CAMERA);
packetContainer.getIntegers().write(0, entityId);
return packetContainer;
}
public static void sendPacket(final Player to, final PacketContainer... packets) {
final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
try {
for (final PacketContainer packet : packets) {
protocolManager.sendServerPacket(to, packet);
}
} catch (final InvocationTargetException exception) {
exception.printStackTrace();
public static void sendTeleportPacket(
final int entityId,
final Location location,
boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerEntityTeleport(
entityId,
new Vector3d(location.getX(), location.getY(), location.getZ()),
location.getYaw(),
location.getPitch(),
onGround
));
}
}
public static void sendPacketToOnline(final PacketContainer... packets) {
for (final Player player : Bukkit.getOnlinePlayers()) {
sendPacket(player, packets);
public static void sendMovePacket(
final int entityId,
final Location from,
final Location to,
final boolean onGround,
final Collection<? extends Player> sendTo
) {
sendMovePacket(entityId, from, to, onGround, sendTo.toArray(new Player[0]));
}
public static void sendMovePacket(
final int entityId,
final Location from,
final Location to,
final boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerEntityRelativeMove(
entityId,
to.getX() - from.getX(),
to.getY() - from.getY(),
to.getZ() - from.getZ(),
onGround
));
}
}
public static void sendLeashPacket(
final int balloonId,
final int entityId,
final Collection<? extends Player> sendTo
) {
sendLeashPacket(balloonId, entityId, sendTo.toArray(new Player[0]));
}
public static void sendLeashPacket(
final int balloonId,
final int entityId,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerAttachEntity(
balloonId,
entityId,
true
));
}
}
public static void sendEquipmentPacket(
final List<Equipment> equipmentList,
final int entityId,
final Collection<? extends Player> sendTo
) {
sendEquipmentPacket(equipmentList, entityId, sendTo.toArray(new Player[0]));
}
public static void sendEquipmentPacket(
final List<Equipment> equipmentList,
final int entityId,
final Player... sendTo
) {
for (final Equipment equipment : equipmentList) {
final ItemStack itemStack = SpigotDataHelper.toBukkitItemStack(equipment.getItem());
}
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerEntityEquipment(
entityId,
equipmentList
));
}
}
public static void sendRotationPacket(
final int entityId,
final Location location,
final boolean onGround,
final Collection<? extends Player> sendTo
) {
sendRotationPacket(entityId, location, onGround, sendTo.toArray(new Player[0]));
}
public static void sendRotationPacket(
final int entityId,
final Location location,
final boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerEntityRotation(
entityId,
location.getYaw(),
location.getPitch(),
onGround
));
}
}
public static void sendLookPacket(
final int entityId,
final Location location,
final Collection<? extends Player> sendTo
) {
sendLookPacket(entityId, location, sendTo.toArray(new Player[0]));
}
public static void sendLookPacket(
final int entityId,
final Location location,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerEntityHeadLook(
entityId,
location.getYaw()
));
}
}
public static void sendRidingPacket(
final int mountId,
final int passengerId,
final Collection<? extends Player> sendTo
) {
sendRidingPacket(mountId, passengerId, sendTo.toArray(new Player[0]));
}
public static void sendRidingPacket(
final int mountId,
final int passengerId,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerSetPassengers(
mountId,
new int[]{passengerId}
));
}
}
public static void sendEntityDestroyPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendEntityDestroyPacket(entityId, sendTo.toArray(new Player[0]));
}
public static void sendEntityDestroyPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerDestroyEntities(entityId));
}
}
// public static void sendSoundPacket(
// final Player player,
// final Location location,
// final MinecraftKey name,
// final float volume,
// final float pitch,
// final EnumWrappers.SoundCategory soundCategory,
// final Player...sendTo
// ) {
// final var packet = new WrapperPlayServerSoundEffect(
//
// );
// final var manager = ProtocolLibrary.getProtocolManager();
// final var packet = manager.createPacket(PacketType.Play.Server.CUSTOM_SOUND_EFFECT);
//
// packet.getMinecraftKeys()
// .write(
// 0,
// name
// );
//
// packet.getSoundCategories()
// .write(0, EnumWrappers.SoundCategory.valueOf(soundCategory.name()));
//
// packet.getIntegers()
// .write(0, location.getBlockX() * 8)
// .write(
// 1, location.getBlockY() * 8
// )
// .write(2, location.getBlockZ() * 8);
//
// packet.getFloat()
// .write(0, volume)
// .write(1, pitch);
//
// return packet;
// }
public static void sendFakePlayerSpawnPacket(
final Location location,
final UUID uuid,
final int entityId,
final Collection<? extends Player> sendTo
) {
sendFakePlayerSpawnPacket(location, uuid, entityId, sendTo.toArray(new Player[0]));
}
public static void sendFakePlayerSpawnPacket(
final Location location,
final UUID uuid,
final int entityId,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerSpawnPlayer(
entityId,
uuid,
new com.github.retrooper.packetevents.protocol.world.Location(
location.getX(),
location.getY(),
location.getZ(),
location.getYaw(),
location.getPitch()
)
));
}
}
public static void sendFakePlayerInfoPacket(
final Player player,
final UUID uuid,
final Collection<? extends Player> sendTo
) {
sendFakePlayerInfoPacket(player, uuid, sendTo.toArray(new Player[0]));
}
public static void sendFakePlayerInfoPacket(
final Player player,
final UUID uuid,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerPlayerInfo(
WrapperPlayServerPlayerInfo.Action.ADD_PLAYER,
new WrapperPlayServerPlayerInfo.PlayerData(
Component.empty(),
new UserProfile(
uuid,
player.getDisplayName()
),
com.github.retrooper.packetevents.protocol.player.GameMode.SURVIVAL,
0
)
));
}
}
public static void sendPlayerOverlayPacket(
final int playerId,
final Collection<? extends Player> sendTo
) {
sendPlayerOverlayPacket(playerId, sendTo.toArray(new Player[0]));
}
public static void sendPlayerOverlayPacket(
final int playerId,
final Player... sendTo
) {
final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerEntityMetadata(
playerId,
List.of(
new EntityData(17, EntityDataTypes.BYTE, mask),
new EntityData(15, EntityDataTypes.BYTE, (byte) 0x10)
)
));
}
}
public static void sendRemovePlayerPacket(
final Player player,
final UUID uuid,
final Collection<? extends Player> sendTo
) {
sendRemovePlayerPacket(player, uuid, sendTo.toArray(new Player[0]));
}
public static void sendRemovePlayerPacket(
final Player player,
final UUID uuid,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketEvents.getAPI().getPlayerManager().sendPacket(p, new WrapperPlayServerPlayerInfo(
WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER,
new WrapperPlayServerPlayerInfo.PlayerData(
Component.empty(),
new UserProfile(
uuid,
player.getDisplayName()
),
com.github.retrooper.packetevents.protocol.player.GameMode.SURVIVAL,
0
)
));
}
}
public static void sendSpectatePacket(final int entityId) {
}
public static EquipmentSlot fromBukkitSlot(final org.bukkit.inventory.EquipmentSlot slot) {
return switch (slot) {
case HEAD -> EquipmentSlot.HELMET;
case CHEST -> EquipmentSlot.CHESTPLATE;
case LEGS -> EquipmentSlot.LEGGINGS;
case FEET -> EquipmentSlot.BOOTS;
case HAND -> EquipmentSlot.MAINHAND;
case OFF_HAND -> EquipmentSlot.OFFHAND;
};
}
}

View File

@@ -33,6 +33,10 @@ public class TaskManager {
this.tasks.add(task);
}
public void submit(final Runnable runnable) {
this.submit(new ImmediateTask(runnable));
}
public void end() {
this.timer.cancel();
for (final Task task : this.tasks) {

View File

@@ -1,8 +1,9 @@
package io.github.fisher2911.hmccosmetics.user;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.Pair;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
@@ -12,19 +13,17 @@ import io.github.fisher2911.hmccosmetics.hook.ModelEngineHook;
import io.github.fisher2911.hmccosmetics.hook.entity.BalloonEntity;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import io.github.retrooper.packetevents.util.SpigotDataHelper;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
@@ -101,7 +100,7 @@ public abstract class BaseUser<T> {
final HookManager hookManager = HookManager.getInstance();
if (!hookManager.isEnabled(ModelEngineHook.class)) return;
this.balloon.remove();
PacketManager.sendPacketToOnline(PacketManager.getEntityDestroyPacket(this.getBalloonId()));
PacketManager.sendEntityDestroyPacket(this.getBalloonId(), Bukkit.getOnlinePlayers());
this.viewingBalloon.clear();
this.balloon.setAlive(false);
}
@@ -110,7 +109,7 @@ public abstract class BaseUser<T> {
final HookManager hookManager = HookManager.getInstance();
if (!hookManager.isEnabled(ModelEngineHook.class)) return;
this.balloon.removePlayerFromModel(other);
PacketManager.sendPacket(other, PacketManager.getEntityDestroyPacket(this.getBalloonId()));
PacketManager.sendEntityDestroyPacket(this.getBalloonId(), other);
this.viewingBalloon.remove(other.getUniqueId());
if (this.viewingBalloon.isEmpty()) {
this.despawnBalloon();
@@ -134,19 +133,10 @@ public abstract class BaseUser<T> {
this.balloon.addPlayerToModel(other, id);
}
this.updateBalloon(other, location, settings);
PacketManager.sendPacket(
other,
PacketManager.getEntitySpawnPacket(
actual,
this.getBalloonId(),
this.balloon.getType()
),
PacketManager.getInvisibilityPacket(this.getBalloonId()),
PacketManager.getLeashPacket(
this.getBalloonId(),
this.getEntityId()
)
);
final int balloonId = this.getBalloonId();
PacketManager.sendEntitySpawnPacket(actual, balloonId, EntityTypes.PUFFERFISH, other);
PacketManager.sendInvisibilityPacket(balloonId, other);
PacketManager.sendLeashPacket(balloonId, this.getEntityId(), other);
}
protected void updateBalloon(final Player other, final Location location, final CosmeticSettings settings) {
@@ -162,16 +152,13 @@ public abstract class BaseUser<T> {
this.balloon.setVelocity(actual.clone().subtract(previous.clone()).toVector());
// hookManager.getModelEngineHook().updateModel(this.balloon);
this.balloon.updateModel();
PacketManager.sendPacket(
other,
PacketManager.getTeleportPacket(this.getBalloonId(), actual),
PacketManager.getLeashPacket(this.getBalloonId(), this.getEntityId())
);
final int balloonId = this.getBalloonId();
PacketManager.sendTeleportPacket(balloonId, actual, false, other);
PacketManager.sendLeashPacket(balloonId, this.getEntityId(), other);
}
private void spawnArmorStand(final Player other, final Location location) {
final PacketContainer packet = PacketManager.getEntitySpawnPacket(location, this.getArmorStandId(), EntityType.ARMOR_STAND);
PacketManager.sendPacket(other, packet);
PacketManager.sendEntitySpawnPacket(location, this.getArmorStandId(), EntityTypes.ARMOR_STAND, other);
}
public void updateOutsideCosmetics(final Settings settings) {
@@ -183,7 +170,7 @@ public abstract class BaseUser<T> {
}
public void updateOutsideCosmetics(final Player other, final Location location, final Settings settings) {
final boolean inViewDistance = this.isInViewDistance(location, other.getLocation(), settings.getCosmeticSettings());
final boolean inViewDistance = settings.getCosmeticSettings().isInViewDistance(location, other.getLocation());
final boolean shouldShow = shouldShow(other);
final UUID otherUUID = other.getUniqueId();
final boolean hasBackpack = !this.playerArmor.getItem(ArmorItem.Type.BACKPACK).isEmpty();
@@ -212,40 +199,37 @@ public abstract class BaseUser<T> {
this.despawnBalloon(other);
}
final List<Pair<EnumWrappers.ItemSlot, ItemStack>> equipmentList = new ArrayList<>();
final List<com.github.retrooper.packetevents.protocol.player.Equipment> equipment = new ArrayList<>();
final boolean hidden = !this.shouldShow(other);
if (hidden) {
equipmentList.add(new Pair<>(EnumWrappers.ItemSlot.HEAD,
new ItemStack(Material.AIR)
final int lookDownPitch = settings.getCosmeticSettings().getLookDownPitch();
final boolean isLookingDown =
this.id.equals(other.getUniqueId()) && lookDownPitch
!= -1 &&
this.isFacingDown(location, lookDownPitch);
if (hidden || isLookingDown) {
equipment.add(new com.github.retrooper.packetevents.protocol.player.Equipment(
EquipmentSlot.HELMET,
new com.github.retrooper.packetevents.protocol.item.ItemStack.Builder().
type(ItemTypes.AIR).
build()
));
} else {
equipmentList.add(new Pair<>(EnumWrappers.ItemSlot.HEAD,
this.playerArmor.getBackpack().getItemStack(ArmorItem.Status.APPLIED)
final com.github.retrooper.packetevents.protocol.item.ItemStack itemStack =
SpigotDataHelper.fromBukkitItemStack(this.playerArmor.getBackpack().getItemStack(ArmorItem.Status.APPLIED));
equipment.add(new com.github.retrooper.packetevents.protocol.player.Equipment(
EquipmentSlot.HELMET,
itemStack
));
}
final int armorStandId = this.getArmorStandId();
final PacketContainer armorPacket = PacketManager.getEquipmentPacket(equipmentList, armorStandId);
final PacketContainer rotationPacket = PacketManager.getRotationPacket(armorStandId, location);
final PacketContainer ridingPacket = PacketManager.getRidingPacket(this.getEntityId(), armorStandId);
final PacketContainer armorStandMetaContainer = PacketManager.getArmorStandMetaContainer(armorStandId);
PacketManager.sendPacket(other, armorPacket, armorStandMetaContainer, rotationPacket, ridingPacket);
PacketManager.sendEquipmentPacket(equipment, armorStandId, other);
PacketManager.sendRotationPacket(armorStandId, location, false, other);
PacketManager.sendRidingPacket(this.getEntityId(), armorStandId, other);
PacketManager.sendArmorStandMetaContainer(armorStandId, other);
if (hidden) return;
this.updateBalloon(other, location, settings.getCosmeticSettings());
final int lookDownPitch = settings.getCosmeticSettings().getLookDownPitch();
if (lookDownPitch != -1 &&
this.isFacingDown(location, lookDownPitch)) {
equipmentList.set(0, new Pair<>(EnumWrappers.ItemSlot.HEAD,
new ItemStack(Material.AIR)
));
if (!this.id.equals(other.getUniqueId())) return;
PacketManager.sendPacket(other, PacketManager.getEquipmentPacket(equipmentList, armorStandId));
}
}
private boolean hasBalloon() {
@@ -255,22 +239,17 @@ public abstract class BaseUser<T> {
public abstract boolean shouldShow(final Player other);
protected boolean isInViewDistance(final Location location, final Location other, final CosmeticSettings settings) {
if (!Objects.equals(other.getWorld(), location.getWorld())) return false;
return !(other.distanceSquared(location) > settings.getViewDistance() * settings.getViewDistance());
}
protected boolean isFacingDown(final Location location, final int pitchLimit) {
return location.getPitch() > pitchLimit;
}
public void despawnAttached(final Player other) {
PacketManager.sendPacket(other, PacketManager.getEntityDestroyPacket(this.getArmorStandId()));
PacketManager.sendEntityDestroyPacket(this.getArmorStandId(), other);
this.viewingArmorStand.remove(other.getUniqueId());
}
public void despawnAttached() {
PacketManager.sendPacketToOnline(PacketManager.getEntityDestroyPacket(this.getArmorStandId()));
PacketManager.sendEntityDestroyPacket(this.getArmorStandId(), Bukkit.getOnlinePlayers());
this.viewingArmorStand.clear();
}

View File

@@ -1,8 +1,5 @@
package io.github.fisher2911.hmccosmetics.user;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.Pair;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.api.CosmeticItem;
import io.github.fisher2911.hmccosmetics.api.event.CosmeticChangeEvent;
@@ -18,6 +15,7 @@ import io.github.fisher2911.hmccosmetics.message.Translation;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import io.github.fisher2911.hmccosmetics.task.InfiniteTask;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import io.github.retrooper.packetevents.util.SpigotDataHelper;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@@ -49,7 +47,6 @@ public class UserManager {
public void add(final User user) {
this.userMap.put(user.getId(), user);
this.updateCosmetics(user);
}
public Optional<User> get(final UUID uuid) {
@@ -78,11 +75,11 @@ public class UserManager {
public void startTeleportTask() {
// throws an error on first load of registry if this isn't here
WrappedDataWatcher.Registry.get(Byte.class);
// WrappedDataWatcher.Registry.get(Byte.class);
this.plugin.getTaskManager().submit(new InfiniteTask(
() -> {
for (final User user : this.userMap.values()) {
user.updateOutsideCosmetics(this.plugin.getSettings());
// user.updateOutsideCosmetics(this.plugin.getSettings());
}
}
));
@@ -92,7 +89,8 @@ public class UserManager {
for (final User user : this.userMap.values()) {
final Player p = user.getPlayer();
if (p == null) continue;
user.updateOutsideCosmetics(player, p.getLocation(), this.settings);
// user.updateOutsideCosmetics(player, p.getLocation(), this.settings);
player.sendMessage("Resending cosmetics");
this.updateCosmetics(user, player);
}
}
@@ -101,16 +99,14 @@ public class UserManager {
this.get(uuid).ifPresent(this::updateCosmetics);
}
public void updateCosmetics(final BaseUser user) {
public void updateCosmetics(final BaseUser<?> user) {
for (final Player player : Bukkit.getOnlinePlayers()) {
this.updateCosmetics(user, player);
}
}
public void updateCosmetics(final BaseUser user, final Player other) {
// final Player player = user.getPlayer();
public void updateCosmetics(final BaseUser<?> user, final Player other) {
final Equipment equipment = user.getEquipment();
for (final ArmorItem.Type type : ArmorItem.Type.values()) {
if (type.getSlot() == null) continue;
this.sendUpdatePacket(
@@ -123,7 +119,7 @@ public class UserManager {
}
private void sendUpdatePacket(
final BaseUser user,
final BaseUser<?> user,
final Player other,
final Equipment equipment,
final ArmorItem.Type type) {
@@ -131,14 +127,14 @@ public class UserManager {
final EquipmentSlot slot = type.getSlot();
final ItemStack itemStack = this.getCosmeticItem(user, equipment, playerArmor.getItem(type), ArmorItem.Status.APPLIED, slot);
if (itemStack != null && itemStack.equals(equipment.getItem(slot))) return;
final List<Pair<EnumWrappers.ItemSlot, ItemStack>> itemList = new ArrayList<>();
itemList.add(new Pair<>(EnumWrappers.ItemSlot.valueOf(slot.toString().replace("_", "")), itemStack));
PacketManager.sendPacket(
other,
PacketManager.getEquipmentPacket(
itemList,
user.getEntityId()
)
final List<com.github.retrooper.packetevents.protocol.player.Equipment> itemList = new ArrayList<>();
itemList.add(new com.github.retrooper.packetevents.protocol.player.Equipment(
PacketManager.fromBukkitSlot(slot), SpigotDataHelper.fromBukkitItemStack(itemStack)
));
PacketManager.sendEquipmentPacket(
itemList,
user.getEntityId(),
other
);
}

View File

@@ -1,6 +1,5 @@
package io.github.fisher2911.hmccosmetics.user;
import com.comphenix.protocol.events.PacketContainer;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.WardrobeSettings;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
@@ -16,7 +15,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
@@ -89,28 +87,18 @@ public class Wardrobe extends User {
return;
}
final PacketContainer playerSpawnPacket = PacketManager.getFakePlayerSpawnPacket(
this.currentLocation,
this.getId(),
this.getEntityId()
);
final PacketContainer playerInfoPacket = PacketManager.getFakePlayerInfoPacket(
viewer,
this.getId()
);
Bukkit.getScheduler().runTaskLaterAsynchronously(
this.plugin,
() -> {
PacketManager.sendPacket(viewer, playerInfoPacket, playerSpawnPacket);
final int entityId = this.getEntityId();
PacketManager.sendFakePlayerSpawnPacket(this.currentLocation, this.getId(), entityId, viewer);
PacketManager.sendFakePlayerInfoPacket(viewer, this.getId(), viewer);
this.updateOutsideCosmetics(viewer, this.currentLocation, plugin.getSettings());
PacketManager.sendPacket(
viewer,
PacketManager.getLookPacket(this.getEntityId(), this.currentLocation),
PacketManager.getRotationPacket(this.getEntityId(), this.currentLocation),
PacketManager.getPlayerOverlayPacket(this.getEntityId())
);
PacketManager.sendLookPacket(entityId, this.currentLocation, viewer);
PacketManager.sendRotationPacket(entityId, this.currentLocation, true, viewer);
PacketManager.sendPlayerOverlayPacket(entityId, viewer);
},
settings.getSpawnDelay()
);
@@ -125,13 +113,9 @@ public class Wardrobe extends User {
Bukkit.getScheduler().runTaskLaterAsynchronously(
this.plugin,
() -> {
PacketManager.sendPacket(
viewer,
PacketManager.getEntityDestroyPacket(this.getEntityId()),
PacketManager.getRemovePlayerPacket(viewer, this.id, this.getEntityId())
// for spectator packets
// PacketManager.getEntityDestroyPacket(this.viewerId)
);
final int entityId = this.getEntityId();
PacketManager.sendEntityDestroyPacket(entityId, viewer);
PacketManager.sendRemovePlayerPacket(viewer, this.id, viewer);
this.despawnAttached();
this.despawnBalloon();
this.showPlayer(this.plugin.getUserManager());
@@ -170,19 +154,17 @@ public class Wardrobe extends User {
private void startSpinTask(final Player player) {
final AtomicInteger data = new AtomicInteger();
final int rotationSpeed = this.plugin.getSettings().getWardrobeSettings().getRotationSpeed();
final int entityId = this.getEntityId();
final Task task = new SupplierTask(
() -> {
if (this.currentLocation == null) return;
final Location location = this.currentLocation.clone();
final int yaw = data.get();
location.setYaw(yaw);
PacketManager.sendPacket(player, PacketManager.getLookPacket(this.getEntityId(), location));
PacketManager.sendLookPacket(entityId, location, player);
this.updateOutsideCosmetics(player, location, this.plugin.getSettings());
location.setYaw(this.getNextYaw(yaw - 30, rotationSpeed));
PacketManager.sendPacket(
player,
PacketManager.getRotationPacket(this.getEntityId(), location)
);
PacketManager.sendRotationPacket(entityId, location, true, player);
data.set(this.getNextYaw(yaw, rotationSpeed));
},
() -> !this.spawned || this.currentLocation == null

View File

@@ -1,74 +0,0 @@
package io.github.fisher2911.hmccosmetics.util;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import org.checkerframework.checker.nullness.qual.Nullable;
public class Keys {
static HMCCosmetics plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
public static final NamespacedKey ITEM_KEY = new NamespacedKey(plugin, "cosmetic");
public static final NamespacedKey TOKEN_KEY = new NamespacedKey(plugin, "token-key");
public static void setKey(final ItemStack itemStack) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
return;
}
itemMeta.getPersistentDataContainer().set(ITEM_KEY, PersistentDataType.BYTE, (byte) 1);
itemStack.setItemMeta(itemMeta);
}
public static <T, Z> void setKey(
final ItemStack itemStack,
final NamespacedKey key,
final PersistentDataType<T, Z> type,
final Z value) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
return;
}
itemMeta.getPersistentDataContainer().set(key, type, value);
itemStack.setItemMeta(itemMeta);
}
public static boolean hasKey(final ItemStack itemStack) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
return false;
}
return itemMeta.getPersistentDataContainer().has(ITEM_KEY, PersistentDataType.BYTE);
}
public static <T, Z> boolean hasKey(final ItemStack itemStack, final NamespacedKey key, final PersistentDataType<T, Z> type) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
return false;
}
return itemMeta.getPersistentDataContainer().has(key, type);
}
@Nullable
public static <T, Z> Z getValue(final ItemStack itemStack, final NamespacedKey key, final PersistentDataType<T, Z> type) {
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
return null;
}
return itemMeta.getPersistentDataContainer().get(key, type);
}
}

View File

@@ -1,41 +0,0 @@
package io.github.fisher2911.hmccosmetics.util;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.message.Adventure;
import net.kyori.adventure.text.Component;
public class StringUtils {
private static final HMCCosmetics plugin;
static {
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
}
/**
* @param parsed message to be parsed
* @return MiniMessage parsed string
*/
public static Component parse(final String parsed) {
return Adventure.MINI_MESSAGE.deserialize(parsed);
}
public static String parseStringToString(final String parsed) {
return Adventure.SERIALIZER.serialize(Adventure.MINI_MESSAGE.deserialize(parsed));
}
public static String formatArmorItemType(String type) {
type = type.toLowerCase();
final String[] parts = type.split(" ");
final String firstPart = parts[0].substring(0, 1).toUpperCase() + parts[0].substring(1);
if (parts.length == 1) {
return firstPart;
}
return firstPart + parts[1].substring(0, 1).toUpperCase() + parts[1].substring(1);
}
}

View File

@@ -1,110 +0,0 @@
package io.github.fisher2911.hmccosmetics.util;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class Utils {
/**
* @param original Object to be checked if null
* @param replacement Object returned if original is null
* @return original if not null, otherwise replacement
*/
public static <T> T replaceIfNull(final @Nullable T original, final @NotNull T replacement) {
return replaceIfNull(original, replacement, t -> {
});
}
public static <T> T replaceIf(final @Nullable T original, final T replacement, final @Nullable T... checks) {
for (final T check : checks) {
if (original == check) return replacement;
}
return original;
}
/**
* @param original Object to be checked if null
* @param replacement Object returned if original is null
* @param consumer accepts the original object, can be used for logging
* @return original if not null, otherwise replacement
*/
public static <T> T replaceIfNull(final @Nullable T original, final T replacement,
final @NotNull Consumer<T> consumer) {
if (original == null) {
consumer.accept(replacement);
return replacement;
}
consumer.accept(original);
return original;
}
/**
* @param t object being checked
* @param consumer accepted if t is not null
* @param <T> type
*/
public static <T> void doIfNotNull(final @Nullable T t, final @NotNull Consumer<T> consumer) {
if (t == null) {
return;
}
consumer.accept(t);
}
/**
* @param t object being checked
* @param function applied if t is not null
* @param <T> type
* @return
*/
public static <T> Optional<T> returnIfNotNull(final @Nullable T t,
final @NotNull Function<T, T> function) {
if (t == null) {
return Optional.empty();
}
return Optional.of(function.apply(t));
}
/**
* @param enumAsString Enum value as a string to be parsed
* @param enumClass enum type enumAsString is to be converted to
* @param defaultEnum default value to be returned
* @return enumAsString as an enum, or default enum if it could not be parsed
*/
public static <E extends Enum<E>> E stringToEnum(final @NotNull String enumAsString,
final @NotNull Class<E> enumClass,
E defaultEnum) {
return stringToEnum(enumAsString, enumClass, defaultEnum, e -> {
});
}
/**
* @param enumAsString Enum value as a string to be parsed
* @param enumClass enum type enumAsString is to be converted to
* @param defaultEnum default value to be returned
* @param consumer accepts the returned enum, can be used for logging
* @return enumAsString as an enum, or default enum if it could not be parsed
*/
public static <E extends Enum<E>> E stringToEnum(final @NotNull String enumAsString,
@NotNull final Class<E> enumClass,
final E defaultEnum,
final @NotNull Consumer<E> consumer) {
try {
final E value = Enum.valueOf(enumClass, enumAsString);
consumer.accept(value);
return value;
} catch (final IllegalArgumentException exception) {
consumer.accept(defaultEnum);
return defaultEnum;
}
}
}

View File

@@ -1,81 +0,0 @@
package io.github.fisher2911.hmccosmetics.util.builder;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
public class ColorBuilder extends ItemBuilder {
/**
* @param material ItemStack material
*/
ColorBuilder(final Material material) {
super(material);
}
/**
* @param itemStack ItemStack
*/
ColorBuilder(final ItemStack itemStack) {
super(itemStack);
}
/**
* @param material ItemStack material
* @return this
* @throws IllegalArgumentException thrown if itemStack's type can not change color
*/
public static ColorBuilder from(final Material material) throws IllegalArgumentException {
if (!canBeColored(material)) {
throw new IllegalArgumentException(material.name() + " is not leather armor!");
}
return new ColorBuilder(material);
}
/**
* @param itemStack ItemStack
* @return this
* @throws IllegalArgumentException thrown if itemStack's type can not change color
*/
public static ColorBuilder from(final ItemStack itemStack) throws IllegalArgumentException {
final Material material = itemStack.getType();
if (!canBeColored(itemStack)) {
throw new IllegalArgumentException(material.name() + " is not leather armor!");
}
return new ColorBuilder(itemStack);
}
public static boolean canBeColored(final Material material) {
return canBeColored(new ItemStack(material));
}
public static boolean canBeColored(final ItemStack itemStack) {
final ItemMeta itemMeta = itemStack.getItemMeta();
return (itemMeta instanceof LeatherArmorMeta ||
itemMeta instanceof PotionMeta);
}
/**
* @param color armor color
* @return this
*/
public ColorBuilder color(final Color color) {
if (this.itemMeta instanceof final PotionMeta meta) {
meta.setColor(color);
}
if (this.itemMeta instanceof final LeatherArmorMeta meta) {
meta.setColor(color);
}
return this;
}
}

View File

@@ -1,255 +0,0 @@
package io.github.fisher2911.hmccosmetics.util.builder;
import io.github.fisher2911.hmccosmetics.message.Placeholder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class ItemBuilder {
protected Material material;
protected int amount;
protected ItemMeta itemMeta;
/**
* @param material builder material
*/
ItemBuilder(final Material material) {
this.material = material;
this.itemMeta = Bukkit.getItemFactory().getItemMeta(material);
}
/**
* @param itemStack builder ItemStack
*/
ItemBuilder(final ItemStack itemStack) {
this.material = itemStack.getType();
this.itemMeta = itemStack.hasItemMeta() ? itemStack.getItemMeta()
: Bukkit.getItemFactory().getItemMeta(this.material);
}
/**
* @param material builder material
* @return
*/
public static ItemBuilder from(final Material material) {
return new ItemBuilder(material);
}
/**
* @param itemStack builder ItemStack
* @return
*/
public static ItemBuilder from(final ItemStack itemStack) {
return new ItemBuilder(itemStack);
}
/**
* @param amount ItemStack amount
* @return this
*/
public ItemBuilder amount(final int amount) {
this.amount = Math.min(Math.max(1, amount), 64);
return this;
}
/**
* @param name ItemStack name
* @return this
*/
public ItemBuilder name(final String name) {
if (this.itemMeta == null) {
return this;
}
this.itemMeta.setDisplayName(name);
return this;
}
/**
* Sets placeholders to the item's name
*
* @param placeholders placeholders
*/
public ItemBuilder namePlaceholders(final Map<String, String> placeholders) {
if (this.itemMeta == null) {
return this;
}
final String name = Placeholder.
applyPlaceholders(this.itemMeta.getDisplayName(), placeholders);
this.itemMeta.setDisplayName(name);
return this;
}
/**
* @param lore ItemStack lore
* @return this
*/
public ItemBuilder lore(final List<String> lore) {
if (this.itemMeta == null) {
return this;
}
this.itemMeta.setLore(lore);
return this;
}
/**
* Sets placeholders to the item's lore
*
* @param placeholders placeholders
*/
public ItemBuilder lorePlaceholders(final Map<String, String> placeholders) {
if (this.itemMeta == null) {
return this;
}
final List<String> lore = new ArrayList<>();
final List<String> previousLore = this.itemMeta.getLore();
if (previousLore == null) {
return this;
}
for (final String line : previousLore) {
lore.add(Placeholder.applyPlaceholders(
line, placeholders
));
}
this.itemMeta.setLore(lore);
return this;
}
public ItemBuilder papiPlaceholders(final Player player) {
this.lorePapiPlaceholders(player);
this.namePapiPlaceholders(player);
return this;
}
private void lorePapiPlaceholders(final Player player) {
if (this.itemMeta == null) {
return;
}
final List<String> newLore = new ArrayList<>();
final List<String> lore = this.itemMeta.getLore();
if (lore == null) {
return;
}
for (final String line : this.itemMeta.getLore()) {
newLore.add(Placeholder.applyPapiPlaceholders(player, line));
}
this.itemMeta.setLore(newLore);
}
private void namePapiPlaceholders(final Player player) {
if (this.itemMeta == null) {
return;
}
this.itemMeta.setDisplayName(
Placeholder.applyPapiPlaceholders(
player,
this.itemMeta.getDisplayName()
)
);
}
/**
* @param unbreakable whether the ItemStack is unbreakable
* @return this
*/
public ItemBuilder unbreakable(final boolean unbreakable) {
if (this.itemMeta == null) {
return this;
}
this.itemMeta.setUnbreakable(unbreakable);
return this;
}
public ItemBuilder glow(final boolean glow) {
if (this.itemMeta == null) {
return this;
}
if (glow) {
this.itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
this.itemMeta.addEnchant(Enchantment.LUCK, 1, true);
}
return this;
}
/**
* @param enchantments enchants to be added to the ItemStack
* @param ignoreLeveLRestrictions whether to ignore enchantment level restrictions
* @return this
*/
public ItemBuilder enchants(final Map<Enchantment, Integer> enchantments,
boolean ignoreLeveLRestrictions) {
if (this.itemMeta == null) {
return this;
}
enchantments.forEach((enchantment, level) -> this.itemMeta.addEnchant(enchantment, level,
ignoreLeveLRestrictions));
return this;
}
/**
* @param itemFlags ItemStack ItemFlags
* @return this
*/
public ItemBuilder itemFlags(final Set<ItemFlag> itemFlags) {
if (this.itemMeta == null) {
return this;
}
this.itemMeta.addItemFlags(itemFlags.toArray(new ItemFlag[0]));
return this;
}
/**
* @param modelData ItemStack modelData
* @return this
*/
public ItemBuilder modelData(final int modelData) {
if (this.itemMeta == null) {
return this;
}
this.itemMeta.setCustomModelData(modelData);
return this;
}
/**
* @return built ItemStack
*/
public ItemStack build() {
final ItemStack itemStack = new ItemStack(this.material, Math.max(this.amount, 1));
itemStack.setItemMeta(itemMeta);
return itemStack;
}
}

View File

@@ -1,93 +0,0 @@
package io.github.fisher2911.hmccosmetics.util.builder;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import java.lang.reflect.Field;
import java.util.UUID;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.NotNull;
/**
* Some parts taken from https://github.com/TriumphTeam/triumph-gui/blob/master/core/src/main/java/dev/triumphteam/gui/builder/item/SkullBuilder.java
*/
public class SkullBuilder extends ItemBuilder {
private static final Field PROFILE_FIELD;
static {
Field field;
try {
final SkullMeta skullMeta = (SkullMeta) new ItemStack(
Material.PLAYER_HEAD).getItemMeta();
field = skullMeta.getClass().getDeclaredField("profile");
field.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
field = null;
}
PROFILE_FIELD = field;
}
/**
* @param material The material
*/
SkullBuilder(final Material material) {
super(material);
}
/**
* Creates a new SkullBuilder instance
*
* @return this
*/
public static SkullBuilder create() {
return new SkullBuilder(Material.PLAYER_HEAD);
}
/**
* @param player skull owner
* @return this
*/
public SkullBuilder owner(final OfflinePlayer player) {
if (this.itemMeta instanceof final SkullMeta skullMeta) {
skullMeta.setOwningPlayer(player);
this.itemMeta = skullMeta;
}
return this;
}
/**
* @param texture skull texture
* @return this
*/
public SkullBuilder texture(@NotNull final String texture) {
if (PROFILE_FIELD == null) {
return this;
}
final SkullMeta skullMeta = (SkullMeta) this.itemMeta;
final GameProfile profile = new GameProfile(UUID.randomUUID(), null);
profile.getProperties().put("textures", new Property("textures", texture));
try {
PROFILE_FIELD.set(skullMeta, profile);
} catch (IllegalArgumentException | IllegalAccessException ex) {
ex.printStackTrace();
}
this.itemMeta = skullMeta;
return this;
}
}

View File

@@ -11,12 +11,12 @@ repositories {
maven("https://papermc.io/repo/repository/maven-public/")
maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://jitpack.io")
maven("https://repo.dmulloy2.net/repository/public/")
// maven("https://repo.dmulloy2.net/repository/public/")
}
dependencies {
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot:1.18-R0.1-SNAPSHOT")
// compileOnly("org.spigotmc:spigot:1.18-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:22.0.0")
compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
// compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
}

View File

@@ -1,19 +1,13 @@
package io.github.fisher2911.nms;
import com.comphenix.protocol.events.PacketContainer;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import java.util.UUID;
public interface PacketHelper {
PacketContainer getPlayerSpawnPacket(final Location location, UUID uuid, final int entityId);
PacketContainer getPlayerInfoPacket(final Player player, final UUID uuid);
PacketContainer getPlayerRemovePacket(final Player player, final UUID uuid, final int entityId);
PacketContainer getPlayerOverlayPacket(final int entityId);
PacketContainer getDestroyPacket(final int entityId);
PacketContainer getArmorStandMeta(final int armorStandId);
// PacketContainer getPlayerSpawnPacket(final Location location, UUID uuid, final int entityId);
// PacketContainer getPlayerInfoPacket(final Player player, final UUID uuid);
// PacketContainer getPlayerRemovePacket(final Player player, final UUID uuid, final int entityId);
// PacketContainer getPlayerOverlayPacket(final int entityId);
// PacketContainer getDestroyPacket(final int entityId);
// PacketContainer getArmorStandMeta(final int armorStandId);
// PacketContainer getGuiOpenPacket(final Player player);
}

View File

@@ -1,8 +1,4 @@
rootProject.name = "HMCCosmetics"
include(
"common",
"nms",
"1.16",
"1.17",
"1.18"
"common"
)