From 6d1b2216464d4dad449ac6fcfec476832224a55e Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Fri, 24 May 2024 19:50:35 +0100 Subject: Merge addon sources --- .../gtPlusPlus/core/util/MovingAverageLong.java | 59 ++ src/main/java/gtPlusPlus/core/util/Utils.java | 436 +++++++++ src/main/java/gtPlusPlus/core/util/data/AES.java | 135 +++ .../java/gtPlusPlus/core/util/data/ArrayUtils.java | 44 + .../java/gtPlusPlus/core/util/data/FileUtils.java | 112 +++ .../gtPlusPlus/core/util/data/LocaleUtils.java | 86 ++ .../gtPlusPlus/core/util/data/StringUtils.java | 177 ++++ .../java/gtPlusPlus/core/util/math/MathUtils.java | 528 ++++++++++ .../core/util/minecraft/EntityUtils.java | 146 +++ .../gtPlusPlus/core/util/minecraft/FluidUtils.java | 667 +++++++++++++ .../core/util/minecraft/InventoryUtils.java | 68 ++ .../gtPlusPlus/core/util/minecraft/ItemUtils.java | 1012 ++++++++++++++++++++ .../gtPlusPlus/core/util/minecraft/LangUtils.java | 41 + .../core/util/minecraft/MaterialUtils.java | 372 +++++++ .../core/util/minecraft/MiningUtils.java | 133 +++ .../gtPlusPlus/core/util/minecraft/NBTUtils.java | 164 ++++ .../core/util/minecraft/OreDictUtils.java | 20 + .../core/util/minecraft/PlayerUtils.java | 206 ++++ .../core/util/minecraft/RecipeUtils.java | 465 +++++++++ .../util/minecraft/gregtech/PollutionUtils.java | 147 +++ .../core/util/recipe/GT_RecipeUtils.java | 95 ++ .../core/util/recipe/RecipeHashStrat.java | 116 +++ .../core/util/reflect/AddGregtechRecipe.java | 77 ++ .../core/util/reflect/ReflectionUtils.java | 727 ++++++++++++++ .../gtPlusPlus/core/util/sys/KeyboardUtils.java | 37 + 25 files changed, 6070 insertions(+) create mode 100644 src/main/java/gtPlusPlus/core/util/MovingAverageLong.java create mode 100644 src/main/java/gtPlusPlus/core/util/Utils.java create mode 100644 src/main/java/gtPlusPlus/core/util/data/AES.java create mode 100644 src/main/java/gtPlusPlus/core/util/data/ArrayUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/data/FileUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/data/LocaleUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/data/StringUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/math/MathUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/EntityUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/FluidUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/InventoryUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/ItemUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/LangUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/MaterialUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/MiningUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/NBTUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/OreDictUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/PlayerUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/RecipeUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/minecraft/gregtech/PollutionUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/recipe/GT_RecipeUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/recipe/RecipeHashStrat.java create mode 100644 src/main/java/gtPlusPlus/core/util/reflect/AddGregtechRecipe.java create mode 100644 src/main/java/gtPlusPlus/core/util/reflect/ReflectionUtils.java create mode 100644 src/main/java/gtPlusPlus/core/util/sys/KeyboardUtils.java (limited to 'src/main/java/gtPlusPlus/core/util') diff --git a/src/main/java/gtPlusPlus/core/util/MovingAverageLong.java b/src/main/java/gtPlusPlus/core/util/MovingAverageLong.java new file mode 100644 index 0000000000..7111fbd5e1 --- /dev/null +++ b/src/main/java/gtPlusPlus/core/util/MovingAverageLong.java @@ -0,0 +1,59 @@ +package gtPlusPlus.core.util; + +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; + +import net.minecraft.nbt.NBTTagCompound; + +public class MovingAverageLong { + + private final long[] storage; + private int ptr; + + public MovingAverageLong(int sampleSize) { + storage = new long[sampleSize]; + } + + public void set(long average) { + Arrays.fill(storage, average); + } + + public void sample(long data) { + storage[ptr] = data; + ptr = (ptr + 1) % storage.length; + } + + public long get() { + BigInteger result = BigInteger.ZERO; + for (long l : storage) { + result = result.add(BigInteger.valueOf(l)); + } + return result.divide(BigInteger.valueOf(storage.length)) + .longValue(); + } + + public void write(NBTTagCompound tagCompound, String key) { + ByteBuffer buf = ByteBuffer.allocate(storage.length * Long.BYTES) + .order(ByteOrder.nativeOrder()); + buf.asLongBuffer() + .put(storage); + tagCompound.setByteArray(key, buf.array()); + } + + /** + * if read failed, the internal states would not be changed. + * + * @return true if successful, false otherwise. + */ + public boolean read(NBTTagCompound tagCompound, String key) { + ByteBuffer buf = ByteBuffer.wrap(tagCompound.getByteArray(key)); + if (buf.remaining() != storage.length * Long.BYTES) + // not very good... + return false; + buf.asLongBuffer() + .get(storage); + return true; + } +} diff --git a/src/main/java/gtPlusPlus/core/util/Utils.java b/src/main/java/gtPlusPlus/core/util/Utils.java new file mode 100644 index 0000000000..610cc4f8fa --- /dev/null +++ b/src/main/java/gtPlusPlus/core/util/Utils.java @@ -0,0 +1,436 @@ +package gtPlusPlus.core.util; + +import java.awt.Color; +import java.io.File; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.util.EnumHelper; +import net.minecraftforge.fluids.FluidContainerRegistry; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; + +import org.apache.commons.lang3.EnumUtils; + +import cpw.mods.fml.common.FMLCommonHandler; +import gregtech.api.GregTech_API; +import gregtech.api.enums.TC_Aspects; +import gregtech.api.enums.TC_Aspects.TC_AspectStack; +import gregtech.api.util.GT_LanguageManager; +import gregtech.api.util.GT_Log; +import gregtech.api.util.GT_Utility; +import gtPlusPlus.api.objects.Logger; +import gtPlusPlus.core.item.ModItems; +import gtPlusPlus.core.lib.CORE; +import gtPlusPlus.core.util.minecraft.FluidUtils; +import gtPlusPlus.core.util.minecraft.ItemUtils; +import gtPlusPlus.core.util.minecraft.NBTUtils; +import ic2.core.Ic2Items; +import ic2.core.init.InternalName; +import ic2.core.item.resources.ItemCell; + +public class Utils { + + public static boolean isServer() { + return FMLCommonHandler.instance() + .getEffectiveSide() + .isServer(); + } + + public static boolean isClient() { + return FMLCommonHandler.instance() + .getEffectiveSide() + .isClient(); + } + + public static TC_AspectStack getTcAspectStack(final TC_Aspects aspect, final long size) { + return getTcAspectStack(aspect.name(), (int) size); + } + + public static TC_AspectStack getTcAspectStack(final String aspect, final long size) { + return getTcAspectStack(aspect, (int) size); + } + + public static TC_AspectStack getTcAspectStack(final TC_Aspects aspect, final int size) { + return getTcAspectStack(aspect.name(), size); + } + + public static TC_AspectStack getTcAspectStack(final String aspect, final int size) { + + TC_AspectStack returnValue = null; + + if (aspect.equalsIgnoreCase("COGNITIO")) { + // Adds in Compat for older GT Versions which Misspell aspects. + try { + if (EnumUtils.isValidEnum(TC_Aspects.class, "COGNITIO")) { + Logger.WARNING("TC Aspect found - " + aspect); + returnValue = new TC_AspectStack(TC_Aspects.valueOf("COGNITIO"), size); + } else { + Logger.INFO( + "Fallback TC Aspect found - " + aspect + + " - PLEASE UPDATE GREGTECH TO A NEWER VERSION TO REMOVE THIS MESSAGE - THIS IS NOT AN ERROR"); + returnValue = new TC_AspectStack(TC_Aspects.valueOf("COGNITO"), size); + } + } catch (final NoSuchFieldError r) { + Logger.INFO("Invalid Thaumcraft Aspects - Report this issue to Alkalus"); + } + } else if (aspect.equalsIgnoreCase("EXANIMUS")) { + // Adds in Compat for older GT Versions which Misspell aspects. + try { + if (EnumUtils.isValidEnum(TC_Aspects.class, "EXANIMUS")) { + Logger.WARNING("TC Aspect found - " + aspect); + returnValue = new TC_AspectStack(TC_Aspects.valueOf("EXANIMUS"), size); + } else { + Logger.INFO( + "Fallback TC Aspect found - " + aspect + + " - PLEASE UPDATE GREGTECH TO A NEWER VERSION TO REMOVE THIS MESSAGE - THIS IS NOT AN ERROR"); + returnValue = new TC_AspectStack(TC_Aspects.valueOf("EXAMINIS"), size); + } + } catch (final NoSuchFieldError r) { + Logger.INFO("Invalid Thaumcraft Aspects - Report this issue to Alkalus"); + } + + } else if (aspect.equalsIgnoreCase("PRAECANTATIO")) { + // Adds in Compat for older GT Versions which Misspell aspects. + try { + if (EnumUtils.isValidEnum(TC_Aspects.class, "PRAECANTATIO")) { + Logger.WARNING("TC Aspect found - " + aspect); + returnValue = new TC_AspectStack(TC_Aspects.valueOf("PRAECANTATIO"), size); + } else { + Logger.INFO( + "Fallback TC Aspect found - " + aspect + + " - PLEASE UPDATE GREGTECH TO A NEWER VERSION TO REMOVE THIS MESSAGE - THIS IS NOT AN ERROR"); + returnValue = new TC_AspectStack(TC_Aspects.valueOf("PRAECANTIO"), size); + } + } catch (final NoSuchFieldError r) { + Logger.INFO("Invalid Thaumcraft Aspects - Report this issue to Alkalus"); + } + } else { + Logger.WARNING("TC Aspect found - " + aspect); + returnValue = new TC_AspectStack(TC_Aspects.valueOf(aspect), size); + } + + return returnValue; + } + + // Register an event to both busses. + public static void registerEvent(Object o) { + MinecraftForge.EVENT_BUS.register(o); + FMLCommonHandler.instance() + .bus() + .register(o); + } + + // Send a message to all players on the server + public static void sendServerMessage(final String translationKey) { + sendServerMessage(new ChatComponentText(translationKey)); + } + + // Send a message to all players on the server + public static void sendServerMessage(final IChatComponent chatComponent) { + MinecraftServer.getServer() + .getConfigurationManager() + .sendChatMsg(chatComponent); + } + + /** + * Returns if that Liquid is IC2Steam. + */ + public static boolean isIC2Steam(final FluidStack aFluid) { + if (aFluid == null) { + return false; + } + return aFluid.isFluidEqual(getIC2Steam(1)); + } + + /** + * Returns a Liquid Stack with given amount of IC2Steam. + */ + public static FluidStack getIC2Steam(final long aAmount) { + return FluidRegistry.getFluidStack("ic2steam", (int) aAmount); + } + + public static int rgbtoHexValue(final int r, final int g, final int b) { + if ((r > 255) || (g > 255) || (b > 255) || (r < 0) || (g < 0) || (b < 0)) { + return 0; + } + final Color c = new Color(r, g, b); + String temp = Integer.toHexString(c.getRGB() & 0xFFFFFF) + .toUpperCase(); + temp = Utils.appenedHexNotationToString(temp); + return Integer.decode(temp); + } + + /* + * http://javadevnotes.com/java-left-pad-string-with-zeros-examples + */ + public static String padWithZerosLefts(final String originalString, final int length) { + final StringBuilder sb = new StringBuilder(); + while ((sb.length() + originalString.length()) < length) { + sb.append('0'); + } + sb.append(originalString); + return sb.toString(); + } + + /* + * Original Code by Chandana Napagoda - https://cnapagoda.blogspot.com.au/2011/03/java-hex-color-code-generator. + * html + */ + public static Map hexColourGeneratorRandom(final int colorCount) { + final HashMap hexColorMap = new HashMap<>(); + for (int a = 0; a < colorCount; a++) { + String code = "" + (int) (Math.random() * 256); + code = code + code + code; + final int i = Integer.parseInt(code); + hexColorMap.put( + a, + Integer.toHexString(0x1000000 | i) + .substring(1) + .toUpperCase()); + Logger.WARNING( + "" + Integer.toHexString(0x1000000 | i) + .substring(1) + .toUpperCase()); + } + return hexColorMap; + } + + public static String appenedHexNotationToString(final Object hexAsStringOrInt) { + final String hexChar = "0x"; + String result; + if (hexAsStringOrInt.getClass() == String.class) { + + if (((String) hexAsStringOrInt).length() != 6) { + final String temp = padWithZerosLefts((String) hexAsStringOrInt, 6); + } + result = hexChar + hexAsStringOrInt; + return result; + } else if (hexAsStringOrInt.getClass() == Integer.class) { + String aa = String.valueOf(hexAsStringOrInt); + if (aa.length() != 6) { + result = padWithZerosLefts(aa, 6); + } else { + result = hexChar + hexAsStringOrInt; + } + return result; + } else { + return null; + } + } + + public static File getMcDir() { + if (Utils.isClient()) { + if (Minecraft.getMinecraft() != null) { + return Minecraft.getMinecraft().mcDataDir; + } + } + return new File("."); + } + + private static short cellID = 15; + + public static ItemStack createInternalNameAndFluidCell(final String s) { + Logger.WARNING("1"); + final InternalName yourName = EnumHelper.addEnum(InternalName.class, s, new Class[0], new Object[0]); + Logger.WARNING("2 " + yourName.name()); + final ItemCell item = (ItemCell) Ic2Items.cell.getItem(); + Logger.WARNING("3 " + item.getUnlocalizedName()); + try { + Logger.WARNING("4"); + final Class clz = item.getClass(); + Logger.WARNING("5 " + clz.getSimpleName()); + final Method methode = clz.getDeclaredMethod("addCell", int.class, InternalName.class, Block[].class); + Logger.WARNING("6 " + methode.getName()); + methode.setAccessible(true); + Logger.WARNING("7 " + methode.isAccessible()); + final ItemStack temp = (ItemStack) methode.invoke(item, cellID++, yourName, new Block[0]); + Logger.WARNING("Successfully created " + temp.getDisplayName() + "s."); + FluidContainerRegistry.registerFluidContainer( + FluidUtils.getFluidStack(s.toLowerCase(), 1000), + temp.copy(), + Ic2Items.cell.copy()); + ItemUtils.addItemToOreDictionary(temp.copy(), "cell" + s); + return temp; + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } + + public static String sanitizeString(final String input, final char[] dontRemove) { + + // List of characters to remove + final HashSet toRemoveSet = new HashSet<>(); + Collections.addAll( + toRemoveSet, + ' ', + '-', + '_', + '~', + '?', + '!', + '@', + '#', + '$', + '%', + '^', + '&', + '*', + '(', + ')', + '{', + '}', + '[', + ']'); + + // Remove characters from the toRemoveSet if they are in dontRemove + for (char e : dontRemove) { + toRemoveSet.remove(e); + } + + // Construct a sanitized string + StringBuilder sanitized = new StringBuilder(); + for (char c : input.toCharArray()) { + if (!toRemoveSet.contains(c)) { + sanitized.append(c); + } + } + + return sanitized.toString(); + } + + public static String sanitizeString(final String input) { + String temp; + String output; + + temp = input.replace(" ", ""); + temp = temp.replace("-", ""); + temp = temp.replace("_", ""); + temp = temp.replace("?", ""); + temp = temp.replace("!", ""); + temp = temp.replace("@", ""); + temp = temp.replace("#", ""); + temp = temp.replace("(", ""); + temp = temp.replace(")", ""); + temp = temp.replace("{", ""); + temp = temp.replace("}", ""); + temp = temp.replace("[", ""); + temp = temp.replace("]", ""); + temp = temp.replace(" ", ""); + output = temp; + return output; + } + + public static String sanitizeStringKeepBrackets(final String input) { + String temp; + String output; + + temp = input.replace(" ", ""); + temp = temp.replace("-", ""); + temp = temp.replace("_", ""); + temp = temp.replace("?", ""); + temp = temp.replace("!", ""); + temp = temp.replace("@", ""); + temp = temp.replace("#", ""); + temp = temp.replace(" ", ""); + output = temp; + return output; + } + + public static String addBookTitleLocalization(final String aTitle) { + return GT_LanguageManager + .addStringLocalization("Book." + aTitle + ".Name", aTitle, !GregTech_API.sPostloadFinished); + } + + public static String[] addBookPagesLocalization(final String aTitle, final String[] aPages) { + String[] aLocalizationPages = new String[aPages.length]; + for (byte i = 0; i < aPages.length; i = (byte) (i + 1)) { + aLocalizationPages[i] = GT_LanguageManager.addStringLocalization( + "Book." + aTitle + ".Page" + ((i < 10) ? "0" + i : Byte.valueOf(i)), + aPages[i], + !GregTech_API.sPostloadFinished); + } + return aLocalizationPages; + } + + public static ItemStack getWrittenBook(ItemStack book, int ID, String mapping, String title, String author, + String[] pages) { + + if (GT_Utility.isStringInvalid(mapping)) { + return null; + } + + ItemStack stack = CORE.sBookList.get(mapping); + if (stack != null) { + return GT_Utility.copyAmount(1L, stack); + } + + if (GT_Utility.isStringInvalid(title) || GT_Utility.isStringInvalid(author) || pages.length <= 0) { + return null; + } + + stack = (book == null) ? new ItemStack(ModItems.itemCustomBook, 1, ID) : book; + + NBTTagCompound NBT = new NBTTagCompound(); + String localizationTitle = addBookTitleLocalization(title); + NBT.setString("title", localizationTitle); + NBT.setString("author", author); + + NBTTagList NBTList = new NBTTagList(); + String[] localizationPages = addBookPagesLocalization(title, pages); + + for (byte i = 0; i < pages.length; i++) { + pages[i] = localizationPages[i].replaceAll("
", "\n"); + if (i < 48) { + if (pages[i].length() < 256) { + NBTList.appendTag(new NBTTagString(pages[i])); + } else { + Logger.INFO("WARNING: String for written Book too long! -> " + pages[i]); + GT_Log.err.println("WARNING: String for written Book too long! -> " + pages[i]); + } + } else { + Logger.INFO("WARNING: Too much Pages for written Book! -> " + title); + GT_Log.err.println("WARNING: Too much Pages for written Book! -> " + title); + break; + } + } + + String credits = String.format( + "Credits to %s for writing this Book. This was Book Nr. %d at its creation. Gotta get 'em all!", + author, + ID); + NBTList.appendTag(new NBTTagString(credits)); + NBT.setTag("pages", NBTList); + + stack.setTagCompound(NBT); + + String logMessage = String.format( + "GT++_Mod: Added Book to Book++ List - Mapping: '%s' - Name: '%s' - Author: '%s'", + mapping, + title, + author); + GT_Log.out.println(logMessage); + + NBTUtils.createIntegerTagCompound(stack, "stats", "mMeta", ID); + CORE.sBookList.put(mapping, stack); + + Logger.INFO(String.format("Creating book: %s by %s. Using Meta %d.", title, author, ID)); + + return GT_Utility.copy(stack); + } + +} diff --git a/src/main/java/gtPlusPlus/core/util/data/AES.java b/src/main/java/gtPlusPlus/core/util/data/AES.java new file mode 100644 index 0000000000..85f20a3367 --- /dev/null +++ b/src/main/java/gtPlusPlus/core/util/data/AES.java @@ -0,0 +1,135 @@ +package gtPlusPlus.core.util.data; + +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Base64; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; + +public class AES { + + private final String secret; + + private final SecretKeySpec secretKey; + + private final byte[] key; + + public AES() { + + this("Darkness In Their Hearts"); + } + + public AES(String aSecret) { + + secret = aSecret; + + key = getBytes(getHashedString(secret)); + + secretKey = generateKey(key); + } + + private static String getHashedString(String aString) { + + return toHexString(getSHA(aString)); + } + + private static byte[] getSHA(String input) { + + MessageDigest md; + + try { + + md = MessageDigest.getInstance("SHA-256"); + + return md.digest(input.getBytes(StandardCharsets.UTF_8)); + + } catch (NoSuchAlgorithmException e) { + + e.printStackTrace(); + } + + return new byte[] {}; + } + + private static String toHexString(byte[] hash) { + + BigInteger number = new BigInteger(1, hash); + + StringBuilder hexString = new StringBuilder(number.toString(16)); + + while (hexString.length() < 32) { + + hexString.insert(0, '0'); + } + + return hexString.toString(); + } + + private byte[] getBytes(String aKey) { + + byte[] aKeyData; + + MessageDigest sha; + + try { + + sha = MessageDigest.getInstance("SHA-256"); + + return sha.digest(aKey.getBytes(StandardCharsets.UTF_8)); + + } catch (NoSuchAlgorithmException e1) { + + e1.printStackTrace(); + + try { + + aKeyData = aKey.getBytes("UTF-8"); + + sha = MessageDigest.getInstance("SHA-1"); + + aKeyData = sha.digest(key); + + aKeyData = Arrays.copyOf(key, 16); + + return aKeyData; + + } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { + + e.printStackTrace(); + + } + } + + return new byte[] {}; + } + + private SecretKeySpec generateKey(byte[] aKey) { + + return new SecretKeySpec(aKey, "AES"); + } + + public String decode(String strToDecrypt) { + + try { + + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); + + cipher.init(Cipher.DECRYPT_MODE, secretKey); + + return new String( + cipher.doFinal( + Base64.getDecoder() + .decode(strToDecrypt))); + + } catch (Exception ignored) { + + } + + return null; + } +} diff --git a/src/main/java/gtPlusPlus/core/util/data/ArrayUtils.java b/src/main/java/gtPlusPlus/core/util/data/ArrayUtils.java new file mode 100644 index 0000000000..d5ab990917 --- /dev/null +++ b/src/main/java/gtPlusPlus/core/util/data/ArrayUtils.java @@ -0,0 +1,44 @@ +package gtPlusPlus.core.util.data; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import net.minecraft.item.ItemStack; + +public class ArrayUtils { + + public static V[] insertElementAtIndex(V[] aArray, int aIndex, V aObjectToInsert) { + V[] newArray = Arrays.copyOf(aArray, aArray.length + 1); + for (int i = 0; i < aIndex; i++) { + newArray[i] = aArray[i]; + } + newArray[aIndex] = aObjectToInsert; + for (int i = (aIndex + 1); i < newArray.length; i++) { + newArray[i] = aArray[i - 1]; + } + return newArray; + } + + public static Object[] removeNulls(final Object[] v) { + List list = new ArrayList<>(Arrays.asList(v)); + list.removeAll(Collections.singleton((Object) null)); + return list.toArray(new Object[list.size()]); + } + + public static ItemStack[] removeNulls(final ItemStack[] v) { + List list = new ArrayList<>(Arrays.asList(v)); + list.removeAll(Collections.singleton((ItemStack) null)); + return list.toArray(new ItemStack[list.size()]); + } + + public static String toString(Object[] aArray, String string) { + return org.apache.commons.lang3.ArrayUtils.toString(aArray, string); + } + + public static String toString(Object[] aArray) { + return org.apache.commons.lang3.ArrayUtils.toString(aArray); + } + +} diff --git a/src/main/java/gtPlusPlus/core/util/data/FileUtils.java b/src/main/java/gtPlusPlus/core/util/data/FileUtils.java new file mode 100644 index 0000000000..b2e5d04375 --- /dev/null +++ b/src/main/java/gtPlusPlus/core/util/data/FileUtils.java @@ -0,0 +1,112 @@ +package gtPlusPlus.core.util.data; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.List; + +import gtPlusPlus.api.objects.Logger; +import gtPlusPlus.core.util.Utils; + +public class FileUtils { + + private static final Charset utf8 = StandardCharsets.UTF_8; + + public static boolean doesFileExist(File f) { + if (f != null && f.exists() && !f.isDirectory()) { + return true; + } + return false; + } + + public static File createFile(String path, String filename, String extension) { + File file = new File(Utils.getMcDir(), path + filename + extension); + return createFile(file); + } + + public static File createFile(File aFile) { + boolean blnCreated = false; + Logger.INFO("Trying to use path " + aFile.getPath()); + try { + Logger.INFO("Trying to use path " + aFile.getCanonicalPath()); + Logger.INFO("Trying to use absolute path " + aFile.getAbsolutePath()); + blnCreated = aFile.createNewFile(); + } catch (IOException ioe) { + Logger.INFO("Error while creating a new empty file :" + ioe); + return null; + } + return blnCreated ? aFile : null; + } + + public static File getFile(String filename, String extension) { + return getFile("", filename, extension); + } + + public static File getFile(String path, String filename, String extension) { + if (path == null || path.length() <= 0) { + path = ""; + } else { + path = path + "/"; + } + if (filename == null || filename.length() <= 0) { + return null; + } + if (extension == null || extension.length() <= 0) { + extension = ".txt"; + } else { + extension = "." + extension; + } + File file = new File(Utils.getMcDir(), path + filename + extension); + boolean doesExist = doesFileExist(file); + + if (doesExist) { + Logger.INFO("Found File: " + file.getAbsolutePath()); + return file; + } else { + Logger.INFO("Creating file, as it was not found."); + return createFile(path, filename, extension); + } + } + + public static void appendListToFile(File file, List content) { + try { + long oldSize; + long newSize; + if (doesFileExist(file)) { + Path p = Paths.get(file.getPath()); + if (p != null && Files.isWritable(p)) { + oldSize = Files.size(p); + try { + Files.write(p, content, utf8, StandardOpenOption.APPEND); + } catch (IOException e) { + e.printStackTrace(); + } + newSize = Files.size(p); + } + } + } catch (IOException ignored) {} + } + + /** + * Reads the contents of a file line by line to a List of Strings using the default encoding for the VM. The file is + * always closed. + * + * @param file the file to read, must not be {@code null} + * @return the list of Strings representing each line in the file, never {@code null} + * @throws IOException in case of an I/O error + * @since 1.3 + */ + public static List readLines(File file) { + try { + return org.apache.commons.io.FileUtils.readLines(file, utf8); + } catch (IOException e) { + return new ArrayList<>(); + } + } +} diff --git a/src/main/java/gtPlusPlus/core/util/data/LocaleUtils.java b/src/main/java/gtPlusPlus/core/util/data/LocaleUtils.java new file mode 100644 index 0000000000..f72e5c6a51 --- /dev/null +++ b/src/main/java/gtPlusPlus/core/util/data/LocaleUtils.java @@ -0,0 +1,86 @@ +package gtPlusPlus.core.util.data; + +import static gregtech.api.enums.Mods.GTPlusPlus; +import static gregtech.api.enums.Mods.GTPlusPlusEverglades; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.common.registry.GameData; +import gtPlusPlus.core.util.Utils; +import gtPlusPlus.core.util.minecraft.ItemUtils; + +public class LocaleUtils { + + public static void generateFakeLocaleFile() { + for (ModContainer modcontainer : Loader.instance() + .getModList()) { + if (modcontainer.getModId() + .toLowerCase() + .equals(GTPlusPlus.ID)) { + String S = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; + writeToFile(S); + dumpItemsAndBlocksForModContainer(modcontainer); + } + } + } + + public static void dumpItemsAndBlocksForModContainer(ModContainer mod) { + writeToFile("Dumping Items from " + mod.getModId() + "."); + for (Object C : GameData.getItemRegistry()) { + + try { + + if (C != null) { + if (C instanceof Item R) { + ItemStack IS = ItemUtils.getSimpleStack(R); + String modid = ItemUtils.getModId(IS); + if (modid.equals(GTPlusPlus.ID) || modid.equals(GTPlusPlusEverglades.ID)) { + String S = "[" + modid + "] " + IS.getUnlocalizedName() + ".name="; + writeToFile(S); + } + } + } + + } catch (Throwable ignored) {} + } + writeToFile("Dumping Blocks from " + mod.getModId() + "."); + for (Object B : GameData.getBlockRegistry()) { + + try { + + if (B != null) { + if (B instanceof Block R) { + ItemStack IS = ItemUtils.getSimpleStack(R); + String modid = ItemUtils.getModId(IS); + if (modid.equals(GTPlusPlus.ID) || modid.equals(GTPlusPlusEverglades.ID)) { + String S = "[" + modid + "] " + IS.getUnlocalizedName() + ".name="; + writeToFile(S); + } + } + } + + } catch (Throwable ignored) {} + } + + } + + public static void writeToFile(String S) { + try { + File F = new File(Utils.getMcDir(), "config/GTplusplus/en_US.lang"); + BufferedWriter writer; + writer = new BufferedWriter(new FileWriter(F, true)); + writer.write(S); + writer.newLine(); + writer.close(); + } catch (IOException ignored) {} + } +} diff --git a/src/main/java/gtPlusPlus/core/util/data/StringUtils.java b/src/main/java/gtPlusPlus/core/util/data/StringUtils.java new file mode 100644 index 0000000000..77efadbc9a --- /dev/null +++ b/src/main/java/gtPlusPlus/core/util/data/StringUtils.java @@ -0,0 +1,177 @@ +package gtPlusPlus.core.util.data; + +import gtPlusPlus.api.objects.Logger; +import gtPlusPlus.api.objects.data.AutoMap; +import gtPlusPlus.core.util.Utils; + +public class StringUtils { + + public static String superscript(String str) { + str = str.replaceAll("0", "\u2070"); + str = str.replaceAll("1", "\u00B9"); + str = str.replaceAll("2", "\u00B2"); + str = str.replaceAll("3", "\u00B3"); + str = str.replaceAll("4", "\u2074"); + str = str.replaceAll("5", "\u2075"); + str = str.replaceAll("6", "\u2076"); + str = str.replaceAll("7", "\u2077"); + str = str.replaceAll("8", "\u2078"); + str = str.replaceAll("9", "\u2079"); + return str; + } + + public static String subscript(String str) { + str = str.replaceAll("0", "\u2080"); + str = str.replaceAll("1", "\u2081"); + str = str.replaceAll("2", "\u2082"); + str = str.replaceAll("3", "\u2083"); + str = str.replaceAll("4", "\u2084"); + str = str.replaceAll("5", "\u2085"); + str = str.replaceAll("6", "\u2086"); + str = str.replaceAll("7", "\u2087"); + str = str.replaceAll("8", "\u2088"); + str = str.replaceAll("9", "\u2089"); + return str; + } + + public static boolean containsSuperOrSubScript(final String s) { + if (s.contains(StringUtils.superscript("0"))) { + return true; + } else if (s.contains(StringUtils.superscript("1"))) { + return true; + } else if (s.contains(StringUtils.superscript("2"))) { + return true; + } else if (s.contains(StringUtils.superscript("3"))) { + return true; + } else if (s.contains(StringUtils.superscript("4"))) { + return true; + } else if (s.contains(StringUtils.superscript("5"))) { + return true; + } else if (s.contains(StringUtils.superscript("6"))) { + return true; + } else if (s.contains(StringUtils.superscript("7"))) { + return true; + } else if (s.contains(StringUtils.superscript("8"))) { + return true; + } else if (s.contains(StringUtils.superscript("9"))) { + return true; + } + if (s.contains(StringUtils.subscript("0"))) { + return true; + } else if (s.contains(StringUtils.subscript("1"))) { + return true; + } else if (s.contains(StringUtils.subscript("2"))) { + return true; + } else if (s.contains(StringUtils.subscript("3"))) { + return true; + } else if (s.contains(StringUtils.subscript("4"))) { + return true; + } else if (s.contains(StringUtils.subscript("5"))) { + return true; + } else if (s.contains(StringUtils.subscript("6"))) { + return true; + } else if (s.contains(StringUtils.subscript("7"))) { + return true; + } else if (s.contains(StringUtils.subscript("8"))) { + return true; + } else if (s.contains(StringUtils.subscript("9"))) { + return true; + } + return false; + } + + public static String firstLetterCaps(String data) { + String firstLetter = data.substring(0, 1) + .toUpperCase(); + String restLetters = data.substring(1) + .toLowerCase(); + return firstLetter + restLetters; + } + + public static String getDataStringFromArray(V[] parameterTypes) { + if (parameterTypes == null || parameterTypes.length == 0) { + return "empty/null"; + } else { + StringBuilder aData = new StringBuilder(); + for (V y : parameterTypes) { + if (y != null) { + aData.append(", ") + .append(y); + } + } + return aData.toString(); + } + } + + /** + * Is this a special regex character for delimination? (.$|()[]{}^?*+\\) + * + * @param aChar - The char to test + * @return - Is this a special character? + */ + public static boolean isSpecialCharacter(char aChar) { + return aChar == '"' || aChar == '.' + || aChar == '$' + || aChar == '|' + || aChar == '(' + || aChar == ')' + || aChar == '[' + || aChar == ']' + || aChar == '{' + || aChar == '}' + || aChar == '^' + || aChar == '?' + || aChar == '*' + || aChar == '+' + || aChar == '\\'; + } + + public static boolean isEscaped(String aString) { + return aString.charAt(0) == '\\'; + } + + public static String splitAndUppercase(String aInput, String aDelim) { + + if (!isEscaped(aDelim)) { + boolean isSpecial = false; + for (int o = 0; o < aInput.length(); o++) { + if (isSpecialCharacter(aInput.charAt(o))) { + isSpecial = true; + } + } + if (isSpecial) { + aDelim = "\\" + aDelim; + } + } + + Logger.INFO("Splitting " + aInput); + String[] aSplit = aInput.split(aDelim); + Logger.INFO("Split into " + aSplit == null ? "" + 0 : aSplit.length + " parts."); + if (aSplit == null || aSplit.length == 0) { + return aInput; + } else { + AutoMap aTemp = new AutoMap<>(); + for (String s : aSplit) { + Logger.INFO("Found: " + s); + s = s.replace(".", ""); + s = Utils.sanitizeString(s); + s = firstLetterCaps(s); + Logger.INFO("Formatted & Captilized: " + s); + aTemp.put(s); + } + Logger.INFO("Rebuilding"); + StringBuilder aReturn = new StringBuilder(); + for (String s : aTemp) { + aReturn.append(s); + Logger.INFO("Step: " + aReturn); + } + return aReturn.toString(); + } + } + + public static long uppercaseCount(String aString) { + return aString.chars() + .filter(Character::isUpperCase) + .count(); + } +} diff --git a/src/main/java/gtPlusPlus/core/util/math/MathUtils.java b/src/main/java/gtPlusPlus/core/util/math/MathUtils.java new file mode 100644 index 0000000000..ac3ef2e947 --- /dev/null +++ b/src/main/java/gtPlusPlus/core/util/math/MathUtils.java @@ -0,0 +1,528 @@ +package gtPlusPlus.core.util.math; + +import java.text.NumberFormat; +import java.util.Map; +import java.util.Random; + +import gregtech.api.enums.GT_Values; +import gtPlusPlus.api.objects.Logger; +import gtPlusPlus.api.objects.data.AutoMap; +import gtPlusPlus.core.lib.CORE; +import gtPlusPlus.core.util.Utils; + +public class MathUtils { + + static final Random rand = CORE.RANDOM; + + /** Formats a number with group separator and at most 2 fraction digits. */ + private static final NumberFormat sNumberFormat = NumberFormat.getInstance(); + + static { + sNumberFormat.setMaximumFractionDigits(2); + } + + /** + * Returns a psuedo-random number between min and max, inclusive. The difference between min and max can be at most + * Integer.MAX_VALUE - 1. + * + * @param min Minimim value + * @param max Maximim value. Must be greater than min. + * @return Integer between min and max, inclusive. + * @see java.util.Random#nextInt(int) + */ + public static int randInt(final int min, final int max) { + // nextInt is normally exclusive of the top value, + // so add 1 to make it inclusive + return rand.nextInt((max - min) + 1) + min; + } + + /** + * Returns a psuedo-random number between min and max, inclusive. The difference between min and max can be at most + * Long.MAX_VALUE - 1. + * + * @param min Minimim value + * @param max Maximim value. Must be greater than min. + * @return Long between min and max, inclusive. + * @see java.util.Random#nextLong(long) + */ + public static long randLong(final long min, final long max) { + // nextInt is normally exclusive of the top value, + // so add 1 to make it inclusive + return MathUtils.nextLong(rand, (max - min) + 1) + min; + } + + private static long nextLong(final Random rng, final long n) { + // error checking and 2^x checking removed for simplicity. + long bits, val; + do { + bits = (rng.nextLong() << 1) >>> 1; + val = bits % n; + } while (((bits - val) + (n - 1)) < 0L); + return val; + } + + /** + * Returns a psuedo-random number between min and max, inclusive. The difference between min and max can be at most + * Double.MAX_VALUE - 1. + * + * @param min Minimim value + * @param max Maximim value. Must be greater than min. + * @return Double between min and max, inclusive. + * @see java.util.Random#nextDouble(double) + */ + public static double randDouble(final double min, final double max) { + // nextInt is normally exclusive of the top value, + // so add 1 to make it inclusive + return MathUtils.nextDouble(rand, (max - min) + 1) + min; + } + + private static double nextDouble(final Random rng, final double n) { + // error checking and 2^x checking removed for simplicity. + double bits, val; + do { + bits = (rng.nextLong() << 1) >>> 1; + val = bits % n; + } while (((bits - val) + (n - 1)) < 0L); + return val; + } + + /** + * Returns a psuedo-random number between min and max, inclusive. The difference between min and max can be at most + * Float.MAX_VALUE - 1. + * + * @param min Minimim value + * @param max Maximim value. Must be greater than min. + * @return Float between min and max, inclusive. + * @see java.util.Random#nextFloat(float) + */ + public static float randFloat(final float min, final float max) { + // nextInt is normally exclusive of the top value, + // so add 1 to make it inclusive + return MathUtils.nextFloat(rand, (max - min) + 1) + min; + } + + private static float nextFloat(final Random rng, final float n) { + // error checking and 2^x checking removed for simplicity. + float bits, val; + do { + bits = (rng.nextLong() << 1) >>> 1; + val = bits % n; + } while (((bits - val) + (n - 1)) < 0L); + return val; + } + + /** + * Returns a percentage. The returned number is the % of X in Y. Supports Doubles. + * + * @param current Current value. + * @param max Maximim value. Must be greater than min. + * @return double between min and max, inclusive. + */ + public static double findPercentage(final double current, final double max) { + return Math.round(((current / max) * 100) * 100.00) / 100.00; + } + + /** + * Returns a percentage. The returned number is the % of X in Y. Supports Floats. + * + * @param current Current value. + * @param max Maximim value. Must be greater than min. + * @return double between min and max, inclusive. + */ + public static float findPercentage(final float current, final float max) { + return (float) (Math.round(((current / max) * 100) * 100.00) / 100.00); + } + + public static int findPercentageOfInt(long input, float percentage) { + return (int) (input * (percentage / 100.0f)); + } + + // Smooth Rounding Function + /** + * Returns a double. The returned number is d rounded to the nearest d.01. Supports Doubles. + * + * @return double Rounded value. + */ + public static double decimalRounding(final double d) { + return Math.round(d * 2) / 2.0; + } + + // Smooth Rounding Function (Nearest 5) + /** + * Returns a double. The returned number is d rounded to the nearest d.5. Supports Doubles. + * + * @return double Rounded value. + */ + public static double decimalRoundingToWholes(final double d) { + return 5 * (Math.round(d / 5)); + } + + // Smooth Rounding Function + /** + * Returns a integer. The returned number is d rounded to the nearest flat integer. Supports Doubles as input. + * + * @return integer Rounded value. + */ + public static int roundToClosestInt(final double d) { + return (int) (Math.round(d * 2) / 2.0); + } + + // Smooth Rounding Function + /** + * Returns a long. The returned number is d rounded to the nearest flat long. Supports Doubles as input. + * + * @return long Rounded value. + */ + public static long roundToClosestLong(final double d) { + return (long) (Math.round(d * 2) / 2.0); + } + + /** + * Returns a boolean. The returned boolean is based on the odd/eveness of the input. Supports ints. + * + * @param x Value A. + * @return boolean Whether or not it divides evenly. + */ + public static boolean isNumberEven(final long x) { + if ((x % 2) == 0) { + return true; + } + return false; + } + + /** + * Returns an int. The returned number is the value on i + 273.15F. Supports ints. + * + * @param i Temp in Celcius. + * @return int The celcius temp returned as Kelvin, rounded to the readest whole. + */ + public static float celsiusToKelvin(final int i) { + final double f = i + 273.15F; + return (int) decimalRoundingToWholes(f); + } + + /** + * Returns a random hex value. The returned value is between 000000-ffffff. + * + * @return hexInteger between min and max, inclusive. + */ + public static int generateSingularRandomHexValue() { + String temp; + final int randomInt = randInt(1, 5); + final Map colours = Utils.hexColourGeneratorRandom(5); + + if ((colours.get(randomInt) != null) && (colours.size() > 0)) { + temp = colours.get(randomInt); + } else { + temp = "0F0F0F"; + } + + Logger.WARNING("Operating with " + temp); + temp = Utils.appenedHexNotationToString(String.valueOf(temp)); + return Integer.decode(temp); + } + + public static long[] simplifyNumbersToSmallestForm(final long[] inputArray) { + final long GCD = gcd(inputArray); + final long[] outputArray = new long[inputArray.length]; + for (int i = 0; i < inputArray.length; i++) { + if (GCD != 0) { + outputArray[i] = (inputArray[i] / GCD); + } else { + outputArray[i] = inputArray[i]; + } + } + if (outputArray.length > 0) { + return outputArray; + } + return new long[] {}; + } + + private static long gcd(long a, long b) { + while (b > 0) { + final long temp = b; + b = a % b; // % is remainder + a = temp; + } + return a; + } + + private static long gcd(final long[] input) { + long result = input[0]; + for (int i = 1; i < input.length; i++) { + result = gcd(result, input[i]); + } + return result; + } + + public static int getRgbAsHex(final short[] RGBA) { + final int returnValue = Utils.rgbtoHexValue(RGBA[0], RGBA[1], RGBA[2]); + return (returnValue == 0) ? 0 : returnValue; + } + + public static byte safeByte(long number) { + return number > Byte.MAX_VALUE ? Byte.MAX_VALUE : (byte) number; + } + + public static short safeShort(long number) { + return number > Short.MAX_VALUE ? Short.MAX_VALUE : (short) number; + } + + public static int safeInt(long number, int margin) { + return number > Integer.MAX_VALUE - margin ? Integer.MAX_VALUE - margin : (int) number; + } + + public static int safeInt(long number) { + return number > GT_Values.V[GT_Values.V.length - 1] ? safeInt(GT_Values.V[GT_Values.V.length - 1], 1) + : number < Integer.MIN_VALUE ? Integer.MIN_VALUE : (int) number; + } + + public static int getRandomFromArray(int[] mValues) { + int[] mLargeChanceArray = new int[(mValues.length - 1) * 1000]; + int mValueSelection; + for (int g = 0; g < mLargeChanceArray.length; g++) { + mValueSelection = randInt(0, mValues.length - 1); + mLargeChanceArray[g] = mValues[mValueSelection]; + } + return mLargeChanceArray[randInt(0, mLargeChanceArray.length - 1)]; + } + + /* + * Averages + */ + + public static byte getByteAverage(AutoMap aDataSet) { + byte[] aNewSet = new byte[aDataSet.size()]; + for (int u = 0; u < aDataSet.size(); u++) { + byte b = getSafeByte(aDataSet.get(u)); + aNewSet[u] = b; + } + return getByteAverage(aNewSet); + } + + public static short getShortAverage(AutoMap aDataSet) { + short[] aNewSet = new short[aDataSet.size()]; + for (int u = 0; u < aDataSet.size(); u++) { + short b = getSafeShort(aDataSet.get(u)); + aNewSet[u] = b; + } + return getShortAverage(aNewSet); + } + + public static int getIntAverage(AutoMap aDataSet) { + int[] aNewSet = new int[aDataSet.size()]; + for (int u = 0; u < aDataSet.size(); u++) { + int b = getSafeInt(aDataSet.get(u)); + aNewSet[u] = b; + } + return getIntAverage(aNewSet); + } + + public static long getLongAverage(AutoMap aDataSet) { + long[] aNewSet = new long[aDataSet.size()]; + for (int u = 0; u < aDataSet.size(); u++) { + long b = getSafeLong(aDataSet.get(u)); + aNewSet[u] = b; + } + return getLongAverage(aNewSet); + } + + public static byte getByteAverage(byte[] aDataSet) { + if (aDataSet.length == 0) { + return 0; + } + int divisor = aDataSet.length; + byte total = 0; + for (byte i : aDataSet) { + total += i; + } + byte result = safeByte(total / divisor); + return result; + } + + public static short getShortAverage(short[] aDataSet) { + if (aDataSet.length == 0) { + return 0; + } + int divisor = aDataSet.length; + Logger.WARNING("Calculating Average Short. Divisor: " + divisor); + short total = 0; + for (short i : aDataSet) { + Logger.WARNING("Adding " + i); + total += i; + } + short result = safeShort((total / divisor)); + Logger.WARNING("Average: " + result); + return result; + } + + public static int getIntAverage(int[] aDataSet) { + if (aDataSet.length == 0) { + return 0; + } + int divisor = aDataSet.length; + int total = 0; + for (int i : aDataSet) { + total += i; + } + int result = safeInt(total / divisor); + return result; + } + + public static long getLongAverage(long[] aDataSet) { + if (aDataSet.length == 0) { + return 0; + } + int divisor = aDataSet.length; + long total = 0; + for (long i : aDataSet) { + total += i; + } + return (total / divisor); + } + + public static int howManyPlaces(int aValueForGen) { + if (aValueForGen < 0) { + aValueForGen = makeNegative(aValueForGen); + } + String a = String.valueOf(aValueForGen); + return a.length(); + } + + /** + * Inverts the value, making Positives into Negatives and vice versa. + * + * @param aPositive - An int value, either positive or negative. + * @return - Inverted int Value. + */ + public static int makeNegative(int aPositive) { + if (aPositive > 0) { + return -aPositive; + } else if (aPositive < 0) { + return +aPositive; + } else { + return 0; + } + } + + public static V safeCast(Object aNumberType) { + long a1; + double a2; + a1 = Long.parseLong(aNumberType.toString()); + a2 = Double.parseDouble(aNumberType.toString()); + + if ((aNumberType.getClass() == byte.class) || (aNumberType instanceof Byte)) { + if (a1 >= Byte.MIN_VALUE && a1 <= Byte.MAX_VALUE) { + String s = String.valueOf(a1); + Byte s1 = Byte.valueOf(s); + return (V) s1; + } + } else if ((aNumberType.getClass() == short.class) || (aNumberType instanceof Short)) { + if (a1 >= Short.MIN_VALUE && a1 <= Short.MAX_VALUE) { + String s = String.valueOf(a1); + Short s1 = Short.valueOf(s); + return (V) s1; + } + } else if ((aNumberType.getClass() == int.class) || (aNumberType instanceof Integer)) { + if (a1 >= Integer.MIN_VALUE && a1 <= Integer.MAX_VALUE) { + String s = String.valueOf(a1); + Integer s1 = Integer.valueOf(s); + return (V) s1; + } + } else if ((aNumberType.getClass() == long.class) || (aNumberType instanceof Long)) { + if (a1 >= Long.MIN_VALUE && a1 <= Long.MAX_VALUE) { + String s = String.valueOf(a1); + Long s1 = Long.valueOf(s); + return (V) s1; + } + } else if ((aNumberType.getClass() == float.class) || (aNumberType instanceof Float)) { + if (a2 >= Float.MIN_VALUE && a2 <= Float.MAX_VALUE) { + String s = String.valueOf(a1); + Float s1 = Float.valueOf(s); + return (V) s1; + } + } else if ((aNumberType.getClass() == double.class) || (aNumberType instanceof Double)) { + if (a2 >= Double.MIN_VALUE && a2 <= Double.MAX_VALUE) { + String s = String.valueOf(a1); + Double s1 = Double.valueOf(s); + return (V) s1; + } + } + + Integer o = 0; + return (V) o; + } + + public static byte getSafeByte(Byte b) { + Byte a = safeCast(b); + return a; + } + + public static short getSafeShort(Short b) { + Short a = safeCast(b); + return a; + } + + public static int getSafeInt(Integer b) { + Integer a = safeCast(b); + return a; + } + + public static long getSafeLong(Long b) { + Long a = safeCast(b); + return a; + } + + public static int safeCast_LongToInt(long o) { + if (o > Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } else { + int i = (int) o; + return i; + } + } + + /** + * Balances a number within a range. + * + * @param aInput - The number to balance + * @param aMin - The minimum bounds + * @param aMax - The maximum bounds + * @return - An Integer which will be between the bounds, or a boundary value. + */ + public static int balance(int aInput, int aMin, int aMax) { + return Math.max(Math.min(aInput, aMax), aMin); + } + + /** + * Returns the smaller of two {@code Number}s. That is, the result the argument closer to the value of + * {@link Long#MIN_VALUE}. If the arguments have the same value, the result is that same value. + * + * @param a an argument. + * @param b another argument. + * @return the smaller of {@code a} and {@code b}. + */ + public static Number min(Number a, Number b) { + return (a.longValue() <= b.longValue()) ? a : b; + } + + /** + * Returns the greater of two {@code Number}s. That is, the result is the argument closer to the value of + * {@link Long#MAX_VALUE}. If the arguments have the same value, the result is that same value. + * + * @param a an argument. + * @param b another argument. + * @return the larger of {@code a} and {@code b}. + */ + public static Number max(Number a, Number b) { + return (a.longValue() >= b.longValue()) ? a : b; + } + + public static String formatNumbers(long aNumber) { + return sNumberFormat.format(aNumber); + } + + public static String formatNumbers(double aNumber) { + return sNumberFormat.format(aNumber); + } +} diff --git a/src/main/java/gtPlusPlus/core/util/minecraft/EntityUtils.java b/src/main/java/gtPlusPlus/core/util/minecraft/EntityUtils.java new file mode 100644 index 0000000000..87bd0e60c6 --- /dev/null +++ b/src/main/java/gtPlusPlus/core/util/minecraft/EntityUtils.java @@ -0,0 +1,146 @@ +package gtPlusPlus.core.util.minecraft; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.EnumCreatureAttribute; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; + +import gregtech.api.util.GT_Utility; +import gtPlusPlus.api.objects.minecraft.BlockPos; +import gtPlusPlus.core.handler.events.EntityDeathHandler; +import ic2.core.IC2Potion; +import ic2.core.item.armor.ItemArmorHazmat; + +public class EntityUtils { + + public static void setEntityOnFire(final Entity aEntity, final int length) { + if (!isEntityImmuneToFire(aEntity)) { + aEntity.setFire(length); + } + } + + public static boolean isEntityImmuneToFire(Entity aEntity) { + return aEntity.isImmuneToFire(); + } + + public static BlockPos findBlockPosUnderEntity(final Entity parEntity) { + final int blockX = MathHelper.floor_double(parEntity.posX); + final int blockY = MathHelper.floor_double(parEntity.boundingBox.minY) - 1; + final int blockZ = MathHelper.floor_double(parEntity.posZ); + return new BlockPos(blockX, blockY, blockZ, parEntity.worldObj); + } + + public static BlockPos findBlockPosOfEntity(final Entity parEntity) { + final int blockX = MathHelper.floor_double(parEntity.posX); + final int blockY = MathHelper.floor_double(parEntity.boundingBox.minY); + final int blockZ = MathHelper.floor_double(parEntity.posZ); + return new BlockPos(blockX, blockY, blockZ, parEntity.worldObj); + } + + public static void applyRadiationDamageToEntity(final int stackSize, final int radiationLevel, final World world, + final Entity entityHolding) { + if (!world.isRemote) { + if ((radiationLevel > 0) && (entityHolding instanceof final EntityLivingBase entityLiving)) { + if (!((EntityPlayer) entityHolding).capabilities.isCreativeMode) { + if (!ItemArmorHazmat.hasCompleteHazmat(entityLiving) + && !GT_Utility.isWearingFullRadioHazmat(entityLiving)) { + if (entityLiving.getActivePotionEffect(IC2Potion.radiation) != null) { + entityLiving.getActivePotionEffect(IC2Potion.radiation); + } + applyRadioactivity(entityLiving, radiationLevel, stackSize); + } + } + } + } + } + + public static void applyRadioactivity(EntityLivingBase aEntity, int aLevel, int aAmountOfItems) { + if (aLevel > 0 && aEntity != null + && aEntity.getCreatureAttribute() != EnumCreatureAttribute.UNDEAD + && aEntity.getCreatureAttribute() != EnumCreatureAttribute.ARTHROPOD + && !ItemArmorHazmat.hasCompleteHazmat(aEntity)) { + PotionEffect tEffect; + aEntity.addPotionEffect( + new PotionEffect( + Potion.moveSlowdown.id, + aLevel * 140 * aAmountOfItems + Math.max( + 0, + ((tEffect = aEntity.getActivePotionEffect(Potion.moveSlowdown)) == null ? 0 + : tEffect.getDuration())), + Math.max(0, (5 * aLevel) / 7))); + aEntity.addPotionEffect( + new PotionEffect( + Potion.digSlowdown.id, + aLevel * 150 * aAmountOfItems + Math.max( + 0, + ((tEffect = aEntity.getActivePotionEffect(Potion.digSlowdown)) == null ? 0 + : tEffect.getDuration())), + Math.max(0, (5 * aLevel) / 7))); + aEntity.addPotionEffect( + new PotionEffect( + Potion.confusion.id, + aLevel * 130 * aAmountOfItems + Math.max( + 0, + ((tEffect = aEntity.getActivePotionEffect(Potion.confusion)) == null ? 0 + : tEffect.getDuration())), + Math.max(0, (5 * aLevel) / 7))); + aEntity.addPotionEffect( + new PotionEffect( + Potion.weakness.id, + aLevel * 150 * aAmountOfItems + Math.max( + 0, + ((tEffect = aEntity.getActivePotionEffect(Potion.weakness)) == null ? 0 + : tEffect.getDuration())), + Math.max(0, (5 * aLevel) / 7))); + aEntity.addPotionEffect( + new PotionEffect( + Potion.hunger.id, + aLevel * 130 * aAmountOfItems + Math.max( + 0, +