diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java
index 32ae9d9..9eacdfb 100644
--- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java
+++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java
@@ -7,6 +7,8 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
import static org.lwjgl.opengles.GLES30.*;
+import org.lwjgl.opengles.GLES31;
+
/**
* Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved.
*
@@ -527,4 +529,8 @@ public class PlatformOpenGL {
return true;
}
+ public static int _wglGetTexLevelParameteri(int glTexture2d, int i, int glTextureWidth) {
+ return GLES31.glGetTexLevelParameteri(glTexture2d, i, glTextureWidth);
+ }
+
}
diff --git a/src/main/java/net/PeytonPlayz585/shadow/AggregateTranslator.java b/src/main/java/net/PeytonPlayz585/shadow/AggregateTranslator.java
new file mode 100644
index 0000000..923e011
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/AggregateTranslator.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.PeytonPlayz585.shadow;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Executes a sequence of translators one after the other. Execution ends whenever
+ * the first translator consumes code points from the input.
+ *
+ * @since 3.0
+ * @deprecated As of 3.6, use Apache Commons Text
+ *
+ * AggregateTranslator instead
+ */
+@Deprecated
+public class AggregateTranslator extends CharSequenceTranslator {
+
+ private final CharSequenceTranslator[] translators;
+
+ /**
+ * Specify the translators to be used at creation time.
+ *
+ * @param translators CharSequenceTranslator array to aggregate
+ */
+ public AggregateTranslator(final CharSequenceTranslator... translators) {
+ this.translators = ArrayUtils.clone(translators);
+ }
+
+ /**
+ * The first translator to consume code points from the input is the 'winner'.
+ * Execution stops with the number of consumed code points being returned.
+ * {@inheritDoc}
+ */
+ @Override
+ public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
+ for (final CharSequenceTranslator translator : translators) {
+ final int consumed = translator.translate(input, index, out);
+ if (consumed != 0) {
+ return consumed;
+ }
+ }
+ return 0;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/net/PeytonPlayz585/shadow/ArrayUtils.java b/src/main/java/net/PeytonPlayz585/shadow/ArrayUtils.java
new file mode 100644
index 0000000..d40ad2a
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/ArrayUtils.java
@@ -0,0 +1,360 @@
+package net.PeytonPlayz585.shadow;
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class ArrayUtils {
+ /**
+ * Clones an array or returns {@code null}.
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static boolean[] clone(final boolean[] array) {
+ return array != null ? array.clone() : null;
+ }
+
+ /**
+ * Clones an array or returns {@code null}.
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static byte[] clone(final byte[] array) {
+ return array != null ? array.clone() : null;
+ }
+
+ /**
+ * Clones an array or returns {@code null}.
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static char[] clone(final char[] array) {
+ return array != null ? array.clone() : null;
+ }
+
+ /**
+ * Clones an array or returns {@code null}.
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static double[] clone(final double[] array) {
+ return array != null ? array.clone() : null;
+ }
+
+ /**
+ * Clones an array or returns {@code null}.
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static float[] clone(final float[] array) {
+ return array != null ? array.clone() : null;
+ }
+
+ /**
+ * Clones an array or returns {@code null}.
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static int[] clone(final int[] array) {
+ return array != null ? array.clone() : null;
+ }
+
+ /**
+ * Clones an array or returns {@code null}.
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static long[] clone(final long[] array) {
+ return array != null ? array.clone() : null;
+ }
+
+ /**
+ * Clones an array or returns {@code null}.
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static short[] clone(final short[] array) {
+ return array != null ? array.clone() : null;
+ }
+
+ /**
+ * Shallow clones an array or returns {@code null}.
+ *
+ * The objects in the array are not cloned, thus there is no special handling for multi-dimensional arrays.
+ *
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ *
+ * @param the component type of the array
+ * @param array the array to shallow clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static T[] clone(final T[] array) {
+ return array != null ? array.clone() : null;
+ }
+
+ /**
+ * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
+ *
+ * @param the type.
+ * @param source the source array.
+ * @param sourcePos starting position in the source array.
+ * @param destPos starting position in the destination data.
+ * @param length the number of array elements to be copied.
+ * @param allocator allocates the array to populate and return.
+ * @return dest
+ * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
+ * @throws ArrayStoreException if an element in the src array could not be stored into the dest array because of a type
+ * mismatch.
+ * @throws NullPointerException if either src or dest is null.
+ * @since 3.15.0
+ */
+ public static T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Function allocator) {
+ return arraycopy(source, sourcePos, allocator.apply(length), destPos, length);
+ }
+
+ /**
+ * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
+ *
+ * @param the type.
+ * @param source the source array.
+ * @param sourcePos starting position in the source array.
+ * @param destPos starting position in the destination data.
+ * @param length the number of array elements to be copied.
+ * @param allocator allocates the array to populate and return.
+ * @return dest
+ * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
+ * @throws ArrayStoreException if an element in the src array could not be stored into the dest array because of a type
+ * mismatch.
+ * @throws NullPointerException if either src or dest is null.
+ * @since 3.15.0
+ */
+ public static T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Supplier allocator) {
+ return arraycopy(source, sourcePos, allocator.get(), destPos, length);
+ }
+
+ /**
+ * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
+ *
+ * @param the type
+ * @param source the source array.
+ * @param sourcePos starting position in the source array.
+ * @param dest the destination array.
+ * @param destPos starting position in the destination data.
+ * @param length the number of array elements to be copied.
+ * @return dest
+ * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
+ * @throws ArrayStoreException if an element in the src array could not be stored into the dest array because of a type
+ * mismatch.
+ * @throws NullPointerException if either src or dest is null.
+ * @since 3.15.0
+ */
+ public static T arraycopy(final T source, final int sourcePos, final T dest, final int destPos, final int length) {
+ System.arraycopy(source, sourcePos, dest, destPos, length);
+ return dest;
+ }
+
+ public static String arrayToString(boolean[] arr, String separator)
+ {
+ if (arr == null)
+ {
+ return "";
+ }
+ else
+ {
+ StringBuffer stringbuffer = new StringBuffer(arr.length * 5);
+
+ for (int i = 0; i < arr.length; ++i)
+ {
+ boolean flag = arr[i];
+
+ if (i > 0)
+ {
+ stringbuffer.append(separator);
+ }
+
+ stringbuffer.append(String.valueOf(flag));
+ }
+
+ return stringbuffer.toString();
+ }
+ }
+
+ public static String arrayToString(float[] arr)
+ {
+ return arrayToString(arr, ", ");
+ }
+
+ public static String arrayToString(float[] arr, String separator)
+ {
+ if (arr == null)
+ {
+ return "";
+ }
+ else
+ {
+ StringBuffer stringbuffer = new StringBuffer(arr.length * 5);
+
+ for (int i = 0; i < arr.length; ++i)
+ {
+ float f = arr[i];
+
+ if (i > 0)
+ {
+ stringbuffer.append(separator);
+ }
+
+ stringbuffer.append(String.valueOf(f));
+ }
+
+ return stringbuffer.toString();
+ }
+ }
+
+ public static String arrayToString(float[] arr, String separator, String format)
+ {
+ if (arr == null)
+ {
+ return "";
+ }
+ else
+ {
+ StringBuffer stringbuffer = new StringBuffer(arr.length * 5);
+
+ for (int i = 0; i < arr.length; ++i)
+ {
+ float f = arr[i];
+
+ if (i > 0)
+ {
+ stringbuffer.append(separator);
+ }
+
+ stringbuffer.append(String.format(format, new Object[] {Float.valueOf(f)}));
+ }
+
+ return stringbuffer.toString();
+ }
+ }
+
+ public static String arrayToString(int[] arr)
+ {
+ return arrayToString(arr, ", ");
+ }
+
+ public static String arrayToString(int[] arr, String separator)
+ {
+ if (arr == null)
+ {
+ return "";
+ }
+ else
+ {
+ StringBuffer stringbuffer = new StringBuffer(arr.length * 5);
+
+ for (int i = 0; i < arr.length; ++i)
+ {
+ int j = arr[i];
+
+ if (i > 0)
+ {
+ stringbuffer.append(separator);
+ }
+
+ stringbuffer.append(String.valueOf(j));
+ }
+
+ return stringbuffer.toString();
+ }
+ }
+
+ public static String arrayToHexString(int[] arr, String separator)
+ {
+ if (arr == null)
+ {
+ return "";
+ }
+ else
+ {
+ StringBuffer stringbuffer = new StringBuffer(arr.length * 5);
+
+ for (int i = 0; i < arr.length; ++i)
+ {
+ int j = arr[i];
+
+ if (i > 0)
+ {
+ stringbuffer.append(separator);
+ }
+
+ stringbuffer.append("0x");
+ stringbuffer.append(Integer.toHexString(j));
+ }
+
+ return stringbuffer.toString();
+ }
+ }
+
+ public static String arrayToString(Object[] arr)
+ {
+ return arrayToString(arr, ", ");
+ }
+
+ public static String arrayToString(Object[] arr, String separator)
+ {
+ if (arr == null)
+ {
+ return "";
+ }
+ else
+ {
+ StringBuffer stringbuffer = new StringBuffer(arr.length * 5);
+
+ for (int i = 0; i < arr.length; ++i)
+ {
+ Object object = arr[i];
+
+ if (i > 0)
+ {
+ stringbuffer.append(separator);
+ }
+
+ stringbuffer.append(String.valueOf(object));
+ }
+
+ return stringbuffer.toString();
+ }
+ }
+}
diff --git a/src/main/java/net/PeytonPlayz585/shadow/CharSequenceTranslator.java b/src/main/java/net/PeytonPlayz585/shadow/CharSequenceTranslator.java
new file mode 100644
index 0000000..e58ebc2
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/CharSequenceTranslator.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.PeytonPlayz585.shadow;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.util.Locale;
+import java.util.Objects;
+
+/**
+ * An API for translating text.
+ * Its core use is to escape and unescape text. Because escaping and unescaping
+ * is completely contextual, the API does not present two separate signatures.
+ *
+ * @since 3.0
+ * @deprecated As of 3.6, use Apache Commons Text
+ *
+ * CharSequenceTranslator instead
+ */
+@Deprecated
+public abstract class CharSequenceTranslator {
+
+ static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ /**
+ * Returns an upper case hexadecimal {@link String} for the given
+ * character.
+ *
+ * @param codePoint The code point to convert.
+ * @return An upper case hexadecimal {@link String}
+ */
+ public static String hex(final int codePoint) {
+ return Integer.toHexString(codePoint).toUpperCase(Locale.ENGLISH);
+ }
+
+ /**
+ * Helper for non-Writer usage.
+ * @param input CharSequence to be translated
+ * @return String output of translation
+ */
+ public final String translate(final CharSequence input) {
+ if (input == null) {
+ return null;
+ }
+ try {
+ final StringWriter writer = new StringWriter(input.length() * 2);
+ translate(input, writer);
+ return writer.toString();
+ } catch (final IOException ioe) {
+ // this should never ever happen while writing to a StringWriter
+ throw new UncheckedIOException(ioe);
+ }
+ }
+
+ /**
+ * Translate a set of code points, represented by an int index into a CharSequence,
+ * into another set of code points. The number of code points consumed must be returned,
+ * and the only IOExceptions thrown must be from interacting with the Writer so that
+ * the top level API may reliably ignore StringWriter IOExceptions.
+ *
+ * @param input CharSequence that is being translated
+ * @param index int representing the current point of translation
+ * @param out Writer to translate the text to
+ * @return int count of code points consumed
+ * @throws IOException if and only if the Writer produces an IOException
+ */
+ public abstract int translate(CharSequence input, int index, Writer out) throws IOException;
+
+ /**
+ * Translate an input onto a Writer. This is intentionally final as its algorithm is
+ * tightly coupled with the abstract method of this class.
+ *
+ * @param input CharSequence that is being translated
+ * @param writer Writer to translate the text to
+ * @throws IOException if and only if the Writer produces an IOException
+ */
+ public final void translate(final CharSequence input, final Writer writer) throws IOException {
+ Objects.requireNonNull(writer, "writer");
+ if (input == null) {
+ return;
+ }
+ int pos = 0;
+ final int len = input.length();
+ while (pos < len) {
+ final int consumed = translate(input, pos, writer);
+ if (consumed == 0) {
+ // inlined implementation of Character.toChars(Character.codePointAt(input, pos))
+ // avoids allocating temp char arrays and duplicate checks
+ final char c1 = input.charAt(pos);
+ writer.write(c1);
+ pos++;
+ if (Character.isHighSurrogate(c1) && pos < len) {
+ final char c2 = input.charAt(pos);
+ if (Character.isLowSurrogate(c2)) {
+ writer.write(c2);
+ pos++;
+ }
+ }
+ continue;
+ }
+ // contract with translators is that they have to understand code points
+ // and they just took care of a surrogate pair
+ for (int pt = 0; pt < consumed; pt++) {
+ pos += Character.charCount(Character.codePointAt(input, pos));
+ }
+ }
+ }
+
+ /**
+ * Helper method to create a merger of this translator with another set of
+ * translators. Useful in customizing the standard functionality.
+ *
+ * @param translators CharSequenceTranslator array of translators to merge with this one
+ * @return CharSequenceTranslator merging this translator with the others
+ */
+ public final CharSequenceTranslator with(final CharSequenceTranslator... translators) {
+ final CharSequenceTranslator[] newArray = new CharSequenceTranslator[translators.length + 1];
+ newArray[0] = this;
+ return new AggregateTranslator(ArrayUtils.arraycopy(translators, 0, newArray, 1, translators.length));
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/net/PeytonPlayz585/shadow/Config.java b/src/main/java/net/PeytonPlayz585/shadow/Config.java
index 64013b6..dffa9ae 100644
--- a/src/main/java/net/PeytonPlayz585/shadow/Config.java
+++ b/src/main/java/net/PeytonPlayz585/shadow/Config.java
@@ -3,12 +3,14 @@ package net.PeytonPlayz585.shadow;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
+import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
+import net.PeytonPlayz585.shadow.reflect.Reflector;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
@@ -298,6 +300,10 @@ public class Config {
}
return !isDynamicLights() ? false : true;
}
+
+ public static boolean isCustomItems() {
+ return gameSettings.ofCustomItems;
+ }
public static int limit(int p_limit_0_, int p_limit_1_, int p_limit_2_) {
return p_limit_0_ < p_limit_1_ ? p_limit_1_ : (p_limit_0_ > p_limit_2_ ? p_limit_2_ : p_limit_0_);
@@ -410,7 +416,7 @@ public class Config {
public static DefaultResourcePack getDefaultResourcePack() {
if (defaultResourcePackLazy == null) {
Minecraft minecraft = Minecraft.getMinecraft();
- defaultResourcePackLazy = (DefaultResourcePack)Minecraft.getMinecraft().mcDefaultResourcePack;
+ defaultResourcePackLazy = (DefaultResourcePack)Reflector.getFieldValue(minecraft, Reflector.Minecraft_defaultResourcePack);
if (defaultResourcePackLazy == null) {
ResourcePackRepository resourcepackrepository = minecraft.getResourcePackRepository();
@@ -452,8 +458,9 @@ public class Config {
List list = resourcepackrepository.getRepositoryEntries();
List list1 = new ArrayList();
- for (Object resourcepackrepository$entry : list) {
- list1.add(((ResourcePackRepository.Entry) resourcepackrepository$entry).getResourcePack());
+ for (Object resourcepackrepository$entry0 : list) {
+ ResourcePackRepository.Entry resourcepackrepository$entry = (ResourcePackRepository.Entry) resourcepackrepository$entry0;
+ list1.add(resourcepackrepository$entry.getResourcePack());
}
if (resourcepackrepository.getResourcePackInstance() != null) {
@@ -595,4 +602,31 @@ public class Config {
return stringbuffer.toString();
}
}
+
+ public static Object[] addObjectsToArray(Object[] p_addObjectsToArray_0_, Object[] p_addObjectsToArray_1_) {
+ if (p_addObjectsToArray_0_ == null) {
+ throw new NullPointerException("The given array is NULL");
+ } else if (p_addObjectsToArray_1_.length == 0) {
+ return p_addObjectsToArray_0_;
+ } else {
+ int i = p_addObjectsToArray_0_.length;
+ int j = i + p_addObjectsToArray_1_.length;
+ Object[] aobject = (Object[])((Object[])Array.newInstance(p_addObjectsToArray_0_.getClass().getComponentType(), j));
+ System.arraycopy(p_addObjectsToArray_0_, 0, aobject, 0, i);
+ System.arraycopy(p_addObjectsToArray_1_, 0, aobject, i, p_addObjectsToArray_1_.length);
+ return aobject;
+ }
+ }
+
+ public static boolean equals(Object p_equals_0_, Object p_equals_1_) {
+ return p_equals_0_ == p_equals_1_ ? true : (p_equals_0_ == null ? false : p_equals_0_.equals(p_equals_1_));
+ }
+
+ public static void error(String s, Throwable t) {
+ LOGGER.error("[Shadow Client] " + s, t);
+ }
+
+ public static void warn(String s, Throwable t) {
+ LOGGER.warn("[Shadow Client] " + s, t);
+ }
}
diff --git a/src/main/java/net/PeytonPlayz585/shadow/CustomItemProperties.java b/src/main/java/net/PeytonPlayz585/shadow/CustomItemProperties.java
new file mode 100644
index 0000000..d279922
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/CustomItemProperties.java
@@ -0,0 +1,968 @@
+package net.PeytonPlayz585.shadow;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite;
+import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
+import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
+import net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums;
+import net.minecraft.client.renderer.block.model.BakedQuad;
+import net.minecraft.client.renderer.block.model.BlockPart;
+import net.minecraft.client.renderer.block.model.BlockPartFace;
+import net.minecraft.client.renderer.block.model.FaceBakery;
+import net.minecraft.client.renderer.block.model.ItemModelGenerator;
+import net.minecraft.client.renderer.block.model.ModelBlock;
+import net.minecraft.client.renderer.texture.ITextureObject;
+import net.minecraft.client.renderer.texture.TextureManager;
+import net.minecraft.client.renderer.texture.TextureMap;
+import net.minecraft.client.resources.model.IBakedModel;
+import net.minecraft.client.resources.model.ModelBakery;
+import net.minecraft.client.resources.model.ModelManager;
+import net.minecraft.client.resources.model.ModelResourceLocation;
+import net.minecraft.client.resources.model.ModelRotation;
+import net.minecraft.client.resources.model.SimpleBakedModel;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemArmor;
+import net.minecraft.util.EnumFacing;
+import net.minecraft.util.ResourceLocation;
+
+public class CustomItemProperties {
+ public String name = null;
+ public String basePath = null;
+ public int type = 1;
+ public int[] items = null;
+ public String texture = null;
+ public Map < String, String > mapTextures = null;
+ public String model = null;
+ public Map < String, String > mapModels = null;
+ public RangeListInt damage = null;
+ public boolean damagePercent = false;
+ public int damageMask = 0;
+ public RangeListInt stackSize = null;
+ public RangeListInt enchantmentIds = null;
+ public RangeListInt enchantmentLevels = null;
+ public NbtTagValue[] nbtTagValues = null;
+ public int hand = 0;
+ public int blend = 1;
+ public float speed = 0.0F;
+ public float rotation = 0.0F;
+ public int layer = 0;
+ public float duration = 1.0F;
+ public int weight = 0;
+ public ResourceLocation textureLocation = null;
+ public Map mapTextureLocations = null;
+ public EaglerTextureAtlasSprite sprite = null;
+ public Map mapSprites = null;
+ public IBakedModel bakedModelTexture = null;
+ public Map < String, IBakedModel > mapBakedModelsTexture = null;
+ public IBakedModel bakedModelFull = null;
+ public Map < String, IBakedModel > mapBakedModelsFull = null;
+ private int textureWidth = 0;
+ private int textureHeight = 0;
+ public static final int TYPE_UNKNOWN = 0;
+ public static final int TYPE_ITEM = 1;
+ public static final int TYPE_ENCHANTMENT = 2;
+ public static final int TYPE_ARMOR = 3;
+ public static final int HAND_ANY = 0;
+ public static final int HAND_MAIN = 1;
+ public static final int HAND_OFF = 2;
+ public static final String INVENTORY = "inventory";
+
+ public CustomItemProperties(Properties props, String path) {
+ this.name = parseName(path);
+ this.basePath = parseBasePath(path);
+ this.type = this.parseType(props.getProperty("type"));
+ this.items = this.parseItems(props.getProperty("items"), props.getProperty("matchItems"));
+ this.mapModels = parseModels(props, this.basePath);
+ this.model = parseModel(props.getProperty("model"), path, this.basePath, this.type, this.mapModels);
+ this.mapTextures = parseTextures(props, this.basePath);
+ boolean flag = this.mapModels == null && this.model == null;
+ this.texture = parseTexture(props.getProperty("texture"), props.getProperty("tile"), props.getProperty("source"), path, this.basePath, this.type, this.mapTextures, flag);
+ String s = props.getProperty("damage");
+
+ if (s != null) {
+ this.damagePercent = s.contains("%");
+ s = s.replace("%", "");
+ this.damage = this.parseRangeListInt(s);
+ this.damageMask = this.parseInt(props.getProperty("damageMask"), 0);
+ }
+
+ this.stackSize = this.parseRangeListInt(props.getProperty("stackSize"));
+ this.enchantmentIds = this.parseRangeListInt(props.getProperty("enchantmentIDs"), new ParserEnchantmentId());
+ this.enchantmentLevels = this.parseRangeListInt(props.getProperty("enchantmentLevels"));
+ this.nbtTagValues = this.parseNbtTagValues(props);
+ this.hand = this.parseHand(props.getProperty("hand"));
+ this.blend = Blender.parseBlend(props.getProperty("blend"));
+ this.speed = this.parseFloat(props.getProperty("speed"), 0.0F);
+ this.rotation = this.parseFloat(props.getProperty("rotation"), 0.0F);
+ this.layer = this.parseInt(props.getProperty("layer"), 0);
+ this.weight = this.parseInt(props.getProperty("weight"), 0);
+ this.duration = this.parseFloat(props.getProperty("duration"), 1.0F);
+ }
+
+ private static String parseName(String path) {
+ String s = path;
+ int i = path.lastIndexOf(47);
+
+ if (i >= 0) {
+ s = path.substring(i + 1);
+ }
+
+ int j = s.lastIndexOf(46);
+
+ if (j >= 0) {
+ s = s.substring(0, j);
+ }
+
+ return s;
+ }
+
+ private static String parseBasePath(String path) {
+ int i = path.lastIndexOf(47);
+ return i < 0 ? "" : path.substring(0, i);
+ }
+
+ private int parseType(String str) {
+ if (str == null) {
+ return 1;
+ } else if (str.equals("item")) {
+ return 1;
+ } else if (str.equals("enchantment")) {
+ return 2;
+ } else if (str.equals("armor")) {
+ return 3;
+ } else {
+ Config.warn("Unknown method: " + str);
+ return 0;
+ }
+ }
+
+ private int[] parseItems(String str, String str2) {
+ if (str == null) {
+ str = str2;
+ }
+
+ if (str == null) {
+ return null;
+ } else {
+ str = str.trim();
+ Set set = new TreeSet();
+ String[] astring = Config.tokenize(str, " ");
+ label45:
+
+ for (int i = 0; i < astring.length; ++i) {
+ String s = astring[i];
+ int j = Config.parseInt(s, -1);
+
+ if (j >= 0) {
+ set.add(new Integer(j));
+ } else {
+ if (s.contains("-")) {
+ String[] astring1 = Config.tokenize(s, "-");
+
+ if (astring1.length == 2) {
+ int k = Config.parseInt(astring1[0], -1);
+ int l = Config.parseInt(astring1[1], -1);
+
+ if (k >= 0 && l >= 0) {
+ int i1 = Math.min(k, l);
+ int j1 = Math.max(k, l);
+ int k1 = i1;
+
+ while (true) {
+ if (k1 > j1) {
+ continue label45;
+ }
+
+ set.add(new Integer(k1));
+ ++k1;
+ }
+ }
+ }
+ }
+
+ Item item = Item.getByNameOrId(s);
+
+ if (item == null) {
+ Config.warn("Item not found: " + s);
+ } else {
+ int i2 = Item.getIdFromItem(item);
+
+ if (i2 <= 0) {
+ Config.warn("Item not found: " + s);
+ } else {
+ set.add(new Integer(i2));
+ }
+ }
+ }
+ }
+
+ Integer[] ainteger = (Integer[])((Integer[]) set.toArray(new Integer[set.size()]));
+ int[] aint = new int[ainteger.length];
+
+ for (int l1 = 0; l1 < aint.length; ++l1) {
+ aint[l1] = ainteger[l1].intValue();
+ }
+
+ return aint;
+ }
+ }
+
+ private static String parseTexture(String texStr, String texStr2, String texStr3, String path, String basePath, int type, Map < String, String > mapTexs, boolean textureFromPath) {
+ if (texStr == null) {
+ texStr = texStr2;
+ }
+
+ if (texStr == null) {
+ texStr = texStr3;
+ }
+
+ if (texStr != null) {
+ String s2 = ".png";
+
+ if (texStr.endsWith(s2)) {
+ texStr = texStr.substring(0, texStr.length() - s2.length());
+ }
+
+ texStr = fixTextureName(texStr, basePath);
+ return texStr;
+ } else if (type == 3) {
+ return null;
+ } else {
+ if (mapTexs != null) {
+ String s = (String) mapTexs.get("texture.bow_standby");
+
+ if (s != null) {
+ return s;
+ }
+ }
+
+ if (!textureFromPath) {
+ return null;
+ } else {
+ String s1 = path;
+ int i = path.lastIndexOf(47);
+
+ if (i >= 0) {
+ s1 = path.substring(i + 1);
+ }
+
+ int j = s1.lastIndexOf(46);
+
+ if (j >= 0) {
+ s1 = s1.substring(0, j);
+ }
+
+ s1 = fixTextureName(s1, basePath);
+ return s1;
+ }
+ }
+ }
+
+ private static Map parseTextures(Properties props, String basePath) {
+ String s = "texture.";
+ Map map = getMatchingProperties(props, s);
+
+ if (map.size() <= 0) {
+ return null;
+ } else {
+ Set set = map.keySet();
+ Map map1 = new LinkedHashMap();
+
+ for (Object e: set) {
+ String s1 = (String) e;
+ String s2 = (String) map.get(s1);
+ s2 = fixTextureName(s2, basePath);
+ map1.put(s1, s2);
+ }
+
+ return map1;
+ }
+ }
+
+ private static String fixTextureName(String iconName, String basePath) {
+ iconName = TextureUtils.fixResourcePath(iconName, basePath);
+
+ if (!iconName.startsWith(basePath) && !iconName.startsWith("textures/") && !iconName.startsWith("mcpatcher/")) {
+ iconName = basePath + "/" + iconName;
+ }
+
+ if (iconName.endsWith(".png")) {
+ iconName = iconName.substring(0, iconName.length() - 4);
+ }
+
+ if (iconName.startsWith("/")) {
+ iconName = iconName.substring(1);
+ }
+
+ return iconName;
+ }
+
+ private static String parseModel(String modelStr, String path, String basePath, int type, Map < String, String > mapModelNames) {
+ if (modelStr != null) {
+ String s1 = ".json";
+
+ if (modelStr.endsWith(s1)) {
+ modelStr = modelStr.substring(0, modelStr.length() - s1.length());
+ }
+
+ modelStr = fixModelName(modelStr, basePath);
+ return modelStr;
+ } else if (type == 3) {
+ return null;
+ } else {
+ if (mapModelNames != null) {
+ String s = (String) mapModelNames.get("model.bow_standby");
+
+ if (s != null) {
+ return s;
+ }
+ }
+
+ return modelStr;
+ }
+ }
+
+ private static Map parseModels(Properties props, String basePath) {
+ String s = "model.";
+ Map map = getMatchingProperties(props, s);
+
+ if (map.size() <= 0) {
+ return null;
+ } else {
+ Set set = map.keySet();
+ Map map1 = new LinkedHashMap();
+
+ for (Object e: set) {
+ String s1 = (String) e;
+ String s2 = (String) map.get(s1);
+ s2 = fixModelName(s2, basePath);
+ map1.put(s1, s2);
+ }
+
+ return map1;
+ }
+ }
+
+ private static String fixModelName(String modelName, String basePath) {
+ modelName = TextureUtils.fixResourcePath(modelName, basePath);
+ boolean flag = modelName.startsWith("block/") || modelName.startsWith("item/");
+
+ if (!modelName.startsWith(basePath) && !flag && !modelName.startsWith("mcpatcher/")) {
+ modelName = basePath + "/" + modelName;
+ }
+
+ String s = ".json";
+
+ if (modelName.endsWith(s)) {
+ modelName = modelName.substring(0, modelName.length() - s.length());
+ }
+
+ if (modelName.startsWith("/")) {
+ modelName = modelName.substring(1);
+ }
+
+ return modelName;
+ }
+
+ private int parseInt(String str, int defVal) {
+ if (str == null) {
+ return defVal;
+ } else {
+ str = str.trim();
+ int i = Config.parseInt(str, Integer.MIN_VALUE);
+
+ if (i == Integer.MIN_VALUE) {
+ Config.warn("Invalid integer: " + str);
+ return defVal;
+ } else {
+ return i;
+ }
+ }
+ }
+
+ private float parseFloat(String str, float defVal) {
+ if (str == null) {
+ return defVal;
+ } else {
+ str = str.trim();
+ float f = Config.parseFloat(str, Float.MIN_VALUE);
+
+ if (f == Float.MIN_VALUE) {
+ Config.warn("Invalid float: " + str);
+ return defVal;
+ } else {
+ return f;
+ }
+ }
+ }
+
+ private RangeListInt parseRangeListInt(String str) {
+ return this.parseRangeListInt(str, (IParserInt) null);
+ }
+
+ private RangeListInt parseRangeListInt(String str, IParserInt parser) {
+ if (str == null) {
+ return null;
+ } else {
+ String[] astring = Config.tokenize(str, " ");
+ RangeListInt rangelistint = new RangeListInt();
+
+ for (int i = 0; i < astring.length; ++i) {
+ String s = astring[i];
+
+ if (parser != null) {
+ int j = parser.parse(s, Integer.MIN_VALUE);
+
+ if (j != Integer.MIN_VALUE) {
+ rangelistint.addRange(new RangeInt(j, j));
+ continue;
+ }
+ }
+
+ RangeInt rangeint = this.parseRangeInt(s);
+
+ if (rangeint == null) {
+ Config.warn("Invalid range list: " + str);
+ return null;
+ }
+
+ rangelistint.addRange(rangeint);
+ }
+
+ return rangelistint;
+ }
+ }
+
+ private RangeInt parseRangeInt(String str) {
+ if (str == null) {
+ return null;
+ } else {
+ str = str.trim();
+ int i = str.length() - str.replace("-", "").length();
+
+ if (i > 1) {
+ Config.warn("Invalid range: " + str);
+ return null;
+ } else {
+ String[] astring = Config.tokenize(str, "- ");
+ int[] aint = new int[astring.length];
+
+ for (int j = 0; j < astring.length; ++j) {
+ String s = astring[j];
+ int k = Config.parseInt(s, -1);
+
+ if (k < 0) {
+ Config.warn("Invalid range: " + str);
+ return null;
+ }
+
+ aint[j] = k;
+ }
+
+ if (aint.length == 1) {
+ int i1 = aint[0];
+
+ if (str.startsWith("-")) {
+ return new RangeInt(0, i1);
+ } else if (str.endsWith("-")) {
+ return new RangeInt(i1, 65535);
+ } else {
+ return new RangeInt(i1, i1);
+ }
+ } else if (aint.length == 2) {
+ int l = Math.min(aint[0], aint[1]);
+ int j1 = Math.max(aint[0], aint[1]);
+ return new RangeInt(l, j1);
+ } else {
+ Config.warn("Invalid range: " + str);
+ return null;
+ }
+ }
+ }
+ }
+
+ private NbtTagValue[] parseNbtTagValues(Properties props) {
+ String s = "nbt.";
+ Map map = getMatchingProperties(props, s);
+
+ if (map.size() <= 0) {
+ return null;
+ } else {
+ List list = new ArrayList();
+
+ for (Object e: map.keySet()) {
+ String s1 = (String) e;
+ String s2 = (String) map.get(s1);
+ String s3 = s1.substring(s.length());
+ NbtTagValue nbttagvalue = new NbtTagValue(s3, s2);
+ list.add(nbttagvalue);
+ }
+
+ NbtTagValue[] anbttagvalue = (NbtTagValue[])((NbtTagValue[]) list.toArray(new NbtTagValue[list.size()]));
+ return anbttagvalue;
+ }
+ }
+
+ private static Map getMatchingProperties(Properties props, String keyPrefix) {
+ Map map = new LinkedHashMap();
+
+ for (Object e: props.keySet()) {
+ String s = (String) e;
+ String s1 = props.getProperty(s);
+
+ if (s.startsWith(keyPrefix)) {
+ map.put(s, s1);
+ }
+ }
+
+ return map;
+ }
+
+ private int parseHand(String str) {
+ if (str == null) {
+ return 0;
+ } else {
+ str = str.toLowerCase();
+
+ if (str.equals("any")) {
+ return 0;
+ } else if (str.equals("main")) {
+ return 1;
+ } else if (str.equals("off")) {
+ return 2;
+ } else {
+ Config.warn("Invalid hand: " + str);
+ return 0;
+ }
+ }
+ }
+
+ public boolean isValid(String path) {
+ if (this.name != null && this.name.length() > 0) {
+ if (this.basePath == null) {
+ Config.warn("No base path found: " + path);
+ return false;
+ } else if (this.type == 0) {
+ Config.warn("No type defined: " + path);
+ return false;
+ } else {
+ if (this.type == 1 || this.type == 3) {
+ if (this.items == null) {
+ this.items = this.detectItems();
+ }
+
+ if (this.items == null) {
+ Config.warn("No items defined: " + path);
+ return false;
+ }
+ }
+
+ if (this.texture == null && this.mapTextures == null && this.model == null && this.mapModels == null) {
+ Config.warn("No texture or model specified: " + path);
+ return false;
+ } else if (this.type == 2 && this.enchantmentIds == null) {
+ Config.warn("No enchantmentIDs specified: " + path);
+ return false;
+ } else {
+ return true;
+ }
+ }
+ } else {
+ Config.warn("No name found: " + path);
+ return false;
+ }
+ }
+
+ private int[] detectItems() {
+ Item item = Item.getByNameOrId(this.name);
+
+ if (item == null) {
+ return null;
+ } else {
+ int i = Item.getIdFromItem(item);
+ return i <= 0 ? null : new int[] {
+ i
+ };
+ }
+ }
+
+ public void updateIcons(TextureMap textureMap) {
+ if (this.texture != null) {
+ this.textureLocation = this.getTextureLocation(this.texture);
+
+ if (this.type == 1) {
+ ResourceLocation resourcelocation = this.getSpriteLocation(this.textureLocation);
+ this.sprite = textureMap.registerSprite(resourcelocation);
+ }
+ }
+
+ if (this.mapTextures != null) {
+ this.mapTextureLocations = new HashMap();
+ this.mapSprites = new HashMap();
+
+ for (String s: this.mapTextures.keySet()) {
+ String s1 = (String) this.mapTextures.get(s);
+ ResourceLocation resourcelocation1 = this.getTextureLocation(s1);
+ this.mapTextureLocations.put(s, resourcelocation1);
+
+ if (this.type == 1) {
+ ResourceLocation resourcelocation2 = this.getSpriteLocation(resourcelocation1);
+ EaglerTextureAtlasSprite textureatlassprite = textureMap.registerSprite(resourcelocation2);
+ this.mapSprites.put(s, textureatlassprite);
+ }
+ }
+ }
+ }
+
+ private ResourceLocation getTextureLocation(String texName) {
+ if (texName == null) {
+ return null;
+ } else {
+ ResourceLocation resourcelocation = new ResourceLocation(texName);
+ String s = resourcelocation.getResourceDomain();
+ String s1 = resourcelocation.getResourcePath();
+
+ if (!s1.contains("/")) {
+ s1 = "textures/items/" + s1;
+ }
+
+ String s2 = s1 + ".png";
+ ResourceLocation resourcelocation1 = new ResourceLocation(s, s2);
+ boolean flag = Config.hasResource(resourcelocation1);
+
+ if (!flag) {
+ Config.warn("File not found: " + s2);
+ }
+
+ return resourcelocation1;
+ }
+ }
+
+ private ResourceLocation getSpriteLocation(ResourceLocation resLoc) {
+ String s = resLoc.getResourcePath();
+ s = StrUtils.removePrefix(s, "textures/");
+ s = StrUtils.removeSuffix(s, ".png");
+ ResourceLocation resourcelocation = new ResourceLocation(resLoc.getResourceDomain(), s);
+ return resourcelocation;
+ }
+
+ public void updateModelTexture(TextureMap textureMap, ItemModelGenerator itemModelGenerator) {
+ if (this.texture != null || this.mapTextures != null) {
+ String[] astring = this.getModelTextures();
+ boolean flag = this.isUseTint();
+ this.bakedModelTexture = makeBakedModel(textureMap, itemModelGenerator, astring, flag);
+
+ if (this.type == 1 && this.mapTextures != null) {
+ for (String s: this.mapTextures.keySet()) {
+ String s1 = (String) this.mapTextures.get(s);
+ String s2 = StrUtils.removePrefix(s, "texture.");
+
+ if (s2.startsWith("bow") || s2.startsWith("fishing_rod") || s2.startsWith("shield")) {
+ String[] astring1 = new String[] {
+ s1
+ };
+ IBakedModel ibakedmodel = makeBakedModel(textureMap, itemModelGenerator, astring1, flag);
+
+ if (this.mapBakedModelsTexture == null) {
+ this.mapBakedModelsTexture = new HashMap();
+ }
+
+ this.mapBakedModelsTexture.put(s2, ibakedmodel);
+ }
+ }
+ }
+ }
+ }
+
+ private boolean isUseTint() {
+ return true;
+ }
+
+ private static IBakedModel makeBakedModel(TextureMap textureMap, ItemModelGenerator itemModelGenerator, String[] textures, boolean useTint) {
+ String[] astring = new String[textures.length];
+
+ for (int i = 0; i < astring.length; ++i) {
+ String s = textures[i];
+ astring[i] = StrUtils.removePrefix(s, "textures/");
+ }
+
+ ModelBlock modelblock = makeModelBlock(astring);
+ ModelBlock modelblock1 = itemModelGenerator.makeItemModel(textureMap, modelblock);
+ IBakedModel ibakedmodel = bakeModel(textureMap, modelblock1, useTint);
+ return ibakedmodel;
+ }
+
+ private String[] getModelTextures() {
+ if (this.type == 1 && this.items.length == 1) {
+ Item item = Item.getItemById(this.items[0]);
+
+ if (item == Items.potionitem && this.damage != null && this.damage.getCountRanges() > 0) {
+ RangeInt rangeint = this.damage.getRange(0);
+ int i = rangeint.getMin();
+ boolean flag = (i & 16384) != 0;
+ String s5 = this.getMapTexture(this.mapTextures, "texture.potion_overlay", "items/potion_overlay");
+ String s6 = null;
+
+ if (flag) {
+ s6 = this.getMapTexture(this.mapTextures, "texture.potion_bottle_splash", "items/potion_bottle_splash");
+ } else {
+ s6 = this.getMapTexture(this.mapTextures, "texture.potion_bottle_drinkable", "items/potion_bottle_drinkable");
+ }
+
+ return new String[] {
+ s5,
+ s6
+ };
+ }
+
+ if (item instanceof ItemArmor) {
+ ItemArmor itemarmor = (ItemArmor) item;
+
+ if (itemarmor.getArmorMaterial() == ItemArmor.ArmorMaterial.LEATHER) {
+ String s = "leather";
+ String s1 = "helmet";
+
+ if (itemarmor.armorType == 0) {
+ s1 = "helmet";
+ }
+
+ if (itemarmor.armorType == 1) {
+ s1 = "chestplate";
+ }
+
+ if (itemarmor.armorType == 2) {
+ s1 = "leggings";
+ }
+
+ if (itemarmor.armorType == 3) {
+ s1 = "boots";
+ }
+
+ String s2 = s + "_" + s1;
+ String s3 = this.getMapTexture(this.mapTextures, "texture." + s2, "items/" + s2);
+ String s4 = this.getMapTexture(this.mapTextures, "texture." + s2 + "_overlay", "items/" + s2 + "_overlay");
+ return new String[] {
+ s3,
+ s4
+ };
+ }
+ }
+ }
+
+ return new String[] {
+ this.texture
+ };
+ }
+
+ private String getMapTexture(Map < String, String > map, String key, String def) {
+ if (map == null) {
+ return def;
+ } else {
+ String s = (String) map.get(key);
+ return s == null ? def : s;
+ }
+ }
+
+ private static ModelBlock makeModelBlock(String[] modelTextures) {
+ StringBuffer stringbuffer = new StringBuffer();
+ stringbuffer.append("{\"parent\": \"builtin/generated\",\"textures\": {");
+
+ for (int i = 0; i < modelTextures.length; ++i) {
+ String s = modelTextures[i];
+
+ if (i > 0) {
+ stringbuffer.append(", ");
+ }
+
+ stringbuffer.append("\"layer" + i + "\": \"" + s + "\"");
+ }
+
+ stringbuffer.append("}}");
+ String s1 = stringbuffer.toString();
+ ModelBlock modelblock = ModelBlock.deserialize(s1);
+ return modelblock;
+ }
+
+ private static IBakedModel bakeModel(TextureMap textureMap, ModelBlock modelBlockIn, boolean useTint) {
+ ModelRotation modelrotation = ModelRotation.X0_Y0;
+ boolean flag = false;
+ String s = modelBlockIn.resolveTextureName("particle");
+ EaglerTextureAtlasSprite textureatlassprite = textureMap.getAtlasSprite((new ResourceLocation(s)).toString());
+ SimpleBakedModel.Builder simplebakedmodel$builder = (new SimpleBakedModel.Builder(modelBlockIn)).setTexture(textureatlassprite);
+
+ for (BlockPart blockpart: modelBlockIn.getElements()) {
+ for (EnumFacing enumfacing: blockpart.mapFaces.keySet()) {
+ BlockPartFace blockpartface = (BlockPartFace) blockpart.mapFaces.get(enumfacing);
+
+ if (!useTint) {
+ blockpartface = new BlockPartFace(blockpartface.cullFace, -1, blockpartface.texture, blockpartface.blockFaceUV);
+ }
+
+ String s1 = modelBlockIn.resolveTextureName(blockpartface.texture);
+ EaglerTextureAtlasSprite textureatlassprite1 = textureMap.getAtlasSprite((new ResourceLocation(s1)).toString());
+ BakedQuad bakedquad = makeBakedQuad(blockpart, blockpartface, textureatlassprite1, enumfacing, modelrotation, flag);
+
+ if (blockpartface.cullFace == null) {
+ simplebakedmodel$builder.addGeneralQuad(bakedquad);
+ } else {
+ simplebakedmodel$builder.addFaceQuad(modelrotation.rotateFace(blockpartface.cullFace), bakedquad);
+ }
+ }
+ }
+
+ return simplebakedmodel$builder.makeBakedModel();
+ }
+
+ private static BakedQuad makeBakedQuad(BlockPart blockPart, BlockPartFace blockPartFace, EaglerTextureAtlasSprite textureAtlasSprite, EnumFacing enumFacing, ModelRotation modelRotation, boolean uvLocked) {
+ FaceBakery facebakery = new FaceBakery();
+ return facebakery.makeBakedQuad(blockPart.positionFrom, blockPart.positionTo, blockPartFace, textureAtlasSprite, enumFacing, modelRotation, blockPart.partRotation, uvLocked, blockPart.shade);
+ }
+
+ public String toString() {
+ return "" + this.basePath + "/" + this.name + ", type: " + this.type + ", items: [" + Config.arrayToString(this.items) + "], textture: " + this.texture;
+ }
+
+ public float getTextureWidth(TextureManager textureManager) {
+ if (this.textureWidth <= 0) {
+ if (this.textureLocation != null) {
+ ITextureObject itextureobject = textureManager.getTexture(this.textureLocation);
+ int i = itextureobject.getGlTextureId();
+ int j = GlStateManager.getBoundTexture();
+ GlStateManager.bindTexture(i);
+ this.textureWidth = EaglercraftGPU.glGetTexLevelParameteri(RealOpenGLEnums.GL_TEXTURE_2D, 0, RealOpenGLEnums.GL_TEXTURE_WIDTH);
+ GlStateManager.bindTexture(j);
+ }
+
+ if (this.textureWidth <= 0) {
+ this.textureWidth = 16;
+ }
+ }
+
+ return (float) this.textureWidth;
+ }
+
+ public float getTextureHeight(TextureManager textureManager) {
+ if (this.textureHeight <= 0) {
+ if (this.textureLocation != null) {
+ ITextureObject itextureobject = textureManager.getTexture(this.textureLocation);
+ int i = itextureobject.getGlTextureId();
+ int j = GlStateManager.getBoundTexture();
+ GlStateManager.bindTexture(i);
+ this.textureHeight = EaglercraftGPU.glGetTexLevelParameteri(RealOpenGLEnums.GL_TEXTURE_2D, 0, RealOpenGLEnums.GL_TEXTURE_HEIGHT);
+ GlStateManager.bindTexture(j);
+ }
+
+ if (this.textureHeight <= 0) {
+ this.textureHeight = 16;
+ }
+ }
+
+ return (float) this.textureHeight;
+ }
+
+ public IBakedModel getBakedModel(ResourceLocation modelLocation, boolean fullModel) {
+ IBakedModel ibakedmodel;
+ Map < String, IBakedModel > map;
+
+ if (fullModel) {
+ ibakedmodel = this.bakedModelFull;
+ map = this.mapBakedModelsFull;
+ } else {
+ ibakedmodel = this.bakedModelTexture;
+ map = this.mapBakedModelsTexture;
+ }
+
+ if (modelLocation != null && map != null) {
+ String s = modelLocation.getResourcePath();
+ IBakedModel ibakedmodel1 = (IBakedModel) map.get(s);
+
+ if (ibakedmodel1 != null) {
+ return ibakedmodel1;
+ }
+ }
+
+ return ibakedmodel;
+ }
+
+ public void loadModels(ModelBakery modelBakery) {
+ if (this.model != null) {
+ loadItemModel(modelBakery, this.model);
+ }
+
+ if (this.type == 1 && this.mapModels != null) {
+ for (String s: this.mapModels.keySet()) {
+ String s1 = (String) this.mapModels.get(s);
+ String s2 = StrUtils.removePrefix(s, "model.");
+
+ if (s2.startsWith("bow") || s2.startsWith("fishing_rod") || s2.startsWith("shield")) {
+ loadItemModel(modelBakery, s1);
+ }
+ }
+ }
+ }
+
+ public void updateModelsFull() {
+ ModelManager modelmanager = Config.getModelManager();
+ IBakedModel ibakedmodel = modelmanager.getMissingModel();
+
+ if (this.model != null) {
+ ResourceLocation resourcelocation = getModelLocation(this.model);
+ ModelResourceLocation modelresourcelocation = new ModelResourceLocation(resourcelocation, "inventory");
+ this.bakedModelFull = modelmanager.getModel(modelresourcelocation);
+
+ if (this.bakedModelFull == ibakedmodel) {
+ Config.warn("Custom Items: Model not found " + modelresourcelocation.getResourcePath());
+ this.bakedModelFull = null;
+ }
+ }
+
+ if (this.type == 1 && this.mapModels != null) {
+ for (String s: this.mapModels.keySet()) {
+ String s1 = (String) this.mapModels.get(s);
+ String s2 = StrUtils.removePrefix(s, "model.");
+
+ if (s2.startsWith("bow") || s2.startsWith("fishing_rod") || s2.startsWith("shield")) {
+ ResourceLocation resourcelocation1 = getModelLocation(s1);
+ ModelResourceLocation modelresourcelocation1 = new ModelResourceLocation(resourcelocation1, "inventory");
+ IBakedModel ibakedmodel1 = modelmanager.getModel(modelresourcelocation1);
+
+ if (ibakedmodel1 == ibakedmodel) {
+ Config.warn("Custom Items: Model not found " + modelresourcelocation1.getResourcePath());
+ } else {
+ if (this.mapBakedModelsFull == null) {
+ this.mapBakedModelsFull = new HashMap();
+ }
+
+ this.mapBakedModelsFull.put(s2, ibakedmodel1);
+ }
+ }
+ }
+ }
+ }
+
+ private static void loadItemModel(ModelBakery modelBakery, String model) {
+ ResourceLocation resourcelocation = getModelLocation(model);
+ ModelResourceLocation modelresourcelocation = new ModelResourceLocation(resourcelocation, "inventory");
+ modelBakery.loadItemModel(resourcelocation.toString(), modelresourcelocation, resourcelocation);
+ }
+
+ private static void checkNull(Object obj, String msg) throws NullPointerException {
+ if (obj == null) {
+ throw new NullPointerException(msg);
+ }
+ }
+
+ private static ResourceLocation getModelLocation(String modelName) {
+ return new ResourceLocation(modelName);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/PeytonPlayz585/shadow/CustomItems.java b/src/main/java/net/PeytonPlayz585/shadow/CustomItems.java
new file mode 100644
index 0000000..c9678fd
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/CustomItems.java
@@ -0,0 +1,841 @@
+package net.PeytonPlayz585.shadow;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.model.ModelBase;
+import net.minecraft.client.renderer.block.model.ItemModelGenerator;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.client.renderer.texture.TextureManager;
+import net.minecraft.client.renderer.texture.TextureMap;
+import net.minecraft.client.resources.IResourcePack;
+import net.minecraft.client.resources.model.IBakedModel;
+import net.minecraft.client.resources.model.ModelBakery;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemArmor;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.potion.Potion;
+import net.minecraft.util.ResourceLocation;
+
+public class CustomItems {
+ private static CustomItemProperties[][] itemProperties = (CustomItemProperties[][]) null;
+ private static CustomItemProperties[][] enchantmentProperties = (CustomItemProperties[][]) null;
+ private static Map mapPotionIds = null;
+ private static ItemModelGenerator itemModelGenerator = new ItemModelGenerator();
+ private static boolean useGlint = true;
+ private static boolean renderOffHand = false;
+ public static final int MASK_POTION_SPLASH = 16384;
+ public static final int MASK_POTION_NAME = 63;
+ public static final int MASK_POTION_EXTENDED = 64;
+ public static final String KEY_TEXTURE_OVERLAY = "texture.potion_overlay";
+ public static final String KEY_TEXTURE_SPLASH = "texture.potion_bottle_splash";
+ public static final String KEY_TEXTURE_DRINKABLE = "texture.potion_bottle_drinkable";
+ public static final String DEFAULT_TEXTURE_OVERLAY = "items/potion_overlay";
+ public static final String DEFAULT_TEXTURE_SPLASH = "items/potion_bottle_splash";
+ public static final String DEFAULT_TEXTURE_DRINKABLE = "items/potion_bottle_drinkable";
+ private static final int[][] EMPTY_INT2_ARRAY = new int[0][];
+ private static final String TYPE_POTION_NORMAL = "normal";
+ private static final String TYPE_POTION_SPLASH = "splash";
+ private static final String TYPE_POTION_LINGER = "linger";
+
+ public static void update() {
+ itemProperties = (CustomItemProperties[][]) null;
+ enchantmentProperties = (CustomItemProperties[][]) null;
+ useGlint = true;
+
+ if (Config.isCustomItems()) {
+ readCitProperties("mcpatcher/cit.properties");
+ IResourcePack[] airesourcepack = Config.getResourcePacks();
+
+ for (int i = airesourcepack.length - 1; i >= 0; --i) {
+ IResourcePack iresourcepack = airesourcepack[i];
+ update(iresourcepack);
+ }
+
+ update(Config.getDefaultResourcePack());
+
+ if (itemProperties.length <= 0) {
+ itemProperties = (CustomItemProperties[][]) null;
+ }
+
+ if (enchantmentProperties.length <= 0) {
+ enchantmentProperties = (CustomItemProperties[][]) null;
+ }
+ }
+ }
+
+ private static void readCitProperties(String fileName) {
+ try {
+ ResourceLocation resourcelocation = new ResourceLocation(fileName);
+ InputStream inputstream = Config.getResourceStream(resourcelocation);
+
+ if (inputstream == null) {
+ return;
+ }
+
+ Config.dbg("CustomItems: Loading " + fileName);
+ Properties properties = new PropertiesOrdered();
+ properties.load(inputstream);
+ inputstream.close();
+ useGlint = Config.parseBoolean(properties.getProperty("useGlint"), true);
+ } catch (FileNotFoundException var4) {
+ return;
+ } catch (IOException ioexception) {
+ ioexception.printStackTrace();
+ }
+ }
+
+ private static void update(IResourcePack rp) {
+ String[] astring = ResUtils.collectFiles(rp, (String)
+ "mcpatcher/cit/", (String)
+ ".properties", (String[]) null);
+ Map map = makeAutoImageProperties(rp);
+
+ if (map.size() > 0) {
+ Set set = map.keySet();
+ String[] astring1 = (String[])((String[]) set.toArray(new String[set.size()]));
+ astring = (String[])((String[]) Config.addObjectsToArray(astring, astring1));
+ }
+
+ Arrays.sort((Object[]) astring);
+ List list = makePropertyList(itemProperties);
+ List list1 = makePropertyList(enchantmentProperties);
+
+ for (int i = 0; i < astring.length; ++i) {
+ String s = astring[i];
+ Config.dbg("CustomItems: " + s);
+
+ try {
+ CustomItemProperties customitemproperties = null;
+
+ if (map.containsKey(s)) {
+ customitemproperties = (CustomItemProperties) map.get(s);
+ }
+
+ if (customitemproperties == null) {
+ ResourceLocation resourcelocation = new ResourceLocation(s);
+ InputStream inputstream = rp.getInputStream(resourcelocation);
+
+ if (inputstream == null) {
+ Config.warn("CustomItems file not found: " + s);
+ continue;
+ }
+
+ Properties properties = new PropertiesOrdered();
+ properties.load(inputstream);
+ inputstream.close();
+ customitemproperties = new CustomItemProperties(properties, s);
+ }
+
+ if (customitemproperties.isValid(s)) {
+ addToItemList(customitemproperties, list);
+ addToEnchantmentList(customitemproperties, list1);
+ }
+ } catch (FileNotFoundException var11) {
+ Config.warn("CustomItems file not found: " + s);
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ itemProperties = propertyListToArray(list);
+ enchantmentProperties = propertyListToArray(list1);
+ Comparator comparator = getPropertiesComparator();
+
+ for (int j = 0; j < itemProperties.length; ++j) {
+ CustomItemProperties[] acustomitemproperties = itemProperties[j];
+
+ if (acustomitemproperties != null) {
+ Arrays.sort(acustomitemproperties, comparator);
+ }
+ }
+
+ for (int k = 0; k < enchantmentProperties.length; ++k) {
+ CustomItemProperties[] acustomitemproperties1 = enchantmentProperties[k];
+
+ if (acustomitemproperties1 != null) {
+ Arrays.sort(acustomitemproperties1, comparator);
+ }
+ }
+ }
+
+ private static Comparator getPropertiesComparator() {
+ Comparator comparator = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ CustomItemProperties customitemproperties = (CustomItemProperties) o1;
+ CustomItemProperties customitemproperties1 = (CustomItemProperties) o2;
+ return customitemproperties.layer != customitemproperties1.layer ? customitemproperties.layer - customitemproperties1.layer : (customitemproperties.weight != customitemproperties1.weight ? customitemproperties1.weight - customitemproperties.weight : (!customitemproperties.basePath.equals(customitemproperties1.basePath) ? customitemproperties.basePath.compareTo(customitemproperties1.basePath) : customitemproperties.name.compareTo(customitemproperties1.name)));
+ }
+ };
+ return comparator;
+ }
+
+ public static void updateIcons(TextureMap textureMap) {
+ for (CustomItemProperties customitemproperties: getAllProperties()) {
+ customitemproperties.updateIcons(textureMap);
+ }
+ }
+
+ public static void loadModels(ModelBakery modelBakery) {
+ for (CustomItemProperties customitemproperties: getAllProperties()) {
+ customitemproperties.loadModels(modelBakery);
+ }
+ }
+
+ public static void updateModels() {
+ for (CustomItemProperties customitemproperties: getAllProperties()) {
+ if (customitemproperties.type == 1) {
+ TextureMap texturemap = Minecraft.getMinecraft().getTextureMapBlocks();
+ customitemproperties.updateModelTexture(texturemap, itemModelGenerator);
+ customitemproperties.updateModelsFull();
+ }
+ }
+ }
+
+ private static List < CustomItemProperties > getAllProperties() {
+ List < CustomItemProperties > list = new ArrayList();
+ addAll(itemProperties, list);
+ addAll(enchantmentProperties, list);
+ return list;
+ }
+
+ private static void addAll(CustomItemProperties[][] cipsArr, List < CustomItemProperties > list) {
+ if (cipsArr != null) {
+ for (int i = 0; i < cipsArr.length; ++i) {
+ CustomItemProperties[] acustomitemproperties = cipsArr[i];
+
+ if (acustomitemproperties != null) {
+ for (int j = 0; j < acustomitemproperties.length; ++j) {
+ CustomItemProperties customitemproperties = acustomitemproperties[j];
+
+ if (customitemproperties != null) {
+ list.add(customitemproperties);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static Map makeAutoImageProperties(IResourcePack rp) {
+ Map map = new HashMap();
+ map.putAll(makePotionImageProperties(rp, "normal", Item.getIdFromItem(Items.potionitem)));
+ map.putAll(makePotionImageProperties(rp, "splash", Item.getIdFromItem(Items.potionitem)));
+ map.putAll(makePotionImageProperties(rp, "linger", Item.getIdFromItem(Items.potionitem)));
+ return map;
+ }
+
+ private static Map makePotionImageProperties(IResourcePack rp, String type, int itemId) {
+ Map map = new HashMap();
+ String s = type + "/";
+ String[] astring = new String[] {
+ "mcpatcher/cit/potion/" + s, "mcpatcher/cit/Potion/" + s
+ };
+ String[] astring1 = new String[] {
+ ".png"
+ };
+ String[] astring2 = ResUtils.collectFiles(rp, astring, astring1);
+
+ for (int i = 0; i < astring2.length; ++i) {
+ String s1 = astring2[i];
+ String name = StrUtils.removePrefixSuffix(s1, astring, astring1);
+ Properties properties = makePotionProperties(name, type, itemId, s1);
+
+ if (properties != null) {
+ String s3 = StrUtils.removeSuffix(s1, astring1) + ".properties";
+ CustomItemProperties customitemproperties = new CustomItemProperties(properties, s3);
+ map.put(s3, customitemproperties);
+ }
+ }
+
+ return map;
+ }
+
+ private static Properties makePotionProperties(String name, String type, int itemId, String path) {
+ if (StrUtils.endsWith(name, new String[] {
+ "_n",
+ "_s"
+ })) {
+ return null;
+ } else if (name.equals("empty") && type.equals("normal")) {
+ itemId = Item.getIdFromItem(Items.glass_bottle);
+ Properties properties = new PropertiesOrdered();
+ properties.put("type", "item");
+ properties.put("items", "" + itemId);
+ return properties;
+ } else {
+ int[] aint = (int[])((int[]) getMapPotionIds().get(name));
+
+ if (aint == null) {
+ Config.warn("Potion not found for image: " + path);
+ return null;
+ } else {
+ StringBuffer stringbuffer = new StringBuffer();
+
+ for (int i = 0; i < aint.length; ++i) {
+ int j = aint[i];
+
+ if (type.equals("splash")) {
+ j |= 16384;
+ }
+
+ if (i > 0) {
+ stringbuffer.append(" ");
+ }
+
+ stringbuffer.append(j);
+ }
+
+ int k = 16447;
+
+ if (name.equals("water") || name.equals("mundane")) {
+ k |= 64;
+ }
+
+ Properties properties1 = new PropertiesOrdered();
+ properties1.put("type", "item");
+ properties1.put("items", "" + itemId);
+ properties1.put("damage", "" + stringbuffer.toString());
+ properties1.put("damageMask", "" + k);
+
+ if (type.equals("splash")) {
+ properties1.put("texture.potion_bottle_splash", name);
+ } else {
+ properties1.put("texture.potion_bottle_drinkable", name);
+ }
+
+ return properties1;
+ }
+ }
+ }
+
+ private static Map getMapPotionIds() {
+ if (mapPotionIds == null) {
+ mapPotionIds = new LinkedHashMap();
+ mapPotionIds.put("water", getPotionId(0, 0));
+ mapPotionIds.put("awkward", getPotionId(0, 1));
+ mapPotionIds.put("thick", getPotionId(0, 2));
+ mapPotionIds.put("potent", getPotionId(0, 3));
+ mapPotionIds.put("regeneration", getPotionIds(1));
+ mapPotionIds.put("movespeed", getPotionIds(2));
+ mapPotionIds.put("fireresistance", getPotionIds(3));
+ mapPotionIds.put("poison", getPotionIds(4));
+ mapPotionIds.put("heal", getPotionIds(5));
+ mapPotionIds.put("nightvision", getPotionIds(6));
+ mapPotionIds.put("clear", getPotionId(7, 0));
+ mapPotionIds.put("bungling", getPotionId(7, 1));
+ mapPotionIds.put("charming", getPotionId(7, 2));
+ mapPotionIds.put("rank", getPotionId(7, 3));
+ mapPotionIds.put("weakness", getPotionIds(8));
+ mapPotionIds.put("damageboost", getPotionIds(9));
+ mapPotionIds.put("moveslowdown", getPotionIds(10));
+ mapPotionIds.put("leaping", getPotionIds(11));
+ mapPotionIds.put("harm", getPotionIds(12));
+ mapPotionIds.put("waterbreathing", getPotionIds(13));
+ mapPotionIds.put("invisibility", getPotionIds(14));
+ mapPotionIds.put("thin", getPotionId(15, 0));
+ mapPotionIds.put("debonair", getPotionId(15, 1));
+ mapPotionIds.put("sparkling", getPotionId(15, 2));
+ mapPotionIds.put("stinky", getPotionId(15, 3));
+ mapPotionIds.put("mundane", getPotionId(0, 4));
+ mapPotionIds.put("speed", mapPotionIds.get("movespeed"));
+ mapPotionIds.put("fire_resistance", mapPotionIds.get("fireresistance"));
+ mapPotionIds.put("instant_health", mapPotionIds.get("heal"));
+ mapPotionIds.put("night_vision", mapPotionIds.get("nightvision"));
+ mapPotionIds.put("strength", mapPotionIds.get("damageboost"));
+ mapPotionIds.put("slowness", mapPotionIds.get("moveslowdown"));
+ mapPotionIds.put("instant_damage", mapPotionIds.get("harm"));
+ mapPotionIds.put("water_breathing", mapPotionIds.get("waterbreathing"));
+ }
+
+ return mapPotionIds;
+ }
+
+ private static int[] getPotionIds(int baseId) {
+ return new int[] {
+ baseId,
+ baseId + 16,
+ baseId + 32,
+ baseId + 48
+ };
+ }
+
+ private static int[] getPotionId(int baseId, int subId) {
+ return new int[] {
+ baseId + subId * 16
+ };
+ }
+
+ private static int getPotionNameDamage(String name) {
+ String s = "potion." + name;
+ Potion[] apotion = Potion.potionTypes;
+
+ for (int i = 0; i < apotion.length; ++i) {
+ Potion potion = apotion[i];
+
+ if (potion != null) {
+ String s1 = potion.getName();
+
+ if (s.equals(s1)) {
+ return potion.getId();
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ private static List makePropertyList(CustomItemProperties[][] propsArr) {
+ List list = new ArrayList();
+
+ if (propsArr != null) {
+ for (int i = 0; i < propsArr.length; ++i) {
+ CustomItemProperties[] acustomitemproperties = propsArr[i];
+ List list1 = null;
+
+ if (acustomitemproperties != null) {
+ list1 = new ArrayList(Arrays.asList(acustomitemproperties));
+ }
+
+ list.add(list1);
+ }
+ }
+
+ return list;
+ }
+
+ private static CustomItemProperties[][] propertyListToArray(List list) {
+ CustomItemProperties[][] acustomitemproperties = new CustomItemProperties[list.size()][];
+
+ for (int i = 0; i < list.size(); ++i) {
+ List list1 = (List) list.get(i);
+
+ if (list1 != null) {
+ CustomItemProperties[] acustomitemproperties1 = (CustomItemProperties[])((CustomItemProperties[]) list1.toArray(new CustomItemProperties[list1.size()]));
+ Arrays.sort(acustomitemproperties1, new CustomItemsComparator());
+ acustomitemproperties[i] = acustomitemproperties1;
+ }
+ }
+
+ return acustomitemproperties;
+ }
+
+ private static void addToItemList(CustomItemProperties cp, List itemList) {
+ if (cp.items != null) {
+ for (int i = 0; i < cp.items.length; ++i) {
+ int j = cp.items[i];
+
+ if (j <= 0) {
+ Config.warn("Invalid item ID: " + j);
+ } else {
+ addToList(cp, itemList, j);
+ }
+ }
+ }
+ }
+
+ private static void addToEnchantmentList(CustomItemProperties cp, List enchantmentList) {
+ if (cp.type == 2) {
+ if (cp.enchantmentIds != null) {
+ for (int i = 0; i < 256; ++i) {
+ if (cp.enchantmentIds.isInRange(i)) {
+ addToList(cp, enchantmentList, i);
+ }
+ }
+ }
+ }
+ }
+
+ private static void addToList(CustomItemProperties cp, List list, int id) {
+ while (id >= list.size()) {
+ list.add(null);
+ }
+
+ List list1 = (List) list.get(id);
+
+ if (list1 == null) {
+ list1 = new ArrayList();
+ list.set(id, list1);
+ }
+
+ list1.add(cp);
+ }
+
+ public static IBakedModel getCustomItemModel(ItemStack itemStack, IBakedModel model, ResourceLocation modelLocation, boolean fullModel) {
+ if (!fullModel && model.isGui3d()) {
+ return model;
+ } else if (itemProperties == null) {
+ return model;
+ } else {
+ CustomItemProperties customitemproperties = getCustomItemProperties(itemStack, 1);
+
+ if (customitemproperties == null) {
+ return model;
+ } else {
+ IBakedModel ibakedmodel = customitemproperties.getBakedModel(modelLocation, fullModel);
+ return ibakedmodel != null ? ibakedmodel : model;
+ }
+ }
+ }
+
+ public static boolean bindCustomArmorTexture(ItemStack itemStack, int layer, String overlay) {
+ if (itemProperties == null) {
+ return false;
+ } else {
+ ResourceLocation resourcelocation = getCustomArmorLocation(itemStack, layer, overlay);
+
+ if (resourcelocation == null) {
+ return false;
+ } else {
+ Config.getTextureManager().bindTexture(resourcelocation);
+ return true;
+ }
+ }
+ }
+
+ private static ResourceLocation getCustomArmorLocation(ItemStack itemStack, int layer, String overlay) {
+ CustomItemProperties customitemproperties = getCustomItemProperties(itemStack, 3);
+
+ if (customitemproperties == null) {
+ return null;
+ } else if (customitemproperties.mapTextureLocations == null) {
+ return customitemproperties.textureLocation;
+ } else {
+ Item item = itemStack.getItem();
+
+ if (!(item instanceof ItemArmor)) {
+ return null;
+ } else {
+ ItemArmor itemarmor = (ItemArmor) item;
+ String s = itemarmor.getArmorMaterial().getName();
+ StringBuffer stringbuffer = new StringBuffer();
+ stringbuffer.append("texture.");
+ stringbuffer.append(s);
+ stringbuffer.append("_layer_");
+ stringbuffer.append(layer);
+
+ if (overlay != null) {
+ stringbuffer.append("_");
+ stringbuffer.append(overlay);
+ }
+
+ String s1 = stringbuffer.toString();
+ ResourceLocation resourcelocation = (ResourceLocation) customitemproperties.mapTextureLocations.get(s1);
+ return resourcelocation == null ? customitemproperties.textureLocation : resourcelocation;
+ }
+ }
+ }
+
+ private static CustomItemProperties getCustomItemProperties(ItemStack itemStack, int type) {
+ if (itemProperties == null) {
+ return null;
+ } else if (itemStack == null) {
+ return null;
+ } else {
+ Item item = itemStack.getItem();
+ int i = Item.getIdFromItem(item);
+
+ if (i >= 0 && i < itemProperties.length) {
+ CustomItemProperties[] acustomitemproperties = itemProperties[i];
+
+ if (acustomitemproperties != null) {
+ for (int j = 0; j < acustomitemproperties.length; ++j) {
+ CustomItemProperties customitemproperties = acustomitemproperties[j];
+
+ if (customitemproperties.type == type && matchesProperties(customitemproperties, itemStack, (int[][]) null)) {
+ return customitemproperties;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+
+ private static boolean matchesProperties(CustomItemProperties cip, ItemStack itemStack, int[][] enchantmentIdLevels) {
+ Item item = itemStack.getItem();
+
+ if (cip.damage != null) {
+ int i = itemStack.getItemDamage();
+
+ if (cip.damageMask != 0) {
+ i &= cip.damageMask;
+ }
+
+ if (cip.damagePercent) {
+ int j = item.getMaxDamage();
+ i = (int)((double)(i * 100) / (double) j);
+ }
+
+ if (!cip.damage.isInRange(i)) {
+ return false;
+ }
+ }
+
+ if (cip.stackSize != null && !cip.stackSize.isInRange(itemStack.stackSize)) {
+ return false;
+ } else {
+ int[][] aint = enchantmentIdLevels;
+
+ if (cip.enchantmentIds != null) {
+ if (enchantmentIdLevels == null) {
+ aint = getEnchantmentIdLevels(itemStack);
+ }
+
+ boolean flag = false;
+
+ for (int k = 0; k < aint.length; ++k) {
+ int l = aint[k][0];
+
+ if (cip.enchantmentIds.isInRange(l)) {
+ flag = true;
+ break;
+ }
+ }
+
+ if (!flag) {
+ return false;
+ }
+ }
+
+ if (cip.enchantmentLevels != null) {
+ if (aint == null) {
+ aint = getEnchantmentIdLevels(itemStack);
+ }
+
+ boolean flag1 = false;
+
+ for (int i1 = 0; i1 < aint.length; ++i1) {
+ int k1 = aint[i1][1];
+
+ if (cip.enchantmentLevels.isInRange(k1)) {
+ flag1 = true;
+ break;
+ }
+ }
+
+ if (!flag1) {
+ return false;
+ }
+ }
+
+ if (cip.nbtTagValues != null) {
+ NBTTagCompound nbttagcompound = itemStack.getTagCompound();
+
+ for (int j1 = 0; j1 < cip.nbtTagValues.length; ++j1) {
+ NbtTagValue nbttagvalue = cip.nbtTagValues[j1];
+
+ if (!nbttagvalue.matches(nbttagcompound)) {
+ return false;
+ }
+ }
+ }
+
+ if (cip.hand != 0) {
+ if (cip.hand == 1 && renderOffHand) {
+ return false;
+ }
+
+ if (cip.hand == 2 && !renderOffHand) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ private static int[][] getEnchantmentIdLevels(ItemStack itemStack) {
+ Item item = itemStack.getItem();
+ NBTTagList nbttaglist = item == Items.enchanted_book ? Items.enchanted_book.getEnchantments(itemStack) : itemStack.getEnchantmentTagList();
+
+ if (nbttaglist != null && nbttaglist.tagCount() > 0) {
+ int[][] aint = new int[nbttaglist.tagCount()][2];
+
+ for (int i = 0; i < nbttaglist.tagCount(); ++i) {
+ NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
+ int j = nbttagcompound.getShort("id");
+ int k = nbttagcompound.getShort("lvl");
+ aint[i][0] = j;
+ aint[i][1] = k;
+ }
+
+ return aint;
+ } else {
+ return EMPTY_INT2_ARRAY;
+ }
+ }
+
+ public static boolean renderCustomEffect(RenderItem renderItem, ItemStack itemStack, IBakedModel model) {
+ if (enchantmentProperties == null) {
+ return false;
+ } else if (itemStack == null) {
+ return false;
+ } else {
+ int[][] aint = getEnchantmentIdLevels(itemStack);
+
+ if (aint.length <= 0) {
+ return false;
+ } else {
+ Set set = null;
+ boolean flag = false;
+ TextureManager texturemanager = Config.getTextureManager();
+
+ for (int i = 0; i < aint.length; ++i) {
+ int j = aint[i][0];
+
+ if (j >= 0 && j < enchantmentProperties.length) {
+ CustomItemProperties[] acustomitemproperties = enchantmentProperties[j];
+
+ if (acustomitemproperties != null) {
+ for (int k = 0; k < acustomitemproperties.length; ++k) {
+ CustomItemProperties customitemproperties = acustomitemproperties[k];
+
+ if (set == null) {
+ set = new HashSet();
+ }
+
+ if (set.add(Integer.valueOf(j)) && matchesProperties(customitemproperties, itemStack, aint) && customitemproperties.textureLocation != null) {
+ texturemanager.bindTexture(customitemproperties.textureLocation);
+ float f = customitemproperties.getTextureWidth(texturemanager);
+
+ if (!flag) {
+ flag = true;
+ GlStateManager.depthMask(false);
+ GlStateManager.depthFunc(514);
+ GlStateManager.disableLighting();
+ GlStateManager.matrixMode(5890);
+ }
+
+ Blender.setupBlend(customitemproperties.blend, 1.0F);
+ GlStateManager.pushMatrix();
+ GlStateManager.scale(f / 2.0F, f / 2.0F, f / 2.0F);
+ float f1 = customitemproperties.speed * (float)(Minecraft.getSystemTime() % 3000L) / 3000.0F / 8.0F;
+ GlStateManager.translate(f1, 0.0F, 0.0F);
+ GlStateManager.rotate(customitemproperties.rotation, 0.0F, 0.0F, 1.0F);
+ renderItem.renderModel(model, -1);
+ GlStateManager.popMatrix();
+ }
+ }
+ }
+ }
+ }
+
+ if (flag) {
+ GlStateManager.enableAlpha();
+ GlStateManager.enableBlend();
+ GlStateManager.blendFunc(770, 771);
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ GlStateManager.matrixMode(5888);
+ GlStateManager.enableLighting();
+ GlStateManager.depthFunc(515);
+ GlStateManager.depthMask(true);
+ texturemanager.bindTexture(TextureMap.locationBlocksTexture);
+ }
+
+ return flag;
+ }
+ }
+ }
+
+ public static boolean renderCustomArmorEffect(EntityLivingBase entity, ItemStack itemStack, ModelBase model, float limbSwing, float prevLimbSwing, float partialTicks, float timeLimbSwing, float yaw, float pitch, float scale) {
+ if (enchantmentProperties == null) {
+ return false;
+ } else if (Config.isShaders()) {
+ return false;
+ } else if (itemStack == null) {
+ return false;
+ } else {
+ int[][] aint = getEnchantmentIdLevels(itemStack);
+
+ if (aint.length <= 0) {
+ return false;
+ } else {
+ Set set = null;
+ boolean flag = false;
+ TextureManager texturemanager = Config.getTextureManager();
+
+ for (int i = 0; i < aint.length; ++i) {
+ int j = aint[i][0];
+
+ if (j >= 0 && j < enchantmentProperties.length) {
+ CustomItemProperties[] acustomitemproperties = enchantmentProperties[j];
+
+ if (acustomitemproperties != null) {
+ for (int k = 0; k < acustomitemproperties.length; ++k) {
+ CustomItemProperties customitemproperties = acustomitemproperties[k];
+
+ if (set == null) {
+ set = new HashSet();
+ }
+
+ if (set.add(Integer.valueOf(j)) && matchesProperties(customitemproperties, itemStack, aint) && customitemproperties.textureLocation != null) {
+ texturemanager.bindTexture(customitemproperties.textureLocation);
+ float f = customitemproperties.getTextureWidth(texturemanager);
+
+ if (!flag) {
+ flag = true;
+
+ GlStateManager.enableBlend();
+ GlStateManager.depthFunc(514);
+ GlStateManager.depthMask(false);
+ }
+
+ Blender.setupBlend(customitemproperties.blend, 1.0F);
+ GlStateManager.disableLighting();
+ GlStateManager.matrixMode(5890);
+ GlStateManager.loadIdentity();
+ GlStateManager.rotate(customitemproperties.rotation, 0.0F, 0.0F, 1.0F);
+ float f1 = f / 8.0F;
+ GlStateManager.scale(f1, f1 / 2.0F, f1);
+ float f2 = customitemproperties.speed * (float)(Minecraft.getSystemTime() % 3000L) / 3000.0F / 8.0F;
+ GlStateManager.translate(0.0F, f2, 0.0F);
+ GlStateManager.matrixMode(5888);
+ model.render(entity, limbSwing, prevLimbSwing, timeLimbSwing, yaw, pitch, scale);
+ }
+ }
+ }
+ }
+ }
+
+ if (flag) {
+ GlStateManager.enableAlpha();
+ GlStateManager.enableBlend();
+ GlStateManager.blendFunc(770, 771);
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ GlStateManager.matrixMode(5890);
+ GlStateManager.loadIdentity();
+ GlStateManager.matrixMode(5888);
+ GlStateManager.enableLighting();
+ GlStateManager.depthMask(true);
+ GlStateManager.depthFunc(515);
+ GlStateManager.disableBlend();
+ }
+
+ return flag;
+ }
+ }
+ }
+
+ public static boolean isUseGlint() {
+ return useGlint;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/PeytonPlayz585/shadow/CustomItemsComparator.java b/src/main/java/net/PeytonPlayz585/shadow/CustomItemsComparator.java
new file mode 100644
index 0000000..8f0a7bd
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/CustomItemsComparator.java
@@ -0,0 +1,11 @@
+package net.PeytonPlayz585.shadow;
+
+import java.util.Comparator;
+
+public class CustomItemsComparator implements Comparator {
+ public int compare(Object o1, Object o2) {
+ CustomItemProperties customitemproperties = (CustomItemProperties)o1;
+ CustomItemProperties customitemproperties1 = (CustomItemProperties)o2;
+ return customitemproperties.weight != customitemproperties1.weight ? customitemproperties1.weight - customitemproperties.weight : (!Config.equals(customitemproperties.basePath, customitemproperties1.basePath) ? customitemproperties.basePath.compareTo(customitemproperties1.basePath) : customitemproperties.name.compareTo(customitemproperties1.name));
+ }
+}
diff --git a/src/main/java/net/PeytonPlayz585/shadow/EntityArrays.java b/src/main/java/net/PeytonPlayz585/shadow/EntityArrays.java
new file mode 100644
index 0000000..c8dc15a
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/EntityArrays.java
@@ -0,0 +1,30 @@
+package net.PeytonPlayz585.shadow;
+
+public class EntityArrays {
+
+ private static final String[][] JAVA_CTRL_CHARS_ESCAPE = {{"\b", "\\b"}, {"\n", "\\n"}, {"\t", "\\t"}, {"\f", "\\f"}, {"\r", "\\r"}};
+
+ private static final String[][] JAVA_CTRL_CHARS_UNESCAPE = invert(JAVA_CTRL_CHARS_ESCAPE);
+
+ /**
+ * Used to invert an escape array into an unescape array
+ * @param array String[][] to be inverted
+ * @return String[][] inverted array
+ */
+ public static String[][] invert(final String[][] array) {
+ final String[][] newarray = new String[array.length][2];
+ for (int i = 0; i
+ * LookupTranslator instead
+ */
+@Deprecated
+public class LookupTranslator extends CharSequenceTranslator {
+
+ private final HashMap lookupMap;
+ private final HashSet prefixSet;
+ private final int shortest;
+ private final int longest;
+
+ /**
+ * Define the lookup table to be used in translation
+ *
+ * Note that, as of Lang 3.1, the key to the lookup table is converted to a
+ * java.lang.String. This is because we need the key to support hashCode and
+ * equals(Object), allowing it to be the key for a HashMap. See LANG-882.
+ *
+ * @param lookup CharSequence[][] table of size [*][2]
+ */
+ public LookupTranslator(final CharSequence[]... lookup) {
+ lookupMap = new HashMap<>();
+ prefixSet = new HashSet<>();
+ int tmpShortest = Integer.MAX_VALUE;
+ int tmpLongest = 0;
+ if (lookup != null) {
+ for (final CharSequence[] seq : lookup) {
+ this.lookupMap.put(seq[0].toString(), seq[1].toString());
+ this.prefixSet.add(seq[0].charAt(0));
+ final int sz = seq[0].length();
+ if (sz < tmpShortest) {
+ tmpShortest = sz;
+ }
+ if (sz > tmpLongest) {
+ tmpLongest = sz;
+ }
+ }
+ }
+ this.shortest = tmpShortest;
+ this.longest = tmpLongest;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
+ // check if translation exists for the input at position index
+ if (prefixSet.contains(input.charAt(index))) {
+ int max = longest;
+ if (index + longest > input.length()) {
+ max = input.length() - index;
+ }
+ // implement greedy algorithm by trying maximum match first
+ for (int i = max; i >= shortest; i--) {
+ final CharSequence subSeq = input.subSequence(index, index + i);
+ final String result = lookupMap.get(subSeq.toString());
+
+ if (result != null) {
+ out.write(result);
+ return i;
+ }
+ }
+ }
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/PeytonPlayz585/shadow/NbtTagValue.java b/src/main/java/net/PeytonPlayz585/shadow/NbtTagValue.java
new file mode 100644
index 0000000..69c9aa3
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/NbtTagValue.java
@@ -0,0 +1,214 @@
+package net.PeytonPlayz585.shadow;
+
+import java.util.Arrays;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagByte;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagDouble;
+import net.minecraft.nbt.NBTTagFloat;
+import net.minecraft.nbt.NBTTagInt;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.NBTTagLong;
+import net.minecraft.nbt.NBTTagShort;
+import net.minecraft.nbt.NBTTagString;
+
+public class NbtTagValue {
+ private String[] parents = null;
+ private String name = null;
+ private int type = 0;
+ private String value = null;
+ private static final int TYPE_TEXT = 0;
+ private static final int TYPE_PATTERN = 1;
+ private static final int TYPE_IPATTERN = 2;
+ private static final int TYPE_REGEX = 3;
+ private static final int TYPE_IREGEX = 4;
+ private static final String PREFIX_PATTERN = "pattern:";
+ private static final String PREFIX_IPATTERN = "ipattern:";
+ private static final String PREFIX_REGEX = "regex:";
+ private static final String PREFIX_IREGEX = "iregex:";
+
+ public NbtTagValue(String p_i69_1_, String p_i69_2_) {
+ String[] astring = Config.tokenize(p_i69_1_, ".");
+ this.parents = (String[]) Arrays.copyOfRange(astring, 0, astring.length - 1);
+ this.name = astring[astring.length - 1];
+
+ if (p_i69_2_.startsWith("pattern:")) {
+ this.type = 1;
+ p_i69_2_ = p_i69_2_.substring("pattern:".length());
+ } else if (p_i69_2_.startsWith("ipattern:")) {
+ this.type = 2;
+ p_i69_2_ = p_i69_2_.substring("ipattern:".length()).toLowerCase();
+ } else if (p_i69_2_.startsWith("regex:")) {
+ this.type = 3;
+ p_i69_2_ = p_i69_2_.substring("regex:".length());
+ } else if (p_i69_2_.startsWith("iregex:")) {
+ this.type = 4;
+ p_i69_2_ = p_i69_2_.substring("iregex:".length()).toLowerCase();
+ } else {
+ this.type = 0;
+ }
+
+ p_i69_2_ = StringEscapeUtils.unescapeJava(p_i69_2_);
+ this.value = p_i69_2_;
+ }
+
+ public boolean matches(NBTTagCompound p_matches_1_) {
+ if (p_matches_1_ == null) {
+ return false;
+ } else {
+ NBTBase nbtbase = p_matches_1_;
+
+ for (int i = 0; i < this.parents.length; ++i) {
+ String s = this.parents[i];
+ nbtbase = getChildTag(nbtbase, s);
+
+ if (nbtbase == null) {
+ return false;
+ }
+ }
+
+ if (this.name.equals("*")) {
+ return this.matchesAnyChild(nbtbase);
+ } else {
+ nbtbase = getChildTag(nbtbase, this.name);
+
+ if (nbtbase == null) {
+ return false;
+ } else if (this.matches(nbtbase)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+
+ private boolean matchesAnyChild(NBTBase p_matchesAnyChild_1_) {
+ if (p_matchesAnyChild_1_ instanceof NBTTagCompound) {
+ NBTTagCompound nbttagcompound = (NBTTagCompound) p_matchesAnyChild_1_;
+
+ for (String s: nbttagcompound.getKeySet()) {
+ NBTBase nbtbase = nbttagcompound.getTag(s);
+
+ if (this.matches(nbtbase)) {
+ return true;
+ }
+ }
+ }
+
+ if (p_matchesAnyChild_1_ instanceof NBTTagList) {
+ NBTTagList nbttaglist = (NBTTagList) p_matchesAnyChild_1_;
+ int i = nbttaglist.tagCount();
+
+ for (int j = 0; j < i; ++j) {
+ NBTBase nbtbase1 = nbttaglist.get(j);
+
+ if (this.matches(nbtbase1)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private static NBTBase getChildTag(NBTBase p_getChildTag_0_, String p_getChildTag_1_) {
+ if (p_getChildTag_0_ instanceof NBTTagCompound) {
+ NBTTagCompound nbttagcompound = (NBTTagCompound) p_getChildTag_0_;
+ return nbttagcompound.getTag(p_getChildTag_1_);
+ } else if (p_getChildTag_0_ instanceof NBTTagList) {
+ NBTTagList nbttaglist = (NBTTagList) p_getChildTag_0_;
+ int i = Config.parseInt(p_getChildTag_1_, -1);
+ return i < 0 ? null : nbttaglist.get(i);
+ } else {
+ return null;
+ }
+ }
+
+ private boolean matches(NBTBase p_matches_1_) {
+ if (p_matches_1_ == null) {
+ return false;
+ } else {
+ String s = getValue(p_matches_1_);
+
+ if (s == null) {
+ return false;
+ } else {
+ switch (this.type) {
+ case 0:
+ return s.equals(this.value);
+ case 1:
+ return this.matchesPattern(s, this.value);
+ case 2:
+ return this.matchesPattern(s.toLowerCase(), this.value);
+ case 3:
+ return this.matchesRegex(s, this.value);
+ case 4:
+ return this.matchesRegex(s.toLowerCase(), this.value);
+ default:
+ throw new IllegalArgumentException("Unknown NbtTagValue type: " + this.type);
+ }
+ }
+ }
+ }
+
+ private boolean matchesPattern(String p_matchesPattern_1_, String p_matchesPattern_2_) {
+ return StrUtils.equalsMask(p_matchesPattern_1_, p_matchesPattern_2_, '*', '?');
+ }
+
+ private boolean matchesRegex(String p_matchesRegex_1_, String p_matchesRegex_2_) {
+ return p_matchesRegex_1_.matches(p_matchesRegex_2_);
+ }
+
+ private static String getValue(NBTBase p_getValue_0_) {
+ if (p_getValue_0_ == null) {
+ return null;
+ } else if (p_getValue_0_ instanceof NBTTagString) {
+ NBTTagString nbttagstring = (NBTTagString) p_getValue_0_;
+ return nbttagstring.getString();
+ } else if (p_getValue_0_ instanceof NBTTagInt) {
+ NBTTagInt nbttagint = (NBTTagInt) p_getValue_0_;
+ return Integer.toString(nbttagint.getInt());
+ } else if (p_getValue_0_ instanceof NBTTagByte) {
+ NBTTagByte nbttagbyte = (NBTTagByte) p_getValue_0_;
+ return Byte.toString(nbttagbyte.getByte());
+ } else if (p_getValue_0_ instanceof NBTTagShort) {
+ NBTTagShort nbttagshort = (NBTTagShort) p_getValue_0_;
+ return Short.toString(nbttagshort.getShort());
+ } else if (p_getValue_0_ instanceof NBTTagLong) {
+ NBTTagLong nbttaglong = (NBTTagLong) p_getValue_0_;
+ return Long.toString(nbttaglong.getLong());
+ } else if (p_getValue_0_ instanceof NBTTagFloat) {
+ NBTTagFloat nbttagfloat = (NBTTagFloat) p_getValue_0_;
+ return Float.toString(nbttagfloat.getFloat());
+ } else if (p_getValue_0_ instanceof NBTTagDouble) {
+ NBTTagDouble nbttagdouble = (NBTTagDouble) p_getValue_0_;
+ return Double.toString(nbttagdouble.getDouble());
+ } else {
+ return p_getValue_0_.toString();
+ }
+ }
+
+ public String toString() {
+ StringBuffer stringbuffer = new StringBuffer();
+
+ for (int i = 0; i < this.parents.length; ++i) {
+ String s = this.parents[i];
+
+ if (i > 0) {
+ stringbuffer.append(".");
+ }
+
+ stringbuffer.append(s);
+ }
+
+ if (stringbuffer.length() > 0) {
+ stringbuffer.append(".");
+ }
+
+ stringbuffer.append(this.name);
+ stringbuffer.append(" = ");
+ stringbuffer.append(this.value);
+ return stringbuffer.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/PeytonPlayz585/shadow/OctalUnescaper.java b/src/main/java/net/PeytonPlayz585/shadow/OctalUnescaper.java
new file mode 100644
index 0000000..b79a7c8
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/OctalUnescaper.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.PeytonPlayz585.shadow;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Translate escaped octal Strings back to their octal values.
+ *
+ * For example, "\45" should go back to being the specific value (a %).
+ *
+ * Note that this currently only supports the viable range of octal for Java; namely
+ * 1 to 377. This is because parsing Java is the main use case.
+ *
+ * @since 3.0
+ * @deprecated As of 3.6, use Apache Commons Text
+ *
+ * OctalUnescaper instead
+ */
+@Deprecated
+public class OctalUnescaper extends CharSequenceTranslator {
+
+ /**
+ * Checks if the given char is an octal digit. Octal digits are the character representations of the digits 0 to 7.
+ * @param ch the char to check
+ * @return true if the given char is the character representation of one of the digits from 0 to 7
+ */
+ private boolean isOctalDigit(final char ch) {
+ return ch >= '0' && ch <= '7';
+ }
+
+ /**
+ * Checks if the given char is the character representation of one of the digit from 0 to 3.
+ * @param ch the char to check
+ * @return true if the given char is the character representation of one of the digits from 0 to 3
+ */
+ private boolean isZeroToThree(final char ch) {
+ return ch >= '0' && ch <= '3';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
+ final int remaining = input.length() - index - 1; // how many characters left, ignoring the first \
+ final StringBuilder builder = new StringBuilder();
+ if (input.charAt(index) == '\\' && remaining > 0 && isOctalDigit(input.charAt(index + 1)) ) {
+ final int next = index + 1;
+ final int next2 = index + 2;
+ final int next3 = index + 3;
+
+ // we know this is good as we checked it in the if block above
+ builder.append(input.charAt(next));
+
+ if (remaining > 1 && isOctalDigit(input.charAt(next2))) {
+ builder.append(input.charAt(next2));
+ if (remaining > 2 && isZeroToThree(input.charAt(next)) && isOctalDigit(input.charAt(next3))) {
+ builder.append(input.charAt(next3));
+ }
+ }
+
+ out.write( Integer.parseInt(builder.toString(), 8) );
+ return 1 + builder.length();
+ }
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/PeytonPlayz585/shadow/ParserEnchantmentId.java b/src/main/java/net/PeytonPlayz585/shadow/ParserEnchantmentId.java
new file mode 100644
index 0000000..625afc4
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/ParserEnchantmentId.java
@@ -0,0 +1,10 @@
+package net.PeytonPlayz585.shadow;
+
+import net.minecraft.enchantment.Enchantment;
+
+public class ParserEnchantmentId implements IParserInt {
+ public int parse(String str, int defVal) {
+ Enchantment enchantment = Enchantment.getEnchantmentByLocation(str);
+ return enchantment == null ? defVal : enchantment.effectId;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/PeytonPlayz585/shadow/PropertiesOrdered.java b/src/main/java/net/PeytonPlayz585/shadow/PropertiesOrdered.java
new file mode 100644
index 0000000..4b9d260
--- /dev/null
+++ b/src/main/java/net/PeytonPlayz585/shadow/PropertiesOrdered.java
@@ -0,0 +1,26 @@
+package net.PeytonPlayz585.shadow;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.Properties;
+import java.util.Set;
+
+public class PropertiesOrdered extends Properties {
+ private Set