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

Compare commits

...

49 Commits

Author SHA1 Message Date
Logan
1ef7f4759f fix: balloon lead not properly disappearing when you unapply a balloon cosmetic 2025-08-17 16:22:32 -05:00
Logan
937f66e8c5 version bump (2.8.1) 2025-08-17 14:43:59 -05:00
Logan
158f3afdec chore: update test server 2025-08-17 14:43:44 -05:00
Logan
38bdc01e9f Merge remote-tracking branch 'origin/remapped' into remapped 2025-08-16 13:30:16 -05:00
Logan
797992362a feat: allow custom dye menu implementations 2025-08-16 13:30:10 -05:00
Logan
9716a079be Merge pull request #189 from Catnies/dev
fix PlayerMenuOpenEvent can't cancel
2025-08-06 16:30:24 -05:00
LoJoSho
dfe51ba5b8 fix: user initialization not checking potion effects 2025-08-06 16:27:27 -05:00
Catnies
f5e81446a6 fix PlayerMenuOpenEvent can't cancel 2025-08-05 14:34:07 +08:00
LoJoSho
c99a57a6bf chore: update adventure dependencies 2025-08-01 22:01:31 -05:00
LoJoSho
79630263f2 chore: exclude lin-bus from worldguard depend 2025-08-01 21:59:30 -05:00
LoJoSho
478c4280c1 feat: finally fully remove mainhand cosmetic 2025-07-19 15:36:11 -05:00
LoJoSho
4fd439acc4 chore: backpack force riding backpack set on by default 2025-07-12 10:32:38 -05:00
LoJoSho
58c955a00f feat: expose the config for a cosmetic if available 2025-07-09 18:06:22 -05:00
Oak
2f9325b2fb Added scale attribute support to backpacks (#186) 2025-07-05 16:15:01 -05:00
LoJoSho
823270648b Merge remote-tracking branch 'origin/remapped' into remapped 2025-07-04 11:59:44 -05:00
LoJoSho
d5e988261b chore: update to 1.21.7 on test server 2025-07-04 11:59:35 -05:00
Logan
13303096ec chore: shading should be off by default 2025-07-04 10:27:20 -05:00
LoJoSho
3ee79e8443 fix: passenger packet interceptor appears to cause instability, disabling for now 2025-07-01 14:50:42 -05:00
LoJoSho
7785556967 chore: remove unused variable 2025-07-01 14:49:39 -05:00
LoJoSho
1296ca6e92 fix: calculating yaw twice causing bad yaw to be sent in rotations 2025-07-01 13:47:50 -05:00
LoJoSho
f56d5c9093 chore: more debug messages on equip 2025-06-28 17:59:23 -05:00
LoJoSho
bae04fba3f chore: update to latest hibiscus commons 2025-06-28 15:30:47 -05:00
LoJoSho
cbe5404399 fix: hibiscus commons version 2025-06-27 15:47:49 -05:00
LoJoSho
dc4098782a fix: latest crash fixes (with latest hibiscus commons) 2025-06-27 15:44:17 -05:00
LoJoSho
2eb0b26fb3 fix: plugin not properly saving resources 2025-06-27 15:15:48 -05:00
LoJoSho
22159fa9f4 fix: duplicate entity ids in passengers 2025-06-27 10:18:35 -05:00
LoJoSho
539c09801c chore: remove cooldown on teleport packet 2025-06-27 08:53:58 -05:00
Logan
bed5cd7bbb Merge pull request #185 from HibiscusMC/commons07
feat: overhaul to new Hibiscus commons packet system
2025-06-26 15:43:12 -05:00
LoJoSho
4a1a631557 chore: update HibiscusCommons 2025-06-26 15:42:58 -05:00
LoJoSho
ad282a9efe feat: overhaul to new Hibiscus commons system 2025-06-26 15:24:54 -05:00
LoJoSho
86ef4d0efa chore: update test server to 1.21.6 2025-06-24 14:23:19 -05:00
LoJoSho
da09a542f1 chore: update luckperms on test server 2025-06-24 14:14:45 -05:00
LoJoSho
62f32cc03d version bump (2.7.10) 2025-06-24 11:14:37 -05:00
lucian929
ff1addfd65 chore: change defaultmenu configurations for new gui 2025-06-24 11:57:38 -04:00
lucian929
73f013bf1f chore: change defaultmenu for new gui 2025-06-24 08:46:48 -04:00
lucian929
204fee4456 chore: change shading pattern for new gui 2025-06-24 08:43:31 -04:00
LoJoSho
e7ea62a4d2 chore: update adventure dependencies 2025-06-22 14:02:58 -05:00
LoJoSho
42802e41b4 fix: dyeable dye click not defaulting to correct value 2025-06-10 10:08:20 -05:00
LoJoSho
7e7d81d0f8 fix: CosmeticUser not handling null entities 2025-06-10 09:21:37 -05:00
LoJoSho
b07c3c9878 fix: Actions not handling nulls properly 2025-06-09 10:53:27 -05:00
LoJoSho
a19d564460 fix: UNDEFINED DISPLAY ITEM using paper-only methods 2025-06-08 10:21:31 -05:00
LoJoSho
b3408143f0 fix: HMCColor integrate (remove legacy formatting, clean dyeclicktype) 2025-05-31 10:22:30 -05:00
LoJoSho
3c1539285d feat: translations no longer go through legacy formatting 2025-05-31 09:35:41 -05:00
LoJoSho
a642d88af2 chore: update luckperms on test server 2025-05-31 09:11:24 -05:00
LoJoSho
36d4009f5e version bump (2.7.9) 2025-05-31 09:07:45 -05:00
LoJoSho
bebee807bc fix: fix possible database memory leak (as well as improvements in code) 2025-05-29 14:59:57 -05:00
LoJoSho
26c579b69f chore: add cosmetic passengers to dump command 2025-05-25 14:02:04 -05:00
LoJoSho
ef665e7e83 fix: improper call to getEntity when not needed 2025-05-23 13:22:29 -05:00
LoJoSho
7a6475c467 chore: update LuckPerms 2025-05-22 21:07:12 -05:00
46 changed files with 951 additions and 1344 deletions

View File

@@ -8,7 +8,7 @@ plugins {
} }
group = "com.hibiscusmc" group = "com.hibiscusmc"
version = "2.7.8${getGitCommitHash()}" version = "2.8.1${getGitCommitHash()}"
allprojects { allprojects {
apply(plugin = "java") apply(plugin = "java")
@@ -16,6 +16,7 @@ allprojects {
repositories { repositories {
mavenCentral() mavenCentral()
mavenLocal()
// Paper Repo // Paper Repo
maven("https://repo.papermc.io/repository/maven-public/") maven("https://repo.papermc.io/repository/maven-public/")
@@ -24,8 +25,7 @@ allprojects {
// Jitpack // Jitpack
maven("https://jitpack.io") maven("https://jitpack.io")
// ProtocolLib repo // Geary
maven("https://repo.dmulloy2.net/repository/public/") //ProtocolLib Repo, constantly down
maven("https://repo.mineinabyss.com/releases/") maven("https://repo.mineinabyss.com/releases/")
maven("https://repo.mineinabyss.com/snapshots/") maven("https://repo.mineinabyss.com/snapshots/")
@@ -75,23 +75,29 @@ allprojects {
compileOnly(fileTree("${project.rootDir}/lib") { include("*.jar") }) compileOnly(fileTree("${project.rootDir}/lib") { include("*.jar") })
compileOnly("com.mojang:authlib:1.5.25") compileOnly("com.mojang:authlib:1.5.25")
//compileOnly("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT") //compileOnly("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT") compileOnly("io.papermc.paper:paper-api:1.20.6-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:24.1.0") compileOnly("org.jetbrains:annotations:24.1.0")
compileOnly("com.comphenix.protocol:ProtocolLib:5.3.0")
compileOnly("me.clip:placeholderapi:2.11.6") compileOnly("me.clip:placeholderapi:2.11.6")
compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.6") compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.6")
compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.12") compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.12") {
exclude(group = "org.bukkit")
exclude(group = "com.google.guava")
exclude(group = "com.google.code.gson")
exclude(group = "it.unimi.dsi")
exclude(group = "com.sk89q.jnbt")
exclude(group = "org.enginehub.lin-bus.format")
}
compileOnly("io.github.toxicity188:BetterHud-standard-api:1.12") //Standard api compileOnly("io.github.toxicity188:BetterHud-standard-api:1.12") //Standard api
compileOnly("io.github.toxicity188:BetterHud-bukkit-api:1.12") //Platform api compileOnly("io.github.toxicity188:BetterHud-bukkit-api:1.12") //Platform api
compileOnly("io.github.toxicity188:BetterCommand:1.3") //BetterCommand library compileOnly("io.github.toxicity188:BetterCommand:1.3") //BetterCommand library
//compileOnly("it.unimi.dsi:fastutil:8.5.14") //compileOnly("it.unimi.dsi:fastutil:8.5.14")
compileOnly("org.projectlombok:lombok:1.18.34") compileOnly("org.projectlombok:lombok:1.18.34")
compileOnly("me.lojosho:HibiscusCommons:0.6.3-0f0baaf4") compileOnly("me.lojosho:HibiscusCommons:0.7.1-6c4e262c")
// Handled by Spigot Library Loader // Handled by Spigot Library Loader
compileOnly("net.kyori:adventure-api:4.19.0") compileOnly("net.kyori:adventure-api:4.24.0")
compileOnly("net.kyori:adventure-text-minimessage:4.19.0") compileOnly("net.kyori:adventure-text-minimessage:4.24.0")
compileOnly("net.kyori:adventure-platform-bukkit:4.3.4") compileOnly("net.kyori:adventure-platform-bukkit:4.4.1")
annotationProcessor("org.projectlombok:lombok:1.18.36") annotationProcessor("org.projectlombok:lombok:1.18.36")
testCompileOnly("org.projectlombok:lombok:1.18.36") testCompileOnly("org.projectlombok:lombok:1.18.36")
@@ -101,7 +107,7 @@ allprojects {
exclude("net.kyori") // Already have adventure API exclude("net.kyori") // Already have adventure API
} }
implementation("com.owen1212055:particlehelper:1.0.0-SNAPSHOT") implementation("com.owen1212055:particlehelper:1.0.0-SNAPSHOT")
implementation("com.ticxo.playeranimator:PlayerAnimator:R1.2.7") implementation("com.ticxo.playeranimator:PlayerAnimator:R1.2.8")
} }
tasks { tasks {
@@ -134,12 +140,12 @@ tasks {
} }
runServer { runServer {
minecraftVersion("1.21.4") minecraftVersion("1.21.8")
downloadPlugins { downloadPlugins {
hangar("PlaceholderAPI", "2.11.6") hangar("PlaceholderAPI", "2.11.6")
url("https://ci.dmulloy2.net/job/ProtocolLib/lastSuccessfulBuild/artifact/build/libs/ProtocolLib.jar") url("https://download.luckperms.net/1593/bukkit/loader/LuckPerms-Bukkit-5.5.8.jar")
url("https://download.luckperms.net/1567/bukkit/loader/LuckPerms-Bukkit-5.4.150.jar") github("Test-Account666", "PlugManX", "2.4.1", "PlugManX-2.4.1.jar")
} }
} }
@@ -175,8 +181,8 @@ bukkit {
main = "com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin" main = "com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin"
apiVersion = "1.20" apiVersion = "1.20"
authors = listOf("LoJoSho") authors = listOf("LoJoSho")
depend = listOf("HibiscusCommons", "ProtocolLib") depend = listOf("HibiscusCommons")
softDepend = listOf("BetterHud", "ModelEngine", "Oraxen", "ItemsAdder", "Geary", "HMCColor", "WorldGuard", "MythicMobs", "PlaceholderAPI", "SuperVanish", "PremiumVanish", "LibsDisguises", "Denizen", "MMOItems", "Eco") softDepend = listOf("Nexo", "BetterHud", "ModelEngine", "Oraxen", "ItemsAdder", "Geary", "HMCColor", "WorldGuard", "MythicMobs", "PlaceholderAPI", "SuperVanish", "PremiumVanish", "LibsDisguises", "Denizen", "MMOItems", "Eco")
version = "${project.version}" version = "${project.version}"
loadBefore = listOf( loadBefore = listOf(
"Cosmin" // Fixes an issue with Cosmin loading before and taking /cosmetic, when messing with what we do. "Cosmin" // Fixes an issue with Cosmin loading before and taking /cosmetic, when messing with what we do.

View File

@@ -11,6 +11,8 @@ import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.database.Database; import com.hibiscusmc.hmccosmetics.database.Database;
import com.hibiscusmc.hmccosmetics.gui.Menu; import com.hibiscusmc.hmccosmetics.gui.Menu;
import com.hibiscusmc.hmccosmetics.gui.Menus; import com.hibiscusmc.hmccosmetics.gui.Menus;
import com.hibiscusmc.hmccosmetics.gui.special.DyeMenuProvider;
import com.hibiscusmc.hmccosmetics.gui.special.impl.HMCColorDyeMenu;
import com.hibiscusmc.hmccosmetics.hooks.items.HookHMCCosmetics; import com.hibiscusmc.hmccosmetics.hooks.items.HookHMCCosmetics;
import com.hibiscusmc.hmccosmetics.hooks.misc.HookBetterHud; import com.hibiscusmc.hmccosmetics.hooks.misc.HookBetterHud;
import com.hibiscusmc.hmccosmetics.hooks.placeholders.HMCPlaceholderExpansion; import com.hibiscusmc.hmccosmetics.hooks.placeholders.HMCPlaceholderExpansion;
@@ -20,6 +22,7 @@ import com.hibiscusmc.hmccosmetics.listener.PaperPlayerGameListener;
import com.hibiscusmc.hmccosmetics.listener.PlayerConnectionListener; import com.hibiscusmc.hmccosmetics.listener.PlayerConnectionListener;
import com.hibiscusmc.hmccosmetics.listener.PlayerGameListener; import com.hibiscusmc.hmccosmetics.listener.PlayerGameListener;
import com.hibiscusmc.hmccosmetics.listener.ServerListener; import com.hibiscusmc.hmccosmetics.listener.ServerListener;
import com.hibiscusmc.hmccosmetics.packets.CosmeticPacketInterface;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers; import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
@@ -28,6 +31,7 @@ import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin;
import me.lojosho.hibiscuscommons.HibiscusPlugin; import me.lojosho.hibiscuscommons.HibiscusPlugin;
import me.lojosho.hibiscuscommons.config.serializer.ItemSerializer; import me.lojosho.hibiscuscommons.config.serializer.ItemSerializer;
import me.lojosho.hibiscuscommons.config.serializer.LocationSerializer; import me.lojosho.hibiscuscommons.config.serializer.LocationSerializer;
import me.lojosho.hibiscuscommons.hooks.Hooks;
import me.lojosho.shaded.configupdater.common.config.CommentedConfiguration; import me.lojosho.shaded.configupdater.common.config.CommentedConfiguration;
import me.lojosho.shaded.configurate.ConfigurateException; import me.lojosho.shaded.configurate.ConfigurateException;
import me.lojosho.shaded.configurate.ConfigurationOptions; import me.lojosho.shaded.configurate.ConfigurationOptions;
@@ -63,7 +67,12 @@ public final class HMCCosmeticsPlugin extends HibiscusPlugin {
if (!Path.of(getDataFolder().getPath(), "messages.yml").toFile().exists()) saveResource("messages.yml", false); if (!Path.of(getDataFolder().getPath(), "messages.yml").toFile().exists()) saveResource("messages.yml", false);
if (!Path.of(getDataFolder().getPath(), "translations.yml").toFile().exists()) saveResource("translations.yml", false); if (!Path.of(getDataFolder().getPath(), "translations.yml").toFile().exists()) saveResource("translations.yml", false);
if (!Path.of(getDataFolder().getPath() + "/cosmetics/").toFile().exists()) saveResource("cosmetics/defaultcosmetics.yml", false); if (!Path.of(getDataFolder().getPath() + "/cosmetics/").toFile().exists()) saveResource("cosmetics/defaultcosmetics.yml", false);
if (!Path.of(getDataFolder().getPath() + "/menus/").toFile().exists()) saveResource("menus/defaultmenu.yml", false); if (!Path.of(getDataFolder().getPath() + "/menus/").toFile().exists()) {
saveResource("menus/defaultmenu_hats.yml", false);
saveResource("menus/defaultmenu_balloons.yml", false);
saveResource("menus/defaultmenu_hands.yml", false);
saveResource("menus/defaultmenu_backpacks.yml", false);
}
// Configuration Sync // Configuration Sync
final File configFile = Path.of(getInstance().getDataFolder().getPath(), "config.yml").toFile(); final File configFile = Path.of(getInstance().getDataFolder().getPath(), "config.yml").toFile();
@@ -83,6 +92,7 @@ public final class HMCCosmeticsPlugin extends HibiscusPlugin {
// Setup // Setup
setup(); setup();
setPacketInterface(new CosmeticPacketInterface());
// Commands // Commands
getServer().getPluginCommand("cosmetic").setExecutor(new CosmeticCommand()); getServer().getPluginCommand("cosmetic").setExecutor(new CosmeticCommand());
@@ -103,6 +113,11 @@ public final class HMCCosmeticsPlugin extends HibiscusPlugin {
if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null && Settings.isWorldGuardMoveCheck()) { if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null && Settings.isWorldGuardMoveCheck()) {
getServer().getPluginManager().registerEvents(new WGListener(), this); getServer().getPluginManager().registerEvents(new WGListener(), this);
} }
// HMCColor
if (Hooks.isActiveHook("HMCColor")) {
DyeMenuProvider.setDyeMenuProvider(new HMCColorDyeMenu());
}
} }
@Override @Override

View File

@@ -12,7 +12,6 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUserProvider;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers; import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import me.lojosho.hibiscuscommons.nms.MinecraftVersion; import me.lojosho.hibiscuscommons.nms.MinecraftVersion;
import me.lojosho.hibiscuscommons.nms.NMSHandlers; import me.lojosho.hibiscuscommons.nms.NMSHandlers;
import me.lojosho.shaded.configurate.ConfigurationNode;
import org.bukkit.Color; import org.bukkit.Color;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -21,7 +20,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.function.BiConsumer;
/** /**
* The main API class for HMCCosmetics. This class provides methods to interact with the plugin. * The main API class for HMCCosmetics. This class provides methods to interact with the plugin.

View File

@@ -1,7 +1,6 @@
package com.hibiscusmc.hmccosmetics.api.events; package com.hibiscusmc.hmccosmetics.api.events;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**

View File

@@ -14,6 +14,7 @@ import com.hibiscusmc.hmccosmetics.database.Database;
import com.hibiscusmc.hmccosmetics.gui.Menu; import com.hibiscusmc.hmccosmetics.gui.Menu;
import com.hibiscusmc.hmccosmetics.gui.Menus; import com.hibiscusmc.hmccosmetics.gui.Menus;
import com.hibiscusmc.hmccosmetics.gui.special.DyeMenu; import com.hibiscusmc.hmccosmetics.gui.special.DyeMenu;
import com.hibiscusmc.hmccosmetics.gui.special.DyeMenuProvider;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers; import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
@@ -329,7 +330,7 @@ public class CosmeticCommand implements CommandExecutor {
} }
user.addCosmetic(cosmetic, color); // #FFFFFF user.addCosmetic(cosmetic, color); // #FFFFFF
} else { } else {
DyeMenu.openMenu(user, cosmetic); DyeMenuProvider.openMenu(player, user, cosmetic);
} }
} }
case ("setwardrobesetting") -> { case ("setwardrobesetting") -> {
@@ -400,6 +401,7 @@ public class CosmeticCommand implements CommandExecutor {
if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) { if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
player.sendMessage("Backpack Location -> " + user.getUserBackpackManager().getEntityManager().getLocation()); player.sendMessage("Backpack Location -> " + user.getUserBackpackManager().getEntityManager().getLocation());
} }
player.sendMessage("Cosmetic Passengers -> " + user.getUserBackpackManager().getAreaEffectEntityId());
player.sendMessage("Cosmetics -> " + user.getCosmetics()); player.sendMessage("Cosmetics -> " + user.getCosmetics());
player.sendMessage("EntityId -> " + player.getEntityId()); player.sendMessage("EntityId -> " + player.getEntityId());
return true; return true;

View File

@@ -228,9 +228,9 @@ public class Settings {
lockedCosmeticColor = shadingSettings.node(LOCKED_COSMETIC_COLOR_PATH).getString(); lockedCosmeticColor = shadingSettings.node(LOCKED_COSMETIC_COLOR_PATH).getString();
ConfigurationNode cosmeticTypeSettings = menuSettings.node(COSMETIC_TYPE_SETTINGS_PATH); ConfigurationNode cosmeticTypeSettings = menuSettings.node(COSMETIC_TYPE_SETTINGS_PATH);
cosmeticEquipClickType = cosmeticTypeSettings.node(EQUIP_CLICK_TYPE).getString("ALL"); cosmeticEquipClickType = cosmeticTypeSettings.node(EQUIP_CLICK_TYPE).getString("ANY");
cosmeticUnEquipClickType = cosmeticTypeSettings.node(UNEQUIP_CLICK_TYPE).getString("ALL"); cosmeticUnEquipClickType = cosmeticTypeSettings.node(UNEQUIP_CLICK_TYPE).getString("ANY");
cosmeticDyeClickType = cosmeticTypeSettings.node(DYE_CLICK_TYPE).getString("ALL"); cosmeticDyeClickType = cosmeticTypeSettings.node(DYE_CLICK_TYPE).getString("ANY");
final var balloonSection = cosmeticSettings.node(BALLOON_OFFSET); final var balloonSection = cosmeticSettings.node(BALLOON_OFFSET);
balloonOffset = loadVector(balloonSection); balloonOffset = loadVector(balloonSection);

View File

@@ -3,16 +3,16 @@ package com.hibiscusmc.hmccosmetics.cosmetic;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import me.lojosho.hibiscuscommons.config.serializer.ItemSerializer; import me.lojosho.hibiscuscommons.config.serializer.ItemSerializer;
import me.lojosho.shaded.configurate.ConfigurationNode; import me.lojosho.shaded.configurate.ConfigurationNode;
import me.lojosho.shaded.configurate.serialize.SerializationException; import me.lojosho.shaded.configurate.serialize.SerializationException;
import net.kyori.adventure.text.Component; import org.bukkit.ChatColor;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -26,13 +26,16 @@ public abstract class Cosmetic {
static { static {
UNDEFINED_DISPLAY_ITEM_STACK = new ItemStack(Material.BARRIER); UNDEFINED_DISPLAY_ITEM_STACK = new ItemStack(Material.BARRIER);
UNDEFINED_DISPLAY_ITEM_STACK.editMeta(meta -> {
meta.displayName(Component.text("Undefined Item Display", NamedTextColor.RED)); ItemMeta meta = UNDEFINED_DISPLAY_ITEM_STACK.getItemMeta();
meta.lore(List.of( if (meta != null) {
Component.text("Please check your configurations & console to", NamedTextColor.RED), // Legacy methods for Spigot >:(
Component.text("ensure there are no errors.", NamedTextColor.RED) meta.setDisplayName(ChatColor.translateAlternateColorCodes('&', "&cUndefined Item Display"));
)); meta.setLore(List.of(
}); ChatColor.translateAlternateColorCodes('&', "&cPlease check your configurations & console to"),
ChatColor.translateAlternateColorCodes('&', "&censure there are no errors.")));
}
UNDEFINED_DISPLAY_ITEM_STACK.setItemMeta(meta);
} }
/** Identifier of the cosmetic. */ /** Identifier of the cosmetic. */
@@ -54,8 +57,12 @@ public abstract class Cosmetic {
/** Whether the cosmetic is dyeable or not. */ /** Whether the cosmetic is dyeable or not. */
private boolean dyeable; private boolean dyeable;
/** The config for the cosmetic */
private ConfigurationNode config;
protected Cosmetic(@NotNull String id, @NotNull ConfigurationNode config) { protected Cosmetic(@NotNull String id, @NotNull ConfigurationNode config) {
this.id = id; this.id = id;
this.config = config;
if (!config.node("permission").virtual()) { if (!config.node("permission").virtual()) {
this.permission = config.node("permission").getString(); this.permission = config.node("permission").getString();
@@ -133,4 +140,14 @@ public abstract class Cosmetic {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
/**
* While cosmetics registered in HMCC are made through a configuration, cosmetics registered from other plugins
* may not and instead opt for {@link Cosmetic#Cosmetic(String, String, ItemStack, String, CosmeticSlot, boolean)}, which doesn't use a config.
* This should be used only for reference.
*/
@ApiStatus.Experimental
public @Nullable ConfigurationNode getConfig() {
return config;
}
} }

View File

@@ -2,12 +2,10 @@ package com.hibiscusmc.hmccosmetics.cosmetic;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.cosmetic.types.*; import com.hibiscusmc.hmccosmetics.cosmetic.types.*;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.lojosho.shaded.configurate.ConfigurationNode; import me.lojosho.shaded.configurate.ConfigurationNode;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map; import java.util.Map;
import java.util.function.BiFunction; import java.util.function.BiFunction;
@@ -24,8 +22,6 @@ public abstract class CosmeticProvider {
Map.entry(CosmeticSlot.BOOTS, CosmeticArmorType::new), Map.entry(CosmeticSlot.BOOTS, CosmeticArmorType::new),
Map.entry(CosmeticSlot.OFFHAND, CosmeticArmorType::new), Map.entry(CosmeticSlot.OFFHAND, CosmeticArmorType::new),
Map.entry(CosmeticSlot.MAINHAND, CosmeticMainhandType::new),
Map.entry(CosmeticSlot.BACKPACK, CosmeticBackpackType::new), Map.entry(CosmeticSlot.BACKPACK, CosmeticBackpackType::new),
Map.entry(CosmeticSlot.BALLOON, CosmeticBalloonType::new) Map.entry(CosmeticSlot.BALLOON, CosmeticBalloonType::new)

View File

@@ -48,9 +48,11 @@ public class CosmeticArmorType extends Cosmetic {
} }
public ItemStack getItem(@NotNull CosmeticUser user, ItemStack cosmeticItem) { public ItemStack getItem(@NotNull CosmeticUser user, ItemStack cosmeticItem) {
if (!(user.getEntity() instanceof HumanEntity humanEntity)) return null; Player player = user.getPlayer();
if (player == null) return null;
if (Settings.getSlotOption(equipSlot).isAddEnchantments()) { if (Settings.getSlotOption(equipSlot).isAddEnchantments()) {
ItemStack equippedItem = humanEntity.getInventory().getItem(equipSlot); ItemStack equippedItem = player.getInventory().getItem(equipSlot);
cosmeticItem.addUnsafeEnchantments(equippedItem.getEnchantments()); cosmeticItem.addUnsafeEnchantments(equippedItem.getEnchantments());
} }
// Basically, if force offhand is off AND there is no item in an offhand slot, then the equipment packet to add the cosmetic // Basically, if force offhand is off AND there is no item in an offhand slot, then the equipment packet to add the cosmetic

View File

@@ -5,13 +5,13 @@ import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.manager.UserBackpackManager; import com.hibiscusmc.hmccosmetics.user.manager.UserBackpackManager;
import com.hibiscusmc.hmccosmetics.user.manager.UserEntity; import com.hibiscusmc.hmccosmetics.user.manager.UserEntity;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager; import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager;
import lombok.Getter; import lombok.Getter;
import me.lojosho.hibiscuscommons.util.packets.PacketManager; import me.lojosho.hibiscuscommons.util.packets.PacketManager;
import me.lojosho.shaded.configurate.ConfigurationNode; import me.lojosho.shaded.configurate.ConfigurationNode;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -22,7 +22,6 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level;
public class CosmeticBackpackType extends Cosmetic { public class CosmeticBackpackType extends Cosmetic {
@@ -65,6 +64,14 @@ public class CosmeticBackpackType extends Cosmetic {
HMCCPacketManager.sendEntitySpawnPacket(entityLocation, firstArmorStandId, EntityType.ARMOR_STAND, UUID.randomUUID(), outsideViewers); HMCCPacketManager.sendEntitySpawnPacket(entityLocation, firstArmorStandId, EntityType.ARMOR_STAND, UUID.randomUUID(), outsideViewers);
HMCCPacketManager.sendArmorstandMetadata(firstArmorStandId, outsideViewers); HMCCPacketManager.sendArmorstandMetadata(firstArmorStandId, outsideViewers);
if (user.getPlayer() != null) {
AttributeInstance scaleAttribute = user.getPlayer().getAttribute(Attribute.GENERIC_SCALE);
if (scaleAttribute != null) {
HMCCPacketManager.sendEntityScalePacket(user.getUserBackpackManager().getFirstArmorStandId(), scaleAttribute.getValue(), outsideViewers);
}
}
PacketManager.equipmentSlotUpdate(firstArmorStandId, EquipmentSlot.HEAD, user.getUserCosmeticItem(this, getItem()), outsideViewers); PacketManager.equipmentSlotUpdate(firstArmorStandId, EquipmentSlot.HEAD, user.getUserCosmeticItem(this, getItem()), outsideViewers);
// If true, it will send the riding packet to all players. If false, it will send the riding packet only to new players // If true, it will send the riding packet to all players. If false, it will send the riding packet only to new players
if (Settings.isBackpackForceRidingEnabled()) HMCCPacketManager.sendRidingPacket(entity.getEntityId(), firstArmorStandId, entityManager.getViewers()); if (Settings.isBackpackForceRidingEnabled()) HMCCPacketManager.sendRidingPacket(entity.getEntityId(), firstArmorStandId, entityManager.getViewers());

View File

@@ -1,23 +0,0 @@
package com.hibiscusmc.hmccosmetics.cosmetic.types;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.HMCCPlayerUtils;
import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager;
import me.lojosho.shaded.configurate.ConfigurationNode;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class CosmeticMainhandType extends Cosmetic {
public CosmeticMainhandType(String id, ConfigurationNode config) {
super(id, config);
}
@Override
protected void doUpdate(@NotNull CosmeticUser user) {
Player player = user.getPlayer();
HMCCPacketManager.equipmentSlotUpdate(player.getEntityId(), user, getSlot(), HMCCPacketManager.getViewers(player.getLocation()));
}
}

View File

@@ -1,6 +1,5 @@
package com.hibiscusmc.hmccosmetics.database.types; package com.hibiscusmc.hmccosmetics.database.types;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot; import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
@@ -9,7 +8,6 @@ import com.hibiscusmc.hmccosmetics.database.UserData;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.EnumUtils;
import org.bukkit.Bukkit;
import org.bukkit.Color; import org.bukkit.Color;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -87,7 +85,7 @@ public abstract class Data {
private boolean shouldHiddenSave(CosmeticUser.HiddenReason reason) { private boolean shouldHiddenSave(CosmeticUser.HiddenReason reason) {
switch (reason) { switch (reason) {
case EMOTE, NONE, GAMEMODE, WORLD, DISABLED -> { case EMOTE, NONE, GAMEMODE, WORLD, DISABLED, POTION -> {
return false; return false;
} }
default -> { default -> {

View File

@@ -39,10 +39,12 @@ public class MySQLData extends SQLData {
try { try {
openConnection(); openConnection();
if (connection == null) throw new NullPointerException("Connection is null"); if (connection == null) throw new NullPointerException("Connection is null");
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `COSMETICDATABASE` " + try (PreparedStatement preparedStatement = connection.prepareStatement("CREATE TABLE IF NOT EXISTS `COSMETICDATABASE` " +
"(UUID varchar(36) PRIMARY KEY, " + "(UUID varchar(36) PRIMARY KEY, " +
"COSMETICS MEDIUMTEXT " + "COSMETICS MEDIUMTEXT " +
");").execute(); ");")) {
preparedStatement.execute();
}
} catch (SQLException | NullPointerException e) { } catch (SQLException | NullPointerException e) {
plugin.getLogger().severe(""); plugin.getLogger().severe("");
plugin.getLogger().severe(""); plugin.getLogger().severe("");
@@ -60,17 +62,11 @@ public class MySQLData extends SQLData {
@Override @Override
public void clear(UUID uniqueId) { public void clear(UUID uniqueId) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> { Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
PreparedStatement preparedSt = null; try (PreparedStatement preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;")) {
try {
preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;");
preparedSt.setString(1, uniqueId.toString()); preparedSt.setString(1, uniqueId.toString());
preparedSt.executeUpdate(); preparedSt.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
try {
if (preparedSt != null) preparedSt.close();
} catch (SQLException e) {}
} }
}); });
} }

View File

@@ -6,7 +6,6 @@ import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.database.UserData; import com.hibiscusmc.hmccosmetics.database.UserData;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Color;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@@ -23,22 +22,17 @@ public abstract class SQLData extends Data {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
UserData data = new UserData(uniqueId); UserData data = new UserData(uniqueId);
PreparedStatement preparedStatement = null; try (PreparedStatement preparedStatement = preparedStatement("SELECT * FROM COSMETICDATABASE WHERE UUID = ?;")){
try {
preparedStatement = preparedStatement("SELECT * FROM COSMETICDATABASE WHERE UUID = ?;");
preparedStatement.setString(1, uniqueId.toString()); preparedStatement.setString(1, uniqueId.toString());
ResultSet rs = preparedStatement.executeQuery(); try (ResultSet rs = preparedStatement.executeQuery()) {
if (rs.next()) { if (rs.next()) {
String rawData = rs.getString("COSMETICS"); String rawData = rs.getString("COSMETICS");
HashMap<CosmeticSlot, Map.Entry<Cosmetic, Integer>> cosmetics = deserializeData(rawData); HashMap<CosmeticSlot, Map.Entry<Cosmetic, Integer>> cosmetics = deserializeData(rawData);
data.setCosmetics(cosmetics); data.setCosmetics(cosmetics);
}
} }
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
try {
if (preparedStatement != null) preparedStatement.close();
} catch (SQLException e) {}
} }
return data; return data;
}); });
@@ -48,18 +42,12 @@ public abstract class SQLData extends Data {
@SuppressWarnings("resource") @SuppressWarnings("resource")
public void save(CosmeticUser user) { public void save(CosmeticUser user) {
Runnable run = () -> { Runnable run = () -> {
PreparedStatement preparedSt = null; try (PreparedStatement preparedSt = preparedStatement("REPLACE INTO COSMETICDATABASE(UUID,COSMETICS) VALUES(?,?);")) {
try {
preparedSt = preparedStatement("REPLACE INTO COSMETICDATABASE(UUID,COSMETICS) VALUES(?,?);");
preparedSt.setString(1, user.getUniqueId().toString()); preparedSt.setString(1, user.getUniqueId().toString());
preparedSt.setString(2, serializeData(user)); preparedSt.setString(2, serializeData(user));
preparedSt.executeUpdate(); preparedSt.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} finally {
try {
if (preparedSt != null) preparedSt.close();
} catch (SQLException e) {}
} }
}; };
if (!HMCCosmeticsPlugin.getInstance().isDisabled()) { if (!HMCCosmeticsPlugin.getInstance().isDisabled()) {

View File

@@ -35,10 +35,12 @@ public class SQLiteData extends SQLData {
connection = DriverManager.getConnection("jdbc:sqlite:" + dataFolder); connection = DriverManager.getConnection("jdbc:sqlite:" + dataFolder);
openConnection(); openConnection();
connection.prepareStatement("CREATE TABLE IF NOT EXISTS `COSMETICDATABASE` " + try (PreparedStatement preparedStatement = connection.prepareStatement("CREATE TABLE IF NOT EXISTS `COSMETICDATABASE` " +
"(UUID varchar(36) PRIMARY KEY, " + "(UUID varchar(36) PRIMARY KEY, " +
"COSMETICS MEDIUMTEXT " + "COSMETICS MEDIUMTEXT " +
");").execute(); ");")) {
preparedStatement.execute();
}
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -48,17 +50,11 @@ public class SQLiteData extends SQLData {
@SuppressWarnings("resource") @SuppressWarnings("resource")
public void clear(UUID uniqueId) { public void clear(UUID uniqueId) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> { Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
PreparedStatement preparedSt = null; try (PreparedStatement preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;")){
try {
preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;");
preparedSt.setString(1, uniqueId.toString()); preparedSt.setString(1, uniqueId.toString());
preparedSt.executeUpdate(); preparedSt.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
try {
if (preparedSt != null) preparedSt.close();
} catch (SQLException e) {}
} }
}); });
} }

View File

@@ -14,21 +14,18 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import dev.triumphteam.gui.builder.item.ItemBuilder; import dev.triumphteam.gui.builder.item.ItemBuilder;
import dev.triumphteam.gui.components.GuiType; import dev.triumphteam.gui.components.GuiType;
import dev.triumphteam.gui.components.InventoryProvider;
import dev.triumphteam.gui.guis.Gui; import dev.triumphteam.gui.guis.Gui;
import dev.triumphteam.gui.guis.GuiItem; import dev.triumphteam.gui.guis.GuiItem;
import lombok.Getter; import lombok.Getter;
import me.lojosho.hibiscuscommons.config.serializer.ItemSerializer; import me.lojosho.hibiscuscommons.config.serializer.ItemSerializer;
import me.lojosho.hibiscuscommons.hooks.Hooks; import me.lojosho.hibiscuscommons.hooks.Hooks;
import me.lojosho.hibiscuscommons.util.AdventureUtils; import me.lojosho.hibiscuscommons.util.AdventureUtils;
import me.lojosho.hibiscuscommons.util.StringUtils;
import me.lojosho.shaded.configurate.ConfigurationNode; import me.lojosho.shaded.configurate.ConfigurationNode;
import me.lojosho.shaded.configurate.serialize.SerializationException; import me.lojosho.shaded.configurate.serialize.SerializationException;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -185,18 +182,25 @@ public class Menu {
if (taskid.get() != -1) Bukkit.getScheduler().cancelTask(taskid.get()); if (taskid.get() != -1) Bukkit.getScheduler().cancelTask(taskid.get());
}); });
Runnable openGuiTask = () -> {
gui.open(viewer);
updateMenu(viewer, cosmeticHolder, gui); // fixes shading? I know I do this twice but it's easier than writing a whole new class to deal with this shit
};
// API // API
if (cosmeticHolder instanceof CosmeticUser user) { if (cosmeticHolder instanceof CosmeticUser user) {
PlayerMenuOpenEvent event = new PlayerMenuOpenEvent(user, this); PlayerMenuOpenEvent event = new PlayerMenuOpenEvent(user, this);
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> Bukkit.getPluginManager().callEvent(event)); Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> {
if (event.isCancelled()) return; Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
openGuiTask.run();
}
});
} }
// Internal // Internal
else {
Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), () -> { Bukkit.getScheduler().runTask(HMCCosmeticsPlugin.getInstance(), openGuiTask);
gui.open(viewer); }
updateMenu(viewer, cosmeticHolder, gui); // fixes shading? I know I do this twice but it's easier than writing a whole new class to deal with this shit
});
} }
private void updateMenu(Player viewer, CosmeticHolder cosmeticHolder, Gui gui) { private void updateMenu(Player viewer, CosmeticHolder cosmeticHolder, Gui gui) {

View File

@@ -3,8 +3,6 @@ package com.hibiscusmc.hmccosmetics.gui;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import lombok.Getter;
import lombok.Setter;
import me.lojosho.shaded.configurate.CommentedConfigurationNode; import me.lojosho.shaded.configurate.CommentedConfigurationNode;
import me.lojosho.shaded.configurate.ConfigurateException; import me.lojosho.shaded.configurate.ConfigurateException;
import me.lojosho.shaded.configurate.yaml.YamlConfigurationLoader; import me.lojosho.shaded.configurate.yaml.YamlConfigurationLoader;

View File

@@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.logging.Level;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class Actions { public class Actions {
@@ -30,7 +31,6 @@ public class Actions {
private static final ActionCosmeticHide ACTION_HIDE = new ActionCosmeticHide(); private static final ActionCosmeticHide ACTION_HIDE = new ActionCosmeticHide();
private static final ActionCosmeticToggle ACTION_TOGGLE = new ActionCosmeticToggle(); private static final ActionCosmeticToggle ACTION_TOGGLE = new ActionCosmeticToggle();
public static Action getAction(@NotNull String id) { public static Action getAction(@NotNull String id) {
return actions.get(id.toUpperCase()); return actions.get(id.toUpperCase());
} }
@@ -45,13 +45,13 @@ public class Actions {
public static void runActions(Player viewer, CosmeticHolder cosmeticHolder, @NotNull List<String> raw) { public static void runActions(Player viewer, CosmeticHolder cosmeticHolder, @NotNull List<String> raw) {
for (String a : raw) { for (String a : raw) {
String id = StringUtils.substringBetween(a, "[", "]").toUpperCase(); String id = StringUtils.substringBetween(a, "[", "]");
String message = StringUtils.substringAfter(a, "] "); String message = StringUtils.substringAfter(a, "] ");
MessagesUtil.sendDebugMessages("ID is " + id + " // Raw Data is " + message); MessagesUtil.sendDebugMessages("ID is " + id + " // Raw Data is " + message);
if (isAction(id)) { if (id != null && isAction(id.toUpperCase())) {
getAction(id).run(viewer, cosmeticHolder, message); getAction(id).run(viewer, cosmeticHolder, message);
} else { } else {
MessagesUtil.sendDebugMessages("Possible ids: " + actions.keySet()); MessagesUtil.sendDebugMessages("Invalid Action ID (" + id + ") used in menus (Full raw: '" + a + "'). Make sure all actions are properly typed out. Here are all possible actions: " + actions.keySet(), Level.WARNING);
} }
} }
} }

View File

@@ -1,67 +1,20 @@
package com.hibiscusmc.hmccosmetics.gui.special; package com.hibiscusmc.hmccosmetics.gui.special;
import com.hibiscusmc.hmccolor.HMCColorApi;
import com.hibiscusmc.hmccolor.shaded.gui.guis.Gui;
import com.hibiscusmc.hmccolor.shaded.gui.guis.GuiItem;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder; import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import me.lojosho.hibiscuscommons.hooks.Hooks;
import me.lojosho.hibiscuscommons.nms.NMSHandlers;
import me.lojosho.hibiscuscommons.util.AdventureUtils;
import me.lojosho.hibiscuscommons.util.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class DyeMenu { public interface DyeMenu {
public static void openMenu(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, Cosmetic cosmetic) {
if (!Hooks.isActiveHook("HMCColor")) {
addCosmetic(viewer, cosmeticHolder, cosmetic, null);
return;
}
ItemStack originalItem = cosmetic.getItem();
if (originalItem == null || !cosmetic.isDyeable()) return;
Gui gui = HMCColorApi.createColorMenu(viewer); /**
gui.updateTitle(AdventureUtils.MINI_MESSAGE.deserialize(Hooks.processPlaceholders(viewer, StringUtils.parseStringToString(Settings.getDyeMenuName())))); * Overrideable method that is called when a player wishing to dye a menu.
gui.setItem(Settings.getDyeMenuInputSlot(), new GuiItem(originalItem)); * After the method is called, the menu plugin itself is supposed to handle everything else, including adding the cosmetic to the CosmeticHolder
gui.setDefaultTopClickAction(event -> { *
if (event.getSlot() == Settings.getDyeMenuOutputSlot()) { * @param viewer The player that is viewing the menu
ItemStack item = event.getInventory().getItem(Settings.getDyeMenuOutputSlot()); * @param cosmeticHolder The CosmeticHolder that is being dyed (Can be different from the viewer)
if (item == null) return; * @param cosmetic (The cosmetic that is wished to be dyed)
*/
void openMenu(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, @NotNull Cosmetic cosmetic);
Color color = NMSHandlers.getHandler().getUtilHandler().getColor(item);
if (color == null) return;
addCosmetic(viewer, cosmeticHolder, cosmetic, color);
event.setCancelled(true);
} else event.setCancelled(true);
});
gui.setPlayerInventoryAction(event -> event.setCancelled(true));
gui.setCloseGuiAction(event -> {});
gui.open(viewer);
}
public static void openMenu(@NotNull CosmeticUser user, Cosmetic cosmetic) {
Player player = user.getPlayer();
if (player == null) return;
openMenu(player, user, cosmetic);
}
private static void addCosmetic(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, @NotNull Cosmetic cosmetic, @Nullable Color color) {
cosmeticHolder.addCosmetic(cosmetic, color);
viewer.setItemOnCursor(new ItemStack(Material.AIR));
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
viewer.closeInventory();
cosmeticHolder.updateCosmetic(cosmetic.getSlot());
}, 2);
}
} }

View File

@@ -0,0 +1,42 @@
package com.hibiscusmc.hmccosmetics.gui.special;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class DyeMenuProvider {
private static DyeMenu instance = null;
/**
* Sets the provider of the DyeMenu. Check {@link DyeMenuProvider#hasMenuProvider()} before attempting to set this,
* it is locked once a dye menu has been set!
* @param dyeMenu The dye menu implementation that wishes to be the provider.
* @throws IllegalStateException IllegalStateException will be thrown if a dye menu provider already is set by another plugin.
*/
public static void setDyeMenuProvider(@NotNull DyeMenu dyeMenu) throws IllegalStateException {
if (instance != null) {
throw new IllegalStateException("DyeMenu Implementation has already been set by another plugin.");
}
instance = dyeMenu;
}
/**
* Called when wishing to dye a cosmetic to hand it off to the dye menu implementation
* @param viewer The viewer of the menu
* @param cosmeticHolder The cosmetic holder that the player viewer wishing to modify (could be themselves or another CosmeticHolder)
* @param cosmetic The cosmetic the user wishes to dye
*/
public static void openMenu(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, @NotNull Cosmetic cosmetic) {
instance.openMenu(viewer, cosmeticHolder, cosmetic);
}
/**
* Does HMCC have a dye menu provider already set?
* @return True if it is already set and locked; false if none have been set.
*/
public static boolean hasMenuProvider() {
return instance != null;
}
}

View File

@@ -0,0 +1,58 @@
package com.hibiscusmc.hmccosmetics.gui.special.impl;
import com.hibiscusmc.hmccolor.HMCColorApi;
import com.hibiscusmc.hmccolor.shaded.gui.guis.Gui;
import com.hibiscusmc.hmccolor.shaded.gui.guis.GuiItem;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticHolder;
import com.hibiscusmc.hmccosmetics.gui.special.DyeMenu;
import me.lojosho.hibiscuscommons.hooks.Hooks;
import me.lojosho.hibiscuscommons.nms.NMSHandlers;
import me.lojosho.hibiscuscommons.util.AdventureUtils;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class HMCColorDyeMenu implements DyeMenu {
@Override
public void openMenu(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, @NotNull Cosmetic cosmetic) {
ItemStack originalItem = cosmetic.getItem();
if (originalItem == null || !cosmetic.isDyeable()) return;
Gui gui = HMCColorApi.createColorMenu(viewer);
gui.updateTitle(AdventureUtils.MINI_MESSAGE.deserialize(Hooks.processPlaceholders(viewer, Settings.getDyeMenuName())));
gui.setItem(Settings.getDyeMenuInputSlot(), new GuiItem(originalItem));
gui.setDefaultTopClickAction(event -> {
if (event.getSlot() == Settings.getDyeMenuOutputSlot()) {
ItemStack item = event.getInventory().getItem(Settings.getDyeMenuOutputSlot());
if (item == null) return;
Color color = NMSHandlers.getHandler().getUtilHandler().getColor(item);
if (color == null) return;
addCosmetic(viewer, cosmeticHolder, cosmetic, color);
event.setCancelled(true);
} else event.setCancelled(true);
});
gui.setPlayerInventoryAction(event -> event.setCancelled(true));
gui.setCloseGuiAction(event -> {});
gui.open(viewer);
}
private void addCosmetic(@NotNull Player viewer, @NotNull CosmeticHolder cosmeticHolder, @NotNull Cosmetic cosmetic, @Nullable Color color) {
cosmeticHolder.addCosmetic(cosmetic, color);
viewer.setItemOnCursor(new ItemStack(Material.AIR));
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
viewer.closeInventory();
cosmeticHolder.updateCosmetic(cosmetic.getSlot());
}, 2);
}
}

View File

@@ -8,6 +8,7 @@ import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetics;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType; import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType;
import com.hibiscusmc.hmccosmetics.gui.action.Actions; import com.hibiscusmc.hmccosmetics.gui.action.Actions;
import com.hibiscusmc.hmccosmetics.gui.special.DyeMenu; import com.hibiscusmc.hmccosmetics.gui.special.DyeMenu;
import com.hibiscusmc.hmccosmetics.gui.special.DyeMenuProvider;
import com.hibiscusmc.hmccosmetics.gui.type.Type; import com.hibiscusmc.hmccosmetics.gui.type.Type;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
@@ -66,14 +67,11 @@ public class TypeCosmetic extends Type {
MessagesUtil.sendDebugMessages("Required click type: " + requiredClick); MessagesUtil.sendDebugMessages("Required click type: " + requiredClick);
MessagesUtil.sendDebugMessages("Click type: " + clickType.name()); MessagesUtil.sendDebugMessages("Click type: " + clickType.name());
boolean isRequiredClick = requiredClick.equalsIgnoreCase("ANY") || requiredClick.equalsIgnoreCase(clickType.name());
boolean isDyeClick = dyeClick.equalsIgnoreCase("ANY") || dyeClick.equalsIgnoreCase(clickType.name());
if (!isRequiredClick && !isDyeClick) {
MessagesUtil.sendMessage(viewer.getPlayer(), "invalid-click-type");
return;
}
if (!isRequiredClick && isDyeClick) isUnEquippingCosmetic = false; final boolean isRequiredClick = requiredClick.equalsIgnoreCase("ANY") || requiredClick.equalsIgnoreCase(clickType.name());
final boolean isDyeClick = dyeClick.equalsIgnoreCase("ANY") || dyeClick.equalsIgnoreCase(clickType.name());
if (!isRequiredClick) isUnEquippingCosmetic = false;
List<String> actionStrings = new ArrayList<>(); List<String> actionStrings = new ArrayList<>();
ConfigurationNode actionConfig = config.node("actions"); ConfigurationNode actionConfig = config.node("actions");
@@ -105,9 +103,11 @@ public class TypeCosmetic extends Type {
} else { } else {
if (!actionConfig.node("on-equip").virtual()) actionStrings.addAll(actionConfig.node("on-equip").getList(String.class)); if (!actionConfig.node("on-equip").virtual()) actionStrings.addAll(actionConfig.node("on-equip").getList(String.class));
MessagesUtil.sendDebugMessages("on-equip"); MessagesUtil.sendDebugMessages("on-equip");
MessagesUtil.sendDebugMessages("Preparing for on-equip with the following checks:");
MessagesUtil.sendDebugMessages("CosmeticDyeable? " + cosmetic.isDyeable() + " / isDyeClick? " + isDyeClick + " / isHMCColorActive? " + Hooks.isActiveHook("HMCColor"));
// TODO: Redo this // TODO: Redo this
if (cosmetic.isDyeable() && isDyeClick && Hooks.isActiveHook("HMCColor")) { if (cosmetic.isDyeable() && isDyeClick && DyeMenuProvider.hasMenuProvider()) {
DyeMenu.openMenu(viewer, cosmeticHolder, cosmetic); DyeMenuProvider.openMenu(viewer, cosmeticHolder, cosmetic);
} else if (isRequiredClick) { } else if (isRequiredClick) {
cosmeticHolder.addCosmetic(cosmetic); cosmeticHolder.addCosmetic(cosmetic);
} }

View File

@@ -9,7 +9,6 @@ import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.TranslationUtil; import com.hibiscusmc.hmccosmetics.util.TranslationUtil;
import me.clip.placeholderapi.expansion.PlaceholderExpansion; import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.apache.commons.lang3.EnumUtils;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;

View File

@@ -20,7 +20,6 @@ import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;

View File

@@ -1,10 +1,5 @@
package com.hibiscusmc.hmccosmetics.listener; package com.hibiscusmc.hmccosmetics.listener;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.*;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.Pair;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.api.events.PlayerCosmeticPostEquipEvent; import com.hibiscusmc.hmccosmetics.api.events.PlayerCosmeticPostEquipEvent;
import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.config.Settings;
@@ -52,17 +47,6 @@ import java.util.*;
public class PlayerGameListener implements Listener { public class PlayerGameListener implements Listener {
public PlayerGameListener() {
registerInventoryClickListener();
registerMenuChangeListener();
registerEntityStatusListener();
registerPlayerEquipmentListener();
registerPlayerArmListener();
registerEntityUseListener();
registerSlotChangeListener();
registerPassengerSetListener();
}
@EventHandler(priority = EventPriority.LOW) @EventHandler(priority = EventPriority.LOW)
public void onPlayerClick(@NotNull InventoryClickEvent event) { public void onPlayerClick(@NotNull InventoryClickEvent event) {
// || !event.getClickedInventory().getType().equals(InventoryType.PLAYER) // || !event.getClickedInventory().getType().equals(InventoryType.PLAYER)
@@ -426,251 +410,6 @@ public class PlayerGameListener implements Listener {
user.showCosmetics(CosmeticUser.HiddenReason.PLUGIN); user.showCosmetics(CosmeticUser.HiddenReason.PLUGIN);
} }
private void registerInventoryClickListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, List.of(PacketType.Play.Client.WINDOW_CLICK), ListenerOptions.ASYNC) {
@Override
public void onPacketReceiving(PacketEvent event) {
Player player = event.getPlayer();
int invTypeClicked = event.getPacket().getIntegers().read(0);
int slotClicked = -999;
if (NMSHandlers.getVersion().isHigherOrEqual(MinecraftVersion.v1_21_5)) {
slotClicked = event.getPacket().getShorts().read(0);
} else {
slotClicked = event.getPacket().getIntegers().read(2);
}
// Must be a player inventory.
if (invTypeClicked != 0) return;
// -999 is when a player clicks outside their inventory. https://wiki.vg/Inventory#Player_Inventory
if (slotClicked == -999) return;
if (event.getPlayer() == null) return;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
if (user.isInWardrobe()) return;
CosmeticSlot cosmeticSlot = HMCCInventoryUtils.NMSCosmeticSlot(slotClicked);
if (cosmeticSlot == null) return;
if (!user.hasCosmeticInSlot(cosmeticSlot)) return;
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> user.updateCosmetic(cosmeticSlot), 1);
MessagesUtil.sendDebugMessages("Packet fired, updated cosmetic " + cosmeticSlot);
}
});
}
private void registerMenuChangeListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, List.of(PacketType.Play.Server.WINDOW_ITEMS), ListenerOptions.ASYNC) {
@Override
public void onPacketSending(PacketEvent event) {
MessagesUtil.sendDebugMessages("Menu Initial ");
Player player = event.getPlayer();
if (event.getPlayer() == null) return;
int windowID = event.getPacket().getIntegers().read(0);
List<ItemStack> slotData = event.getPacket().getItemListModifier().read(0);
if (windowID != 0) return;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
HashMap<Integer, ItemStack> items = new HashMap<>();
if (!user.isInWardrobe()) {
for (Cosmetic cosmetic : user.getCosmetics()) {
if ((cosmetic instanceof CosmeticArmorType cosmeticArmorType)) {
boolean requireEmpty = Settings.getSlotOption(cosmeticArmorType.getEquipSlot()).isRequireEmpty();
boolean isAir = user.getPlayer().getInventory().getItem(cosmeticArmorType.getEquipSlot()).getType().isAir();
MessagesUtil.sendDebugMessages("Menu Fired (Checks) - " + cosmeticArmorType.getId() + " - " + requireEmpty + " - " + isAir);
if (requireEmpty && !isAir) continue;
items.put(HMCCInventoryUtils.getPacketArmorSlot(cosmeticArmorType.getEquipSlot()), user.getUserCosmeticItem(cosmeticArmorType));
}
}
}
PacketContainer packet = new PacketContainer(PacketType.Play.Server.WINDOW_ITEMS);
packet.getIntegers().write(0, 0);
for (int slot = 0; slot < 46; slot++) {
if ((slot >= 5 && slot <= 8) || slot == 45) {
if (!items.containsKey(slot)) continue;
slotData.set(slot, items.get(slot));
if (Settings.isDebugMode()) MessagesUtil.sendDebugMessages("Set " + slot + " as " + items.get(slot));
}
}
packet.getItemListModifier().write(0, slotData);
packet.getItemModifier().write(0, event.getPacket().getItemModifier().read(0));
event.setPacket(packet);
MessagesUtil.sendDebugMessages("Menu Fired, updated cosmetics " + " on slotdata " + windowID + " with " + slotData.size());
/*
for (Cosmetic cosmetic : user.getCosmetic()) {
if ((cosmetic instanceof CosmeticArmorType) || (cosmetic instanceof CosmeticMainhandType)) {
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> {
user.updateCosmetic(cosmetic);
}, 1);
}
}
*/
}
});
}
private void registerSlotChangeListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.SET_SLOT) {
@Override
public void onPacketSending(PacketEvent event) {
MessagesUtil.sendDebugMessages("SetSlot Initial ");
Player player = event.getPlayer();
if (event.getPlayer() == null) return;
int windowID = event.getPacket().getIntegers().read(0);
if (windowID != 0) return;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
if (user.isInWardrobe()) return;
int slot = event.getPacket().getIntegers().read(2);
MessagesUtil.sendDebugMessages("SetSlot Slot " + slot);
CosmeticSlot cosmeticSlot = HMCCInventoryUtils.NMSCosmeticSlot(slot);
EquipmentSlot equipmentSlot = HMCCInventoryUtils.getPacketArmorSlot(slot);
if (cosmeticSlot == null || equipmentSlot == null) return;
if (!user.hasCosmeticInSlot(cosmeticSlot)) return;
if (Settings.getSlotOption(equipmentSlot).isRequireEmpty()) {
if (!player.getInventory().getItem(equipmentSlot).getType().isAir()) return;
}
event.getPacket().getItemModifier().write(0, user.getUserCosmeticItem(cosmeticSlot));
}
});
}
private void registerPlayerEquipmentListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_EQUIPMENT) {
@Override
public void onPacketSending(PacketEvent event) {
Player player = event.getPlayer(); // Player that's sent
int entityID = event.getPacket().getIntegers().read(0);
// User
CosmeticUser user = CosmeticUsers.getUser(entityID);
if (user == null) return;
if (user.isInWardrobe()) return;
List<com.comphenix.protocol.wrappers.Pair<EnumWrappers.ItemSlot, ItemStack>> armor = event.getPacket().getSlotStackPairLists().read(0);
for (int i = 0; i < armor.size(); i++) {
com.comphenix.protocol.wrappers.Pair<EnumWrappers.ItemSlot, ItemStack> pair = armor.get(i);
switch (pair.getFirst()) {
case MAINHAND -> {
if (user.getPlayer() == event.getPlayer()) continue; // When a player scrolls real fast, it messes up the mainhand. This fixes it
if (user.getPlayer() != null && user.getPlayer().isInvisible()) continue; // Fixes integration with GSit still showing mainhand even when hidden
armor.set(i, new Pair<>(pair.getFirst(), user.getPlayer().getInventory().getItemInMainHand()));
}
default -> {
EquipmentSlot slot = HMCCInventoryUtils.getEquipmentSlot(pair.getFirst());
CosmeticSlot cosmeticSlot = HMCCInventoryUtils.getItemSlotToCosmeticSlot(pair.getFirst());
if (slot == null || cosmeticSlot == null) continue;
if (Settings.getSlotOption(slot).isRequireEmpty()
&& !user.getPlayer().getInventory().getItem(slot).getType().isAir()) continue;
CosmeticArmorType cosmeticArmor = (CosmeticArmorType) user.getCosmetic(cosmeticSlot);
if (cosmeticArmor == null) continue;
ItemStack item = user.getUserCosmeticItem(cosmeticArmor);
if (item == null) continue;
Pair<EnumWrappers.ItemSlot, ItemStack> armorPair = new Pair<>(HMCCInventoryUtils.itemBukkitSlot(slot), item);
armor.set(i, armorPair);
}
}
}
event.getPacket().getSlotStackPairLists().write(0, armor);
MessagesUtil.sendDebugMessages("Equipment for " + user.getPlayer().getName() + " has been updated for " + player.getName());
}
});
}
private void registerEntityStatusListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_STATUS) {
@Override
public void onPacketSending(PacketEvent event) {
int entityid = event.getPacket().getIntegers().read(0);
byte status = event.getPacket().getBytes().read(0);
MessagesUtil.sendDebugMessages("EntityStatus Initial " + entityid + " - " + status);
if (status != 55) return;
CosmeticUser user = CosmeticUsers.getUser(entityid);
if (user == null) {
MessagesUtil.sendDebugMessages("EntityStatus User is null");
return;
}
if (!user.hasCosmeticInSlot(CosmeticSlot.OFFHAND)) return;
event.setCancelled(true);
}
});
}
private void registerPassengerSetListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.MOUNT) {
@Override
public void onPacketSending(PacketEvent event) {
CosmeticUser viewerUser = CosmeticUsers.getUser(event.getPlayer().getUniqueId());
if (viewerUser == null) return;
if (viewerUser.isInWardrobe()) return;
int ownerId = event.getPacket().getIntegers().read(0);
MessagesUtil.sendDebugMessages("Mount Packet Sent - Read - EntityID: " + ownerId);
Entity entity = HMCCServerUtils.getEntity(ownerId);
if (entity == null) return;
CosmeticUser user = CosmeticUsers.getUser(entity.getUniqueId());
if (user == null) return;
MessagesUtil.sendDebugMessages("Mount Packet Sent - " + user.getUniqueId());
if (!user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) return;
if (user.getUserBackpackManager() == null) return;
// Basically, take the original passengers and "bump" them to the end of the list
int[] originalPassengers = event.getPacket().getIntegerArrays().read(0);
List<Integer> passengers = new ArrayList<>(user.getUserBackpackManager().getEntityManager().getIds());
passengers.addAll(Arrays.stream(originalPassengers).boxed().toList());
event.getPacket().getIntegerArrays().write(0, passengers.stream().mapToInt(Integer::intValue).toArray());
}
});
}
private void registerPlayerArmListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Client.ARM_ANIMATION) {
@Override
public void onPacketReceiving(PacketEvent event) {
if (event.getPlayer() == null) return;
Player player = event.getPlayer();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return;
if (!user.isInWardrobe()) return;
if (!user.getWardrobeManager().getWardrobeStatus().equals(UserWardrobeManager.WardrobeStatus.RUNNING)) return;
Menu menu = user.getWardrobeManager().getLastOpenMenu();
if (menu == null) return;
menu.openMenu(user);
event.setCancelled(true);
}
});
}
private void registerEntityUseListener() {
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmeticsPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Client.USE_ENTITY) {
@Override
public void onPacketReceiving(PacketEvent event) {
if (event.getPlayer() == null) return;
CosmeticUser user = CosmeticUsers.getUser(event.getPlayer());
if (user == null) return;
if (user.isInWardrobe()) {
event.setCancelled(true);
}
}
});
}
@Nullable @Nullable
private EquipmentSlot getArmorSlot(final Material material) { private EquipmentSlot getArmorSlot(final Material material) {
for (final EquipmentSlot slot : EquipmentSlot.values()) { for (final EquipmentSlot slot : EquipmentSlot.values()) {

View File

@@ -0,0 +1,225 @@
package com.hibiscusmc.hmccosmetics.packets;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType;
import com.hibiscusmc.hmccosmetics.gui.Menu;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.user.manager.UserBackpackManager;
import com.hibiscusmc.hmccosmetics.user.manager.UserWardrobeManager;
import com.hibiscusmc.hmccosmetics.util.HMCCInventoryUtils;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager;
import me.lojosho.hibiscuscommons.packets.PacketAction;
import me.lojosho.hibiscuscommons.packets.PacketInterface;
import me.lojosho.hibiscuscommons.packets.wrapper.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class CosmeticPacketInterface implements PacketInterface {
@Override
public @NotNull PacketAction writeContainerContent(@NotNull Player player, @NotNull ContainerContentWrapper wrapper) {
int windowId = wrapper.getWindowId();
MessagesUtil.sendDebugMessages("writeContainerContent (windowid: " + windowId + " )");
if (windowId != 0) return PacketAction.NOTHING;
List<ItemStack> slotData = wrapper.getSlotData();
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return PacketAction.NOTHING;
HashMap<Integer, ItemStack> cosmeticItems = new HashMap<>();
if (!user.isInWardrobe()) {
for (Cosmetic cosmetic : user.getCosmetics()) {
if (cosmetic instanceof CosmeticArmorType armorType) {
boolean requireEmpty = Settings.getSlotOption(armorType.getEquipSlot()).isRequireEmpty();
boolean isAir = user.getPlayer().getInventory().getItem(armorType.getEquipSlot()).getType().isAir();
MessagesUtil.sendDebugMessages("Menu Fired (Checks) - " + armorType.getId() + " - " + requireEmpty + " - " + isAir);
if (requireEmpty && !isAir) continue;
cosmeticItems.put(HMCCInventoryUtils.getPacketArmorSlot(armorType.getEquipSlot()), user.getUserCosmeticItem(armorType));
}
}
}
for (int slot = 0; slot < 46; slot++) {
if ((slot >= 5 && slot <= 8) || slot == 45) {
if (!cosmeticItems.containsKey(slot)) continue;
slotData.set(slot, cosmeticItems.get(slot));
if (Settings.isDebugMode()) MessagesUtil.sendDebugMessages("Set " + slot + " as " + cosmeticItems.get(slot));
}
}
wrapper.setSlotData(slotData);
MessagesUtil.sendDebugMessages("Menu Fired, updated cosmetics " + " on slotdata " + windowId + " with " + slotData.size());
return PacketAction.CHANGED;
}
@Override
public @NotNull PacketAction writeSlotContent(@NotNull Player player, @NotNull SlotContentWrapper wrapper) {
int windowId = wrapper.getWindowId();
int slot = wrapper.getSlot();
ItemStack itemStack = wrapper.getItemStack();
MessagesUtil.sendDebugMessages("SetSlot Initial ");
if (windowId != 0) return PacketAction.NOTHING;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null || user.isInWardrobe()) return PacketAction.NOTHING;
MessagesUtil.sendDebugMessages("SetSlot Slot " + slot);
CosmeticSlot cosmeticSlot = HMCCInventoryUtils.NMSCosmeticSlot(slot);
EquipmentSlot equipmentSlot = HMCCInventoryUtils.getPacketArmorSlot(slot);
if (cosmeticSlot == null || equipmentSlot == null) return PacketAction.NOTHING;
if (!user.hasCosmeticInSlot(cosmeticSlot)) return PacketAction.NOTHING;
if (Settings.getSlotOption(equipmentSlot).isRequireEmpty()) {
if (!player.getInventory().getItem(equipmentSlot).getType().isAir()) return PacketAction.NOTHING;
}
wrapper.setItemStack(user.getUserCosmeticItem(cosmeticSlot));
return PacketAction.CHANGED;
}
@Override
public @NotNull PacketAction writeEquipmentContent(@NotNull Player player, @NotNull EntityEquipmentWrapper wrapper) {
if (player.getEntityId() != wrapper.getEntityId()) return PacketAction.NOTHING;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null || user.isInWardrobe()) return PacketAction.NOTHING;
Map<EquipmentSlot, ItemStack> armor = wrapper.getArmor();
for (Map.Entry<EquipmentSlot, ItemStack> armorSlot : armor.entrySet()) {
EquipmentSlot slot = armorSlot.getKey();
if (slot == EquipmentSlot.HAND) {
if (user.getPlayer().getUniqueId() == player.getUniqueId())
continue; // When a player scrolls real fast, it messes up the mainhand. This fixes it
if (user.getPlayer() != null && user.getPlayer().isInvisible())
continue; // Fixes integration with GSit still showing mainhand even when hidden
armor.put(slot, player.getInventory().getItemInMainHand());
} else {
CosmeticSlot cosmeticSlot = HMCCInventoryUtils.BukkitCosmeticSlot(slot);
if (cosmeticSlot == null) continue;
if (Settings.getSlotOption(slot).isRequireEmpty() && player.getInventory().getItem(slot).getType().isAir())
continue;
CosmeticArmorType cosmeticArmor = (CosmeticArmorType) user.getCosmetic(cosmeticSlot);
if (cosmeticArmor == null) continue;
ItemStack item = user.getUserCosmeticItem(cosmeticSlot);
if (item == null) continue;
armor.put(slot, item);
}
}
wrapper.setArmor(armor);
MessagesUtil.sendDebugMessages("Equipment for " + user.getPlayer().getName() + " has been updated for " + player.getName());
return PacketAction.CHANGED;
}
@Override
public @NotNull PacketAction writePassengerContent(@NotNull Player player, @NotNull PassengerWrapper wrapper) {
return PacketAction.NOTHING;
// TODO: Figure out what to do with this, because with it in, it ruins backpacks (they keep getting thrown to random locations).
// When you have this all disabled, it works better
/*
CosmeticUser viewerUser = CosmeticUsers.getUser(player);
if (viewerUser == null || viewerUser.isInWardrobe()) return PacketAction.NOTHING;
int ownerId = wrapper.getOwner();
List<Integer> originalPassengers = wrapper.getPassengers();
MessagesUtil.sendDebugMessages("Mount Packet Read - EntityID: " + ownerId);
Optional<CosmeticUser> optionalCosmeticUser = CosmeticUsers.values().stream().filter(user -> user.getPlayer() != null).filter(user -> ownerId == user.getPlayer().getEntityId()).findFirst();
if (optionalCosmeticUser.isEmpty()) return PacketAction.NOTHING;
CosmeticUser user = optionalCosmeticUser.get();
MessagesUtil.sendDebugMessages("Mount Packet Sent - " + user.getUniqueId());
if (!user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) return PacketAction.NOTHING;
if (user.getUserBackpackManager() == null) return PacketAction.NOTHING;
List<Integer> passengers = new ArrayList<>(user.getUserBackpackManager().getEntityManager().getIds());
passengers.addAll(originalPassengers);
wrapper.setPassengers(passengers);
return PacketAction.CHANGED;
*/
}
@Override
public PacketAction readPlayerScale(@NotNull Player player, @NotNull PlayerScaleWrapper wrapper) {
int entityId = wrapper.getEntityId();
Player changedPlayer = Bukkit.getOnlinePlayers().stream()
.filter(onlinePlayer -> onlinePlayer.getEntityId() == entityId)
.findFirst()
.orElse(null);
if (changedPlayer == null) return PacketAction.NOTHING;
CosmeticUser cosmeticUser = CosmeticUsers.getUser(changedPlayer.getUniqueId());
if (cosmeticUser == null || cosmeticUser.isInWardrobe()) return PacketAction.NOTHING;
UserBackpackManager backpack = cosmeticUser.getUserBackpackManager();
if (backpack != null) {
for (int cosmeticId : backpack.getEntityManager().getIds()) {
HMCCPacketManager.sendEntityScalePacket(cosmeticId, wrapper.getScale(), Collections.singletonList(player));
}
}
return PacketAction.NOTHING;
}
@Override
public @NotNull PacketAction readInventoryClick(@NotNull Player player, @NotNull InventoryClickWrapper wrapper) {
int clickType = wrapper.getClickType();
int slotNumber = wrapper.getSlotNumber();
if (clickType != 0 || slotNumber == -999) return PacketAction.NOTHING;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null || user.isInWardrobe()) return PacketAction.NOTHING;
CosmeticSlot cosmeticSlot = HMCCInventoryUtils.NMSCosmeticSlot(slotNumber);
if (cosmeticSlot == null || !user.hasCosmeticInSlot(cosmeticSlot)) return PacketAction.NOTHING;
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> user.updateCosmetic(cosmeticSlot), 1);
MessagesUtil.sendDebugMessages("Packet fired, updated cosmetic " + cosmeticSlot);
return PacketAction.NOTHING;
}
@Override
public @NotNull PacketAction readPlayerAction(@NotNull Player player, @NotNull PlayerActionWrapper wrapper) {
String actionType = wrapper.getActionType();
MessagesUtil.sendDebugMessages("EntityStatus Initial " + player.getEntityId() + " - " + actionType);
// If it's not SWAP_ITEM_WITH_OFFHAND, ignore
if (!actionType.equalsIgnoreCase("SWAP_ITEM_WITH_OFFHAND")) return PacketAction.NOTHING;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) {
MessagesUtil.sendDebugMessages("EntityStatus User is null");
return PacketAction.NOTHING;
}
if (!user.hasCosmeticInSlot(CosmeticSlot.OFFHAND)) return PacketAction.NOTHING;
return PacketAction.CANCELLED;
}
@Override
public @NotNull PacketAction readPlayerArm(@NotNull Player player, @NotNull PlayerSwingWrapper wrapper) {
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null || !user.isInWardrobe() || !user.getWardrobeManager().getWardrobeStatus().equals(UserWardrobeManager.WardrobeStatus.RUNNING)) return PacketAction.NOTHING;
Menu menu = user.getWardrobeManager().getLastOpenMenu();
if (menu == null) return PacketAction.NOTHING;
menu.openMenu(user);
return PacketAction.CANCELLED;
}
@Override
public @NotNull PacketAction readEntityHandle(@NotNull Player player, @NotNull PlayerInteractWrapper wrapper) {
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null || !user.isInWardrobe()) return PacketAction.NOTHING;
else return PacketAction.CANCELLED;
}
}

