com.jroossien.boxx.util.Utils.java Source code

Java tutorial

Introduction

Here is the source code for com.jroossien.boxx.util.Utils.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Rojoss <http://jroossien.com>
 * Copyright (c) 2016 contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.jroossien.boxx.util;

import com.jroossien.boxx.messages.Msg;
import com.jroossien.boxx.messages.Param;
import com.jroossien.boxx.nms.item.ItemUtils;
import org.apache.commons.codec.binary.Base64;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.inventory.meta.SkullMeta;

import java.io.File;
import java.io.FilenameFilter;
import java.util.*;

public class Utils {

    public static final int MSEC_IN_DAY = 86400000;
    public static final int MSEC_IN_HOUR = 3600000;
    public static final int MSEC_IN_MIN = 60000;
    public static final int MSEC_IN_SEC = 1000;
    public static final Set<Material> TRANSPARENT_MATERIALS = new HashSet<Material>();

    static {
        for (Material material : Material.values()) {
            if (material.isTransparent()) {
                TRANSPARENT_MATERIALS.add(material);
            }
        }
    }

    public static <T> T convertInstance(Object o, Class<T> clazz) {
        try {
            return clazz.cast(o);
        } catch (ClassCastException e) {
            return null;
        }
    }

    public static Map<String, File> getFiles(File dir, final String extension) {
        Map<String, File> names = new HashMap<String, File>();
        if (dir == null || !dir.exists() || !dir.isDirectory()) {
            return names;
        }

        File[] files = dir.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.toLowerCase().endsWith("." + extension);
            }
        });

        for (File file : files) {
            names.put(file.getName().substring(0, file.getName().length() - extension.length() - 1), file);
        }

        return names;
    }

    /**
     * Split a camel cased string and put something else in between each word.
     * For example a space and then a string like 'GameSession' would change to 'Game Session'
     * Some other examples: 'SimpleXMLParser' -> 'Simple XML Parser', 'May12' -> 'May 12'
     * http://stackoverflow.com/a/2560017
     *
     * @param string The string to split and replace.
     * @param splitReplace The string to put between each split.
     * @return The formatted string.
     */
    public static String splitCamelCase(String string, String splitReplace) {
        return string.replaceAll(String.format("%s|%s|%s", "(?<=[A-Z])(?=[A-Z][a-z])", "(?<=[^A-Z])(?=[A-Z])",
                "(?<=[A-Za-z])(?=[^A-Za-z])"), splitReplace);
    }

    /**
     * Fixes the specified list of command arguments.
     * It will combine arguments that are quoted with spaces.
     * For example the following string: 'Hello there "you''re awesome"!'
     * Would result in 0:Hello 1:there 2:You''re awesome 3:!
     *
     * @param args The list of arguments to fix.
     * @return The modified array with arguments.
     */
    public static String[] fixCommandArgs(String[] args) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < args.length; i++) {
            builder.append(args[i]);
            if (i + 1 < args.length) {
                builder.append(" ");
            }
        }

        List<String> newArgList = Str.splitQuotes(builder.toString());
        return newArgList.toArray(new String[newArgList.size()]);
    }

    /**
     * Get the highest block at the given x and z coordinate.
     * It will work properly for the nether and such.
     * Basically instead of starting from the top it will first scan down for the first empty block.
     * From there on it will scan down for air and then return the first non air block.
     *
     * @param world The world to look in.
     * @param x The x coordinate.
     * @param z The z coordinate.
     * @return The highest non air block respecting the nether ceiling.
     */
    public static Block getHighestBlockAt(World world, int x, int z) {
        Block block = world.getBlockAt(x, world.getEnvironment() == World.Environment.NETHER ? 127 : 255, z);
        while (block.getType() != Material.AIR && block.getY() > 0) {
            block = block.getRelative(BlockFace.DOWN);
        }
        while (block.getType() == Material.AIR && block.getY() > 0) {
            block = block.getRelative(BlockFace.DOWN);
        }
        return block;
    }

    /**
     * Format a timestamp to a string with days/hours/mins/secs/ms.
     * For example: '%Dd %H:%M:%S' will be replaced with something like '1d 23:12:52'
     * The possible options in the syntax are:
     * %D = Days
     * %H = Hours
     * %M = Minutes
     * %S = Seconds
     * %MS = MilliSeconds
     * %% Remainder percentage of seconds with 1 decimal like '%S.%%s' could be '34.1s'
     * %%% Remainder percentage of seconds with 2 decimals like '%S.%%%s' could be '34.13s'
     *
     * @param time The time to convert to min:sec
     * @param syntax The string with the above options which will be replaced with the time.
     * @return Formatted time string.
     */
    public static String formatTime(long time, String syntax, boolean extraZeros) {
        //time = time / 1000;

        int days = (int) time / MSEC_IN_DAY;
        time = time - days * MSEC_IN_DAY;

        int hours = (int) time / MSEC_IN_HOUR;
        time = time - hours * MSEC_IN_HOUR;

        int mins = (int) time / MSEC_IN_MIN;
        time = time - mins * MSEC_IN_MIN;

        int secs = (int) time / MSEC_IN_SEC;
        time = time - secs * MSEC_IN_SEC;

        int ms = (int) time;
        int ds = (int) time / 100;
        int fs = (int) time / 10;

        syntax = syntax.replace("%D", "" + days);
        syntax = syntax.replace("%H", "" + (hours < 10 && extraZeros ? "0" + hours : hours));
        syntax = syntax.replace("%M", "" + (mins < 10 && extraZeros ? "0" + mins : mins));
        syntax = syntax.replace("%S", "" + (secs < 10 && extraZeros ? "0" + secs : secs));
        syntax = syntax.replace("%MS", "" + ms);
        syntax = syntax.replace("%%%", "" + fs);
        syntax = syntax.replace("%%", "" + ds);
        return syntax;
    }

    public static String getAliasesString(String key, Map<String, List<String>> values) {
        Msg format = Msg.get(key);
        if (format.isUndefined()) {
            format = new Msg("[[<aliases>||<name>]]");
        }
        List<String> formats = new ArrayList<>();
        for (Map.Entry<String, List<String>> entry : values.entrySet()) {
            String name = entry.getKey();
            String aliases = Str.wrapString("&7" + Str.implode(entry.getValue(), "&8, &7"), 50);

            formats.add(format.clone()
                    .params(Param.P("name", name), Param.P("key", name), Param.P("display", name),
                            Param.P("value", name), Param.P("aliases", aliases), Param.P("alias", aliases),
                            Param.P("values", aliases))
                    .getRaw());
        }
        return Str.implode(formats, "&8, &r");
    }

    public static Location getLocation(CommandSender sender) {
        if (sender instanceof Entity) {
            return ((Entity) sender).getLocation();
        } else if (sender instanceof BlockCommandSender) {
            return ((BlockCommandSender) sender).getBlock().getLocation().add(0.5f, 0.5f, 0.5f);
        }
        return null;
    }

    /**
     * Get a Byte[] array with the texture skull url
     * The input string can be a textures.minecraft.net link, the code from the link only or a Base64 encoded string.
     * http://heads.freshcoal.com/maincollection.php
     * </p>
     * Used by {@link ItemUtils#setSkullTexture(SkullMeta, String)}
     */
    public static byte[] getSkullTexture(String input) {
        if (input.endsWith("=")) {
            //Encoded texture.
            //eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTU1ZDYxMWE4NzhlODIxMjMxNzQ5YjI5NjU3MDhjYWQ5NDI2NTA2NzJkYjA5ZTI2ODQ3YTg4ZTJmYWMyOTQ2In19fQ==
            return input.getBytes();
        } else {
            if (input.contains("/")) {
                //Whole texture url from textures.minecraft.net
                //http://textures.minecraft.net/texture/955d611a878e821231749b2965708cad942650672db09e26847a88e2fac2946
                String[] split = input.split("/");
                input = split[split.length - 1];
            }
            //Texture code split from the url.
            //955d611a878e821231749b2965708cad942650672db09e26847a88e2fac2946
            input = "http://textures.minecraft.net/texture/" + input;
            return Base64
                    .encodeBase64(String.format("{\"textures\":{\"SKIN\":{\"url\":\"%s\"}}}", input).getBytes());
        }
    }

}