commit c0fdd970ea91ab9a76acf19634e5dfd89222f7f2 Author: LoJoSho Date: Fri Dec 22 21:24:55 2023 -0600 feat: Initial Commit diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..eb75980 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,255 @@ +import net.minecrell.pluginyml.bukkit.BukkitPluginDescription + +plugins { + id("java") + id("maven-publish") + id("com.github.johnrengelman.shadow") version "8.1.1" + id("net.minecrell.plugin-yml.bukkit") version "0.6.0" +} + +group = "me.lojosho" +version = "0.1.6" + +allprojects { + apply(plugin = "java") + apply(plugin = "java-library") + + repositories { + mavenCentral() + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") + maven("https://oss.sonatype.org/content/groups/public/") + maven("https://oss.sonatype.org/content/repositories/snapshots") + + // UpdateChecker + maven("https://hub.jeff-media.com/nexus/repository/jeff-media-public/") + + // Geary & Backup ProtocolLib repo + maven("https://repo.mineinabyss.com/releases/") + maven("https://repo.mineinabyss.com/snapshots/") + + // Citizens & Denizen + maven("https://maven.citizensnpcs.co/repo") + + // Jitpack + maven("https://jitpack.io") + + // md-5 Repo + maven("https://repo.md-5.net/content/groups/public/") + + // MMOItems + maven("https://nexus.phoenixdevt.fr/repository/maven-public/") + + // Eco-Suite/Auxilor Repo + maven("https://repo.auxilor.io/repository/maven-public/") + + // PlaceholderAPI + maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") + + // ProtocolLib + maven("https://repo.dmulloy2.net/repository/public/") + + // MythicMobs + maven { + url = uri("https://mvn.lumine.io/repository/maven-public") + metadataSources { + artifact() + } + } + } + + dependencies { + compileOnly(fileTree("${project.rootDir}/lib") { include("*.jar") }) + + // Included externally + compileOnly("com.mojang:authlib:1.5.25") + compileOnly("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT") + compileOnly("org.jetbrains:annotations:23.0.0") + compileOnly("com.github.oraxen:oraxen:1.160.0") + compileOnly("com.github.LoneDev6:API-ItemsAdder:3.2.5") + compileOnly("com.mineinabyss:geary-papermc:0.27.0") + compileOnly("it.unimi.dsi:fastutil:8.5.11") + compileOnly("com.denizenscript:denizen:1.2.7-SNAPSHOT") + compileOnly("io.lumine:Mythic-Dist:5.2.1") + compileOnly("com.github.LeonMangler:SuperVanish:6.2.17") + compileOnly("net.Indyuce:MMOItems-API:6.9.4-SNAPSHOT") + compileOnly("com.willfp:eco:6.67.2") + compileOnly("me.clip:placeholderapi:2.11.5") + compileOnly("it.unimi.dsi:fastutil:8.5.11") + compileOnly("LibsDisguises:LibsDisguises:10.0.21") { + exclude("org.spigotmc", "spigot") + } + + // Lombok <3 + annotationProcessor("org.projectlombok:lombok:1.18.28") + testCompileOnly("org.projectlombok:lombok:1.18.28") + testAnnotationProcessor("org.projectlombok:lombok:1.18.28") + + // Spigot Auto Loader Libraries + compileOnly("net.kyori:adventure-api:4.15.0") + compileOnly("net.kyori:adventure-text-minimessage:4.15.0") + compileOnly("net.kyori:adventure-platform-bukkit:4.3.1") + compileOnly("org.apache.commons:commons-lang3:3.14.0") + + // Shaded Dependencies + implementation("org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT") + implementation("org.bstats:bstats-bukkit:3.0.2") + implementation("com.jeff_media:SpigotUpdateChecker:3.0.0") + implementation("com.github.BG-Software-LLC:CommentedConfiguration:bed3c46369") + } +} + +dependencies { + implementation(project(path = ":common")) + implementation(project(path = ":v1_20_R3", configuration = "reobf")) +} + +tasks { + compileJava { + options.encoding = Charsets.UTF_8.name() + options.release.set(17) + } + + javadoc { + options.encoding = Charsets.UTF_8.name() + } + + processResources { + duplicatesStrategy = DuplicatesStrategy.INCLUDE + filteringCharset = Charsets.UTF_8.name() + } + + shadowJar { + dependsOn(":v1_20_R3:reobfJar") + mergeServiceFiles() + + relocate("org.bstats", "me.lojosho.shaded.bstats") + relocate("org.spongepowered.configurate", "me.lojosho.shaded.configurate") + relocate("com.jeff_media.updatechecker", "me.lojosho.shaded.updatechecker") + relocate("com.bgsoftware", "me.lojosho.shaded.configupdater") + + dependencies { + exclude(dependency("org.yaml:snakeyaml")) + } + + archiveFileName.set("${project.name}-${project.version}.jar") + + doLast { + archiveFile.get().asFile.copyTo(layout.projectDirectory.file("output/${project.name}-${project.version}.jar").asFile, true) + } + } + + build { + dependsOn(shadowJar) + } +} + +java { + toolchain.languageVersion.set(JavaLanguageVersion.of(17 + )) +} + +// Handles generating the plugin yml + +bukkit { + load = BukkitPluginDescription.PluginLoadOrder.POSTWORLD + main = "me.lojosho.hibiscuscommons.HibiscusCommonsPlugin" + apiVersion = "1.18" + authors = listOf("LoJoSho") + depend = listOf("ProtocolLib") + softDepend = listOf( + "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. + ) + + libraries = listOf( + "net.kyori:adventure-api:4.15.0", + "net.kyori:adventure-text-minimessage:4.15.0", + "net.kyori:adventure-platform-bukkit:4.3.1", + "org.apache.commons:commons-lang3:3.14.0" + //"org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT" // Readd when 4.2.0 releases + ) +} + +// Publishing stuff below here to a remote maven repo + +publishing { + val publishData = PublishData(project) + publications { + create("maven") { + groupId = "${rootProject.group}" + artifactId = "${rootProject.name}" + version = "${rootProject.version}" + + from(components["java"]) + } + } + + repositories { + maven { + authentication { + credentials(PasswordCredentials::class) { + username = System.getenv("REPO_USERNAME") + password = System.getenv("REPO_PASSWORD") + } + } + + name = "HibiscusMCRepository" + url = uri(publishData.getRepository()) + } + } +} + +class PublishData(private val project: Project) { + var type: Type = getReleaseType() + var hashLength: Int = 7 + + private fun getReleaseType(): Type { + val version = "${project.version}" + return when { + version.contains("dev") -> Type.DEV + version.contains("SNAPSHOT") -> Type.SNAPSHOT + else -> Type.RELEASE + } + } + + private fun getCheckedOutGitCommitHash(): String = + System.getenv("GITHUB_SHA")?.substring(0, hashLength) ?: "local" + + private fun getCheckedOutBranch(): String = + System.getenv("GITHUB_REF")?.replace("refs/heads/", "") ?: "local" + + fun getVersion(): String = getVersion(false) + + fun getVersion(appendCommit: Boolean): String = + type.append(getVersionString(), appendCommit, getCheckedOutGitCommitHash()) + + private fun getVersionString(): String = + (rootProject.version as String).replace("-SNAPSHOT", "").replace("-DEV", "") + + fun getRepository(): String = type.repo + + enum class Type(private val append: String, val repo: String, private val addCommit: Boolean) { + RELEASE("", "https://repo.hibiscusmc.com/releases/", false), + DEV("", "https://repo.hibiscusmc.com/development/", true), + SNAPSHOT("", "https://repo.hibiscusmc.com/snapshots/", true); + + fun append(name: String, appendCommit: Boolean, commitHash: String): String = + name.plus(append).plus(if (appendCommit && addCommit) "-".plus(commitHash) else "") + } +} \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts new file mode 100644 index 0000000..c126806 --- /dev/null +++ b/common/build.gradle.kts @@ -0,0 +1,18 @@ + +// Look into the possibility of splitting off the API portion into its own module? (Probably not worth it right now) - 12/22/23 + +tasks { + compileJava { + options.encoding = Charsets.UTF_8.name() + options.release.set(17) + } + + javadoc { + options.encoding = Charsets.UTF_8.name() + } + + processResources { + duplicatesStrategy = DuplicatesStrategy.INCLUDE + filteringCharset = Charsets.UTF_8.name() + } +} \ No newline at end of file diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/HibiscusCommonsPlugin.java b/common/src/main/java/me/lojosho/hibiscuscommons/HibiscusCommonsPlugin.java new file mode 100644 index 0000000..6b80540 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/HibiscusCommonsPlugin.java @@ -0,0 +1,37 @@ +package me.lojosho.hibiscuscommons; + +import lombok.Getter; +import me.lojosho.hibiscuscommons.hooks.Hooks; +import me.lojosho.hibiscuscommons.nms.NMSHandlers; +import me.lojosho.hibiscuscommons.util.ServerUtils; +import org.bukkit.plugin.java.JavaPlugin; + +public final class HibiscusCommonsPlugin extends HibiscusPlugin { + + @Getter + private static HibiscusCommonsPlugin instance; + @Getter + private static boolean onPaper = false; + + @Override + public void onStart() { + instance = this; + + // Detects if a user is running a paper server + if (ServerUtils.hasClass("com.destroystokyo.paper.PaperConfig") || ServerUtils.hasClass("io.papermc.paper.configuration.Configuration")) { + onPaper = true; + getLogger().info("Detected Paper! Enabling Paper support..."); + //getServer().getPluginManager().registerEvents(new PaperPlayerGameListener(), this); + } + + if (!NMSHandlers.isVersionSupported()) { + getLogger().severe("This version is not supported! Consider switching versions?"); + getServer().getPluginManager().disablePlugin(this); + return; + } + + // Plugin startup logic + Hooks.setup(); + + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/HibiscusPlugin.java b/common/src/main/java/me/lojosho/hibiscuscommons/HibiscusPlugin.java new file mode 100644 index 0000000..b378eae --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/HibiscusPlugin.java @@ -0,0 +1,96 @@ +package me.lojosho.hibiscuscommons; + +import com.jeff_media.updatechecker.UpdateCheckSource; +import com.jeff_media.updatechecker.UpdateChecker; +import lombok.Getter; +import org.bstats.bukkit.Metrics; +import org.bukkit.plugin.java.JavaPlugin; + +public abstract class HibiscusPlugin extends JavaPlugin { + + @Getter + private final int bstats; + @Getter + private final int resourceID; + @Getter + private String latestVersion = ""; + @Getter + private boolean onLatestVersion = true; + @Getter + private boolean disabled = false; + + protected HibiscusPlugin() { + this(-1); + } + + protected HibiscusPlugin(int bstats) { + this(bstats, -1); + } + + protected HibiscusPlugin(int bstats, int resourceID) { + this.bstats = bstats; + this.resourceID = resourceID; + } + + @Override + public final void onEnable() { + super.onEnable(); + + if (bstats > 0) { + Metrics metrics = new Metrics(this, bstats); + } + if (resourceID > 0) { + // Update Checker + UpdateChecker checker = new UpdateChecker(this, UpdateCheckSource.POLYMART, String.valueOf(resourceID)) + .onSuccess((commandSenders, latestVersion) -> { + this.latestVersion = (String) latestVersion; + String pluginName = getDescription().getName(); + + if (!this.latestVersion.equalsIgnoreCase(getDescription().getVersion())) { + getLogger().info("+++++++++++++++++++++++++++++++++++"); + getLogger().info("There is a new update for " + pluginName + "!"); + getLogger().info("Please download it as soon as possible for possible fixes and new features."); + getLogger().info("Current Version " + getDescription().getVersion() + " | Latest Version " + latestVersion); + //getLogger().info("Spigot: https://www.spigotmc.org/resources/100107/"); + getLogger().info("Polymart: https://polymart.org/resource/" + resourceID); + getLogger().info("+++++++++++++++++++++++++++++++++++"); + } else { + getLogger().info("You are running the latest version of " + pluginName + "!"); + } + }) + .setNotifyRequesters(false) + .setNotifyOpsOnJoin(false) + .checkEveryXHours(24) + .checkNow(); + onLatestVersion = checker.isUsingLatestVersion(); + } + + onStart(); + } + + + @Override + public final void onDisable() { + disabled = true; + + onEnd(); + } + + + public void onStart() { + // Override + } + + public void onReload() { + // Override + } + + public void onEnd() { + // Override + } + + public HibiscusPlugin get() { + return this; + } + +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/api/HibiscusCommonsAPI.java b/common/src/main/java/me/lojosho/hibiscuscommons/api/HibiscusCommonsAPI.java new file mode 100644 index 0000000..6c8a308 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/api/HibiscusCommonsAPI.java @@ -0,0 +1,17 @@ +package me.lojosho.hibiscuscommons.api; + +import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; +import org.jetbrains.annotations.NotNull; + +public class HibiscusCommonsAPI { + + /** + * Returns the version of HibiscusCommons + * @return + */ + @NotNull + public static String getHibiscusVersion() { + return HibiscusCommonsPlugin.getInstance().getDescription().getVersion(); + } + +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/api/events/HibiscusHookReload.java b/common/src/main/java/me/lojosho/hibiscuscommons/api/events/HibiscusHookReload.java new file mode 100644 index 0000000..ba742e4 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/api/events/HibiscusHookReload.java @@ -0,0 +1,29 @@ +package me.lojosho.hibiscuscommons.api.events; + +import me.lojosho.hibiscuscommons.hooks.Hook; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +/** + * This is called when a hook is reloaded from a plugin. This is useful for plugins like ItemsAdder, which loads items async from the main thread. + */ +public class HibiscusHookReload extends Event { + + private static final HandlerList handlers = new HandlerList(); + private final Hook hook; + + public HibiscusHookReload(Hook hook) { + this.hook = hook; + } + + public Hook getHook() { + return hook; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/api/events/HibiscusPlayerUnVanishEvent.java b/common/src/main/java/me/lojosho/hibiscuscommons/api/events/HibiscusPlayerUnVanishEvent.java new file mode 100644 index 0000000..61a54b5 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/api/events/HibiscusPlayerUnVanishEvent.java @@ -0,0 +1,39 @@ +package me.lojosho.hibiscuscommons.api.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.jetbrains.annotations.NotNull; + +public class HibiscusPlayerUnVanishEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + + private boolean cancel = false; + + public HibiscusPlayerUnVanishEvent(Player player) { + super(player); + } + + @NotNull + @Override + public HandlerList getHandlers() { + return handlers; + } + + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public boolean isCancelled() { + return cancel; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancel = cancel; + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/api/events/HibiscusPlayerVanishEvent.java b/common/src/main/java/me/lojosho/hibiscuscommons/api/events/HibiscusPlayerVanishEvent.java new file mode 100644 index 0000000..b2012b6 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/api/events/HibiscusPlayerVanishEvent.java @@ -0,0 +1,39 @@ +package me.lojosho.hibiscuscommons.api.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.jetbrains.annotations.NotNull; + +public class HibiscusPlayerVanishEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + + private boolean cancel = false; + + public HibiscusPlayerVanishEvent(Player player) { + super(player); + } + + @NotNull + @Override + public HandlerList getHandlers() { + return handlers; + } + + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public boolean isCancelled() { + return cancel; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancel = cancel; + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/config/GlobalSettings.java b/common/src/main/java/me/lojosho/hibiscuscommons/config/GlobalSettings.java new file mode 100644 index 0000000..ffb8e6e --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/config/GlobalSettings.java @@ -0,0 +1,7 @@ +package me.lojosho.hibiscuscommons.config; + +public class GlobalSettings { + + + +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/config/serializer/ItemSerializer.java b/common/src/main/java/me/lojosho/hibiscuscommons/config/serializer/ItemSerializer.java new file mode 100644 index 0000000..1207079 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/config/serializer/ItemSerializer.java @@ -0,0 +1,162 @@ +package me.lojosho.hibiscuscommons.config.serializer; + +import me.lojosho.hibiscuscommons.hooks.Hooks; +import me.lojosho.hibiscuscommons.util.ColorBuilder; +import me.lojosho.hibiscuscommons.util.InventoryUtils; +import me.lojosho.hibiscuscommons.util.ServerUtils; +import me.lojosho.hibiscuscommons.util.StringUtils; +import org.apache.commons.lang3.EnumUtils; +import org.bukkit.*; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.persistence.PersistentDataType; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.serialize.SerializationException; +import org.spongepowered.configurate.serialize.TypeSerializer; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.stream.Collectors; + +public class ItemSerializer implements TypeSerializer { + + public static final ItemSerializer INSTANCE = new ItemSerializer(); + private static final String MATERIAL = "material"; + private static final String AMOUNT = "amount"; + private static final String NAME = "name"; + private static final String UNBREAKABLE = "unbreakable"; + private static final String GLOWING = "glowing"; + private static final String LORE = "lore"; + private static final String MODEL_DATA = "model-data"; + private static final String NBT_TAGS = "nbt-tag"; + private static final String ENCHANTS = "enchants"; + private static final String ITEM_FLAGS = "item-flags"; + private static final String TEXTURE = "texture"; + private static final String OWNER = "owner"; + private static final String COLOR = "color"; + private static final String RED = "red"; + private static final String GREEN = "green"; + private static final String BLUE = "blue"; + + private ItemSerializer() { + } + + @Override + public ItemStack deserialize(final Type type, final ConfigurationNode source) + throws SerializationException { + final ConfigurationNode materialNode = source.node(MATERIAL); + final ConfigurationNode amountNode = source.node(AMOUNT); + final ConfigurationNode nameNode = source.node(NAME); + final ConfigurationNode unbreakableNode = source.node(UNBREAKABLE); + final ConfigurationNode glowingNode = source.node(GLOWING); + final ConfigurationNode loreNode = source.node(LORE); + final ConfigurationNode modelDataNode = source.node(MODEL_DATA); + final ConfigurationNode nbtNode = source.node(NBT_TAGS); + final ConfigurationNode enchantsNode = source.node(ENCHANTS); + final ConfigurationNode itemFlagsNode = source.node(ITEM_FLAGS); + final ConfigurationNode textureNode = source.node(TEXTURE); + final ConfigurationNode ownerNode = source.node(OWNER); + final ConfigurationNode colorNode = source.node(COLOR); + final ConfigurationNode redNode = colorNode.node(RED); + final ConfigurationNode greenNode = colorNode.node(GREEN); + final ConfigurationNode blueNode = colorNode.node(BLUE); + + if (materialNode.virtual()) return null; + + String material = materialNode.getString(); + + ItemStack item = Hooks.getItem(material); + if (item == null) { + //HMCCosmeticsPlugin.getInstance().getLogger().severe("Invalid Material -> " + material); + return new ItemStack(Material.AIR); + } + item.setAmount(amountNode.getInt(1)); + + ItemMeta itemMeta = item.getItemMeta(); + if (itemMeta == null) return item; + if (!nameNode.virtual()) + itemMeta.setDisplayName(StringUtils.parseStringToString((nameNode.getString("")))); + if (!unbreakableNode.virtual()) itemMeta.setUnbreakable(unbreakableNode.getBoolean()); + if (!glowingNode.virtual()) { + itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS); + itemMeta.addEnchant(Enchantment.LUCK, 1, true); + } + if (!loreNode.virtual()) itemMeta.setLore(loreNode.getList(String.class, new ArrayList()). + stream().map(StringUtils::parseStringToString).collect(Collectors.toList())); + if (!modelDataNode.virtual()) itemMeta.setCustomModelData(modelDataNode.getInt()); + + if (!nbtNode.virtual()) { + for (ConfigurationNode nbtNodes : nbtNode.childrenMap().values()) { + itemMeta.getPersistentDataContainer().set(NamespacedKey.minecraft(nbtNodes.key().toString()), PersistentDataType.STRING, nbtNodes.getString()); + } + } + + if (!enchantsNode.virtual()) { + for (ConfigurationNode enchantNode : enchantsNode.childrenMap().values()) { + if (Enchantment.getByKey(NamespacedKey.minecraft(enchantNode.key().toString())) == null) continue; + itemMeta.addEnchant(Enchantment.getByKey(NamespacedKey.minecraft(enchantNode.key().toString())), enchantNode.getInt(1), true); + } + } + + try { + if (!itemFlagsNode.virtual()) { + for (String itemFlag : itemFlagsNode.getList(String.class)) { + if (!EnumUtils.isValidEnum(ItemFlag.class, itemFlag)) continue; + //MessagesUtil.sendDebugMessages("Added " + itemFlag + " to the item!"); + itemMeta.addItemFlags(ItemFlag.valueOf(itemFlag)); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + if (item.getType() == Material.PLAYER_HEAD) { + SkullMeta skullMeta = (SkullMeta) itemMeta; + if (!ownerNode.virtual()) { + String ownerString = ownerNode.getString(); + if (ownerString.contains("%")) { + // This means it has PAPI placeholders in it + skullMeta.getPersistentDataContainer().set(InventoryUtils.getSkullOwner(), PersistentDataType.STRING, ownerString); + } + OfflinePlayer player = Bukkit.getOfflinePlayer(ownerString); + skullMeta.setOwningPlayer(player); + } + + if (!textureNode.virtual()) { + String textureString = textureNode.getString(); + if (textureString.contains("%")) { + // This means it has PAPI placeholders in it + skullMeta.getPersistentDataContainer().set(InventoryUtils.getSkullTexture(), PersistentDataType.STRING, textureString); + } + Bukkit.getUnsafe().modifyItemStack(item, "{SkullOwner:{Id:[I;0,0,0,0],Properties:{textures:[{Value:\"" + + textureString + "\"}]}}}"); + + + itemMeta = skullMeta; + } + } + + if (!colorNode.virtual()) { + if (ColorBuilder.canBeColored(item.getType())) { + if (!redNode.virtual()) { + itemMeta = ColorBuilder.color(itemMeta, Color.fromRGB(redNode.getInt(0), greenNode.getInt(0), blueNode.getInt(0))); + } else { + itemMeta = ColorBuilder.color(itemMeta, ServerUtils.hex2Rgb(colorNode.getString("#FFFFFF"))); + } + } + } + + item.setItemMeta(itemMeta); + return item; + } + @Override + public void serialize(final Type type, @Nullable final ItemStack obj, final ConfigurationNode node) throws SerializationException { + + } + +} + diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/config/serializer/LocationSerializer.java b/common/src/main/java/me/lojosho/hibiscuscommons/config/serializer/LocationSerializer.java new file mode 100644 index 0000000..e0bff17 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/config/serializer/LocationSerializer.java @@ -0,0 +1,43 @@ +package me.lojosho.hibiscuscommons.config.serializer; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.serialize.SerializationException; +import org.spongepowered.configurate.serialize.TypeSerializer; + +import java.lang.reflect.Type; + +public class LocationSerializer implements TypeSerializer { + public static final LocationSerializer INSTANCE = new LocationSerializer(); + + private static final String WORLD = "world"; + private static final String X = "x"; + private static final String Y = "y"; + private static final String Z = "z"; + private static final String PITCH = "pitch"; + private static final String YAW = "yaw"; + + + @Override + @Nullable + public Location deserialize(final Type type, final ConfigurationNode source) throws SerializationException { + final World world = Bukkit.getWorld(source.node(WORLD).getString()); + if (world == null) return null; + return new Location( + world, + source.node(X).getDouble(), + source.node(Y).getDouble(), + source.node(Z).getDouble(), + source.node(YAW).getFloat(), + source.node(PITCH).getFloat() + ); + } + + @Override + public void serialize(final Type type, @Nullable final Location loc, final ConfigurationNode source) throws SerializationException { + // Empty + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/Hook.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/Hook.java new file mode 100644 index 0000000..4d42d2d --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/Hook.java @@ -0,0 +1,100 @@ +package me.lojosho.hibiscuscommons.hooks; + +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Represents a hook into other minecraft plugins + */ +public abstract class Hook implements Listener { + private final String id; + private boolean active = false; + private boolean itemHook = false; + + public Hook(@NotNull String id, HookFlag... flags) { + this.id = id; + for (HookFlag flag : flags) { + switch (flag) { + case ITEM_SUPPORT: + setEnabledItemHook(true); + break; + } + } + Hooks.addHook(this); + } + + /** + * Loads this hook + * + * @implNote By default, this method does nothing. It should be overridden by child classes to implement any necessary loading logic + */ + public void load() { } + + /** + * Gets an {@link ItemStack} that is associated with the provided id from the hooked plugin + * @param itemId The id of the {@link ItemStack} + * @return The {@link ItemStack} with the id provided. If an invalid id was provided or if the hook doesn't have any related {@link ItemStack}s then this will return null + * @implNote By default, this method returns null. It should be overridden by child classes if you will to have your hook return a related {@link ItemStack} + */ + @Nullable + public ItemStack getItem(@NotNull String itemId) { + return null; + } + + /** + * Gets the id of this hook + * + * @return The unique id for this hook + */ + @NotNull + public final String getId() { + return id; + } + + /** + * Gets whether this hook has been activated + * @return true if this hook is active, false otherwise + * @deprecated As of release 2.2.5+, replaced by {@link #isActive()} + */ + @Deprecated + public boolean getActive() { + return this.active; + } + + /** + * Gets whether this hook has been activated + * @return true if this hook is active, false otherwise + * @since 2.2.5 + */ + public final boolean isActive() { + return this.active; + } + + /** + * Sets whether this hook is active + * @param active true to activate the hook, false otherwise + */ + public final void setActive(boolean active) { + this.active = active; + } + + /** + * Whether the method {@link #getItem(String)} should return a non-null value + * @return true if {@link #getItem(String)} should return a non-null value, false otherwise + * + * @apiNote Even though this method returns true does not mean that {@link #getItem(String)} won't return null, rather if this returns false then {@link #getItem(String)} should return false everytime + */ + public final boolean hasEnabledItemHook() { + return itemHook; + } + + /** + * Sets whether the method {@link #getItem(String)} should return a non-null value + * @param enabled true if {@link #getItem(String)} should return a non-null value, false otherwise + */ + public final void setEnabledItemHook(boolean enabled) { + itemHook = enabled; + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/HookFlag.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/HookFlag.java new file mode 100644 index 0000000..5c7cd92 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/HookFlag.java @@ -0,0 +1,5 @@ +package me.lojosho.hibiscuscommons.hooks; + +public enum HookFlag { + ITEM_SUPPORT +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/Hooks.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/Hooks.java new file mode 100644 index 0000000..6a1baa6 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/Hooks.java @@ -0,0 +1,98 @@ +package me.lojosho.hibiscuscommons.hooks; + +import me.clip.placeholderapi.PlaceholderAPI; +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; +import me.lojosho.hibiscuscommons.hooks.items.*; +import me.lojosho.hibiscuscommons.hooks.misc.*; +import me.lojosho.hibiscuscommons.hooks.placeholders.HookPlaceholderAPI; +import me.lojosho.hibiscuscommons.util.MessagesUtil; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; + +public class Hooks { + + private static final HashMap hooks = new HashMap<>(); + private static final HookOraxen ORAXEN_HOOK = new HookOraxen(); + private static final HookItemAdder ITEMADDER_HOOK = new HookItemAdder(); + private static final HookGeary GEARY_HOOK = new HookGeary(); + private static final HookMythic MYTHIC_HOOK = new HookMythic(); + private static final HookDenizen DENIZEN_HOOK = new HookDenizen(); + private static final HookPremiumVanish PREMIUM_VANISH_HOOK = new HookPremiumVanish(); + private static final HookSuperVanish SUPER_VANISH_HOOK = new HookSuperVanish(); + private static final HookHMCColor HMC_COLOR_HOOK = new HookHMCColor(); + private static final HookCMI CMI_HOOK = new HookCMI(); + private static final HookLibsDisguises LIBS_DISGUISES_HOOK = new HookLibsDisguises(); + private static final HookModelEngine MODEL_ENGINE_HOOK = new HookModelEngine(); + private static final HookMMOItems MMO_ITEMS_HOOK = new HookMMOItems(); + private static final HookEco ECO_ITEMS_HOOK = new HookEco(); + private static final HookPlaceholderAPI PAPI_HOOK = new HookPlaceholderAPI(); + + public static Hook getHook(@NotNull String id) { + return hooks.get(id.toLowerCase()); + } + + public static boolean isItemHook(@NotNull String id) { + return hooks.containsKey(id.toLowerCase()); + } + + public static void addHook(Hook hook) { + hooks.put(hook.getId().toLowerCase(), hook); + } + + public static void addPlaceholderAPI(PlaceholderExpansion expansion) { + if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { + HookPlaceholderAPI hook = (HookPlaceholderAPI) getHook("PlaceholderAPI"); + hook.registerPlaceholder(expansion); + } + } + + @NotNull + public static String processPlaceholders(OfflinePlayer player, String raw) { + if (isActiveHook("PlaceholderAPI")) return PlaceholderAPI.setPlaceholders(player, raw); + return raw; + } + + public static void setup() { + for (Hook hook : hooks.values()) { + HibiscusCommonsPlugin.getInstance().getLogger().info("Attempting to hook into " + hook.getId()); + if (Bukkit.getPluginManager().getPlugin(hook.getId()) != null) { + HibiscusCommonsPlugin.getInstance().getServer().getPluginManager().registerEvents(hook, HibiscusCommonsPlugin.getInstance()); + hook.setActive(true); + hook.load(); + HibiscusCommonsPlugin.getInstance().getLogger().info("Successfully hooked into " + hook.getId()); + } + } + } + + @Nullable + public static ItemStack getItem(@NotNull String raw) { + if (!raw.contains(":")) { + Material mat = Material.getMaterial(raw.toUpperCase()); + if (mat == null) return null; + return new ItemStack(mat); + } + // Ex. Oraxen:BigSword + // split[0] is the plugin name + // split[1] is the item name + String[] split = raw.split(":", 2); + + if (!isItemHook(split[0])) return null; + Hook hook = getHook(split[0]); + if (!hook.hasEnabledItemHook()) return null; + if (!hook.isActive()) return null; + return hook.getItem(split[1]); + } + + public static boolean isActiveHook(String id) { + Hook hook = getHook(id); + if (hook == null) return false; + return hook.isActive(); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookDenizen.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookDenizen.java new file mode 100644 index 0000000..0770095 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookDenizen.java @@ -0,0 +1,27 @@ +package me.lojosho.hibiscuscommons.hooks.items; + +import com.denizenscript.denizen.objects.ItemTag; +import com.denizenscript.denizencore.utilities.CoreUtilities; +import me.lojosho.hibiscuscommons.hooks.Hook; +import me.lojosho.hibiscuscommons.hooks.HookFlag; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * A hook that integrates the plugin {@link com.denizenscript.denizen.Denizen Denizen} to provide custom items + */ +@SuppressWarnings("SpellCheckingInspection") +public class HookDenizen extends Hook { + public HookDenizen() { + super("denizen", HookFlag.ITEM_SUPPORT); + } + + /** + * Gets a cosmetic {@link ItemStack} that is associated with the provided id from the plugin {@link com.denizenscript.denizen.Denizen Denizen} + */ + @Override + public ItemStack getItem(@NotNull String itemId) { + ItemTag item = ItemTag.valueOf(itemId, CoreUtilities.noDebugContext); + return item == null ? null : item.getItemStack(); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookEco.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookEco.java new file mode 100644 index 0000000..dad3e63 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookEco.java @@ -0,0 +1,18 @@ +package me.lojosho.hibiscuscommons.hooks.items; + +import com.willfp.eco.core.items.Items; +import me.lojosho.hibiscuscommons.hooks.Hook; +import me.lojosho.hibiscuscommons.hooks.HookFlag; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +public class HookEco extends Hook { + public HookEco() { + super("Eco", HookFlag.ITEM_SUPPORT); + } + + @Override + public ItemStack getItem(@NotNull String itemId) { + return Items.lookup(itemId).getItem(); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookGeary.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookGeary.java new file mode 100644 index 0000000..4d2a3ef --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookGeary.java @@ -0,0 +1,28 @@ +package me.lojosho.hibiscuscommons.hooks.items; + +import com.mineinabyss.geary.papermc.tracking.items.ItemTrackingKt; +import com.mineinabyss.geary.prefabs.PrefabKey; +import me.lojosho.hibiscuscommons.hooks.Hook; +import me.lojosho.hibiscuscommons.hooks.HookFlag; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * A hook that integrates the plugin {@link com.mineinabyss.geary.papermc.GearyPlugin Geary} to provide custom items + */ +public class HookGeary extends Hook { + + public HookGeary() { + super("geary", HookFlag.ITEM_SUPPORT); + } + + /** + * Gets a cosmetic {@link ItemStack} that is associated with the provided id from the plugin {@link com.mineinabyss.geary.papermc.GearyPlugin Geary} + */ + @Override + public ItemStack getItem(@NotNull String itemId) { + PrefabKey prefabKey = PrefabKey.Companion.ofOrNull(itemId); + if (prefabKey == null) return null; + return ItemTrackingKt.getGearyItems().createItem(prefabKey, null); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookItemAdder.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookItemAdder.java new file mode 100644 index 0000000..4bedffb --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookItemAdder.java @@ -0,0 +1,48 @@ +package me.lojosho.hibiscuscommons.hooks.items; + +import dev.lone.itemsadder.api.CustomStack; +import dev.lone.itemsadder.api.Events.ItemsAdderLoadDataEvent; +import me.lojosho.hibiscuscommons.api.events.HibiscusHookReload; +import me.lojosho.hibiscuscommons.hooks.Hook; +import me.lojosho.hibiscuscommons.hooks.HookFlag; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * A hook that integrates the plugin {@link dev.lone.itemsadder.api.ItemsAdder ItemsAdder} to provide custom items + */ +@SuppressWarnings("SpellCheckingInspection") +public class HookItemAdder extends Hook { + private boolean enabled = false; + + public HookItemAdder() { + super("itemsadder", HookFlag.ITEM_SUPPORT); + } + + /** + * Gets a cosmetic {@link ItemStack} that is associated with the provided id from the plugin {@link dev.lone.itemsadder.api.ItemsAdder ItemsAdder} + */ + @Override + public ItemStack getItem(@NotNull String itemId) { + if (enabled) { + CustomStack stack = CustomStack.getInstance(itemId); + if (stack == null) return null; + return stack.getItemStack(); + } else { + return new ItemStack(Material.AIR); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onItemAdderDataLoad(ItemsAdderLoadDataEvent event) { + HibiscusHookReload newEvent = new HibiscusHookReload(this); + Bukkit.getPluginManager().callEvent(newEvent); + //if (enabled && !Settings.isItemsAdderChangeReload()) return; + this.enabled = true; + //HMCCosmeticsPlugin.setup(); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookMMOItems.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookMMOItems.java new file mode 100644 index 0000000..20ac493 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookMMOItems.java @@ -0,0 +1,22 @@ +package me.lojosho.hibiscuscommons.hooks.items; + +import me.lojosho.hibiscuscommons.hooks.Hook; +import me.lojosho.hibiscuscommons.hooks.HookFlag; +import net.Indyuce.mmoitems.MMOItems; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +public class HookMMOItems extends Hook { + public HookMMOItems() { + super("MMOItems", HookFlag.ITEM_SUPPORT); + } + + @Override + public ItemStack getItem(@NotNull String itemId) { + String[] split = itemId.split(":", 2); + if (split.length == 2) { + return MMOItems.plugin.getItem(split[0], split[1]); + } + return null; + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookMythic.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookMythic.java new file mode 100644 index 0000000..ac74b48 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookMythic.java @@ -0,0 +1,25 @@ +package me.lojosho.hibiscuscommons.hooks.items; + +import io.lumine.mythic.bukkit.MythicBukkit; +import me.lojosho.hibiscuscommons.hooks.Hook; +import me.lojosho.hibiscuscommons.hooks.HookFlag; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * A hook that integrates the plugin {@link io.lumine.mythic.bukkit.MythicBukkit MythicBukkit} to provide custom items + */ +@SuppressWarnings("SpellCheckingInspection") +public class HookMythic extends Hook { + public HookMythic() { + super("mythicmobs", HookFlag.ITEM_SUPPORT); + } + + /** + * Gets a cosmetic {@link ItemStack} that is associated with the provided id from the plugin {@link io.lumine.mythic.bukkit.MythicBukkit MythicBukkit} + */ + @Override + public ItemStack getItem(@NotNull String itemId) { + return MythicBukkit.inst().getItemManager().getItemStack(itemId); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookOraxen.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookOraxen.java new file mode 100644 index 0000000..f48d669 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/items/HookOraxen.java @@ -0,0 +1,28 @@ +package me.lojosho.hibiscuscommons.hooks.items; + +import io.th0rgal.oraxen.api.OraxenItems; +import io.th0rgal.oraxen.items.ItemBuilder; +import me.lojosho.hibiscuscommons.hooks.Hook; +import me.lojosho.hibiscuscommons.hooks.HookFlag; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * A hook that integrates the plugin {@link io.th0rgal.oraxen.OraxenPlugin OraxenPlugin} to provide custom items + */ +@SuppressWarnings("SpellCheckingInspection") +public class HookOraxen extends Hook { + public HookOraxen() { + super("oraxen", HookFlag.ITEM_SUPPORT); + } + + /** + * Gets a cosmetic {@link ItemStack} that is associated with the provided id from the plugin {@link io.th0rgal.oraxen.OraxenPlugin OraxenPlugin} + */ + @Override + public ItemStack getItem(@NotNull String itemId) { + ItemBuilder builder = OraxenItems.getItemById(itemId); + if (builder == null) return null; + return builder.build(); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookCMI.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookCMI.java new file mode 100644 index 0000000..fcaae53 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookCMI.java @@ -0,0 +1,32 @@ +package me.lojosho.hibiscuscommons.hooks.misc; + +import com.Zrips.CMI.events.CMIPlayerUnVanishEvent; +import com.Zrips.CMI.events.CMIPlayerVanishEvent; +import me.lojosho.hibiscuscommons.api.events.HibiscusPlayerUnVanishEvent; +import me.lojosho.hibiscuscommons.api.events.HibiscusPlayerVanishEvent; +import me.lojosho.hibiscuscommons.hooks.Hook; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.jetbrains.annotations.NotNull; + +/** + * A hook that integrates the plugin {@link com.Zrips.CMI.CMI CMI} + */ +public class HookCMI extends Hook { + public HookCMI() { + super("CMI"); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerVanish(@NotNull CMIPlayerVanishEvent event) { + HibiscusPlayerVanishEvent newEvent = new HibiscusPlayerVanishEvent(event.getPlayer()); + Bukkit.getPluginManager().callEvent(newEvent); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerShow(@NotNull CMIPlayerUnVanishEvent event) { + HibiscusPlayerUnVanishEvent newEvent = new HibiscusPlayerUnVanishEvent(event.getPlayer()); + Bukkit.getPluginManager().callEvent(newEvent); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookHMCColor.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookHMCColor.java new file mode 100644 index 0000000..d3748b9 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookHMCColor.java @@ -0,0 +1,10 @@ +package me.lojosho.hibiscuscommons.hooks.misc; + + +import me.lojosho.hibiscuscommons.hooks.Hook; + +public class HookHMCColor extends Hook { + public HookHMCColor() { + super("HMCColor"); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookLibsDisguises.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookLibsDisguises.java new file mode 100644 index 0000000..c06f4d7 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookLibsDisguises.java @@ -0,0 +1,31 @@ +package me.lojosho.hibiscuscommons.hooks.misc; + +import me.libraryaddict.disguise.events.DisguiseEvent; +import me.libraryaddict.disguise.events.UndisguiseEvent; +import me.lojosho.hibiscuscommons.api.events.HibiscusPlayerVanishEvent; +import me.lojosho.hibiscuscommons.hooks.Hook; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.jetbrains.annotations.NotNull; + +public class HookLibsDisguises extends Hook { + public HookLibsDisguises() { + super("LibsDisguises"); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerVanish(@NotNull DisguiseEvent event) { + if (!(event.getEntity() instanceof Player player)) return; + HibiscusPlayerVanishEvent newEvent = new HibiscusPlayerVanishEvent(player); + Bukkit.getPluginManager().callEvent(newEvent); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerShow(@NotNull UndisguiseEvent event) { + if (!(event.getEntity() instanceof Player player)) return; + HibiscusPlayerVanishEvent newEvent = new HibiscusPlayerVanishEvent(player); + Bukkit.getPluginManager().callEvent(newEvent); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookModelEngine.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookModelEngine.java new file mode 100644 index 0000000..3808a67 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookModelEngine.java @@ -0,0 +1,10 @@ +package me.lojosho.hibiscuscommons.hooks.misc; + +import me.lojosho.hibiscuscommons.hooks.Hook; + +public class HookModelEngine extends Hook { + + public HookModelEngine() { + super("ModelEngine"); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookPremiumVanish.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookPremiumVanish.java new file mode 100644 index 0000000..10f4b3e --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookPremiumVanish.java @@ -0,0 +1,34 @@ +package me.lojosho.hibiscuscommons.hooks.misc; + +import de.myzelyam.api.vanish.PlayerHideEvent; +import de.myzelyam.api.vanish.PlayerShowEvent; +import me.lojosho.hibiscuscommons.api.events.HibiscusPlayerUnVanishEvent; +import me.lojosho.hibiscuscommons.api.events.HibiscusPlayerVanishEvent; +import me.lojosho.hibiscuscommons.hooks.Hook; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.jetbrains.annotations.NotNull; + +/** + * A hook that integrates the plugin {@link de.myzelyam.api.vanish.VanishAPI Supervanish} + * + * @implSpec Supervanish and Premium Vanish both use the same api + */ +public class HookPremiumVanish extends Hook { + public HookPremiumVanish() { + super("PremiumVanish"); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerVanish(@NotNull PlayerHideEvent event) { + HibiscusPlayerVanishEvent newEvent = new HibiscusPlayerVanishEvent(event.getPlayer()); + Bukkit.getPluginManager().callEvent(newEvent); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerShow(@NotNull PlayerShowEvent event) { + HibiscusPlayerUnVanishEvent newEvent = new HibiscusPlayerUnVanishEvent(event.getPlayer()); + Bukkit.getPluginManager().callEvent(newEvent); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookSuperVanish.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookSuperVanish.java new file mode 100644 index 0000000..ef2b222 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookSuperVanish.java @@ -0,0 +1,34 @@ +package me.lojosho.hibiscuscommons.hooks.misc; + +import de.myzelyam.api.vanish.PlayerHideEvent; +import de.myzelyam.api.vanish.PlayerShowEvent; +import me.lojosho.hibiscuscommons.api.events.HibiscusPlayerUnVanishEvent; +import me.lojosho.hibiscuscommons.api.events.HibiscusPlayerVanishEvent; +import me.lojosho.hibiscuscommons.hooks.Hook; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.jetbrains.annotations.NotNull; + +/** + * A hook that integrates the plugin {@link de.myzelyam.api.vanish.VanishAPI Supervanish} + * + * @implSpec Supervanish and Premium Vanish both use the same api + */ +public class HookSuperVanish extends Hook { + public HookSuperVanish() { + super("SuperVanish"); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerVanish(@NotNull PlayerHideEvent event) { + HibiscusPlayerVanishEvent newEvent = new HibiscusPlayerVanishEvent(event.getPlayer()); + Bukkit.getPluginManager().callEvent(newEvent); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerShow(@NotNull PlayerShowEvent event) { + HibiscusPlayerUnVanishEvent newEvent = new HibiscusPlayerUnVanishEvent(event.getPlayer()); + Bukkit.getPluginManager().callEvent(newEvent); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/placeholders/HookPlaceholderAPI.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/placeholders/HookPlaceholderAPI.java new file mode 100644 index 0000000..ee35449 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/placeholders/HookPlaceholderAPI.java @@ -0,0 +1,26 @@ +package me.lojosho.hibiscuscommons.hooks.placeholders; + +import me.lojosho.hibiscuscommons.hooks.Hook; +import me.clip.placeholderapi.expansion.PlaceholderExpansion; + +import java.util.ArrayList; + +public class HookPlaceholderAPI extends Hook { + + private ArrayList placeHolders = new ArrayList<>(); + + public HookPlaceholderAPI() { + super("PlaceholderAPI"); + } + + public void registerPlaceholder(PlaceholderExpansion placeholderExpansion) { + placeHolders.add(placeholderExpansion); + } + + @Override + public void load() { + for (PlaceholderExpansion placeholderExpansion : placeHolders) { + placeholderExpansion.register(); + } + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSHandler.java b/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSHandler.java new file mode 100644 index 0000000..d1a0eb8 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSHandler.java @@ -0,0 +1,15 @@ +package me.lojosho.hibiscuscommons.nms; + +import org.bukkit.entity.Entity; + +public interface NMSHandler { + + int getNextEntityId(); + + Entity getEntity(int entityId); + + default boolean getSupported () { + return false; + } + +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSHandlers.java b/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSHandlers.java new file mode 100644 index 0000000..d9f9ac4 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSHandlers.java @@ -0,0 +1,52 @@ +package me.lojosho.hibiscuscommons.nms; + +import lombok.Getter; +import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; + +public class NMSHandlers { + + private static final String[] SUPPORTED_VERSION = new String[]{"v1_18_R2", "v1_19_R1", "v1_19_R2", "v1_19_R3", "v1_20_R1", "v1_20_R2", "v1_20_R3"}; + private static NMSHandler handler; + @Getter + private static String version; + + @Nullable + public static NMSHandler getHandler() { + if (handler != null) { + return handler; + } else { + setup(); + } + return handler; + } + + public static boolean isVersionSupported() { + if (getHandler() == null) return false; + return getHandler().getSupported(); + } + + public static void setup() { + if (handler != null) return; + final String packageName = HibiscusCommonsPlugin.getInstance().getServer().getClass().getPackage().getName(); + String packageVersion = packageName.substring(packageName.lastIndexOf('.') + 1); + + for (String selectedVersion : SUPPORTED_VERSION) { + if (!selectedVersion.contains(packageVersion)) { + continue; + } + //MessagesUtil.sendDebugMessages(packageVersion + " has been detected.", Level.INFO); + version = packageVersion; + try { + handler = (NMSHandler) Class.forName("me.lojosho.hibiscuscommons.nms." + packageVersion + ".NMSHandler").getConstructor().newInstance(); + return; + } catch (ClassNotFoundException | InvocationTargetException | InstantiationException | + IllegalAccessException | NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/util/Adventure.java b/common/src/main/java/me/lojosho/hibiscuscommons/util/Adventure.java new file mode 100644 index 0000000..4a09336 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/util/Adventure.java @@ -0,0 +1,19 @@ +package me.lojosho.hibiscuscommons.util; + +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.standard.StandardTags; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; + +public class Adventure { + + public static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer.builder() + .hexColors() + .useUnusualXRepeatedCharacterHexFormat() + .build(); + + public static final MiniMessage MINI_MESSAGE = MiniMessage.builder().tags( + StandardTags.defaults() + ). + build(); + +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/util/ColorBuilder.java b/common/src/main/java/me/lojosho/hibiscuscommons/util/ColorBuilder.java new file mode 100644 index 0000000..bc59d16 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/util/ColorBuilder.java @@ -0,0 +1,39 @@ +package me.lojosho.hibiscuscommons.util; + +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import org.bukkit.inventory.meta.PotionMeta; +import org.jetbrains.annotations.NotNull; + +public class ColorBuilder { + + public static boolean canBeColored(final Material material) { + return canBeColored(new ItemStack(material)); + } + + public static boolean canBeColored(final @NotNull ItemStack itemStack) { + final ItemMeta itemMeta = itemStack.getItemMeta(); + + return (itemMeta instanceof LeatherArmorMeta || + itemMeta instanceof PotionMeta); + } + + /** + * @param color armor color + * @return this + */ + + public static ItemMeta color(ItemMeta itemMeta, final Color color) { + if (itemMeta instanceof final PotionMeta meta) { + meta.setColor(color); + } + if (itemMeta instanceof final LeatherArmorMeta meta) { + meta.setColor(color); + } + return itemMeta; + } + +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/util/InventoryUtils.java b/common/src/main/java/me/lojosho/hibiscuscommons/util/InventoryUtils.java new file mode 100644 index 0000000..e5ca1fb --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/util/InventoryUtils.java @@ -0,0 +1,20 @@ +package me.lojosho.hibiscuscommons.util; + +import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; +import org.bukkit.NamespacedKey; + +public class InventoryUtils { + + + public static NamespacedKey getOwnerKey() { + return new NamespacedKey(HibiscusCommonsPlugin.getInstance(), "owner"); + } + + public static NamespacedKey getSkullOwner() { + return new NamespacedKey(HibiscusCommonsPlugin.getInstance(), "skullowner"); + } + + public static NamespacedKey getSkullTexture() { + return new NamespacedKey(HibiscusCommonsPlugin.getInstance(), "skulltexture"); + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/util/MessagesUtil.java b/common/src/main/java/me/lojosho/hibiscuscommons/util/MessagesUtil.java new file mode 100644 index 0000000..2d07acf --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/util/MessagesUtil.java @@ -0,0 +1,21 @@ +package me.lojosho.hibiscuscommons.util; + +import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; + +import java.util.logging.Level; + +public class MessagesUtil { + + private static boolean debug = false; + + + public static void sendDebugMessages(String message) { + sendDebugMessages(message, Level.INFO); + } + + public static void sendDebugMessages(String message, Level level) { + if (!debug) return; + HibiscusCommonsPlugin.getInstance().getLogger().log(level, message); + } + +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/util/ServerUtils.java b/common/src/main/java/me/lojosho/hibiscuscommons/util/ServerUtils.java new file mode 100644 index 0000000..3a11513 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/util/ServerUtils.java @@ -0,0 +1,104 @@ +package me.lojosho.hibiscuscommons.util; + +import com.comphenix.protocol.wrappers.WrappedGameProfile; +import com.comphenix.protocol.wrappers.WrappedSignedProperty; +import me.lojosho.hibiscuscommons.nms.NMSHandler; +import me.lojosho.hibiscuscommons.nms.NMSHandlers; +import org.bukkit.Color; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +public class ServerUtils { + + public static int getNextEntityId() { + return NMSHandlers.getHandler().getNextEntityId(); + } + + @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()); + } + + /** + * Parse a color from a string. + * Formats: #RRGGBB; R,G,B + * + * @param color The string + * @return The color, if the string can't be parsed, null is returned + */ + public static Color colorFromString(@Nullable String color) { + if (color == null) { + return null; + } + try { + var decodedColor = java.awt.Color.decode(color.startsWith("#") ? color : "#" + color); + return Color.fromRGB(decodedColor.getRed(), decodedColor.getGreen(), decodedColor.getBlue()); + } catch (NumberFormatException invalidHex) { + try { + var rgbValues = Arrays.stream(color.split(",")).map(Integer::parseInt).toArray(Integer[]::new); + return Color.fromRGB(rgbValues[0], rgbValues[1], rgbValues[2]); + } catch (Exception invalidRgb) { + return null; + } + } + } + + /** + * This takes in a string like #FFFFFF to convert it into a Bukkit color + * @param colorStr + * @return + */ + public static Color hex2Rgb(String colorStr) { + if (colorStr.startsWith("#")) return Color.fromRGB(Integer.valueOf(colorStr.substring(1), 16)); + if (colorStr.startsWith("0x")) return Color.fromRGB(Integer.valueOf(colorStr.substring(2), 16)); + if (colorStr.contains(",")) { + String[] colorString = colorStr.replace(" ", "").split(","); + for (String color : colorString) if (Integer.valueOf(color) == null) return Color.WHITE; + Color.fromRGB(Integer.valueOf(colorString[0]), Integer.valueOf(colorString[1]), Integer.valueOf(colorString[2])); + } + + return Color.WHITE; + } + + /** + * This takes in a string like 55,49,181 to convert it into a Bukkit Color + * @param colorStr + * @return + */ + public static Color rgbToRgb(String colorStr) { + if (colorStr.contains(",")) { + String[] colors = colorStr.split(",", 3); + if (colors.length == 3) { + return Color.fromRGB(Integer.parseInt(colors[0]), Integer.parseInt(colors[1]), Integer.parseInt(colors[2])); + } + } + + return Color.WHITE; + } + + public static int getNextYaw(final int current, final int rotationSpeed) { + int nextYaw = current + rotationSpeed; + if (nextYaw > 179) { + nextYaw = (current + rotationSpeed) - 358; + return nextYaw; + } + return nextYaw; + } + + public static boolean hasClass(String className) { + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/util/StringUtils.java b/common/src/main/java/me/lojosho/hibiscuscommons/util/StringUtils.java new file mode 100644 index 0000000..4ce3bb1 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/util/StringUtils.java @@ -0,0 +1,12 @@ +package me.lojosho.hibiscuscommons.util; + +import org.jetbrains.annotations.NotNull; + +public class StringUtils { + + @NotNull + public static String parseStringToString(final String parsed) { + return Adventure.SERIALIZER.serialize(Adventure.MINI_MESSAGE.deserialize(parsed)); + } + +} diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/util/packets/PacketManager.java b/common/src/main/java/me/lojosho/hibiscuscommons/util/packets/PacketManager.java new file mode 100644 index 0000000..6f0d4d4 --- /dev/null +++ b/common/src/main/java/me/lojosho/hibiscuscommons/util/packets/PacketManager.java @@ -0,0 +1,233 @@ +package me.lojosho.hibiscuscommons.util.packets; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import me.lojosho.hibiscuscommons.util.MessagesUtil; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class PacketManager { + + public static void sendEntitySpawnPacket( + final @NotNull Location location, + final int entityId, + final EntityType entityType, + final UUID uuid, + final @NotNull List sendTo + ) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY); + 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 gamemodeChangePacket( + Player player, + int gamemode + ) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.GAME_STATE_CHANGE); + packet.getGameStateIDs().write(0, 3); + // Tells what event this is. This is a change gamemode event. + packet.getFloat().write(0, (float) gamemode); + sendPacket(player, packet); + MessagesUtil.sendDebugMessages("Gamemode Change sent to " + player + " to be " + gamemode); + } + + public static void ridingMountPacket( + int mountId, + int passengerId, + @NotNull List sendTo + ) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.MOUNT); + packet.getIntegers().write(0, mountId); + packet.getIntegerArrays().write(0, new int[]{passengerId}); + for (Player p : sendTo) sendPacket(p, packet); + } + + public static void sendLookPacket( + int entityId, + @NotNull Location location, + @NotNull List sendTo + ) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_HEAD_ROTATION); + packet.getIntegers().write(0, entityId); + packet.getBytes().write(0, (byte) (location.getYaw() * 256.0F / 360.0F)); + for (Player p : sendTo) sendPacket(p, packet); + } + + public static void sendRotationPacket( + int entityId, + @NotNull Location location, + boolean onGround, + @NotNull List sendTo + ) { + float ROTATION_FACTOR = 256.0F / 360.0F; + 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( + int entityId, + int yaw, + boolean onGround, + @NotNull List sendTo + ) { + float ROTATION_FACTOR = 256.0F / 360.0F; + 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); + } + + public static void sendRidingPacket( + final int mountId, + final int passengerId, + final @NotNull List sendTo + ) { + sendRidingPacket(mountId, new int[] {passengerId}, sendTo); + } + + public static void sendRidingPacket( + final int mountId, + final int[] passengerIds, + final @NotNull List sendTo + ) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.MOUNT); + packet.getIntegers().write(0, mountId); + packet.getIntegerArrays().write(0, passengerIds); + for (final Player p : sendTo) { + sendPacket(p, packet); + } + } + + /** + * Destroys an entity from a player + * @param entityId The entity to delete for a player + * @param sendTo The players the packet should be sent to + */ + public static void sendEntityDestroyPacket(final int entityId, @NotNull List sendTo) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY); + packet.getModifier().write(0, new IntArrayList(new int[]{entityId})); + for (final Player p : sendTo) sendPacket(p, packet); + } + + /** + * Destroys an entity from a player + * @param sendTo The players the packet should be sent to + */ + public static void sendEntityDestroyPacket(final List ids, @NotNull List sendTo) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY); + IntArrayList entities = new IntArrayList(new int[]{}); + for (int id : ids) entities.add(id); + packet.getModifier().write(0, entities); + for (final Player p : sendTo) sendPacket(p, packet); + } + + /** + * Sends a camera packet + * @param entityId The Entity ID that camera will go towards + * @param sendTo The players that will be sent this packet + */ + public static void sendCameraPacket(final int entityId, @NotNull List sendTo) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.CAMERA); + packet.getIntegers().write(0, entityId); + for (final Player p : sendTo) sendPacket(p, packet); + MessagesUtil.sendDebugMessages(sendTo + " | " + entityId + " has had a camera packet on them!"); + } + + public static void sendLeashPacket( + final int leashedEntity, + final int entityId, + final @NotNull List sendTo + ) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.ATTACH_ENTITY); + packet.getIntegers().write(0, leashedEntity); + packet.getIntegers().write(1, entityId); + for (final Player p : sendTo) { + sendPacket(p, packet); + } + } + + /** + * Used when a player is sent 8+ blocks. + * @param entityId Entity this affects + * @param location Location a player is being teleported to + * @param onGround If the packet is on the ground + * @param sendTo Whom to send the packet to + */ + public static void sendTeleportPacket( + final int entityId, + final @NotNull Location location, + boolean onGround, + final @NotNull List sendTo + ) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT); + packet.getIntegers().write(0, entityId); + packet.getDoubles().write(0, location.getX()); + packet.getDoubles().write(1, location.getY()); + packet.getDoubles().write(2, location.getZ()); + packet.getBytes().write(0, (byte) (location.getYaw() * 256.0F / 360.0F)); + packet.getBytes().write(1, (byte) (location.getPitch() * 256.0F / 360.0F)); + packet.getBooleans().write(0, onGround); + for (final Player p : sendTo) { + sendPacket(p, packet); + } + } + + + + @NotNull + public static List getViewers(Location location, int distance) { + ArrayList viewers = new ArrayList<>(); + if (distance <= 0) { + viewers.addAll(location.getWorld().getPlayers()); + } else { + viewers.addAll(getNearbyPlayers(location, distance)); + } + return viewers; + } + + private static List getNearbyPlayers(Location location, int distance) { + List players = new ArrayList<>(); + for (Entity entity : location.getWorld().getNearbyEntities(location, distance, distance, distance)) { + if (entity instanceof Player) { + players.add((Player) entity); + } + } + return players; + } + + public static void sendPacket(Player player, PacketContainer packet) { + if (player == null) return; + ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, null,false); + } + +} diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml new file mode 100644 index 0000000..e69de29 diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..e69de29 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..c1962a7 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..37aef8d --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..aeb74cb --- /dev/null +++ b/gradlew @@ -0,0 +1,245 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..93e3f59 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/lib/CMI-API9.3.1.5.jar b/lib/CMI-API9.3.1.5.jar new file mode 100644 index 0000000..08052ab Binary files /dev/null and b/lib/CMI-API9.3.1.5.jar differ diff --git a/lib/CMILib1.2.4.6.jar b/lib/CMILib1.2.4.6.jar new file mode 100644 index 0000000..7a1aadb Binary files /dev/null and b/lib/CMILib1.2.4.6.jar differ diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..ba46238 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven("https://repo.papermc.io/repository/maven-public/") + } +} + +rootProject.name = "HibiscusCommons" +include( + "common", + "v1_18_R2", + "v1_19_R1", + "v1_19_R2", + "v1_19_R3", + "v1_20_R1", + "v1_20_R2", + "v1_20_R3" +) \ No newline at end of file diff --git a/v1_20_R3/build.gradle.kts b/v1_20_R3/build.gradle.kts new file mode 100644 index 0000000..e64891c --- /dev/null +++ b/v1_20_R3/build.gradle.kts @@ -0,0 +1,27 @@ +plugins { + id("java") + id("io.papermc.paperweight.userdev") version "1.5.1" +} + +dependencies { + paperDevBundle("1.20.4-R0.1-SNAPSHOT") + implementation(project(":common")) +} + +tasks { + + build { + dependsOn(reobfJar) + } + + compileJava { + options.encoding = Charsets.UTF_8.name() + options.release.set(17) + } + javadoc { + options.encoding = Charsets.UTF_8.name() + } + processResources { + filteringCharset = Charsets.UTF_8.name() + } +} \ No newline at end of file diff --git a/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSHandler.java b/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSHandler.java new file mode 100644 index 0000000..12a8197 --- /dev/null +++ b/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSHandler.java @@ -0,0 +1,32 @@ +package me.lojosho.hibiscuscommons.nms.v1_20_R3; + +import net.minecraft.server.level.ServerLevel; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R3.CraftServer; +public class NMSHandler implements me.lojosho.hibiscuscommons.nms.NMSHandler { + @Override + public int getNextEntityId() { + return net.minecraft.world.entity.Entity.nextEntityId(); + } + + @Override + public org.bukkit.entity.Entity getEntity(int entityId) { + net.minecraft.world.entity.Entity entity = getNMSEntity(entityId); + if (entity == null) return null; + return entity.getBukkitEntity(); + } + + private net.minecraft.world.entity.Entity getNMSEntity(int entityId) { + for (ServerLevel world : ((CraftServer) Bukkit.getServer()).getHandle().getServer().getAllLevels()) { + net.minecraft.world.entity.Entity entity = world.getEntity(entityId); + if (entity == null) continue; + return entity; + } + return null; + } + + @Override + public boolean getSupported() { + return true; + } +}