/**
* ****************************************************************************************************************
* Authors: SanAndreasP
* Copyright: SanAndreasP
* License: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
* http://creativecommons.org/licenses/by-nc-sa/4.0/
* *****************************************************************************************************************
*/
package de.sanandrew.core.manpack.util.helpers;
import com.mojang.authlib.GameProfile;
import cpw.mods.fml.common.eventhandler.EventBus;
import cpw.mods.fml.common.registry.GameRegistry;
import de.sanandrew.core.manpack.util.ReflectionNames;
import de.sanandrew.core.manpack.util.SAPReflectionHelper;
import de.sanandrew.core.manpack.util.javatuples.Quartet;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemTool;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.StatCollector;
import net.minecraftforge.oredict.RecipeSorter;
import net.minecraftforge.oredict.RecipeSorter.Category;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
/**
* A helper class for common used stuff, which is not found somewhere else and
* not as easy and short to write. It's goal is to shorten and cleanse the
* sourcecode with unnecessary stuff.
*/
public final class SAPUtils
{
/**
* My personal RNG Deity, to be used whenever a global RNG is needed
*/
public static final Random RNG = new Random();
/**
* The EventBus for this coremod. It prevents cluttering the Forge event bus with the SAPMP events!
*/
public static final EventBus EVENT_BUS = new EventBus();
/**
* The pattern of a Version-4-UUID
*/
private static final Pattern UUID_PTRN = Pattern.compile("[a-f0-9]{8}\\-[a-f0-9]{4}\\-4[a-f0-9]{3}\\-[89ab][a-f0-9]{3}\\-[a-f0-9]{12}", Pattern.CASE_INSENSITIVE);
/**
* Gets a value in the middle of 2 values, for example val1 is 1 and val2 is 5, the value returned would be 3.
* Note: val1 doesn't have to be smaller than val2
*
* @param val1 the first value
* @param val2 the second value
* @return the value in between val1 and val2 (the average)
*/
public static int getAverage(int val1, int val2) {
return Math.round((val1 + val2) / 2.0F);
}
/**
* Gets the effective blocks array from the ItemTool.
*
* @param tool The ItemTool instance whose array should be grabbed
* @return the effective blocks array
*/
public static Block[] getToolBlocks(ItemTool tool) {
Set set = SAPReflectionHelper.getCachedFieldValue(ItemTool.class, tool, ReflectionNames.FIELD_150914_C.mcpName, ReflectionNames.FIELD_150914_C.srgName);
Set<Block> blockSet = SAPUtils.getCasted(set);
return blockSet.toArray(new Block[blockSet.size()]);
}
/**
* Gets the n-th parameter of a parameterized type (for example ArrayList<String> or HashMap<UUID, String>)
*
* @param obj An object instance of that type
* @param pos the index of the desired parameter (an 1 on a HashMap<UUID, String> instance would return Class<String>
* @param <T> The returned parameter type
* @return A class representing the parameter
*/
public static <T> Class<T> getGenericType(Object obj, int pos) {
Type genSuperCls = obj.getClass().getGenericSuperclass();
if( genSuperCls instanceof ParameterizedType ) {
Type[] paramTypes = ((ParameterizedType) genSuperCls).getActualTypeArguments();
if( paramTypes.length > 0 ) {
return SAPUtils.getCasted(paramTypes[0]);
}
}
return null;
}
/**
* Registers all blocks with their unlocalized name to the GameRegistry.
*
* @param blocks The blocks to be registered
* @see GameRegistry#registerBlock(Block, String)
*/
public static void registerBlocks(Block... blocks) {
for( Block block : blocks ) {
String blockName = block.getUnlocalizedName();
blockName = blockName.substring(blockName.lastIndexOf(':') + 1);
GameRegistry.registerBlock(block, blockName.toLowerCase());
}
}
/**
* Registers a block with their unlocalized name to the GameRegistry. It binds the supplied itemClass as its ItemBlock to this block.
*
* @param block The block to be registered
* @param itemClass the ItemBlock class to be bound to the block
* @see GameRegistry#registerBlock(Block, Class, String)
*/
public static void registerBlockWithItem(Block block, Class<? extends ItemBlock> itemClass) {
String blockName = block.getUnlocalizedName();
blockName = blockName.substring(blockName.lastIndexOf(':') + 1);
GameRegistry.registerBlock(block, itemClass, blockName.toLowerCase());
}
/**
* Registers all items with their unlocalized name to the GameRegistry.
*
* @param items The blocks to be registered
* @see GameRegistry#registerItem(Item, String)
*/
public static void registerItems(Item... items) {
for( Item item : items ) {
String itemName = item.getUnlocalizedName();
itemName = itemName.substring(itemName.lastIndexOf(':') + 1);
GameRegistry.registerItem(item, itemName.toLowerCase());
}
}
/**
* Gets an {@link de.sanandrew.core.manpack.util.helpers.SAPUtils.RGBAValues} instance from a color integer (0xAARRGGBB).
*
* @param rgba The RGBA value as int
* @return an RGBAValues instance
*/
public static RGBAValues getRgbaFromColorInt(int rgba) {
return new RGBAValues(((rgba) >> 16) & 255, ((rgba) >> 8) & 255, rgba & 255, ((rgba) >> 24) & 255);
}
public static void restartApp() {
AppHelper.restartApp();
}
public static void shutdownApp() {
AppHelper.shutdownApp();
}
/**
* Checks if the index is within the range of the array.
*
* @param array The array to check against
* @param index The index to be checked
* @return true, if the index is within range, false otherwise
*/
public static boolean isIndexInRange(Object[] array, int index) {
return index >= 0 && index < array.length;
}
/**
* Registers a new IRecipe instance into the RecipeSorter and the CraftingManager
*
* @param recipe The recipe to be registered
* @param name the recipe name
* @param category the recipe category it will be sorted in
* @param dependencies a string representing the dependencies for this recipe
*/
@SuppressWarnings( "unchecked" )
public static void registerSortedRecipe(IRecipe recipe, String name, Category category, String dependencies) {
RecipeSorter.register(name, recipe.getClass(), category, dependencies);
CraftingManager.getInstance().getRecipeList().add(recipe);
}
/**
* translates a key via {@link StatCollector#translateToLocal(String)}
*
* @param key The key to be translated
* @return The translated key
*/
public static String translate(String key) {
return StatCollector.translateToLocal(key);
}
@SuppressWarnings( "unchecked" )
public static <T> T getCasted(Object obj) {
return (T) obj;
}
/**
* translates a key and then formats the translated string with the data afterwards.
*
* @param key The key to be translated
* @param data The data to be injected into the translated string
* @return The translated string
*/
public static String translatePostFormat(String key, Object... data) {
return String.format(translate(key), data);
}
/**
* formats a key with the data and translates the formated string afterwards.
*
* @param key The key to be translated
* @param data The data to be injected into the key
* @return The translated string
*/
public static String translatePreFormat(String key, Object... data) {
return translate(String.format(key, data));
}
public static boolean isStringUuid(String uuid) {
return UUID_PTRN.matcher(uuid).matches();
}
public static boolean isPlayerNameOrUuidEqual(EntityPlayer e, String... namesUuids) {
for( String val : namesUuids ) {
GameProfile profile = e.getGameProfile();
if( (isStringUuid(val) && profile.getId().equals(UUID.fromString(val))) || profile.getName().equals(val) ) {
return true;
}
}
return false;
}
public static class RGBAValues
{
private final Quartet<Integer, Integer, Integer, Integer> value;
public RGBAValues(int r, int g, int b, int a) {
this.value = Quartet.with(r, g, b, a);
}
public RGBAValues(int color) {
this((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, (color >> 24) & 0xFF);
}
public int getRed() {
return this.value.getValue0();
}
public int getGreen() {
return this.value.getValue1();
}
public int getBlue() {
return this.value.getValue2();
}
public int getAlpha() {
return this.value.getValue3();
}
public float[] getColorFloatArray() {
return new float[] { this.getRed() / 255.0F, this.getGreen() / 255.0F, this.getBlue() / 255.0F, this.getAlpha() / 255.0F };
}
public int getColorInt() {
return ((this.value.getValue3() & 0xFF) << 24) | ((this.value.getValue0() & 0xFF) << 16) | ((this.value.getValue1() & 0xFF) << 8) | (this.value.getValue2() & 0xFF);
}
}
}