View File

@@ -13,7 +13,6 @@ import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType; import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType; import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBalloonType; import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBalloonType;
import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticMainhandType;
import com.hibiscusmc.hmccosmetics.database.UserData; import com.hibiscusmc.hmccosmetics.database.UserData;
import com.hibiscusmc.hmccosmetics.gui.Menus; import com.hibiscusmc.hmccosmetics.gui.Menus;
import com.hibiscusmc.hmccosmetics.user.manager.UserBackpackManager; import com.hibiscusmc.hmccosmetics.user.manager.UserBackpackManager;
@@ -22,7 +21,6 @@ import com.hibiscusmc.hmccosmetics.user.manager.UserWardrobeManager;
import com.hibiscusmc.hmccosmetics.util.HMCCInventoryUtils; import com.hibiscusmc.hmccosmetics.util.HMCCInventoryUtils;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager; import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager;
import com.ticxo.modelengine.api.nms.NMSHandler;
import lombok.Getter; import lombok.Getter;
import me.lojosho.hibiscuscommons.hooks.Hooks; import me.lojosho.hibiscuscommons.hooks.Hooks;
import me.lojosho.hibiscuscommons.nms.NMSHandlers; import me.lojosho.hibiscuscommons.nms.NMSHandlers;
@@ -30,7 +28,6 @@ import me.lojosho.hibiscuscommons.util.InventoryUtils;
import me.lojosho.hibiscuscommons.util.packets.PacketManager; import me.lojosho.hibiscuscommons.util.packets.PacketManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Color; import org.bukkit.Color;
import org.bukkit.FireworkEffect;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
@@ -39,6 +36,7 @@ import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.*; import org.bukkit.inventory.meta.*;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -144,13 +142,18 @@ public class CosmeticUser implements CosmeticHolder {
showCosmetics(HiddenReason.GAMEMODE); showCosmetics(HiddenReason.GAMEMODE);
} }
if (bukkitPlayer != null && Settings.getDisabledWorlds().contains(getEntity().getLocation().getWorld().getName())) { if (bukkitPlayer != null && Settings.getDisabledWorlds().contains(bukkitPlayer.getLocation().getWorld().getName())) {
MessagesUtil.sendDebugMessages("Hiding Cosmetics due to world"); MessagesUtil.sendDebugMessages("Hiding Cosmetics due to world");
hideCosmetics(CosmeticUser.HiddenReason.WORLD); hideCosmetics(CosmeticUser.HiddenReason.WORLD);
} else if (this.isHidden(HiddenReason.WORLD)) { } else if (this.isHidden(HiddenReason.WORLD)) {
MessagesUtil.sendDebugMessages("Showing Cosmetics due to world"); MessagesUtil.sendDebugMessages("Showing Cosmetics due to world");
showCosmetics(HiddenReason.WORLD); showCosmetics(HiddenReason.WORLD);
} }
if (bukkitPlayer != null && bukkitPlayer.hasPotionEffect(PotionEffectType.INVISIBILITY)) {
hideCosmetics(HiddenReason.POTION);
}
if (Settings.isAllPlayersHidden()) { if (Settings.isAllPlayersHidden()) {
hideCosmetics(HiddenReason.DISABLED); hideCosmetics(HiddenReason.DISABLED);
} }
@@ -345,7 +348,7 @@ public class CosmeticUser implements CosmeticHolder {
if (cosmetic instanceof CosmeticArmorType armorType) { if (cosmetic instanceof CosmeticArmorType armorType) {
item = armorType.getItem(this, cosmetic.getItem()); item = armorType.getItem(this, cosmetic.getItem());
} }
if (cosmetic instanceof CosmeticBackpackType || cosmetic instanceof CosmeticMainhandType) { if (cosmetic instanceof CosmeticBackpackType) {
item = cosmetic.getItem(); item = cosmetic.getItem();
} }
if (cosmetic instanceof CosmeticBalloonType) { if (cosmetic instanceof CosmeticBalloonType) {
@@ -603,7 +606,7 @@ public class CosmeticUser implements CosmeticHolder {
* @return Entity * @return Entity
*/ */
public Entity getEntity() { public Entity getEntity() {
return Bukkit.getEntity(uniqueId); return getPlayer();
} }
public Color getCosmeticColor(CosmeticSlot slot) { public Color getCosmeticColor(CosmeticSlot slot) {
@@ -626,7 +629,12 @@ public class CosmeticUser implements CosmeticHolder {
if (isInWardrobe() && !ignoreWardrobe) { if (isInWardrobe() && !ignoreWardrobe) {
if (WardrobeSettings.isTryCosmeticsInWardrobe() && userWardrobeManager.getWardrobeStatus().equals(UserWardrobeManager.WardrobeStatus.RUNNING)) return true; if (WardrobeSettings.isTryCosmeticsInWardrobe() && userWardrobeManager.getWardrobeStatus().equals(UserWardrobeManager.WardrobeStatus.RUNNING)) return true;
} }
return getEntity().hasPermission(cosmetic.getPermission()); final Player player = getPlayer();
if (player != null) return player.hasPermission(cosmetic.getPermission());
// This sucks, but basically if we can find a player, use that. If not, try to find the entity. If it can't find the entity, just return false.
final Entity entity = getEntity();
if (entity != null) return entity.hasPermission(cosmetic.getPermission());
return false;
} }
public void hidePlayer() { public void hidePlayer() {

View File

@@ -5,12 +5,12 @@ import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager; import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager;
import com.ticxo.modelengine.api.ModelEngineAPI;
import lombok.Getter; import lombok.Getter;
import me.lojosho.hibiscuscommons.hooks.Hooks;
import me.lojosho.hibiscuscommons.util.ServerUtils; import me.lojosho.hibiscuscommons.util.ServerUtils;
import me.lojosho.hibiscuscommons.util.packets.PacketManager; import me.lojosho.hibiscuscommons.util.packets.PacketManager;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -20,7 +20,6 @@ import org.bukkit.inventory.ItemStack;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level;
public class UserBackpackManager { public class UserBackpackManager {
@@ -59,6 +58,13 @@ public class UserBackpackManager {
HMCCPacketManager.sendEntitySpawnPacket(user.getEntity().getLocation(), getFirstArmorStandId(), EntityType.ARMOR_STAND, UUID.randomUUID(), getEntityManager().getViewers()); HMCCPacketManager.sendEntitySpawnPacket(user.getEntity().getLocation(), getFirstArmorStandId(), EntityType.ARMOR_STAND, UUID.randomUUID(), getEntityManager().getViewers());
HMCCPacketManager.sendArmorstandMetadata(getFirstArmorStandId(), outsideViewers); HMCCPacketManager.sendArmorstandMetadata(getFirstArmorStandId(), outsideViewers);
if (user.getPlayer() != null) {
AttributeInstance scaleAttribute = user.getPlayer().getAttribute(Attribute.GENERIC_SCALE);
if (scaleAttribute != null) {
HMCCPacketManager.sendEntityScalePacket(getFirstArmorStandId(), scaleAttribute.getValue(), outsideViewers);
}
}
Entity entity = user.getEntity(); Entity entity = user.getEntity();
int[] passengerIDs = new int[entity.getPassengers().size() + 1]; int[] passengerIDs = new int[entity.getPassengers().size() + 1];

View File

@@ -99,7 +99,12 @@ public class UserBalloonManager {
} }
public void remove() { public void remove() {
pufferfish.destroyPufferfish(); // This code is like a brick road, always bumpy.
// Basically, the balloon viewers ignore people in wardrobe, which well, if your the user in the wardrobe, ain't including you.
// This manually passes in the viewers for it to destroy, which includes the person in the wardrobe
if (user.getPlayer() != null && user.isInWardrobe()) pufferfish.destroyPufferfish(List.of(user.getPlayer()));
else pufferfish.destroyPufferfish();
if (balloonType == BalloonType.MODELENGINE) { if (balloonType == BalloonType.MODELENGINE) {
final ModeledEntity entity = ModelEngineAPI.getModeledEntity(modelEntity); final ModeledEntity entity = ModelEngineAPI.getModeledEntity(modelEntity);
if (entity == null) { if (entity == null) {

View File

@@ -1,17 +1,12 @@
package com.hibiscusmc.hmccosmetics.user.manager; package com.hibiscusmc.hmccosmetics.user.manager;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.HMCCPlayerUtils;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager; import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@@ -45,6 +40,12 @@ public class UserBalloonPufferfish extends UserEntity {
destroyed = true; destroyed = true;
} }
public void destroyPufferfish(List<Player> viewers) {
HMCCPacketManager.sendEntityDestroyPacket(pufferFishEntityId, viewers);
//getViewers().clear();
destroyed = true;
}
@Override @Override
public List<Player> refreshViewers(Location location) { public List<Player> refreshViewers(Location location) {
if (destroyed) return List.of(); //Prevents refreshing a destroyed entity if (destroyed) return List.of(); //Prevents refreshing a destroyed entity

View File

@@ -3,7 +3,6 @@ package com.hibiscusmc.hmccosmetics.user.manager;
import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers; import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.HMCCPlayerUtils;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager; import com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager;
import lombok.Getter; import lombok.Getter;
@@ -80,7 +79,7 @@ public class UserEntity {
if (this.getLocation() != null && this.getLocation().getWorld() == location.getWorld()) { if (this.getLocation() != null && this.getLocation().getWorld() == location.getWorld()) {
// Was thinking about using schedulers to just send the packet later... but that would be a lot of tasks and // Was thinking about using schedulers to just send the packet later... but that would be a lot of tasks and
// would probably cause more lag. Furthermore, the server "ticks" the cosmetics every second by defualt. So it's fine like this. // would probably cause more lag. Furthermore, the server "ticks" the cosmetics every second by defualt. So it's fine like this.
if (System.currentTimeMillis() - getLastPositionUpdate() <= Settings.getPacketEntityTeleportCooldown()) return; //if (System.currentTimeMillis() - getLastPositionUpdate() <= Settings.getPacketEntityTeleportCooldown()) return;
} }
this.location = location; this.location = location;
for (Integer entity : ids) { for (Integer entity : ids) {
@@ -99,7 +98,7 @@ public class UserEntity {
// First person backpacks need both packets to rotate properly, otherwise they look off // First person backpacks need both packets to rotate properly, otherwise they look off
// Regular backpacks just need the look packet // Regular backpacks just need the look packet
if (additonalPacket) HMCCPacketManager.sendRotationPacket(entity, yaw, false, getViewers()); if (additonalPacket) HMCCPacketManager.sendRotationPacket(entity, yaw, false, getViewers());
HMCCPacketManager.sendLookPacket(entity, location, getViewers()); HMCCPacketManager.sendRotateHeadPacket(entity, location, getViewers());
} }
} }
} }

View File

@@ -117,12 +117,14 @@ public class UserWardrobeManager {
// Armorstand // Armorstand
HMCCPacketManager.sendEntitySpawnPacket(viewingLocation, ARMORSTAND_ID, EntityType.ARMOR_STAND, UUID.randomUUID(), viewer); HMCCPacketManager.sendEntitySpawnPacket(viewingLocation, ARMORSTAND_ID, EntityType.ARMOR_STAND, UUID.randomUUID(), viewer);
HMCCPacketManager.sendArmorstandMetadata(ARMORSTAND_ID, viewer); HMCCPacketManager.sendArmorstandMetadata(ARMORSTAND_ID, viewer);
HMCCPacketManager.sendLookPacket(ARMORSTAND_ID, viewingLocation, viewer); NMSHandlers.getHandler().getPacketHandler().sendTeleportPacket(ARMORSTAND_ID, viewingLocation.getX(), viewingLocation.getY(), viewingLocation.getZ(), viewingLocation.getYaw(), viewingLocation.getPitch(), false, viewer);
//NMSHandlers.getHandler().getPacketHandler().sendLookAtPacket(ARMORSTAND_ID, viewingLocation, viewer);
HMCCPacketManager.sendRotateHeadPacket(ARMORSTAND_ID, viewingLocation, viewer);
// Player // Player
player.teleport(viewingLocation, PlayerTeleportEvent.TeleportCause.PLUGIN); player.teleport(viewingLocation, PlayerTeleportEvent.TeleportCause.PLUGIN);
player.setInvisible(true); player.setInvisible(true);
HMCCPacketManager.gamemodeChangePacket(player, 3); HMCCPacketManager.gamemodeChangePacket(player, GameMode.SPECTATOR);
HMCCPacketManager.sendCameraPacket(ARMORSTAND_ID, viewer); HMCCPacketManager.sendCameraPacket(ARMORSTAND_ID, viewer);
// NPC // NPC
@@ -142,7 +144,7 @@ public class UserWardrobeManager {
}, 4); }, 4);
// Location // Location
HMCCPacketManager.sendLookPacket(NPC_ID, npcLocation, viewer); HMCCPacketManager.sendRotateHeadPacket(NPC_ID, npcLocation, viewer);
HMCCPacketManager.sendRotationPacket(NPC_ID, npcLocation, true, viewer); HMCCPacketManager.sendRotationPacket(NPC_ID, npcLocation, true, viewer);
// Misc // Misc
@@ -247,11 +249,11 @@ public class UserWardrobeManager {
if (WardrobeSettings.isForceExitGamemode()) { if (WardrobeSettings.isForceExitGamemode()) {
MessagesUtil.sendDebugMessages("Force Exit Gamemode " + WardrobeSettings.getExitGamemode()); MessagesUtil.sendDebugMessages("Force Exit Gamemode " + WardrobeSettings.getExitGamemode());
player.setGameMode(WardrobeSettings.getExitGamemode()); player.setGameMode(WardrobeSettings.getExitGamemode());
HMCCPacketManager.gamemodeChangePacket(player, HMCCServerUtils.convertGamemode(WardrobeSettings.getExitGamemode())); // Success HMCCPacketManager.gamemodeChangePacket(player, WardrobeSettings.getExitGamemode()); // Success
} else { } else {
MessagesUtil.sendDebugMessages("Original Gamemode " + this.originalGamemode); MessagesUtil.sendDebugMessages("Original Gamemode " + this.originalGamemode);
player.setGameMode(this.originalGamemode); player.setGameMode(this.originalGamemode);
HMCCPacketManager.gamemodeChangePacket(player, HMCCServerUtils.convertGamemode(this.originalGamemode)); // Success HMCCPacketManager.gamemodeChangePacket(player, this.originalGamemode); // Success
} }
user.showPlayer(); user.showPlayer();
@@ -311,11 +313,13 @@ public class UserWardrobeManager {
int yaw = data.get(); int yaw = data.get();
location.setYaw(yaw); location.setYaw(yaw);
HMCCPacketManager.sendLookPacket(NPC_ID, location, viewer); HMCCPacketManager.sendRotateHeadPacket(NPC_ID, location, viewer);
user.hidePlayer(); user.hidePlayer();
int rotationSpeed = WardrobeSettings.getRotationSpeed(); int rotationSpeed = WardrobeSettings.getRotationSpeed();
location.setYaw(HMCCServerUtils.getNextYaw(yaw - 30, rotationSpeed)); int newYaw = HMCCServerUtils.getNextYaw(yaw - 30, rotationSpeed);
HMCCPacketManager.sendRotationPacket(NPC_ID, location, true, viewer); location.setYaw(newYaw);
NMSHandlers.getHandler().getPacketHandler().sendRotationPacket(NPC_ID, newYaw, 0, false, viewer);
HMCCPacketManager.sendRotationPacket(NPC_ID, newYaw, true, viewer);
int nextyaw = HMCCServerUtils.getNextYaw(yaw, rotationSpeed); int nextyaw = HMCCServerUtils.getNextYaw(yaw, rotationSpeed);
data.set(nextyaw); data.set(nextyaw);

View File

@@ -1,6 +1,5 @@
package com.hibiscusmc.hmccosmetics.util; package com.hibiscusmc.hmccosmetics.util;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot; import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
@@ -28,22 +27,6 @@ public class HMCCInventoryUtils {
SLOT_MAP.put(CosmeticSlot.MAINHAND, EquipmentSlot.HAND); SLOT_MAP.put(CosmeticSlot.MAINHAND, EquipmentSlot.HAND);
} }
/**
* Converts from the Bukkit item slots to ProtocolLib item slots. Will produce a null if an improper bukkit item slot is sent through
* @param slot The BUKKIT item slot to convert.
* @return The ProtocolLib item slot that is returned
*/
public static EnumWrappers.ItemSlot itemBukkitSlot(final EquipmentSlot slot) {
return switch (slot) {
case HEAD -> EnumWrappers.ItemSlot.HEAD;
case CHEST -> EnumWrappers.ItemSlot.CHEST;
case LEGS -> EnumWrappers.ItemSlot.LEGS;
case FEET -> EnumWrappers.ItemSlot.FEET;
case HAND -> EnumWrappers.ItemSlot.MAINHAND;
case OFF_HAND -> EnumWrappers.ItemSlot.OFFHAND;
};
}
public static int getPacketArmorSlot(final EquipmentSlot slot) { public static int getPacketArmorSlot(final EquipmentSlot slot) {
return switch (slot) { return switch (slot) {
case HEAD -> 5; case HEAD -> 5;
@@ -67,18 +50,6 @@ public class HMCCInventoryUtils {
}; };
} }
public static CosmeticSlot getItemSlotToCosmeticSlot(final EnumWrappers.ItemSlot slot) {
return switch (slot) {
case HEAD -> CosmeticSlot.HELMET;
case CHEST -> CosmeticSlot.CHESTPLATE;
case LEGS -> CosmeticSlot.LEGGINGS;
case FEET -> CosmeticSlot.BOOTS;
case OFFHAND -> CosmeticSlot.OFFHAND;
case MAINHAND -> CosmeticSlot.MAINHAND;
default -> null;
};
}
public static CosmeticSlot BukkitCosmeticSlot(EquipmentSlot slot) { public static CosmeticSlot BukkitCosmeticSlot(EquipmentSlot slot) {
return switch (slot) { return switch (slot) {
case HAND -> CosmeticSlot.MAINHAND; case HAND -> CosmeticSlot.MAINHAND;
@@ -147,32 +118,6 @@ public class HMCCInventoryUtils {
return SLOT_MAP.get(slot); return SLOT_MAP.get(slot);
} }
public static EquipmentSlot getEquipmentSlot(@NotNull EnumWrappers.ItemSlot slot) {
switch (slot) {
case HEAD -> {
return EquipmentSlot.HEAD;
}
case CHEST -> {
return EquipmentSlot.CHEST;
}
case LEGS -> {
return EquipmentSlot.LEGS;
}
case FEET -> {
return EquipmentSlot.FEET;
}
case OFFHAND -> {
return EquipmentSlot.OFF_HAND;
}
case MAINHAND -> {
return EquipmentSlot.HAND;
}
default -> {
return null;
}
}
}
public static boolean isCosmeticItem(ItemStack itemStack) { public static boolean isCosmeticItem(ItemStack itemStack) {
if (itemStack == null) return false; if (itemStack == null) return false;
itemStack = itemStack.clone(); itemStack = itemStack.clone();

View File

@@ -1,29 +1,15 @@
package com.hibiscusmc.hmccosmetics.util; package com.hibiscusmc.hmccosmetics.util;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.config.Settings;
import me.lojosho.hibiscuscommons.util.packets.PacketManager; import me.lojosho.hibiscuscommons.util.packets.PacketManager;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
public class HMCCPlayerUtils { public class HMCCPlayerUtils {
@Nullable
public static WrappedSignedProperty getSkin(Player player) {
WrappedSignedProperty skinData = WrappedGameProfile.fromPlayer(player).getProperties()
.get("textures").stream().findAny().orElse(null);
if (skinData == null) {
return null;
}
return new WrappedSignedProperty("textures", skinData.getValue(), skinData.getSignature());
}
/** /**
* Get nearby players. {@link com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager#getViewers(Location)} * Get nearby players. {@link com.hibiscusmc.hmccosmetics.util.packets.HMCCPacketManager#getViewers(Location)}
* @param player * @param player

View File

@@ -1,6 +1,5 @@
package com.hibiscusmc.hmccosmetics.util; package com.hibiscusmc.hmccosmetics.util;
import me.lojosho.hibiscuscommons.util.StringUtils;
import me.lojosho.shaded.configurate.ConfigurationNode; import me.lojosho.shaded.configurate.ConfigurationNode;
import java.util.ArrayList; import java.util.ArrayList;
@@ -32,7 +31,7 @@ public class TranslationUtil {
public static String getTranslation(String key, String message) { public static String getTranslation(String key, String message) {
List<TranslationPair> pairs = keys.get(key); List<TranslationPair> pairs = keys.get(key);
for (TranslationPair pair : pairs) { for (TranslationPair pair : pairs) {
if (pair.key().equals(message)) return StringUtils.parseStringToString(pair.value()); if (pair.key().equals(message)) return pair.value();
} }
return message; return message;

View File

@@ -1,28 +1,23 @@
package com.hibiscusmc.hmccosmetics.util.packets; package com.hibiscusmc.hmccosmetics.util.packets;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.*;
import com.google.common.collect.Lists;
import com.hibiscusmc.hmccosmetics.api.HMCCosmeticsAPI;
import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot; import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers; import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.HMCCInventoryUtils; import com.hibiscusmc.hmccosmetics.util.HMCCInventoryUtils;
import com.hibiscusmc.hmccosmetics.util.HMCCPlayerUtils; import me.lojosho.hibiscuscommons.nms.NMSHandlers;
import com.hibiscusmc.hmccosmetics.util.packets.wrappers.WrapperPlayServerNamedEntitySpawn;
import com.hibiscusmc.hmccosmetics.util.packets.wrappers.WrapperPlayServerPlayerInfo;
import com.hibiscusmc.hmccosmetics.util.packets.wrappers.WrapperPlayServerRelEntityMove;
import me.lojosho.hibiscuscommons.util.packets.PacketManager; import me.lojosho.hibiscuscommons.util.packets.PacketManager;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Display;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.ItemDisplay;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.util.*; import java.util.*;
@@ -46,16 +41,7 @@ public class HMCCPacketManager extends PacketManager {
final UUID uuid, final UUID uuid,
final @NotNull List<Player> sendTo final @NotNull List<Player> sendTo
) { ) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY); NMSHandlers.getHandler().getPacketHandler().sendSpawnEntityPacket(entityId, uuid, entityType, location, sendTo);
packet.getModifier().writeDefaults();
packet.getUUIDs().write(0, uuid);
packet.getIntegers().write(0, entityId);
packet.getEntityTypeModifier().write(0, entityType);
packet.getDoubles().
write(0, location.getX()).
write(1, location.getY()).
write(2, location.getZ());
for (Player p : sendTo) sendPacket(p, packet);
} }
public static void equipmentSlotUpdate( public static void equipmentSlotUpdate(
@@ -101,49 +87,24 @@ public class HMCCPacketManager extends PacketManager {
int entityId, int entityId,
List<Player> sendTo List<Player> sendTo
) { ) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); byte mask = (byte) (Settings.isBackpackPreventDarkness() ? 0x21 : 0x20);
packet.getModifier().writeDefaults(); Map<Integer, Number> dataValues = Map.of(0, mask, 15, (byte) 0x10);
packet.getIntegers().write(0, entityId); NMSHandlers.getHandler().getPacketHandler().sendSharedEntityData(entityId, dataValues, sendTo);
final List<WrappedDataValue> wrappedDataValueList = Lists.newArrayList();
// 0x21 = Invisible + Fire (Aka, burns to make it not take the light of the block its in, avoiding turning it black)
byte mask = 0x20;
if (Settings.isBackpackPreventDarkness()) mask = 0x21;
wrappedDataValueList.add(new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), mask));
wrappedDataValueList.add(new WrappedDataValue(15, WrappedDataWatcher.Registry.get(Byte.class), (byte) 0x10));
packet.getDataValueCollectionModifier().write(0, wrappedDataValueList);
for (Player p : sendTo) sendPacket(p, packet);
} }
public static void sendInvisibilityPacket( public static void sendInvisibilityPacket(
int entityId, int entityId,
List<Player> sendTo List<Player> sendTo
) { ) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); NMSHandlers.getHandler().getPacketHandler().sendSharedEntityData(entityId, Map.of(0, (byte) 0x20), sendTo);
packet.getModifier().writeDefaults();
packet.getIntegers().write(0, entityId);
final List<WrappedDataValue> wrappedDataValueList = Lists.newArrayList();
wrappedDataValueList.add(new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte) 0x20));
packet.getDataValueCollectionModifier().write(0, wrappedDataValueList);
for (Player p : sendTo) sendPacket(p, packet);
} }
public static void sendCloudEffect( public static void sendCloudEffect(
int entityId, int entityId,
List<Player> sendTo List<Player> sendTo
) { ) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); Map<Integer, Number> dataValues = Map.of(0, (byte) 0x20, 8, 0f);
packet.getModifier().writeDefaults(); NMSHandlers.getHandler().getPacketHandler().sendSharedEntityData(entityId, dataValues, sendTo);
packet.getIntegers().write(0, entityId);
final List<WrappedDataValue> wrappedDataValueList = Lists.newArrayList();
wrappedDataValueList.add(new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte) 0x20));
wrappedDataValueList.add(new WrappedDataValue(8, WrappedDataWatcher.Registry.get(Float.class), 0f));
//wrappedDataValueList.add(new WrappedDataValue(11, WrappedDataWatcher.Registry.get(Integer.class), 21));
packet.getDataValueCollectionModifier().write(0, wrappedDataValueList);
for (Player p : sendTo) sendPacket(p, packet);
} }
public static void sendRotationPacket( public static void sendRotationPacket(
@@ -160,17 +121,7 @@ public class HMCCPacketManager extends PacketManager {
boolean onGround, boolean onGround,
@NotNull List<Player> sendTo @NotNull List<Player> sendTo
) { ) {
float ROTATION_FACTOR = 256.0F / 360.0F; NMSHandlers.getHandler().getPacketHandler().sendRotationPacket(entityId, location.getYaw(), location.getPitch(), onGround, sendTo);
float yaw = location.getYaw() * ROTATION_FACTOR;
float pitch = location.getPitch() * ROTATION_FACTOR;
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_LOOK);
packet.getIntegers().write(0, entityId);
packet.getBytes().write(0, (byte) yaw);
packet.getBytes().write(1, (byte) pitch);
//Bukkit.getLogger().info("DEBUG: Yaw: " + (location.getYaw() * ROTATION_FACTOR) + " | Original Yaw: " + location.getYaw());
packet.getBooleans().write(0, onGround);
for (Player p : sendTo) sendPacket(p, packet);
} }
public static void sendRotationPacket( public static void sendRotationPacket(
@@ -179,19 +130,9 @@ public class HMCCPacketManager extends PacketManager {
boolean onGround, boolean onGround,
@NotNull List<Player> sendTo @NotNull List<Player> sendTo
) { ) {
float ROTATION_FACTOR = 256.0F / 360.0F; NMSHandlers.getHandler().getPacketHandler().sendRotationPacket(entityId, yaw, 0, onGround, sendTo);
float yaw2 = yaw * ROTATION_FACTOR;
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_LOOK);
packet.getIntegers().write(0, entityId);
packet.getBytes().write(0, (byte) yaw2);
packet.getBytes().write(1, (byte) 0);
//Bukkit.getLogger().info("DEBUG: Yaw: " + (location.getYaw() * ROTATION_FACTOR) + " | Original Yaw: " + location.getYaw());
packet.getBooleans().write(0, onGround);
for (Player p : sendTo) sendPacket(p, packet);
} }
/** /**
* Mostly to deal with backpacks, this deals with entities riding other entities. * Mostly to deal with backpacks, this deals with entities riding other entities.
* @param mountId The entity that is the "mount", ex. a player * @param mountId The entity that is the "mount", ex. a player
@@ -216,12 +157,7 @@ public class HMCCPacketManager extends PacketManager {
final int[] passengerIds, final int[] passengerIds,
final @NotNull List<Player> sendTo final @NotNull List<Player> sendTo
) { ) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.MOUNT); NMSHandlers.getHandler().getPacketHandler().sendMountPacket(mountId, passengerIds, sendTo);
packet.getIntegers().write(0, mountId);
packet.getIntegerArrays().write(0, passengerIds);
for (final Player p : sendTo) {
sendPacket(p, packet);
}
} }
/** /**
@@ -251,17 +187,7 @@ public class HMCCPacketManager extends PacketManager {
final int entityId, final int entityId,
final @NotNull List<Player> sendTo final @NotNull List<Player> sendTo
) { ) {
if (HMCCosmeticsAPI.getNMSVersion().contains("v1_19_R3") || HMCCosmeticsAPI.getNMSVersion().contains("v1_20_R1")) { sendEntitySpawnPacket(location, entityId, EntityType.PLAYER, uuid, sendTo);
WrapperPlayServerNamedEntitySpawn wrapper = new WrapperPlayServerNamedEntitySpawn();
wrapper.setEntityID(entityId);
wrapper.setPlayerUUID(uuid);
wrapper.setPosition(location.toVector());
wrapper.setPitch(location.getPitch());
wrapper.setYaw(location.getYaw());
for (final Player p : sendTo) sendPacket(p, wrapper.getHandle());
return;
}
sendEntitySpawnPacket(location, entityId, EntityType.PLAYER, uuid);
} }
/** /**
@@ -274,28 +200,10 @@ public class HMCCPacketManager extends PacketManager {
final Player skinnedPlayer, final Player skinnedPlayer,
final int entityId, final int entityId,
final UUID uuid, final UUID uuid,
final String NPCName, final String npcName,
final List<Player> sendTo final List<Player> sendTo
) { ) {
WrapperPlayServerPlayerInfo info = new WrapperPlayServerPlayerInfo(); NMSHandlers.getHandler().getPacketHandler().sendFakePlayerInfoPacket(skinnedPlayer, entityId, uuid, npcName, sendTo);
info.setAction(EnumWrappers.PlayerInfoAction.ADD_PLAYER);
String name = NPCName;
while (name.length() > 16) {
name = name.substring(16);
}
WrappedGameProfile wrappedGameProfile = new WrappedGameProfile(uuid, name);
WrappedSignedProperty skinData = HMCCPlayerUtils.getSkin(skinnedPlayer);
if (skinData != null) wrappedGameProfile.getProperties().put("textures", skinData);
info.getHandle().getPlayerInfoDataLists().write(1, Collections.singletonList(new PlayerInfoData(
wrappedGameProfile,
0,
EnumWrappers.NativeGameMode.CREATIVE,
WrappedChatComponent.fromText(name)
)));
for (final Player p : sendTo) sendPacket(p, info.getHandle());
} }
/** /**
@@ -319,15 +227,7 @@ public class HMCCPacketManager extends PacketManager {
https://wiki.vg/Entity_metadata#Entity https://wiki.vg/Entity_metadata#Entity
*/ */
final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40; final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); NMSHandlers.getHandler().getPacketHandler().sendSharedEntityData(playerId, Map.of(17, mask), sendTo);
packet.getModifier().writeDefaults();
packet.getIntegers().write(0, playerId);
final List<WrappedDataValue> wrappedDataValueList = Lists.newArrayList();
wrappedDataValueList.add(new WrappedDataValue(17, WrappedDataWatcher.Registry.get(Byte.class), mask));
packet.getDataValueCollectionModifier().write(0, wrappedDataValueList);
for (final Player p : sendTo) sendPacket(p, packet);
} }
/** /**
@@ -342,9 +242,7 @@ public class HMCCPacketManager extends PacketManager {
final UUID uuid, final UUID uuid,
final List<Player> sendTo final List<Player> sendTo
) { ) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.PLAYER_INFO_REMOVE); NMSHandlers.getHandler().getPacketHandler().sendPlayerInfoRemovePacket(uuid, sendTo);
packet.getUUIDLists().write(0, List.of(uuid));
for (final Player p : sendTo) sendPacket(p, packet);
} }
public static void sendLeashPacket( public static void sendLeashPacket(
@@ -370,16 +268,51 @@ public class HMCCPacketManager extends PacketManager {
final boolean onGround, final boolean onGround,
@NotNull List<Player> sendTo @NotNull List<Player> sendTo
) { ) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE); NMSHandlers.getHandler().getPacketHandler().sendMovePacket(entityId, from, to, onGround, sendTo);
WrapperPlayServerRelEntityMove wrapper = new WrapperPlayServerRelEntityMove(packet); }
wrapper.setEntityID(entityId);
wrapper.setDx(to.getX() - from.getX()); public static void sendEntityScalePacket(
wrapper.setDy(to.getY() - from.getY()); int entityId,
wrapper.setDz(to.getZ() - from.getZ()); double scale,
wrapper.setOnGround(onGround); List<Player> sendTo
for (final Player p : sendTo) { ) {
sendPacket(p, wrapper.getHandle()); NMSHandlers.getHandler().getPacketHandler().sendEntityScalePacket(entityId, scale, sendTo);
} }
// For future transition to display entities
public static void sendDisplayEntityMetadataPacket(
int entityid,
ItemStack backpackItem,
List<Player> sendTo) {
// TODO: Make the default values adjustable
Vector3f translation = new Vector3f(0, 3, 0);
Vector3f scale = new Vector3f(1, 1, 1);
Quaternionf rotationLeft = new Quaternionf();
Quaternionf rotationRight = new Quaternionf();
Display.Billboard billboard = Display.Billboard.FIXED;
int blockLight = 15;
int skylight = 15;
int viewRange = Settings.getViewDistance();
int width = 0;
int height = 0;
ItemDisplay.ItemDisplayTransform transform = ItemDisplay.ItemDisplayTransform.HEAD;
NMSHandlers.getHandler().getPacketHandler().sendItemDisplayMetadata(
entityid,
translation,
scale,
rotationLeft,
rotationRight,
billboard,
blockLight,
skylight,
viewRange,
width,
height,
transform,
backpackItem,
sendTo
);
} }
/** /**
@@ -391,9 +324,4 @@ public class HMCCPacketManager extends PacketManager {
public static List<Player> getViewers(@NotNull Location location) { public static List<Player> getViewers(@NotNull Location location) {
return PacketManager.getViewers(location, Settings.getViewDistance()); return PacketManager.getViewers(location, Settings.getViewDistance());
} }
public static void sendPacket(Player player, PacketContainer packet) {
if (player == null) return;
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, null,false);
}
} }

View File

@@ -1,92 +0,0 @@
package com.hibiscusmc.hmccosmetics.util.packets.wrappers;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import com.google.common.base.Objects;
import org.bukkit.entity.Player;
// Courtesy of Packet Wrapper
public class AbstractPacket {
// The packet we will be modifying
protected PacketContainer handle;
/**
* Constructs a new strongly typed wrapper for the given packet.
*
* @param handle - handle to the raw packet data.
* @param type - the packet type.
*/
protected AbstractPacket(PacketContainer handle, PacketType type) {
// Make sure we're given a valid packet
if (handle == null)
throw new IllegalArgumentException("Packet handle cannot be NULL.");
if (!Objects.equal(handle.getType(), type))
throw new IllegalArgumentException(handle.getHandle()
+ " is not a packet of type " + type);
this.handle = handle;
}
/**
* Retrieve a handle to the raw packet data.
*
* @return Raw packet data.
*/
public PacketContainer getHandle() {
return handle;
}
/**
* Send the current packet to the given receiver.
*
* @param receiver - the receiver.
* @throws RuntimeException If the packet cannot be sent.
*/
public void sendPacket(Player receiver) {
ProtocolLibrary.getProtocolManager().sendServerPacket(receiver,
getHandle());
}
/**
* Send the current packet to all online players.
*/
public void broadcastPacket() {
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getHandle());
}
/**
* Simulate receiving the current packet from the given sender.
*
* @param sender - the sender.
* @throws RuntimeException If the packet cannot be received.
* @deprecated Misspelled. recieve to receive
* @see #receivePacket(Player)
*/
@Deprecated
public void recievePacket(Player sender) {
try {
ProtocolLibrary.getProtocolManager().receiveClientPacket(sender,
getHandle());
} catch (Exception e) {
throw new RuntimeException("Cannot recieve packet.", e);
}
}
/**
* Simulate receiving the current packet from the given sender.
*
* @param sender - the sender.
* @throws RuntimeException if the packet cannot be received.
*/
public void receivePacket(Player sender) {
try {
ProtocolLibrary.getProtocolManager().receiveClientPacket(sender,
getHandle());
} catch (Exception e) {
throw new RuntimeException("Cannot receive packet.", e);
}
}
}

View File

@@ -1,165 +0,0 @@
package com.hibiscusmc.hmccosmetics.util.packets.wrappers;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class WrapperPlayServerNamedEntitySpawn extends AbstractPacket {
public static final PacketType TYPE =
PacketType.Play.Server.NAMED_ENTITY_SPAWN;
public WrapperPlayServerNamedEntitySpawn() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerNamedEntitySpawn(PacketContainer packet) {
super(packet, TYPE);
}
/**
* Retrieve Entity ID.
* <p>
* Notes: entity's ID
*
* @return The current Entity ID
*/
public int getEntityID() {
return handle.getIntegers().read(0);
}
/**
* Set Entity ID.
*
* @param value - new value.
*/
public void setEntityID(int value) {
handle.getIntegers().write(0, value);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param world - the current world of the entity.
* @return The spawned entity.
*/
public Entity getEntity(World world) {
return handle.getEntityModifier(world).read(0);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param event - the packet event.
* @return The spawned entity.
*/
public Entity getEntity(@NotNull PacketEvent event) {
return getEntity(event.getPlayer().getWorld());
}
/**
* Retrieve Player UUID.
* <p>
* Notes: player's UUID
*
* @return The current Player UUID
*/
public UUID getPlayerUUID() {
return handle.getUUIDs().read(0);
}
/**
* Set Player UUID.
*
* @param value - new value.
*/
public void setPlayerUUID(UUID value) {
handle.getUUIDs().write(0, value);
}
/**
* Retrieve the position of the spawned entity as a vector.
*
* @return The position as a vector.
*/
public Vector getPosition() {
return new Vector(getX(), getY(), getZ());
}
/**
* Set the position of the spawned entity using a vector.
*
* @param position - the new position.
*/
public void setPosition(@NotNull Vector position) {
setX(position.getX());
setY(position.getY());
setZ(position.getZ());
}
public double getX() {
return handle.getDoubles().read(0);
}
public void setX(double value) {
handle.getDoubles().write(0, value);
}
public double getY() {
return handle.getDoubles().read(1);
}
public void setY(double value) {
handle.getDoubles().write(1, value);
}
public double getZ() {
return handle.getDoubles().read(2);
}
public void setZ(double value) {
handle.getDoubles().write(2, value);
}
/**
* Retrieve the yaw of the spawned entity.
*
* @return The current Yaw
*/
public float getYaw() {
return (handle.getBytes().read(0) * 360.F) / 256.0F;
}
/**
* Set the yaw of the spawned entity.
*
* @param value - new yaw.
*/
public void setYaw(float value) {
handle.getBytes().write(0, (byte) (value * 256.0F / 360.0F));
}
/**
* Retrieve the pitch of the spawned entity.
*
* @return The current pitch
*/
public float getPitch() {
return (handle.getBytes().read(1) * 360.F) / 256.0F;
}
/**
* Set the pitch of the spawned entity.
*
* @param value - new pitch.
*/
public void setPitch(float value) {
handle.getBytes().write(1, (byte) (value * 256.0F / 360.0F));
}
}

View File

@@ -1,44 +0,0 @@
package com.hibiscusmc.hmccosmetics.util.packets.wrappers;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.EnumWrappers.PlayerInfoAction;
import com.comphenix.protocol.wrappers.PlayerInfoData;
import com.hibiscusmc.hmccosmetics.api.HMCCosmeticsAPI;
import java.util.List;
import java.util.Set;
public class WrapperPlayServerPlayerInfo extends AbstractPacket {
public static final PacketType TYPE = PacketType.Play.Server.PLAYER_INFO;
public WrapperPlayServerPlayerInfo() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerPlayerInfo(PacketContainer packet) {
super(packet, TYPE);
}
public PlayerInfoAction getAction() {
return handle.getPlayerInfoAction().read(0);
}
public void setAction(PlayerInfoAction value) {
if (HMCCosmeticsAPI.getNMSVersion().contains("v1_17_R1") || HMCCosmeticsAPI.getNMSVersion().contains("v1_18_R2") || HMCCosmeticsAPI.getNMSVersion().contains("v1_19_R1")) {
handle.getPlayerInfoAction().write(0, value);
return;
}
// New way of handling it 1.19.3+
handle.getPlayerInfoActions().write(0, Set.of(value));
}
public List<PlayerInfoData> getData() {
return handle.getPlayerInfoDataLists().read(0);
}
public void setData(List<PlayerInfoData> value) {
handle.getPlayerInfoDataLists().write(0, value);
}
}

View File

@@ -1,170 +0,0 @@
package com.hibiscusmc.hmccosmetics.util.packets.wrappers;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
public class WrapperPlayServerRelEntityMove extends AbstractPacket {
public static final PacketType TYPE =
PacketType.Play.Server.REL_ENTITY_MOVE;
public WrapperPlayServerRelEntityMove() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerRelEntityMove(PacketContainer packet) {
super(packet, TYPE);
}
/**
* Retrieve Entity ID.
* <p>
* Notes: entity's ID
*
* @return The current Entity ID
*/
public int getEntityID() {
return handle.getIntegers().read(0);
}
/**
* Set Entity ID.
*
* @param value - new value.
*/
public void setEntityID(int value) {
handle.getIntegers().write(0, value);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param world - the current world of the entity.
* @return The spawned entity.
*/
public Entity getEntity(World world) {
return handle.getEntityModifier(world).read(0);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param event - the packet event.
* @return The spawned entity.
*/
public Entity getEntity(@NotNull PacketEvent event) {
return getEntity(event.getPlayer().getWorld());
}
/**
* Retrieve DX.
*
* @return The current DX
*/
public double getDx() {
return handle.getShorts().read(0) / 4096D;
}
/**
* Set DX.
*
* @param value - new value.
*/
public void setDx(double value) {
handle.getShorts().write(0, (short) (value * 4096));
}
/**
* Retrieve DY.
*
* @return The current DY
*/
public double getDy() {
return handle.getShorts().read(1) / 4096D;
}
/**
* Set DY.
*
* @param value - new value.
*/
public void setDy(double value) {
handle.getShorts().write(1, (short) (value * 4096));
}
/**
* Retrieve DZ.
*
* @return The current DZ
*/
public double getDz() {
return handle.getShorts().read(2) / 4096D;
}
/**
* Set DZ.
*
* @param value - new value.
*/
public void setDz(double value) {
handle.getShorts().write(2, (short) (value * 4096));
}
/**
* Retrieve the yaw of the current entity.
*
* @return The current Yaw
*/
public float getYaw() {
return (handle.getBytes().read(0) * 360.F) / 256.0F;
}
/**
* Set the yaw of the current entity.
*
* @param value - new yaw.
*/
public void setYaw(float value) {
handle.getBytes().write(0, (byte) (value * 256.0F / 360.0F));
}
/**
* Retrieve the pitch of the current entity.
*
* @return The current pitch
*/
public float getPitch() {
return (handle.getBytes().read(1) * 360.F) / 256.0F;
}
/**
* Set the pitch of the current entity.
*
* @param value - new pitch.
*/
public void setPitch(float value) {
handle.getBytes().write(1, (byte) (value * 256.0F / 360.0F));
}
/**
* Retrieve On Ground.
*
* @return The current On Ground
*/
public boolean getOnGround() {
return handle.getBooleans().read(0);
}
/**
* Set On Ground.
*
* @param value - new value.
*/
public void setOnGround(boolean value) {
handle.getBooleans().write(0, value);
}
}

View File

@@ -3,7 +3,7 @@
# #
config-version: 1 config-version: 1
default-menu: defaultmenu default-menu: defaultmenu_hats
debug-mode: false debug-mode: false
database-settings: database-settings:
type: sqlite # SQLite (Default), MYSQL, NONE type: sqlite # SQLite (Default), MYSQL, NONE
@@ -41,7 +41,7 @@ cosmetic-settings:
- "SPECTATOR" - "SPECTATOR"
# This make it so it always sends the riding packets for the backpack. This sends more packets but is more reliable for servers which modify player passengers. # This make it so it always sends the riding packets for the backpack. This sends more packets but is more reliable for servers which modify player passengers.
backpack-force-riding-packet: false backpack-force-riding-packet: true
# This prevents the backpack from being dark when the player is below a block at the expense of making the backpack bright # This prevents the backpack from being dark when the player is below a block at the expense of making the backpack bright
backpack-prevent-darkness: true backpack-prevent-darkness: true
# This helps reduce the amount of packets sent for packet entities, but reduces accuracy of the entity. This is in milliseconds. -1 to disable. # This helps reduce the amount of packets sent for packet entities, but reduces accuracy of the entity. This is in milliseconds. -1 to disable.
@@ -96,8 +96,8 @@ menu-settings:
# The shading is done through the title and by shifting textures around. This is done by offsets. # The shading is done through the title and by shifting textures around. This is done by offsets.
# Only Nexo is support by default. Vanilla can't properly handle it without a lot of unicodes and ItemsAdder adds weird offsets and decolors it. (This is why it is disabled by default) # Only Nexo is support by default. Vanilla can't properly handle it without a lot of unicodes and ItemsAdder adds weird offsets and decolors it. (This is why it is disabled by default)
enabled: false # Default of menus having shading. This can be toggled individually in menus with "shading: true/false" enabled: false # Default of menus having shading. This can be toggled individually in menus with "shading: true/false"
first-row-shift: "<shift:-169>" # Nexo: "<shift:-169>" first-row-shift: "<shift:-153>" # Nexo: "<shift:-153>"
sequent-row-shift: " <shift:-169>" # Nexo: " <shift:-169>" (Space is important here!) sequent-row-shift: " <shift:-153>" # Nexo: " <shift:-153>" (Space is important here!)
individual-column-shift: "<shift:-3>" # Nexo: "<shift:-3>" individual-column-shift: "<shift:-3>" # Nexo: "<shift:-3>"
background: "<glyph:shade_row_<row>:colorable> " # Nexo: "<glyph:shade_row_<row>:colorable> background: "<glyph:shade_row_<row>:colorable> " # Nexo: "<glyph:shade_row_<row>:colorable>
clear-background: "<glyph:clear_row_<row>:colorable> " # Nexo: "<glyph:clear_row_<row>:colorable> " clear-background: "<glyph:clear_row_<row>:colorable> " # Nexo: "<glyph:clear_row_<row>:colorable> "

View File

@@ -1,180 +0,0 @@
title: "<white>"
rows: 6
refresh-rate: 20 # Set to -1 or remove to disable auto-updating, leading to it only using event-based updates.
items:
beanie:
slots:
- 0
item:
material: hmccosmetics:beanie
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_beanie%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_beanie%"
type: cosmetic
cosmetic: beanie
backpack:
slots:
- 1
item:
material: hmccosmetics:backpack
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_backpack%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_backpack%"
type: cosmetic
cosmetic: backpack
future_wings:
slots:
- 2
item:
material: hmccosmetics:future_wings
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_future_wings%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_future_wings%"
type: cosmetic
cosmetic: future_wings
lantern_cosmetic:
slots:
- 3
item:
material: hmccosmetics:lantern_cosmetic
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_lantern_cosmetic%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_lantern_cosmetic%"
type: cosmetic
cosmetic: lantern_cosmetic
baseball_hat:
slots:
- 4
item:
material: hmccosmetics:baseball_hat
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_baseball_hat%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_baseball_hat%"
type: cosmetic
cosmetic: baseball_hat
frog_hat:
slots:
- 5
item:
material: hmccosmetics:frog_hat
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_frog_hat%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_frog_hat%"
type: cosmetic
cosmetic: frog_hat
jetpack:
slots:
- 6
item:
material: hmccosmetics:jetpack
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_jetpack%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_jetpack%"
type: cosmetic
cosmetic: jetpack
hammer:
slots:
- 7
item:
material: hmccosmetics:hammer
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_hammer%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_hammer%"
type: cosmetic
cosmetic: hammer
chestplate:
slots:
- 8
item:
material: hmccosmetics:chestplate
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_chestplate%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_chestplate%"
type: cosmetic
cosmetic: chestplate
pants:
slots:
- 9
item:
material: hmccosmetics:pants
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_pants%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_pants%"
type: cosmetic
cosmetic: pants
boots:
slots:
- 10
item:
material: hmccosmetics:boots
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_boots%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_boots%"
type: cosmetic
cosmetic: boots
kite:
slots:
- 11
item:
material: hmccosmetics:kite
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_kite%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_kite%"
type: cosmetic
cosmetic: kite
explorer_backpack:
slots:
- 12
item:
material: hmccosmetics:explorer_backpack
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_explorer_backpack%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_explorer_backpack%"
type: cosmetic
cosmetic: explorer_backpack
garbage_truck_balloon:
slots:
- 13
item:
material: hmccosmetics:garbage_truck_balloon
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_garbage_truck_balloon%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_garbage_truck_balloon%"
type: cosmetic
cosmetic: garbage_truck_balloon
earth_day_grabber:
slots:
- 14
item:
material: hmccosmetics:earth_day_grabber
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_earth_day_grabber%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_earth_day_grabber%"
type: cosmetic
cosmetic: earth_day_grabber
hibiscus_flower:
slots:
- 15
item:
material: hmccosmetics:hibiscus_flower
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_hibiscus_flower%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_hibiscus_flower%"
type: cosmetic
cosmetic: hibiscus_flower

View File

@@ -0,0 +1,99 @@
title: "<white>"
rows: 6
items:
backpack:
slots:
- 1
item:
material: hmccosmetics:backpack
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_backpack%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_backpack%"
type: cosmetic
cosmetic: backpack
future_wings:
slots:
- 2
item:
material: hmccosmetics:future_wings
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_future_wings%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_future_wings%"
type: cosmetic
cosmetic: future_wings
jetpack:
slots:
- 3
item:
material: hmccosmetics:jetpack
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_jetpack%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_jetpack%"
type: cosmetic
cosmetic: jetpack
explorer_backpack:
slots:
- 4
item:
material: hmccosmetics:explorer_backpack
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_explorer_backpack%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_explorer_backpack%"
type: cosmetic
cosmetic: explorer_backpack
button_backpacks_menu:
slots:
- 0
item:
material: PAPER
model-data: 18
name: "<blue>Backpack Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_backpacks"
- "[SOUND] minecraft:ui.button.click 1 1"
button_hand_menu:
slots:
- 18
item:
material: PAPER
model-data: 19
name: "<blue>Hand Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_hands"
- "[SOUND] minecraft:ui.button.click 1 1"
button_balloon_menu:
slots:
- 27
item:
material: PAPER
model-data: 20
name: "<blue>Balloon Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_balloons"
- "[SOUND] minecraft:ui.button.click 1 1"
button_hats_menu:
slots:
- 36
item:
material: PAPER
model-data: 17
name: "<blue>Hat Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_hats"
- "[SOUND] minecraft:ui.button.click 1 1"

View File

@@ -0,0 +1,77 @@
title: "<white>"
rows: 6
items:
garbage_truck_balloon:
slots:
- 1
item:
material: hmccosmetics:garbage_truck_balloon
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_garbage_truck_balloon%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_garbage_truck_balloon%"
type: cosmetic
cosmetic: garbage_truck_balloon
kite:
slots:
- 2
item:
material: hmccosmetics:kite
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_kite%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_kite%"
type: cosmetic
cosmetic: kite
button_backpacks_menu:
slots:
- 27
item:
material: PAPER
model-data: 18
name: "<blue>Backpack Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_backpacks"
- "[SOUND] minecraft:ui.button.click 1 1"
button_hand_menu:
slots:
- 36
item:
material: PAPER
model-data: 19
name: "<blue>Hand Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_hands"
- "[SOUND] minecraft:ui.button.click 1 1"
button_balloon_menu:
slots:
- 0
item:
material: PAPER
model-data: 20
name: "<blue>Balloon Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_balloons"
- "[SOUND] minecraft:ui.button.click 1 1"
button_hats_menu:
slots:
- 18
item:
material: PAPER
model-data: 17
name: "<blue>Hat Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_hats"
- "[SOUND] minecraft:ui.button.click 1 1"

View File

@@ -0,0 +1,99 @@
title: "<white>"
rows: 6
items:
lantern_cosmetic:
slots:
- 1
item:
material: hmccosmetics:lantern_cosmetic
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_lantern_cosmetic%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_lantern_cosmetic%"
type: cosmetic
cosmetic: lantern_cosmetic
hammer:
slots:
- 2
item:
material: hmccosmetics:hammer
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_hammer%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_hammer%"
type: cosmetic
cosmetic: hammer
earth_day_grabber:
slots:
- 3
item:
material: hmccosmetics:earth_day_grabber
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_earth_day_grabber%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_earth_day_grabber%"
type: cosmetic
cosmetic: earth_day_grabber
hibiscus_flower:
slots:
- 4
item:
material: hmccosmetics:hibiscus_flower
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_hibiscus_flower%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_hibiscus_flower%"
type: cosmetic
cosmetic: hibiscus_flower
button_backpacks_menu:
slots:
- 36
item:
material: PAPER
model-data: 18
name: "<blue>Backpack Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_backpacks"
- "[SOUND] minecraft:ui.button.click 1 1"
button_hand_menu:
slots:
- 0
item:
material: PAPER
model-data: 19
name: "<blue>Hand Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_hands"
- "[SOUND] minecraft:ui.button.click 1 1"
button_balloon_menu:
slots:
- 18
item:
material: PAPER
model-data: 20
name: "<blue>Balloon Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_balloons"
- "[SOUND] minecraft:ui.button.click 1 1"
button_hats_menu:
slots:
- 27
item:
material: PAPER
model-data: 17
name: "<blue>Hat Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_hats"
- "[SOUND] minecraft:ui.button.click 1 1"

View File

@@ -0,0 +1,88 @@
title: "<white>"
rows: 6
items:
beanie:
slots:
- 1
item:
material: hmccosmetics:beanie
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_beanie%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_beanie%"
type: cosmetic
cosmetic: beanie
baseball_hat:
slots:
- 2
item:
material: hmccosmetics:baseball_hat
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_baseball_hat%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_baseball_hat%"
type: cosmetic
cosmetic: baseball_hat
frog_hat:
slots:
- 3
item:
material: hmccosmetics:frog_hat
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%HMCCosmetics_equipped_frog_hat%"
- "<gray>Allowed: <#6D9DC5>%HMCCosmetics_unlocked_frog_hat%"
type: cosmetic
cosmetic: frog_hat
button_hats_menu:
slots:
- 0
item:
material: PAPER
model-data: 17
name: "<blue>Hat Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_hats"
- "[SOUND] minecraft:ui.button.click 1 1"
button_backpacks_menu:
slots:
- 18
item:
material: PAPER
model-data: 18
name: "<blue>Backpack Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_backpacks"
- "[SOUND] minecraft:ui.button.click 1 1"
button_hand_menu:
slots:
- 27
item:
material: PAPER
model-data: 19
name: "<blue>Hand Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_hands"
- "[SOUND] minecraft:ui.button.click 1 1"
button_balloon_menu:
slots:
- 36
item:
material: PAPER
model-data: 20
name: "<blue>Balloon Cosmetics"
amount: 1
type: empty
actions:
any:
- "[MENU] defaultmenu_balloons"
- "[SOUND] minecraft:ui.button.click 1 1"