package de.fanta.challenges.gravestones;
import de.fanta.challenges.Challenges;
import de.fanta.challenges.utils.ChatUtil;
import de.fanta.challenges.utils.ItemStackUtil;
import de.iani.cubesideutils.bukkit.items.ItemGroups;
import net.kyori.adventure.text.Component;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.Slab;
import org.bukkit.block.data.type.Snow;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.logging.Level;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
public class GravestoneUtils {
private static final NamespacedKey UUIDKey = new NamespacedKey(Challenges.getPlugin(), "uuid_gravestone");
private static final NamespacedKey inventoryKey = new NamespacedKey(Challenges.getPlugin(), "inventory_gravestone");
private static final NamespacedKey inventoryBase64Key = new NamespacedKey(Challenges.getPlugin(), "inventory_base64_gravestone");
public static byte[] compressString(String s) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
OutputStreamWriter osw = new OutputStreamWriter(new DeflaterOutputStream(baos, new Deflater(Deflater.BEST_COMPRESSION)), StandardCharsets.UTF_8);
osw.write(s);
osw.flush();
osw.close();
} catch (IOException e) {
throw new RuntimeException("Could not compress data", e);
}
return baos.toByteArray();
}
public static String decompressString(byte[] data) {
try {
InputStreamReader reader = new InputStreamReader(new InflaterInputStream(new ByteArrayInputStream(data)), StandardCharsets.UTF_8);
StringBuilder sb = new StringBuilder();
char[] temp = new char[1024];
while (true) {
int readBytes;
readBytes = reader.read(temp);
if (readBytes < 0) {
break;
}
sb.append(temp, 0, readBytes);
}
return sb.toString();
} catch (IOException e) {
throw new RuntimeException("Error while decompressing inventory string", e);
}
}
public static String createInventoryString(ItemStack[] inventory) {
YamlConfiguration conf = new YamlConfiguration();
String[] base64Items = new String[inventory.length];
for (int i = 0; i < inventory.length; i++) {
ItemStack stack = inventory[i];
if (stack != null && stack.getItemMeta() != null) {
if (stack.getItemMeta().hasEnchant(Enchantment.VANISHING_CURSE)) {
base64Items[i] = null;
} else {
base64Items[i] = ItemStackUtil.getBase64StringFromItemStack(stack);
}
}
}
conf.set("inv", base64Items);
return conf.saveToString();
}
public static ItemStack[] createItemArrayFromString(String yamlstring) {
ItemStack[] inventory = new ItemStack[0];
try {
YamlConfiguration conf = new YamlConfiguration();
conf.loadFromString(yamlstring);
List<?> stacks = conf.getList("inv");
if (stacks == null) {
return inventory;
}
inventory = new ItemStack[stacks.size()];
for (int i = 0; i < stacks.size(); i++) {
String base64Item = (String) stacks.get(i);
if (base64Item != null) {
inventory[i] = ItemStackUtil.getItemStackFromBase64(base64Item);
} else {
inventory[i] = null;
}
}
} catch (InvalidConfigurationException ex) {
Challenges.getPlugin().getLogger().log(Level.SEVERE, "Error while loading yaml Config", ex);
}
return inventory;
}
public static void spawnAtBlock(Block block, Player player, byte[] inventoryBytes) {
World world = block.getWorld();
double y = block.getY();
Material type = block.getType();
String typeName = type.name();
double placeableY;
if (typeName.endsWith("_SLAB")) {
Slab slab = (Slab) block.getBlockData();
placeableY = y - 0.44;
if (slab.getType() == Slab.Type.BOTTOM) {
placeableY -= 0.5;
}
} else if (typeName.endsWith("_STAIRS") || type.isOccluding() || type == Material.GLASS || ItemGroups.isStainedGlass(type) || type == Material.ICE || type == Material.PACKED_ICE || type == Material.BLUE_ICE || ItemGroups.isLeaves(type)) {
placeableY = y - 0.44;
} else if (ItemGroups.isCarpet(type)) {
placeableY = y - 1.44 + (1 / 16.0);
} else if (type == Material.SNOW) {
Snow snow = (Snow) block.getBlockData();
int layers = snow.getLayers();
placeableY = y - 1.44 + (layers / 8.0);
} else {
placeableY = y - 0.44;
}
if (!Double.isNaN(placeableY)) {
world.spawn(new Location(world, block.getX() + 0.5, placeableY, block.getZ() + 0.5, player.getLocation().getYaw(), 0), ArmorStand.class, t -> {
t.setVisible(false);
t.setGravity(false);
t.customName(Component.text("R.I.P. ", ChatUtil.RED).append(player.name().color(ChatUtil.BLUE)));
t.setCustomNameVisible(true);
ItemStack itemStack = new ItemStack(Material.PLAYER_HEAD, 1);
SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
meta.setPlayerProfile(player.getPlayerProfile());
itemStack.setItemMeta(meta);
t.getEquipment().setHelmet(itemStack);
PersistentDataContainer container = t.getPersistentDataContainer();
container.set(UUIDKey, PersistentDataType.STRING, player.getUniqueId().toString());
container.set(inventoryBase64Key, PersistentDataType.BYTE_ARRAY, inventoryBytes);
});
ChatUtil.sendMessage(player, Component.text("Dein Grabschstein steht bei:", ChatUtil.GREEN).append(Component.text(" (" + player.getLocation().getBlockX() + "/" + player.getLocation().getBlockY() + "/" + player.getLocation().getBlockZ() + ")", ChatUtil.ORANGE)));
}
}
public static NamespacedKey getUUIDKey() {
return UUIDKey;
}
public static NamespacedKey getInventoryKey() {
return inventoryKey;
}
public static NamespacedKey getInventoryBase64Key() {
return inventoryBase64Key;
}
}