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

Compare commits

..

21 Commits

Author SHA1 Message Date
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
29 changed files with 677 additions and 600 deletions

View File

@@ -8,7 +8,7 @@ plugins {
}
group = "com.hibiscusmc"
version = "2.7.8${getGitCommitHash()}"
version = "2.8.0${getGitCommitHash()}"
allprojects {
apply(plugin = "java")
@@ -16,6 +16,7 @@ allprojects {
repositories {
mavenCentral()
mavenLocal()
// Paper Repo
maven("https://repo.papermc.io/repository/maven-public/")
@@ -24,8 +25,7 @@ allprojects {
// Jitpack
maven("https://jitpack.io")
// ProtocolLib repo
maven("https://repo.dmulloy2.net/repository/public/") //ProtocolLib Repo, constantly down
// Geary
maven("https://repo.mineinabyss.com/releases/")
maven("https://repo.mineinabyss.com/snapshots/")
@@ -69,14 +69,13 @@ allprojects {
// Hibiscus Commons
maven("https://repo.hibiscusmc.com/releases")
mavenLocal()
}
dependencies {
compileOnly(fileTree("${project.rootDir}/lib") { include("*.jar") })
compileOnly("com.mojang:authlib:1.5.25")
//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("me.clip:placeholderapi:2.11.6")
compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.6")
@@ -92,12 +91,12 @@ allprojects {
compileOnly("io.github.toxicity188:BetterCommand:1.3") //BetterCommand library
//compileOnly("it.unimi.dsi:fastutil:8.5.14")
compileOnly("org.projectlombok:lombok:1.18.34")
compileOnly("me.lojosho:HibiscusCommons:0.6.3-32402bd")
compileOnly("me.lojosho:HibiscusCommons:0.7.0-d301221e")
// Handled by Spigot Library Loader
compileOnly("net.kyori:adventure-api:4.19.0")
compileOnly("net.kyori:adventure-text-minimessage:4.19.0")
compileOnly("net.kyori:adventure-platform-bukkit:4.3.4")
compileOnly("net.kyori:adventure-api:4.23.0")
compileOnly("net.kyori:adventure-text-minimessage:4.23.0")
compileOnly("net.kyori:adventure-platform-bukkit:4.4.0")
annotationProcessor("org.projectlombok:lombok:1.18.36")
testCompileOnly("org.projectlombok:lombok:1.18.36")
@@ -140,12 +139,11 @@ tasks {
}
runServer {
minecraftVersion("1.21.4")
minecraftVersion("1.21.6")
downloadPlugins {
hangar("PlaceholderAPI", "2.11.6")
url("https://ci.dmulloy2.net/job/ProtocolLib/lastSuccessfulBuild/artifact/build/libs/ProtocolLib.jar")
url("https://download.luckperms.net/1567/bukkit/loader/LuckPerms-Bukkit-5.4.150.jar")
url("https://download.luckperms.net/1593/bukkit/loader/LuckPerms-Bukkit-5.5.8.jar")
}
}
@@ -182,7 +180,7 @@ bukkit {
apiVersion = "1.20"
authors = listOf("LoJoSho")
depend = listOf("HibiscusCommons")
softDepend = listOf("BetterHud", "ModelEngine", "Nexo", "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}"
loadBefore = listOf(
"Cosmin" // Fixes an issue with Cosmin loading before and taking /cosmetic, when messing with what we do.

View File

@@ -1,11 +1,6 @@
plugins {
id("java")
id("maven-publish")
id("io.papermc.paperweight.userdev") version "2.0.0-beta.17"
}
dependencies {
paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT")
}
java {

View File

@@ -20,6 +20,7 @@ import com.hibiscusmc.hmccosmetics.listener.PaperPlayerGameListener;
import com.hibiscusmc.hmccosmetics.listener.PlayerConnectionListener;
import com.hibiscusmc.hmccosmetics.listener.PlayerGameListener;
import com.hibiscusmc.hmccosmetics.listener.ServerListener;
import com.hibiscusmc.hmccosmetics.packets.CosmeticPacketInterface;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
@@ -83,6 +84,7 @@ public final class HMCCosmeticsPlugin extends HibiscusPlugin {
// Setup
setup();
setPacketInterface(new CosmeticPacketInterface());
// Commands
getServer().getPluginCommand("cosmetic").setExecutor(new CosmeticCommand());

View File

@@ -400,6 +400,7 @@ public class CosmeticCommand implements CommandExecutor {
if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) {
player.sendMessage("Backpack Location -> " + user.getUserBackpackManager().getEntityManager().getLocation());
}
player.sendMessage("Cosmetic Passengers -> " + user.getUserBackpackManager().getAreaEffectEntityId());
player.sendMessage("Cosmetics -> " + user.getCosmetics());
player.sendMessage("EntityId -> " + player.getEntityId());
return true;

View File

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

View File

@@ -3,16 +3,15 @@ package com.hibiscusmc.hmccosmetics.cosmetic;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import me.lojosho.hibiscuscommons.config.serializer.ItemSerializer;
import me.lojosho.shaded.configurate.ConfigurationNode;
import me.lojosho.shaded.configurate.serialize.SerializationException;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,13 +25,16 @@ public abstract class Cosmetic {
static {
UNDEFINED_DISPLAY_ITEM_STACK = new ItemStack(Material.BARRIER);
UNDEFINED_DISPLAY_ITEM_STACK.editMeta(meta -> {
meta.displayName(Component.text("Undefined Item Display", NamedTextColor.RED));
meta.lore(List.of(
Component.text("Please check your configurations & console to", NamedTextColor.RED),
Component.text("ensure there are no errors.", NamedTextColor.RED)
));
});
ItemMeta meta = UNDEFINED_DISPLAY_ITEM_STACK.getItemMeta();
if (meta != null) {
// Legacy methods for Spigot >:(
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. */

View File

@@ -39,10 +39,12 @@ public class MySQLData extends SQLData {
try {
openConnection();
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, " +
"COSMETICS MEDIUMTEXT " +
");").execute();
");")) {
preparedStatement.execute();
}
} catch (SQLException | NullPointerException e) {
plugin.getLogger().severe("");
plugin.getLogger().severe("");
@@ -60,17 +62,11 @@ public class MySQLData extends SQLData {
@Override
public void clear(UUID uniqueId) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
PreparedStatement preparedSt = null;
try {
preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;");
try (PreparedStatement preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;")) {
preparedSt.setString(1, uniqueId.toString());
preparedSt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (preparedSt != null) preparedSt.close();
} catch (SQLException e) {}
}
});
}

View File

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

View File

@@ -35,10 +35,12 @@ public class SQLiteData extends SQLData {
connection = DriverManager.getConnection("jdbc:sqlite:" + dataFolder);
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, " +
"COSMETICS MEDIUMTEXT " +
");").execute();
");")) {
preparedStatement.execute();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
@@ -48,17 +50,11 @@ public class SQLiteData extends SQLData {
@SuppressWarnings("resource")
public void clear(UUID uniqueId) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmeticsPlugin.getInstance(), () -> {
PreparedStatement preparedSt = null;
try {
preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;");
try (PreparedStatement preparedSt = preparedStatement("DELETE FROM COSMETICDATABASE WHERE UUID=?;")){
preparedSt.setString(1, uniqueId.toString());
preparedSt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (preparedSt != null) preparedSt.close();
} catch (SQLException e) {}
}
});
}

View File

@@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
@SuppressWarnings("unused")
public class Actions {
@@ -30,7 +31,6 @@ public class Actions {
private static final ActionCosmeticHide ACTION_HIDE = new ActionCosmeticHide();
private static final ActionCosmeticToggle ACTION_TOGGLE = new ActionCosmeticToggle();
public static Action getAction(@NotNull String id) {
return actions.get(id.toUpperCase());
}
@@ -45,13 +45,13 @@ public class Actions {
public static void runActions(Player viewer, CosmeticHolder cosmeticHolder, @NotNull List<String> raw) {
for (String a : raw) {
String id = StringUtils.substringBetween(a, "[", "]").toUpperCase();
String id = StringUtils.substringBetween(a, "[", "]");
String message = StringUtils.substringAfter(a, "] ");
MessagesUtil.sendDebugMessages("ID is " + id + " // Raw Data is " + message);
if (isAction(id)) {
if (id != null && isAction(id.toUpperCase())) {
getAction(id).run(viewer, cosmeticHolder, message);
} 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

@@ -30,7 +30,7 @@ public class DyeMenu {
if (originalItem == null || !cosmetic.isDyeable()) return;
Gui gui = HMCColorApi.createColorMenu(viewer);
gui.updateTitle(AdventureUtils.MINI_MESSAGE.deserialize(Hooks.processPlaceholders(viewer, StringUtils.parseStringToString(Settings.getDyeMenuName()))));
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()) {

View File

@@ -66,14 +66,11 @@ public class TypeCosmetic extends Type {
MessagesUtil.sendDebugMessages("Required click type: " + requiredClick);
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<>();
ConfigurationNode actionConfig = config.node("actions");

View File

@@ -1,27 +0,0 @@
package com.hibiscusmc.hmccosmetics.listener;
import com.hibiscusmc.hmccosmetics.nms.CosmeticChannelHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelPipeline;
import net.minecraft.network.Connection;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
public class PlayerPacketListener implements Listener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
Channel channel = ((CraftPlayer) event.getPlayer()).getHandle().connection.connection.channel;
ChannelPipeline pipeline = channel.pipeline();
CosmeticChannelHandler channelHandler = new CosmeticChannelHandler(player);
for (String key : pipeline.toMap().keySet()) {
if (!(pipeline.get(key) instanceof Connection)) continue;
pipeline.addBefore(key, "hmccosmetics_channel_handler", channelHandler);
}
}
}

View File

@@ -1,247 +0,0 @@
package com.hibiscusmc.hmccosmetics.nms;
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.UserWardrobeManager;
import com.hibiscusmc.hmccosmetics.util.HMCCInventoryUtils;
import com.hibiscusmc.hmccosmetics.util.HMCCServerUtils;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
import com.mojang.datafixers.util.Pair;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import me.lojosho.hibiscuscommons.nms.NMSHandlers;
import net.minecraft.core.NonNullList;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.*;
import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket;
import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.item.ItemStack;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.CraftEquipmentSlot;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
public class CosmeticChannelHandler extends ChannelDuplexHandler {
private final Player player;
public CosmeticChannelHandler(Player player) {
this.player = player;
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (!(msg instanceof Packet packet)) {
super.write(ctx, msg, promise);
return;
}
switch (packet) {
case ClientboundContainerSetContentPacket setContentPacket -> msg = handleMenuChange(setContentPacket);
case ClientboundContainerSetSlotPacket setSlotPacket -> msg = handleSlotChange(setSlotPacket);
case ClientboundSetEquipmentPacket equipmentPacket -> msg = handlePlayerEquipment(equipmentPacket);
case ClientboundSetPassengersPacket passengerPacket -> msg = handlePassengerSet(passengerPacket);
default -> {
}
}
if (msg == null) return;
else super.write(ctx, msg, promise);
}
private Packet<?> handleMenuChange(ClientboundContainerSetContentPacket packet) {
MessagesUtil.sendDebugMessages("Menu Initial ");
int windowId = packet.getContainerId();
NonNullList<ItemStack> slotData = NonNullList.create();
slotData.addAll(packet.getItems());
if (windowId != 0) return packet;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) return packet;
HashMap<Integer, ItemStack> items = 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;
items.put(HMCCInventoryUtils.getPacketArmorSlot(armorType.getEquipSlot()), CraftItemStack.asNMSCopy(user.getUserCosmeticItem(armorType)));
}
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));
}
}
MessagesUtil.sendDebugMessages("Menu Fired, updated cosmetics " + " on slotdata " + windowId + " with " + slotData.size());
return new ClientboundContainerSetContentPacket(0, packet.getStateId(), slotData, packet.getCarriedItem());
}
private Packet<?> handleSlotChange(ClientboundContainerSetSlotPacket packet) {
MessagesUtil.sendDebugMessages("SetSlot Initial ");
int windowId = packet.getContainerId();
if (windowId != 0) return packet;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null || user.isInWardrobe()) return packet;
int slot = packet.getSlot();
MessagesUtil.sendDebugMessages("SetSlot Slot " + slot);
CosmeticSlot cosmeticSlot = HMCCInventoryUtils.NMSCosmeticSlot(slot);
EquipmentSlot equipmentSlot = HMCCInventoryUtils.getPacketArmorSlot(slot);
if (cosmeticSlot == null || equipmentSlot == null) return packet;
if (!user.hasCosmeticInSlot(cosmeticSlot)) return packet;
if (Settings.getSlotOption(equipmentSlot).isRequireEmpty()) {
if (!player.getInventory().getItem(equipmentSlot).getType().isAir()) return packet;
}
ItemStack item = CraftItemStack.asNMSCopy(user.getUserCosmeticItem(cosmeticSlot));
return new ClientboundContainerSetSlotPacket(0, packet.getStateId(), slot, item);
}
private Packet<?> handlePlayerEquipment(ClientboundSetEquipmentPacket packet) {
CosmeticUser user = CosmeticUsers.getUser(packet.getEntity());
if (user == null || user.isInWardrobe()) return packet;
List<Pair<net.minecraft.world.entity.EquipmentSlot, ItemStack>> armor = packet.getSlots();
for (int i = 0; i < armor.size(); i++) {
Pair<net.minecraft.world.entity.EquipmentSlot, ItemStack> pair = armor.get(i);
if (pair.getFirst() == net.minecraft.world.entity.EquipmentSlot.MAINHAND) {
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.set(i, new Pair<>(pair.getFirst(), CraftItemStack.asNMSCopy(player.getInventory().getItemInMainHand())));
} else {
EquipmentSlot slot = CraftEquipmentSlot.getSlot(pair.getFirst());
if (slot == null) continue;
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 = CraftItemStack.asNMSCopy(user.getUserCosmeticItem(cosmeticSlot));
if (item == null) continue;
armor.set(i, new Pair<>(pair.getFirst(), item));
}
}
MessagesUtil.sendDebugMessages("Equipment for " + user.getPlayer().getName() + " has been updated for " + player.getName());
return new ClientboundSetEquipmentPacket(packet.getEntity(), armor);
}
private Packet<?> handlePassengerSet(ClientboundSetPassengersPacket packet) {
CosmeticUser viewerUser = CosmeticUsers.getUser(player);
if (viewerUser == null || viewerUser.isInWardrobe()) return packet;
int ownerId = packet.getVehicle();
MessagesUtil.sendDebugMessages("Mount Packet Sent - Read - EntityID: " + ownerId);
Entity entity = HMCCServerUtils.getEntity(ownerId);
if (entity == null) return packet;
CosmeticUser user = CosmeticUsers.getUser(entity.getUniqueId());
if (user == null) return packet;
MessagesUtil.sendDebugMessages("Mount Packet Sent - " + user.getUniqueId());
if (!user.hasCosmeticInSlot(CosmeticSlot.BACKPACK)) return packet;
if (user.getUserBackpackManager() == null) return packet;
List<Integer> passengers = new ArrayList<>(user.getUserBackpackManager().getEntityManager().getIds());
for (int passenger : packet.getPassengers()) passengers.add(passenger);
int[] passengerIds = passengers.stream().mapToInt(Integer::intValue).toArray();
return (Packet<?>) NMSHandlers.getHandler().getPacketHandler().createMountPacket(ownerId, passengerIds);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (!(msg instanceof Packet packet)) {
super.channelRead(ctx, msg);
return;
}
switch (packet) {
case ServerboundContainerClickPacket clickPacket -> handleInventoryClick(clickPacket);
case ServerboundPlayerActionPacket playerActionPacket -> msg = handlePlayerAction(playerActionPacket);
case ServerboundSwingPacket swingPacket -> msg = handlePlayerArm(swingPacket);
case ServerboundUseItemOnPacket useItemOnPacket -> msg = handleEntityUse(useItemOnPacket);
default -> {
}
}
if (msg == null) return;
else super.channelRead(ctx, msg);
}
private void handleInventoryClick(ServerboundContainerClickPacket packet) {
ClickType clickType = packet.getClickType();
int slotClicked = packet.getSlotNum();
if (clickType != ClickType.PICKUP || slotClicked == -999) return;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null || user.isInWardrobe()) return;
CosmeticSlot cosmeticSlot = HMCCInventoryUtils.NMSCosmeticSlot(slotClicked);
if (cosmeticSlot == null || !user.hasCosmeticInSlot(cosmeticSlot)) return;
Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> user.updateCosmetic(cosmeticSlot), 1);
MessagesUtil.sendDebugMessages("Packet fired, updated cosmetic " + cosmeticSlot);
}
private Packet<?> handlePlayerAction(ServerboundPlayerActionPacket packet) {
ServerboundPlayerActionPacket.Action action = packet.getAction();
MessagesUtil.sendDebugMessages("EntityStatus Initial " + player.getEntityId() + " - " + action);
if (action != ServerboundPlayerActionPacket.Action.SWAP_ITEM_WITH_OFFHAND) return packet;
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null) {
MessagesUtil.sendDebugMessages("EntityStatus User is null");
return packet;
}
if (!user.hasCosmeticInSlot(CosmeticSlot.OFFHAND)) return packet;
return null;
}
private Packet<?> handlePlayerArm(ServerboundSwingPacket packet) {
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null || !user.isInWardrobe() || !user.getWardrobeManager().getWardrobeStatus().equals(UserWardrobeManager.WardrobeStatus.RUNNING)) return packet;
Menu menu = user.getWardrobeManager().getLastOpenMenu();
if (menu == null) return packet;
menu.openMenu(user);
return null;
}
private Packet<?> handleEntityUse(ServerboundUseItemOnPacket packet) {
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null || !user.isInWardrobe()) return packet;
else return null;
}
}

View File

@@ -0,0 +1,195 @@
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.UserWardrobeManager;
import com.hibiscusmc.hmccosmetics.util.HMCCInventoryUtils;
import com.hibiscusmc.hmccosmetics.util.MessagesUtil;
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 PacketAction writeContainerContent(@NotNull Player player, @NotNull ContainerContentWrapper wrapper) {
int windowId = wrapper.getWindowId();
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> items = 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;
items.put(HMCCInventoryUtils.getPacketArmorSlot(armorType.getEquipSlot()), user.getUserCosmeticItem(armorType));
}
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));
}
}
wrapper.setSlotData(slotData);
MessagesUtil.sendDebugMessages("Menu Fired, updated cosmetics " + " on slotdata " + windowId + " with " + slotData.size());
return PacketAction.CHANGED;
}
@Override
public 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 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 PacketAction writePassengerContent(@NotNull Player player, @NotNull PassengerWrapper wrapper) {
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 Sent - 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;
Player entity = optionalCosmeticUser.get().getPlayer();
CosmeticUser user = CosmeticUsers.getUser(entity.getUniqueId());
if (user == null) return PacketAction.NOTHING;
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());
for (int passenger : originalPassengers) passengers.add(passenger);
wrapper.setPassengers(passengers);
return PacketAction.CHANGED;
}
@Override
public 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 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 PacketAction readPlayerArm(@NotNull Player player) {
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 PacketAction readEntityHandle(@NotNull Player player) {
CosmeticUser user = CosmeticUsers.getUser(player);
if (user == null || !user.isInWardrobe()) return PacketAction.NOTHING;
else return PacketAction.CANCELLED;
}
}

View File

@@ -144,7 +144,7 @@ public class CosmeticUser implements CosmeticHolder {
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");
hideCosmetics(CosmeticUser.HiddenReason.WORLD);
} else if (this.isHidden(HiddenReason.WORLD)) {
@@ -603,7 +603,7 @@ public class CosmeticUser implements CosmeticHolder {
* @return Entity
*/
public Entity getEntity() {
return Bukkit.getEntity(uniqueId);
return getPlayer();
}
public Color getCosmeticColor(CosmeticSlot slot) {
@@ -626,7 +626,12 @@ public class CosmeticUser implements CosmeticHolder {
if (isInWardrobe() && !ignoreWardrobe) {
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() {

View File

@@ -1,5 +1,6 @@
package com.hibiscusmc.hmccosmetics.user.manager;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.HMCCPlayerUtils;
@@ -79,7 +80,7 @@ public class UserEntity {
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
// 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;
for (Integer entity : ids) {

View File

@@ -117,6 +117,8 @@ public class UserWardrobeManager {
// Armorstand
HMCCPacketManager.sendEntitySpawnPacket(viewingLocation, ARMORSTAND_ID, EntityType.ARMOR_STAND, UUID.randomUUID(), viewer);
HMCCPacketManager.sendArmorstandMetadata(ARMORSTAND_ID, 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
@@ -234,7 +236,7 @@ public class UserWardrobeManager {
// NPC
if (user.isBalloonSpawned()) user.getBalloonManager().sendRemoveLeashPacket();
HMCCPacketManager.sendEntityDestroyPacket(NPC_ID, viewer); // Success
HMCCPacketManager.sendRemovePlayerPacket(WARDROBE_UUID, viewer); // Success
HMCCPacketManager.sendRemovePlayerPacket(player, WARDROBE_UUID, viewer); // Success
// Player
HMCCPacketManager.sendCameraPacket(player.getEntityId(), viewer);
@@ -314,8 +316,10 @@ public class UserWardrobeManager {
HMCCPacketManager.sendRotateHeadPacket(NPC_ID, location, viewer);
user.hidePlayer();
int rotationSpeed = WardrobeSettings.getRotationSpeed();
location.setYaw(HMCCServerUtils.getNextYaw(yaw - 30, rotationSpeed));
HMCCPacketManager.sendRotationPacket(NPC_ID, location, true, viewer);
int newYaw = HMCCServerUtils.getNextYaw(yaw - 30, rotationSpeed);
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);
data.set(nextyaw);
@@ -323,11 +327,10 @@ public class UserWardrobeManager {
HMCCPacketManager.equipmentSlotUpdate(NPC_ID, user, slot, viewer);
}
// Handle backpacks
if (user.hasCosmeticInSlot(CosmeticSlot.BACKPACK) && user.getUserBackpackManager() != null) {
HMCCPacketManager.sendTeleportPacket(user.getUserBackpackManager().getFirstArmorStandId(), location, false, viewer);
HMCCPacketManager.ridingMountPacket(NPC_ID, user.getUserBackpackManager().getFirstArmorStandId(), viewer);
//user.getUserBackpackManager().getEntityManager().setRotation(nextyaw);
user.getUserBackpackManager().getEntityManager().setRotation(nextyaw);
HMCCPacketManager.sendEntityDestroyPacket(user.getUserBackpackManager().getFirstArmorStandId(), outsideViewers);
}
@@ -359,4 +362,5 @@ public class UserWardrobeManager {
RUNNING,
STOPPING,
}
}

View File

@@ -50,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) {
return switch (slot) {
case HAND -> CosmeticSlot.MAINHAND;
@@ -130,32 +118,6 @@ public class HMCCInventoryUtils {
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) {
if (itemStack == null) return false;
itemStack = itemStack.clone();

View File

@@ -18,6 +18,20 @@ public class HMCCServerUtils {
private static String COLOR_CHAR = "&";
/**
* Converts a bukkit gamemode into an integer for use in packets
* @param gamemode Bukkit gamemode to convert.
* @return int of the gamemode
*/
public static int convertGamemode(final GameMode gamemode) {
return switch (gamemode) {
case SURVIVAL -> 0;
case CREATIVE -> 1;
case ADVENTURE -> 2;
case SPECTATOR -> 3;
};
}
public static org.bukkit.entity.Entity getEntity(int entityId) {
return NMSHandlers.getHandler().getUtilHandler().getEntity(entityId);
}

View File

@@ -32,7 +32,7 @@ public class TranslationUtil {
public static String getTranslation(String key, String message) {
List<TranslationPair> pairs = keys.get(key);
for (TranslationPair pair : pairs) {
if (pair.key().equals(message)) return StringUtils.parseStringToString(pair.value());
if (pair.key().equals(message)) return pair.value();
}
return message;

View File

@@ -1,27 +1,25 @@
package com.hibiscusmc.hmccosmetics.util.packets;
import com.google.common.collect.Lists;
import com.hibiscusmc.hmccosmetics.config.Settings;
import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot;
import com.hibiscusmc.hmccosmetics.user.CosmeticUser;
import com.hibiscusmc.hmccosmetics.user.CosmeticUsers;
import com.hibiscusmc.hmccosmetics.util.HMCCInventoryUtils;
import me.lojosho.hibiscuscommons.nms.NMSHandlers;
import me.lojosho.hibiscuscommons.nms.NMSHandlers;
import me.lojosho.hibiscuscommons.util.packets.PacketManager;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.*;
import org.bukkit.entity.Display;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ItemDisplay;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
public class HMCCPacketManager extends PacketManager {
@@ -85,18 +83,26 @@ public class HMCCPacketManager extends PacketManager {
equipmentSlotUpdate(entityId, HMCCInventoryUtils.getEquipmentSlot(cosmeticSlot), user.getUserCosmeticItem(cosmeticSlot), sendTo);
}
public static void sendArmorstandMetadata(int entityId, List<Player> sendTo) {
// 0x21 = Invisible + Fire (Aka, burns to make it not take the light of the block its in, avoiding turning it black)
public static void sendArmorstandMetadata(
int entityId,
List<Player> sendTo
) {
byte mask = (byte) (Settings.isBackpackPreventDarkness() ? 0x21 : 0x20);
Map<Integer, Number> dataValues = Map.of(0, mask, 15, (byte) 0x10);
NMSHandlers.getHandler().getPacketHandler().sendSharedEntityData(entityId, dataValues, sendTo);
}
public static void sendInvisibilityPacket(int entityId, List<Player> sendTo) {
public static void sendInvisibilityPacket(
int entityId,
List<Player> sendTo
) {
NMSHandlers.getHandler().getPacketHandler().sendSharedEntityData(entityId, Map.of(0, (byte) 0x20), sendTo);
}
public static void sendCloudEffect(int entityId, List<Player> sendTo) {
public static void sendCloudEffect(
int entityId,
List<Player> sendTo
) {
Map<Integer, Number> dataValues = Map.of(0, (byte) 0x20, 8, 0f);
NMSHandlers.getHandler().getPacketHandler().sendSharedEntityData(entityId, dataValues, sendTo);
}
@@ -132,7 +138,6 @@ public class HMCCPacketManager extends PacketManager {
NMSHandlers.getHandler().getPacketHandler().sendRotationPacket(entityId, yaw * ROTATION_FACTOR, 0, onGround, sendTo);
}
/**
* Mostly to deal with backpacks, this deals with entities riding other entities.
* @param mountId The entity that is the "mount", ex. a player
@@ -232,11 +237,13 @@ public class HMCCPacketManager extends PacketManager {
/**
* Removes a fake player from being seen by players.
* @param player Which gameprofile to wrap for removing the player.
* @param uuid What is the fake player UUID
* @param sendTo Whom to send the packet to
*/
@SuppressWarnings("deprecation")
public static void sendRemovePlayerPacket(
final Player player,
final UUID uuid,
final List<Player> sendTo
) {
@@ -269,7 +276,11 @@ public class HMCCPacketManager extends PacketManager {
NMSHandlers.getHandler().getPacketHandler().sendMovePacket(entityId, from, to, onGround, sendTo);
}
public static void sendDisplayEntityMetadataPacket(int entityid, ItemStack backpackItem, List<Player> 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);

View File

@@ -3,7 +3,7 @@
#
config-version: 1
default-menu: defaultmenu
default-menu: defaultmenu_hats
debug-mode: false
database-settings:
type: sqlite # SQLite (Default), MYSQL, NONE
@@ -95,9 +95,9 @@ menu-settings:
# Below is the shading mechanism behind cosmetic items. This is a bit complicated, but it allows for a lot of customization.
# 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)
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>"
sequent-row-shift: " <shift:-169>" # Nexo: " <shift:-169>" (Space is important here!)
enabled: true # Default of menus having shading. This can be toggled individually in menus with "shading: true/false"
first-row-shift: "<shift:-153>" # Nexo: "<shift:-153>"
sequent-row-shift: " <shift:-153>" # Nexo: " <shift:-153>" (Space is important here!)
individual-column-shift: "<shift:-3>" # Nexo: "<shift:-3>"
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> "

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"

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME