Dev Build

This commit is contained in:
LikeWhat 2021-07-08 22:03:37 +02:00
parent 61fd882dc7
commit df54f14811
14 changed files with 227 additions and 68 deletions

5
ISSUE_TEMPLATE.md Normal file
View File

@ -0,0 +1,5 @@
## Issue Description
## Infos
- Plugin Version:
- Minecraft Version (ex. Spigot 1.8, Paper 1.12.2):

View File

@ -76,8 +76,8 @@
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<groupId>com.destroystokyo.paper</groupId>
<artifactId>paper</artifactId>
<version>1.8.8</version>
<scope>provided</scope>
</dependency>

View File

@ -14,6 +14,7 @@ import de.likewhat.customheads.listener.OtherListeners;
import de.likewhat.customheads.loader.Language;
import de.likewhat.customheads.loader.Looks;
import de.likewhat.customheads.utils.*;
import de.likewhat.customheads.utils.reflection.NBTTagUtils;
import de.likewhat.customheads.utils.reflection.TagEditor;
import de.likewhat.customheads.utils.stuff.CHCommand;
import de.likewhat.customheads.utils.stuff.CHTabCompleter;
@ -271,6 +272,8 @@ public class CustomHeads extends JavaPlugin {
if(exception instanceof GitHubDownloader.RateLimitExceededException) {
GitHubDownloader.RateLimitExceededException rateLimitException = (GitHubDownloader.RateLimitExceededException)exception;
getLogger().log(Level.SEVERE, "GitHub Rate-Limited the Plugins Requests. Please try again later. (Time until Reset: " + rateLimitException.getTimeUntilReset() + ")");
getLogger().log(Level.SEVERE, "If this Error continues to occur try downloading it manually from Github (https://github.com/IHasName/CustomHeads/releases/download/" + instance.getDescription().getVersion() + "/en_EN.zip)");
getLogger().log(Level.INFO, "A Tutorial on how to do that can be found on the Wiki");
Bukkit.getPluginManager().disablePlugin(instance);
} else {
getLogger().log(Level.WARNING, "Failed to lookup Languages trying to use default instead");
@ -376,6 +379,9 @@ public class CustomHeads extends JavaPlugin {
}
if (!USE_TEXTURES) {
if(NBTTagUtils.MC_VERSION == 17) {
return;
}
getServer().getConsoleSender().sendMessage(chWarning + "Hrm. Seems like CustomHeads wasn't tested on this Minecraft Version yet...");
getServer().getConsoleSender().sendMessage(chWarning + "Please report this to me on Discord (Link's on the Spigot Page)");
}

View File

@ -88,11 +88,21 @@ public interface CustomHeadsAPI {
* Will return an Head from the given ID.
* Might be null if the Head doesnt exists
*
* @param category from Which Category to pull from
* @param id Head ID
* @param categoryId from Which Category to pull from
* @param headId Head ID
* @return Head from Database
*/
CustomHead getHead(Category category, int id);
CustomHead getHead(Category categoryId, int headId);
/**
* Will return an Head from the given ID.
* Might be null if the Head doesnt exists
*
* @param categoryId from Which Category to pull from
* @param headId Head ID
* @return Head from Database
*/
CustomHead getHead(String categoryId, int headId);
/**
* Starts a Firework in the world

View File

@ -0,0 +1,41 @@
package de.likewhat.customheads.api.events;
import de.likewhat.customheads.category.CustomHead;
import lombok.Getter;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@Getter
public class PlayerClickCustomHeadEvent extends Event implements Cancellable {
private static HandlerList handlers = new HandlerList();
private Player player;
private CustomHead head;
private boolean cancelled = false;
public PlayerClickCustomHeadEvent(Player player, CustomHead head) {
this.player = player;
this.head = head;
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public static HandlerList getHandlerList() {
return handlers;
}
public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -81,7 +81,7 @@ public class Category extends BaseCategory {
return !heads.isEmpty();
}
Category setSubCategories(List<SubCategory> subCategories) {
public Category setSubCategories(List<SubCategory> subCategories) {
this.subCategories = subCategories;
return this;
}

View File

@ -29,7 +29,7 @@ public class CustomHead extends ItemStack {
}
public String toString() {
return originCategory.getId() + ":" + id + " - " + price;
return "CustomHead:{" + originCategory.getId() + ":" + id + " - " + price + "}";
}
public boolean isFree() {

View File

@ -2,6 +2,7 @@ package de.likewhat.customheads.listener;
import de.likewhat.customheads.CustomHeads;
import de.likewhat.customheads.api.CustomHeadsPlayer;
import de.likewhat.customheads.api.events.PlayerClickCustomHeadEvent;
import de.likewhat.customheads.category.BaseCategory;
import de.likewhat.customheads.category.Category;
import de.likewhat.customheads.category.CustomHead;
@ -132,16 +133,14 @@ public class InventoryListener implements Listener {
@EventHandler
public void onInvClick(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked();
if(event.getRawSlot() >= event.getInventory().getSize() && event.isShiftClick()) {
if(event.getClickedInventory() != null && event.getClickedInventory().getType() == InventoryType.PLAYER && event.isShiftClick()) {
handleInventoryAction(event);
return;
}
if (event.getInventory() == null || event.getRawSlot() >= event.getInventory().getSize() || event.getInventory().getType() != InventoryType.CHEST || !hasPermission(player, "heads.use")) {
return;
}
player.sendMessage("§7[CHTags Tags] §r" + CustomHeads.getTagEditor().getTags(event.getCurrentItem()) + " lastActiveMenu: " + lastActiveMenu.getOrDefault(player.getUniqueId(), "none")); // Yeah debug at its finest
//player.sendMessage("§7[CHTags Tags] §r" + CustomHeads.getTagEditor().getTags(event.getCurrentItem()) + " lastActiveMenu: " + lastActiveMenu.getOrDefault(player.getUniqueId(), "none")); // Yeah debug at its finest
if (event.getView().getTitle().equals(CustomHeads.getLanguageManager().LOADING)) {
event.setCancelled(true);
@ -149,6 +148,18 @@ public class InventoryListener implements Listener {
CustomHeadsPlayer customHeadsPlayer = CustomHeads.getApi().wrapPlayer(player);
List<String> itemTags = CustomHeads.getTagEditor().getTags(event.getCurrentItem());
if(itemTags.contains("headID")) {
CustomHead head = Utils.getHeadFromItem(event.getCurrentItem());
if(head != null) {
PlayerClickCustomHeadEvent otherClickEvent = new PlayerClickCustomHeadEvent(player, head);
Bukkit.getPluginManager().callEvent(otherClickEvent);
if(otherClickEvent.isCancelled()) {
event.setCancelled(true);
return;
}
}
}
// Delete Head
if (event.getView().getTitle().equals(CustomHeads.getLanguageManager().SAVED_HEADS_TITLE.replace("{PLAYER}", player.getName()))) {
if (event.getClick() == ClickType.SHIFT_RIGHT) {

View File

@ -40,8 +40,8 @@ public class APIHandler implements CustomHeadsAPI {
static {
tileEntitySkullClass = Utils.getMCServerClassByName("TileEntitySkull");
blockPositionClass = Utils.getMCServerClassByName("BlockPosition");
tileEntitySkullClass = Utils.getMCServerClassByName("TileEntitySkull", "world.level.block.entity");
blockPositionClass = Utils.getMCServerClassByName("BlockPosition", "core");
try {
blockPositionConstructor = blockPositionClass.getConstructor(int.class, int.class, int.class);
} catch(Exception e) {
@ -106,13 +106,13 @@ public class APIHandler implements CustomHeadsAPI {
Object skullInstance = tileEntitySkullClass.getConstructor().newInstance();
Object positionInstance = blockPositionConstructor.newInstance(location.getBlockX(), location.getBlockY(), location.getBlockZ());
tileEntitySkullClass.getMethod("setLocation", Utils.getMCServerClassByName("World"), blockPositionClass).invoke(skullInstance, nmsWorld, positionInstance);
tileEntitySkullClass.getMethod("setLocation", Utils.getMCServerClassByName("World", "world.level"), blockPositionClass).invoke(skullInstance, nmsWorld, positionInstance);
Class<?> craftBlockDataClass = Utils.getCBClass("block.data.CraftBlockData");
Object blockDataState = craftBlockDataClass.getMethod("getState").invoke(craftBlockDataClass.cast(Material.class.getMethod("createBlockData").invoke(NMSUtils.getEnumFromClass(Material.class, "player_head"))));
nmsWorld.getClass().getMethod("setTypeAndData", blockPositionClass, Utils.getMCServerClassByName("IBlockData"), int.class).invoke(nmsWorld, positionInstance, blockDataState, 3);
nmsWorld.getClass().getMethod("setTileEntity", blockPositionClass, Utils.getMCServerClassByName("TileEntity")).invoke(nmsWorld, positionInstance, skullInstance);
nmsWorld.getClass().getMethod("setTypeAndData", blockPositionClass, Utils.getMCServerClassByName("IBlockData", "world.level.block.state"), int.class).invoke(nmsWorld, positionInstance, blockDataState, 3);
nmsWorld.getClass().getMethod("setTileEntity", blockPositionClass, Utils.getMCServerClassByName("TileEntity", "world.level.block.entity")).invoke(nmsWorld, positionInstance, skullInstance);
skull = (Skull) block.getState();
} else {
block.setType(Material.SKULL);
@ -139,8 +139,16 @@ public class APIHandler implements CustomHeadsAPI {
}
}
public CustomHead getHead(Category category, int id) {
return category.getHeads().stream().filter(customHead -> customHead.getId() == id).findFirst().orElse(null);
public CustomHead getHead(String categoryId, int headId) {
Category category = CustomHeads.getCategoryManager().getCategory(categoryId);
if(category == null) {
throw new NullPointerException("Unknown Category ID: " + categoryId);
}
return category.getHeads().stream().filter(customHead -> customHead.getId() == headId).findFirst().orElse(null);
}
public CustomHead getHead(Category category, int headId) {
return category.getHeads().stream().filter(customHead -> customHead.getId() == headId).findFirst().orElse(null);
}
// API Impl

View File

@ -11,6 +11,7 @@ import de.likewhat.customheads.category.Category;
import de.likewhat.customheads.category.CustomHead;
import de.likewhat.customheads.category.SubCategory;
import de.likewhat.customheads.utils.reflection.AnvilGUI;
import de.likewhat.customheads.utils.reflection.NBTTagUtils;
import de.likewhat.customheads.utils.reflection.TagEditor;
import de.likewhat.customheads.utils.stuff.CHSearchQuery;
import de.likewhat.customheads.utils.updaters.AsyncFileDownloader;
@ -669,11 +670,11 @@ public class Utils {
public static void sendJSONMessage(String json, Player p) {
try {
Object chat = getMCServerClassByName("ChatSerializer").getMethod("a", String.class).invoke(null, json);
Object packet = getMCServerClassByName("PacketPlayOutChat").getConstructor(getMCServerClassByName("IChatBaseComponent")).newInstance(chat);
Object chat = getMCServerClassByName("ChatSerializer", "network.chat").getMethod("a", String.class).invoke(null, json);
Object packet = getMCServerClassByName("PacketPlayOutChat", "network.protocol.game").getConstructor(getMCServerClassByName("IChatBaseComponent", "network.chat")).newInstance(chat);
Object player = p.getClass().getMethod("getHandle").invoke(p);
Object connection = player.getClass().getField("playerConnection").get(player);
connection.getClass().getMethod("sendPacket", getMCServerClassByName("Packet")).invoke(connection, packet);
connection.getClass().getMethod("sendPacket", getMCServerClassByName("Packet", "network.protocol.game")).invoke(connection, packet);
} catch (Exception e) {
CustomHeads.getInstance().getLogger().log(Level.WARNING, "Could not send JSON-Message to Player", e);
}
@ -695,11 +696,19 @@ public class Utils {
return "";
}
public static Class<?> getMCServerClassByName(String className) {
public static Class<?> getMCServerClassByName(String className, String... alternativePrefix) {
try {
if (className.equals("ChatSerializer") && !CustomHeads.version.equals("v1_8_R1"))
className = "IChatBaseComponent$ChatSerializer";
return Class.forName("net.minecraft.server." + CustomHeads.version + "." + className);
if(NBTTagUtils.MC_VERSION >= 17) {
String altPrefix = "";
if(alternativePrefix != null && alternativePrefix.length > 0) {
altPrefix = alternativePrefix[0] + ".";
}
return Class.forName("net.minecraft." + altPrefix + className);
} else {
return Class.forName("net.minecraft.server." + CustomHeads.version + "." + className);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

View File

@ -9,38 +9,22 @@ package de.likewhat.customheads.utils.reflection;
import de.likewhat.customheads.CustomHeads;
import de.likewhat.customheads.utils.Utils;
import org.bukkit.Bukkit;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.logging.Level;
public class NBTTagUtils {
public static final int MC_VERSION;
public static final String[] ALLOWED_CLASSES = new String[] {"NBTBase", "NBTTagEnd", "NBTTagByte", "NBTTagShort", "NBTTagInt", "NBTTagLong", "NBTTagFloat", "NBTTagDouble", "NBTTagByteArray", "NBTTagString", "NBTTagList", "NBTTagCompound", "NBTTagIntArray"};
static {
MC_VERSION = Integer.parseInt(CustomHeads.version.split("_")[1]);
}
public static Object createNBTTagString(String string) {
try {
switch (MC_VERSION) {
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
return Utils.getMCServerClassByName("NBTTagString").getConstructor(String.class).newInstance(string);
case 15:
case 16:
return Utils.getMCServerClassByName("NBTTagString").getMethod("a", String.class).invoke(null, string);
default:
throw new UnsupportedOperationException("Unsupported MC_VERSION: " + MC_VERSION + " Please report this to me on my Discord (Link's on the Spigot Page)");
}
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
public static void addObjectToNBTList(Object list, Object objectToAdd) {
try {
switch (MC_VERSION) {
@ -50,19 +34,93 @@ public class NBTTagUtils {
case 11:
case 12:
case 13:
list.getClass().getMethod("add", Utils.getMCServerClassByName("NBTBase")).invoke(list, objectToAdd);
list.getClass().getMethod("add", getNBTClass("NBTBase")).invoke(list, objectToAdd);
break;
default:
Bukkit.getLogger().log(Level.WARNING, "Falling back to newest Method since the current Version isn't tested yet... (This may not work so here goes)");
case 14:
case 15:
case 16:
list.getClass().getMethod("add", int.class, Utils.getMCServerClassByName("NBTBase")).invoke(list, list.getClass().getMethod("size").invoke(list), objectToAdd);
case 17:
list.getClass().getMethod("add", int.class, getNBTClass("NBTBase")).invoke(list, list.getClass().getMethod("size").invoke(list), objectToAdd);
break;
default:
throw new UnsupportedOperationException("Unsupported MC_VERSION: " + MC_VERSION + " Please report this to me on my Discord (Link's on the Spigot Page)");
}
} catch(Exception e) {
} catch(NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
public static Class<?> getNBTClass(String className) {
try {
if(!Arrays.asList(ALLOWED_CLASSES).contains(className)) {
throw new IllegalArgumentException("Class " + className + " is not allowed!");
}
Class<?> clazz;
switch (MC_VERSION) {
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
clazz = Utils.getMCServerClassByName(className);
break;
default:
Bukkit.getLogger().log(Level.WARNING, "Falling back to newest Method since the current Version isn't tested yet... (This may not work so here goes)");
case 17:
clazz = Utils.getClassByName("net.minecraft.nbt." + className);
break;
}
return clazz;
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
public static Object createInstance(String className) {
try {
Class<?> clazz = getNBTClass(className);
if(clazz == null) {
return null;
}
return clazz.newInstance();
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
public static <T> Object createInstance(String className, T newInstanceObject) {
try {
Class<?> clazz = getNBTClass(className);
if(clazz == null) {
return null;
}
Object instance = null;
// Just return an new empty Instance if the Object is null
if(newInstanceObject == null) {
return clazz.newInstance();
}
try {
Constructor<?> constructor = clazz.getConstructor(newInstanceObject.getClass());
instance = constructor.newInstance(newInstanceObject);
} catch(NoSuchMethodException e) {
try {
// Newer Versions use the a Method to initialize an Instance
instance = clazz.getMethod("a", newInstanceObject.getClass()).invoke(null, newInstanceObject);
} catch(NoSuchMethodException e2) {
Bukkit.getLogger().log(Level.WARNING, "Failed to initialize Instance of " + className);
}
}
return instance;
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -4,6 +4,7 @@ import de.likewhat.customheads.CustomHeads;
import de.likewhat.customheads.utils.Utils;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -26,15 +27,15 @@ public class TagEditor {
public static ItemStack clearTags(ItemStack itemStack) {
try {
Object copy = getAsMNSCopy(itemStack);
Object itemTagCompound = hasNBTTag(itemStack) ? copy.getClass().getMethod("getTag").invoke(copy) : Utils.getMCServerClassByName("NBTTagCompound").newInstance();
Object nbtTagCompound = Utils.getMCServerClassByName("NBTTagCompound").newInstance();
itemTagCompound.getClass().getMethod("set", String.class, Utils.getMCServerClassByName("NBTBase")).invoke(itemTagCompound, "tagEditor", nbtTagCompound);
copy.getClass().getMethod("setTag", Utils.getMCServerClassByName("NBTTagCompound")).invoke(copy, itemTagCompound);
return (ItemStack) Utils.getCBClass("inventory.CraftItemStack").getMethod("asBukkitCopy", Utils.getMCServerClassByName("ItemStack")).invoke(Utils.getCBClass("inventory.CraftItemStack"), copy);
Object itemTagCompound = hasNBTTag(itemStack) ? copy.getClass().getMethod("getTag").invoke(copy) : NBTTagUtils.createInstance("NBTTagCompound");
Object nbtTagCompound = NBTTagUtils.createInstance("NBTTagCompound");
itemTagCompound.getClass().getMethod("set", String.class, NBTTagUtils.getNBTClass("NBTBase")).invoke(itemTagCompound, "tagEditor", nbtTagCompound);
copy.getClass().getMethod("setTag", NBTTagUtils.getNBTClass("NBTTagCompound")).invoke(copy, itemTagCompound);
return asBukkitCopy(copy);
} catch (Exception e) {
CustomHeads.getInstance().getLogger().log(Level.WARNING, "Failed to reset Tags from Item", e);
return null;
}
return itemStack;
}
public static Object getAsMNSCopy(ItemStack item) {
@ -59,20 +60,20 @@ public class TagEditor {
public ItemStack setTags(ItemStack itemStack, List<String> tags) {
try {
Object copy = getAsMNSCopy(itemStack);
Object itemTagCompound = hasNBTTag(itemStack) ? copy.getClass().getMethod("getTag").invoke(copy) : Utils.getMCServerClassByName("NBTTagCompound").newInstance();
Object nbtTagCompound = ((boolean) itemTagCompound.getClass().getMethod("hasKey", String.class).invoke(itemTagCompound, "tagEditor")) ? itemTagCompound.getClass().getMethod("get", String.class).invoke(itemTagCompound, "tagEditor") : Utils.getMCServerClassByName("NBTTagCompound").newInstance();
Object nbtTagList = Utils.getMCServerClassByName("NBTTagList").newInstance();
Object itemTagCompound = hasNBTTag(itemStack) ? copy.getClass().getMethod("getTag").invoke(copy) : NBTTagUtils.createInstance("NBTTagCompound");
Object nbtTagCompound = ((boolean) itemTagCompound.getClass().getMethod("hasKey", String.class).invoke(itemTagCompound, "tagEditor")) ? itemTagCompound.getClass().getMethod("get", String.class).invoke(itemTagCompound, "tagEditor") : NBTTagUtils.createInstance("NBTTagCompound");
Object nbtTagList = NBTTagUtils.createInstance("NBTTagList");
for (String tag : tags) {
NBTTagUtils.addObjectToNBTList(nbtTagList, NBTTagUtils.createNBTTagString(tag));
NBTTagUtils.addObjectToNBTList(nbtTagList, NBTTagUtils.createInstance("NBTTagString", tag));
}
nbtTagCompound.getClass().getMethod("set", String.class, Utils.getMCServerClassByName("NBTBase")).invoke(nbtTagCompound, tagname, nbtTagList);
itemTagCompound.getClass().getMethod("set", String.class, Utils.getMCServerClassByName("NBTBase")).invoke(itemTagCompound, "tagEditor", nbtTagCompound);
copy.getClass().getMethod("setTag", Utils.getMCServerClassByName("NBTTagCompound")).invoke(copy, itemTagCompound);
return (ItemStack) Utils.getCBClass("inventory.CraftItemStack").getMethod("asBukkitCopy", Utils.getMCServerClassByName("ItemStack")).invoke(Utils.getCBClass("inventory.CraftItemStack"), copy);
nbtTagCompound.getClass().getMethod("set", String.class, NBTTagUtils.getNBTClass("NBTBase")).invoke(nbtTagCompound, tagname, nbtTagList);
itemTagCompound.getClass().getMethod("set", String.class, NBTTagUtils.getNBTClass("NBTBase")).invoke(itemTagCompound, "tagEditor", nbtTagCompound);
copy.getClass().getMethod("setTag", NBTTagUtils.getNBTClass("NBTTagCompound")).invoke(copy, itemTagCompound);
return asBukkitCopy(copy);
} catch (Exception e) {
CustomHeads.getInstance().getLogger().log(Level.WARNING, "Failed to save Tags to Item", e);
return null;
}
return itemStack;
}
public ItemStack setTags(ItemStack itemStack, String... tags) {
@ -144,4 +145,13 @@ public class TagEditor {
}
}
private static ItemStack asBukkitCopy(Object object) {
try {
return (ItemStack) Utils.getCBClass("inventory.CraftItemStack").getMethod("asBukkitCopy", Utils.getMCServerClassByName("ItemStack", "world.item")).invoke(Utils.getCBClass("inventory.CraftItemStack"), object);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -80,6 +80,7 @@ public class GitHubDownloader {
getRateLimit(new FetchResult<JsonObject>() {
public void success(JsonObject rateLimit) {
if(rateLimit.get("remaining").getAsInt() == 0) {
Bukkit.getLogger().info(Utils.GSON_PRETTY.toJson(rateLimit));
fetchResult.error(new RateLimitExceededException(rateLimit.get("reset").getAsLong()));
return;
}

View File

@ -1,7 +1,7 @@
main: ${project.groupId}.${project.artifactId}
name: ${project.artifactId}
version: ${project.version}
author: ${user.name}
author: LikeWhat
softdepend: [Vault]
commands: