base mod created
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
package net.minecraft.client.util;
|
||||
|
||||
import java.util.List;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public interface ISearchTree<T>
|
||||
{
|
||||
/**
|
||||
* Searches this search tree for the given text.
|
||||
* <p>
|
||||
* If the query does not contain a <code>:</code>, then only {@link #byName} is searched; if it does contain a
|
||||
* colon, both {@link #byName} and {@link #byId} are searched and the results are merged using a {@link
|
||||
* MergingIterator}.
|
||||
* @return A list of all matching items in this search tree.
|
||||
*
|
||||
* @param searchText The text to search for. Must be normalized with <code>toLowerCase(Locale.ROOT)</code> before
|
||||
* calling this method.
|
||||
*/
|
||||
List<T> search(String searchText);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package net.minecraft.client.util;
|
||||
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public interface ITooltipFlag
|
||||
{
|
||||
boolean isAdvanced();
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public static enum TooltipFlags implements ITooltipFlag
|
||||
{
|
||||
NORMAL(false),
|
||||
ADVANCED(true);
|
||||
|
||||
final boolean isAdvanced;
|
||||
|
||||
private TooltipFlags(boolean advanced)
|
||||
{
|
||||
this.isAdvanced = advanced;
|
||||
}
|
||||
|
||||
public boolean isAdvanced()
|
||||
{
|
||||
return this.isAdvanced;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
package net.minecraft.client.util;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.Locale;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class JsonBlendingMode
|
||||
{
|
||||
private static JsonBlendingMode lastApplied;
|
||||
private final int srcColorFactor;
|
||||
private final int srcAlphaFactor;
|
||||
private final int destColorFactor;
|
||||
private final int destAlphaFactor;
|
||||
private final int blendFunction;
|
||||
private final boolean separateBlend;
|
||||
private final boolean opaque;
|
||||
|
||||
private JsonBlendingMode(boolean separateBlendIn, boolean opaqueIn, int srcColorFactorIn, int destColorFactorIn, int srcAlphaFactorIn, int destAlphaFactorIn, int blendFunctionIn)
|
||||
{
|
||||
this.separateBlend = separateBlendIn;
|
||||
this.srcColorFactor = srcColorFactorIn;
|
||||
this.destColorFactor = destColorFactorIn;
|
||||
this.srcAlphaFactor = srcAlphaFactorIn;
|
||||
this.destAlphaFactor = destAlphaFactorIn;
|
||||
this.opaque = opaqueIn;
|
||||
this.blendFunction = blendFunctionIn;
|
||||
}
|
||||
|
||||
public JsonBlendingMode()
|
||||
{
|
||||
this(false, true, 1, 0, 1, 0, 32774);
|
||||
}
|
||||
|
||||
public JsonBlendingMode(int srcFactor, int dstFactor, int blendFunctionIn)
|
||||
{
|
||||
this(false, false, srcFactor, dstFactor, srcFactor, dstFactor, blendFunctionIn);
|
||||
}
|
||||
|
||||
public JsonBlendingMode(int srcColorFactorIn, int destColorFactorIn, int srcAlphaFactorIn, int destAlphaFactorIn, int blendFunctionIn)
|
||||
{
|
||||
this(true, false, srcColorFactorIn, destColorFactorIn, srcAlphaFactorIn, destAlphaFactorIn, blendFunctionIn);
|
||||
}
|
||||
|
||||
public void apply()
|
||||
{
|
||||
if (!this.equals(lastApplied))
|
||||
{
|
||||
if (lastApplied == null || this.opaque != lastApplied.isOpaque())
|
||||
{
|
||||
lastApplied = this;
|
||||
|
||||
if (this.opaque)
|
||||
{
|
||||
GlStateManager.disableBlend();
|
||||
return;
|
||||
}
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
}
|
||||
|
||||
GlStateManager.glBlendEquation(this.blendFunction);
|
||||
|
||||
if (this.separateBlend)
|
||||
{
|
||||
GlStateManager.tryBlendFuncSeparate(this.srcColorFactor, this.destColorFactor, this.srcAlphaFactor, this.destAlphaFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
GlStateManager.blendFunc(this.srcColorFactor, this.destColorFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object p_equals_1_)
|
||||
{
|
||||
if (this == p_equals_1_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (!(p_equals_1_ instanceof JsonBlendingMode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
JsonBlendingMode jsonblendingmode = (JsonBlendingMode)p_equals_1_;
|
||||
|
||||
if (this.blendFunction != jsonblendingmode.blendFunction)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.destAlphaFactor != jsonblendingmode.destAlphaFactor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.destColorFactor != jsonblendingmode.destColorFactor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.opaque != jsonblendingmode.opaque)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.separateBlend != jsonblendingmode.separateBlend)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (this.srcAlphaFactor != jsonblendingmode.srcAlphaFactor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.srcColorFactor == jsonblendingmode.srcColorFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
int i = this.srcColorFactor;
|
||||
i = 31 * i + this.srcAlphaFactor;
|
||||
i = 31 * i + this.destColorFactor;
|
||||
i = 31 * i + this.destAlphaFactor;
|
||||
i = 31 * i + this.blendFunction;
|
||||
i = 31 * i + (this.separateBlend ? 1 : 0);
|
||||
i = 31 * i + (this.opaque ? 1 : 0);
|
||||
return i;
|
||||
}
|
||||
|
||||
public boolean isOpaque()
|
||||
{
|
||||
return this.opaque;
|
||||
}
|
||||
|
||||
public static JsonBlendingMode parseBlendNode(JsonObject json)
|
||||
{
|
||||
if (json == null)
|
||||
{
|
||||
return new JsonBlendingMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = 32774;
|
||||
int j = 1;
|
||||
int k = 0;
|
||||
int l = 1;
|
||||
int i1 = 0;
|
||||
boolean flag = true;
|
||||
boolean flag1 = false;
|
||||
|
||||
if (JsonUtils.isString(json, "func"))
|
||||
{
|
||||
i = stringToBlendFunction(json.get("func").getAsString());
|
||||
|
||||
if (i != 32774)
|
||||
{
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (JsonUtils.isString(json, "srcrgb"))
|
||||
{
|
||||
j = stringToBlendFactor(json.get("srcrgb").getAsString());
|
||||
|
||||
if (j != 1)
|
||||
{
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (JsonUtils.isString(json, "dstrgb"))
|
||||
{
|
||||
k = stringToBlendFactor(json.get("dstrgb").getAsString());
|
||||
|
||||
if (k != 0)
|
||||
{
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (JsonUtils.isString(json, "srcalpha"))
|
||||
{
|
||||
l = stringToBlendFactor(json.get("srcalpha").getAsString());
|
||||
|
||||
if (l != 1)
|
||||
{
|
||||
flag = false;
|
||||
}
|
||||
|
||||
flag1 = true;
|
||||
}
|
||||
|
||||
if (JsonUtils.isString(json, "dstalpha"))
|
||||
{
|
||||
i1 = stringToBlendFactor(json.get("dstalpha").getAsString());
|
||||
|
||||
if (i1 != 0)
|
||||
{
|
||||
flag = false;
|
||||
}
|
||||
|
||||
flag1 = true;
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
return new JsonBlendingMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
return flag1 ? new JsonBlendingMode(j, k, l, i1, i) : new JsonBlendingMode(j, k, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a blend function name to an id, returning add (32774) if not recognized.
|
||||
*/
|
||||
private static int stringToBlendFunction(String funcName)
|
||||
{
|
||||
String s = funcName.trim().toLowerCase(Locale.ROOT);
|
||||
|
||||
if ("add".equals(s))
|
||||
{
|
||||
return 32774;
|
||||
}
|
||||
else if ("subtract".equals(s))
|
||||
{
|
||||
return 32778;
|
||||
}
|
||||
else if ("reversesubtract".equals(s))
|
||||
{
|
||||
return 32779;
|
||||
}
|
||||
else if ("reverse_subtract".equals(s))
|
||||
{
|
||||
return 32779;
|
||||
}
|
||||
else if ("min".equals(s))
|
||||
{
|
||||
return 32775;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "max".equals(s) ? 32776 : 32774;
|
||||
}
|
||||
}
|
||||
|
||||
private static int stringToBlendFactor(String factorName)
|
||||
{
|
||||
String s = factorName.trim().toLowerCase(Locale.ROOT);
|
||||
s = s.replaceAll("_", "");
|
||||
s = s.replaceAll("one", "1");
|
||||
s = s.replaceAll("zero", "0");
|
||||
s = s.replaceAll("minus", "-");
|
||||
|
||||
if ("0".equals(s))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if ("1".equals(s))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if ("srccolor".equals(s))
|
||||
{
|
||||
return 768;
|
||||
}
|
||||
else if ("1-srccolor".equals(s))
|
||||
{
|
||||
return 769;
|
||||
}
|
||||
else if ("dstcolor".equals(s))
|
||||
{
|
||||
return 774;
|
||||
}
|
||||
else if ("1-dstcolor".equals(s))
|
||||
{
|
||||
return 775;
|
||||
}
|
||||
else if ("srcalpha".equals(s))
|
||||
{
|
||||
return 770;
|
||||
}
|
||||
else if ("1-srcalpha".equals(s))
|
||||
{
|
||||
return 771;
|
||||
}
|
||||
else if ("dstalpha".equals(s))
|
||||
{
|
||||
return 772;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "1-dstalpha".equals(s) ? 773 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package net.minecraft.client.util;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class JsonException extends IOException
|
||||
{
|
||||
private final List<JsonException.Entry> entries = Lists.<JsonException.Entry>newArrayList();
|
||||
private final String message;
|
||||
|
||||
public JsonException(String messageIn)
|
||||
{
|
||||
this.entries.add(new JsonException.Entry());
|
||||
this.message = messageIn;
|
||||
}
|
||||
|
||||
public JsonException(String messageIn, Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
this.entries.add(new JsonException.Entry());
|
||||
this.message = messageIn;
|
||||
}
|
||||
|
||||
public void prependJsonKey(String key)
|
||||
{
|
||||
((JsonException.Entry)this.entries.get(0)).addJsonKey(key);
|
||||
}
|
||||
|
||||
public void setFilenameAndFlush(String filenameIn)
|
||||
{
|
||||
(this.entries.get(0)).filename = filenameIn;
|
||||
this.entries.add(0, new JsonException.Entry());
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return "Invalid " + this.entries.get(this.entries.size() - 1) + ": " + this.message;
|
||||
}
|
||||
|
||||
public static JsonException forException(Exception exception)
|
||||
{
|
||||
if (exception instanceof JsonException)
|
||||
{
|
||||
return (JsonException)exception;
|
||||
}
|
||||
else
|
||||
{
|
||||
String s = exception.getMessage();
|
||||
|
||||
if (exception instanceof FileNotFoundException)
|
||||
{
|
||||
s = "File not found";
|
||||
}
|
||||
|
||||
return new JsonException(s, exception);
|
||||
}
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public static class Entry
|
||||
{
|
||||
private String filename;
|
||||
private final List<String> jsonKeys;
|
||||
|
||||
private Entry()
|
||||
{
|
||||
this.jsonKeys = Lists.<String>newArrayList();
|
||||
}
|
||||
|
||||
private void addJsonKey(String key)
|
||||
{
|
||||
this.jsonKeys.add(0, key);
|
||||
}
|
||||
|
||||
public String getJsonKeys()
|
||||
{
|
||||
return StringUtils.join((Iterable)this.jsonKeys, "->");
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
if (this.filename != null)
|
||||
{
|
||||
return this.jsonKeys.isEmpty() ? this.filename : this.filename + " " + this.getJsonKeys();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.jsonKeys.isEmpty() ? "(Unknown file)" : "(Unknown file) " + this.getJsonKeys();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package net.minecraft.client.util;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Table;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.gui.recipebook.RecipeList;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.CraftingManager;
|
||||
import net.minecraft.item.crafting.IRecipe;
|
||||
import net.minecraft.stats.RecipeBook;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class RecipeBookClient extends RecipeBook
|
||||
{
|
||||
public static final Map<CreativeTabs, List<RecipeList>> RECIPES_BY_TAB = Maps.<CreativeTabs, List<RecipeList>>newHashMap();
|
||||
public static final List<RecipeList> ALL_RECIPES = Lists.<RecipeList>newArrayList();
|
||||
|
||||
private static RecipeList newRecipeList(CreativeTabs p_194082_0_)
|
||||
{
|
||||
RecipeList recipelist = new RecipeList();
|
||||
ALL_RECIPES.add(recipelist);
|
||||
(RECIPES_BY_TAB.computeIfAbsent(p_194082_0_, (p_194085_0_) ->
|
||||
{
|
||||
return new ArrayList();
|
||||
})).add(recipelist);
|
||||
(RECIPES_BY_TAB.computeIfAbsent(CreativeTabs.SEARCH, (p_194083_0_) ->
|
||||
{
|
||||
return new ArrayList();
|
||||
})).add(recipelist);
|
||||
return recipelist;
|
||||
}
|
||||
|
||||
private static CreativeTabs getItemStackTab(ItemStack p_194084_0_)
|
||||
{
|
||||
CreativeTabs creativetabs = p_194084_0_.getItem().getCreativeTab();
|
||||
|
||||
if (creativetabs != CreativeTabs.BUILDING_BLOCKS && creativetabs != CreativeTabs.TOOLS && creativetabs != CreativeTabs.REDSTONE)
|
||||
{
|
||||
return creativetabs == CreativeTabs.COMBAT ? CreativeTabs.TOOLS : CreativeTabs.MISC;
|
||||
}
|
||||
else
|
||||
{
|
||||
return creativetabs;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
rebuildTable();
|
||||
}
|
||||
|
||||
public static void rebuildTable()
|
||||
{
|
||||
RECIPES_BY_TAB.clear();
|
||||
ALL_RECIPES.clear();
|
||||
|
||||
Table<CreativeTabs, String, RecipeList> table = HashBasedTable.<CreativeTabs, String, RecipeList>create();
|
||||
|
||||
for (IRecipe irecipe : CraftingManager.REGISTRY)
|
||||
{
|
||||
if (!irecipe.isDynamic())
|
||||
{
|
||||
CreativeTabs creativetabs = getItemStackTab(irecipe.getRecipeOutput());
|
||||
String s = irecipe.getGroup();
|
||||
RecipeList recipelist1;
|
||||
|
||||
if (s.isEmpty())
|
||||
{
|
||||
recipelist1 = newRecipeList(creativetabs);
|
||||
}
|
||||
else
|
||||
{
|
||||
recipelist1 = table.get(creativetabs, s);
|
||||
|
||||
if (recipelist1 == null)
|
||||
{
|
||||
recipelist1 = newRecipeList(creativetabs);
|
||||
table.put(creativetabs, s, recipelist1);
|
||||
}
|
||||
}
|
||||
|
||||
recipelist1.add(irecipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
package net.minecraft.client.util;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntCollection;
|
||||
import it.unimi.dsi.fastutil.ints.IntIterator;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import it.unimi.dsi.fastutil.ints.IntListIterator;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.crafting.IRecipe;
|
||||
import net.minecraft.item.crafting.Ingredient;
|
||||
|
||||
public class RecipeItemHelper
|
||||
{
|
||||
/** Map from {@link #pack} packed ids to counts */
|
||||
public final Int2IntMap itemToCount = new Int2IntOpenHashMap();
|
||||
|
||||
public void accountStack(ItemStack stack)
|
||||
{
|
||||
this.accountStack(stack, -1);
|
||||
}
|
||||
|
||||
public void accountStack(ItemStack stack, int forceCount)
|
||||
{
|
||||
if (!stack.isEmpty() && !stack.isItemDamaged() && !stack.isItemEnchanted() && !stack.hasDisplayName())
|
||||
{
|
||||
int i = pack(stack);
|
||||
int j = forceCount == -1 ? stack.getCount() : forceCount;
|
||||
this.increment(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
public static int pack(ItemStack stack)
|
||||
{
|
||||
Item item = stack.getItem();
|
||||
int i = item.getHasSubtypes() ? stack.getMetadata() : 0;
|
||||
return Item.REGISTRY.getIDForObject(item) << 16 | i & 65535;
|
||||
}
|
||||
|
||||
public boolean containsItem(int p_194120_1_)
|
||||
{
|
||||
return this.itemToCount.get(p_194120_1_) > 0;
|
||||
}
|
||||
|
||||
public int tryTake(int p_194122_1_, int maximum)
|
||||
{
|
||||
int i = this.itemToCount.get(p_194122_1_);
|
||||
|
||||
if (i >= maximum)
|
||||
{
|
||||
this.itemToCount.put(p_194122_1_, i - maximum);
|
||||
return p_194122_1_;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void increment(int p_194117_1_, int amount)
|
||||
{
|
||||
this.itemToCount.put(p_194117_1_, this.itemToCount.get(p_194117_1_) + amount);
|
||||
}
|
||||
|
||||
public boolean canCraft(IRecipe recipe, @Nullable IntList p_194116_2_)
|
||||
{
|
||||
return this.canCraft(recipe, p_194116_2_, 1);
|
||||
}
|
||||
|
||||
public boolean canCraft(IRecipe recipe, @Nullable IntList p_194118_2_, int p_194118_3_)
|
||||
{
|
||||
return (new RecipeItemHelper.RecipePicker(recipe)).tryPick(p_194118_3_, p_194118_2_);
|
||||
}
|
||||
|
||||
public int getBiggestCraftableStack(IRecipe recipe, @Nullable IntList p_194114_2_)
|
||||
{
|
||||
return this.getBiggestCraftableStack(recipe, Integer.MAX_VALUE, p_194114_2_);
|
||||
}
|
||||
|
||||
public int getBiggestCraftableStack(IRecipe recipe, int p_194121_2_, @Nullable IntList p_194121_3_)
|
||||
{
|
||||
return (new RecipeItemHelper.RecipePicker(recipe)).tryPickAll(p_194121_2_, p_194121_3_);
|
||||
}
|
||||
|
||||
public static ItemStack unpack(int p_194115_0_)
|
||||
{
|
||||
return p_194115_0_ == 0 ? ItemStack.EMPTY : new ItemStack(Item.getItemById(p_194115_0_ >> 16 & 65535), 1, p_194115_0_ & 65535);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
this.itemToCount.clear();
|
||||
}
|
||||
|
||||
class RecipePicker
|
||||
{
|
||||
private final IRecipe recipe;
|
||||
private final List<Ingredient> ingredients = Lists.<Ingredient>newArrayList();
|
||||
private final int ingredientCount;
|
||||
private final int[] possessedIngredientStacks;
|
||||
private final int possessedIngredientStackCount;
|
||||
private final BitSet data;
|
||||
private IntList path = new IntArrayList();
|
||||
|
||||
public RecipePicker(IRecipe p_i47608_2_)
|
||||
{
|
||||
this.recipe = p_i47608_2_;
|
||||
this.ingredients.addAll(p_i47608_2_.getIngredients());
|
||||
this.ingredients.removeIf((p_194103_0_) ->
|
||||
{
|
||||
return p_194103_0_ == Ingredient.EMPTY;
|
||||
});
|
||||
this.ingredientCount = this.ingredients.size();
|
||||
this.possessedIngredientStacks = this.getUniqueAvailIngredientItems();
|
||||
this.possessedIngredientStackCount = this.possessedIngredientStacks.length;
|
||||
this.data = new BitSet(this.ingredientCount + this.possessedIngredientStackCount + this.ingredientCount + this.ingredientCount * this.possessedIngredientStackCount);
|
||||
|
||||
for (int i = 0; i < this.ingredients.size(); ++i)
|
||||
{
|
||||
IntList intlist = ((Ingredient)this.ingredients.get(i)).getValidItemStacksPacked();
|
||||
|
||||
for (int j = 0; j < this.possessedIngredientStackCount; ++j)
|
||||
{
|
||||
if (intlist.contains(this.possessedIngredientStacks[j]))
|
||||
{
|
||||
this.data.set(this.getIndex(true, j, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tryPick(int p_194092_1_, @Nullable IntList listIn)
|
||||
{
|
||||
if (p_194092_1_ <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = 0; this.dfs(p_194092_1_); ++k)
|
||||
{
|
||||
RecipeItemHelper.this.tryTake(this.possessedIngredientStacks[this.path.getInt(0)], p_194092_1_);
|
||||
int l = this.path.size() - 1;
|
||||
this.setSatisfied(this.path.getInt(l));
|
||||
|
||||
for (int i1 = 0; i1 < l; ++i1)
|
||||
{
|
||||
this.toggleResidual((i1 & 1) == 0, ((Integer)this.path.get(i1)).intValue(), ((Integer)this.path.get(i1 + 1)).intValue());
|
||||
}
|
||||
|
||||
this.path.clear();
|
||||
this.data.clear(0, this.ingredientCount + this.possessedIngredientStackCount);
|
||||
}
|
||||
|
||||
boolean flag = k == this.ingredientCount;
|
||||
boolean flag1 = flag && listIn != null;
|
||||
|
||||
if (flag1)
|
||||
{
|
||||
listIn.clear();
|
||||
}
|
||||
|
||||
this.data.clear(0, this.ingredientCount + this.possessedIngredientStackCount + this.ingredientCount);
|
||||
int j1 = 0;
|
||||
List<Ingredient> list = this.recipe.getIngredients();
|
||||
|
||||
for (int k1 = 0; k1 < list.size(); ++k1)
|
||||
{
|
||||
if (flag1 && list.get(k1) == Ingredient.EMPTY)
|
||||
{
|
||||
listIn.add(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int l1 = 0; l1 < this.possessedIngredientStackCount; ++l1)
|
||||
{
|
||||
if (this.hasResidual(false, j1, l1))
|
||||
{
|
||||
this.toggleResidual(true, l1, j1);
|
||||
RecipeItemHelper.this.increment(this.possessedIngredientStacks[l1], p_194092_1_);
|
||||
|
||||
if (flag1)
|
||||
{
|
||||
listIn.add(this.possessedIngredientStacks[l1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++j1;
|
||||
}
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
|
||||
private int[] getUniqueAvailIngredientItems()
|
||||
{
|
||||
IntCollection intcollection = new IntAVLTreeSet();
|
||||
|
||||
for (Ingredient ingredient : this.ingredients)
|
||||
{
|
||||
intcollection.addAll(ingredient.getValidItemStacksPacked());
|
||||
}
|
||||
|
||||
IntIterator intiterator = intcollection.iterator();
|
||||
|
||||
while (intiterator.hasNext())
|
||||
{
|
||||
if (!RecipeItemHelper.this.containsItem(intiterator.nextInt()))
|
||||
{
|
||||
intiterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
return intcollection.toIntArray();
|
||||
}
|
||||
|
||||
private boolean dfs(int p_194098_1_)
|
||||
{
|
||||
int k = this.possessedIngredientStackCount;
|
||||
|
||||
for (int l = 0; l < k; ++l)
|
||||
{
|
||||
if (RecipeItemHelper.this.itemToCount.get(this.possessedIngredientStacks[l]) >= p_194098_1_)
|
||||
{
|
||||
this.visit(false, l);
|
||||
|
||||
while (!this.path.isEmpty())
|
||||
{
|
||||
int i1 = this.path.size();
|
||||
boolean flag = (i1 & 1) == 1;
|
||||
int j1 = this.path.getInt(i1 - 1);
|
||||
|
||||
if (!flag && !this.isSatisfied(j1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int k1 = flag ? this.ingredientCount : k;
|
||||
|
||||
for (int l1 = 0; l1 < k1; ++l1)
|
||||
{
|
||||
if (!this.hasVisited(flag, l1) && this.hasConnection(flag, j1, l1) && this.hasResidual(flag, j1, l1))
|
||||
{
|
||||
this.visit(flag, l1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int i2 = this.path.size();
|
||||
|
||||
if (i2 == i1)
|
||||
{
|
||||
this.path.removeInt(i2 - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.path.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isSatisfied(int p_194091_1_)
|
||||
{
|
||||
return this.data.get(this.getSatisfiedIndex(p_194091_1_));
|
||||
}
|
||||
|
||||
private void setSatisfied(int p_194096_1_)
|
||||
{
|
||||
this.data.set(this.getSatisfiedIndex(p_194096_1_));
|
||||
}
|
||||
|
||||
private int getSatisfiedIndex(int p_194094_1_)
|
||||
{
|
||||
return this.ingredientCount + this.possessedIngredientStackCount + p_194094_1_;
|
||||
}
|
||||
|
||||
private boolean hasConnection(boolean p_194093_1_, int p_194093_2_, int p_194093_3_)
|
||||
{
|
||||
return this.data.get(this.getIndex(p_194093_1_, p_194093_2_, p_194093_3_));
|
||||
}
|
||||
|
||||
private boolean hasResidual(boolean p_194100_1_, int p_194100_2_, int p_194100_3_)
|
||||
{
|
||||
return p_194100_1_ != this.data.get(1 + this.getIndex(p_194100_1_, p_194100_2_, p_194100_3_));
|
||||
}
|
||||
|
||||
private void toggleResidual(boolean p_194089_1_, int p_194089_2_, int p_194089_3_)
|
||||
{
|
||||
this.data.flip(1 + this.getIndex(p_194089_1_, p_194089_2_, p_194089_3_));
|
||||
}
|
||||
|
||||
private int getIndex(boolean p_194095_1_, int p_194095_2_, int p_194095_3_)
|
||||
{
|
||||
int k = p_194095_1_ ? p_194095_2_ * this.ingredientCount + p_194095_3_ : p_194095_3_ * this.ingredientCount + p_194095_2_;
|
||||
return this.ingredientCount + this.possessedIngredientStackCount + this.ingredientCount + 2 * k;
|
||||
}
|
||||
|
||||
private void visit(boolean p_194088_1_, int p_194088_2_)
|
||||
{
|
||||
this.data.set(this.getVisitedIndex(p_194088_1_, p_194088_2_));
|
||||
this.path.add(p_194088_2_);
|
||||
}
|
||||
|
||||
private boolean hasVisited(boolean p_194101_1_, int p_194101_2_)
|
||||
{
|
||||
return this.data.get(this.getVisitedIndex(p_194101_1_, p_194101_2_));
|
||||
}
|
||||
|
||||
private int getVisitedIndex(boolean p_194099_1_, int p_194099_2_)
|
||||
{
|
||||
return (p_194099_1_ ? 0 : this.ingredientCount) + p_194099_2_;
|
||||
}
|
||||
|
||||
public int tryPickAll(int p_194102_1_, @Nullable IntList list)
|
||||
{
|
||||
int k = 0;
|
||||
int l = Math.min(p_194102_1_, this.getMinIngredientCount()) + 1;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int i1 = (k + l) / 2;
|
||||
|
||||
if (this.tryPick(i1, (IntList)null))
|
||||
{
|
||||
if (l - k <= 1)
|
||||
{
|
||||
if (i1 > 0)
|
||||
{
|
||||
this.tryPick(i1, list);
|
||||
}
|
||||
|
||||
return i1;
|
||||
}
|
||||
|
||||
k = i1;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = i1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getMinIngredientCount()
|
||||
{
|
||||
int k = Integer.MAX_VALUE;
|
||||
|
||||
for (Ingredient ingredient : this.ingredients)
|
||||
{
|
||||
int l = 0;
|
||||
int i1;
|
||||
|
||||
for (IntListIterator intlistiterator = ingredient.getValidItemStacksPacked().iterator(); intlistiterator.hasNext(); l = Math.max(l, RecipeItemHelper.this.itemToCount.get(i1)))
|
||||
{
|
||||
i1 = ((Integer)intlistiterator.next()).intValue();
|
||||
}
|
||||
|
||||
if (k > 0)
|
||||
{
|
||||
k = Math.min(k, l);
|
||||
}
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package net.minecraft.client.util;
|
||||
|
||||
import com.google.common.collect.AbstractIterator;
|
||||
import com.google.common.collect.Lists;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class SearchTree<T> implements ISearchTree<T>
|
||||
{
|
||||
/** A {@link SuffixArray} that contains values keyed by the ID (as produced by {@link #idFunc}). */
|
||||
protected SuffixArray<T> byId = new SuffixArray<T>();
|
||||
/** A {@link SuffixArray} that contains values keyed by the name (as produced by {@link #nameFunc}). */
|
||||
protected SuffixArray<T> byName = new SuffixArray<T>();
|
||||
/**
|
||||
* A function that takes a <code>T</code> and returns a list of Strings describing it normally.
|
||||
* <p>
|
||||
* For both items and recipes, this is implemented via {@link net.minecraft.item.ItemStack#getTooltip()
|
||||
* ItemStack.getTooltip} (with NORMAL tooltip flags), with formatting codes stripped, text trimmed, and empty lines
|
||||
* removed.
|
||||
*
|
||||
* The result does not need to be corrected for
|
||||
*/
|
||||
private final Function<T, Iterable<String>> nameFunc;
|
||||
/**
|
||||
* A function that takes a <code>T</code> and returns a list of {@link ResourceLocation}s describing it.
|
||||
* <p>
|
||||
* For both items and recipes, this is implemented via <code>Item.REGISTRY.getNameForObject</code>. (In the case of
|
||||
* registries, it is applied to all results)
|
||||
*/
|
||||
private final Function<T, Iterable<ResourceLocation>> idFunc;
|
||||
/** All entries in the search tree. */
|
||||
private final List<T> contents = Lists.<T>newArrayList();
|
||||
/** Maps each entry in the search tree to a locally unique, increasing number (staring at 0). */
|
||||
private Object2IntMap<T> numericContents = new Object2IntOpenHashMap<T>();
|
||||
|
||||
public SearchTree(Function<T, Iterable<String>> nameFuncIn, Function<T, Iterable<ResourceLocation>> idFuncIn)
|
||||
{
|
||||
this.nameFunc = nameFuncIn;
|
||||
this.idFunc = idFuncIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculates the contents of this search tree, reapplying {@link #nameFunc} and {@link #idFunc}. Should be called
|
||||
* whenever resources are reloaded (e.g. language changes).
|
||||
*/
|
||||
public void recalculate()
|
||||
{
|
||||
this.byId = new SuffixArray<T>();
|
||||
this.byName = new SuffixArray<T>();
|
||||
|
||||
for (T t : this.contents)
|
||||
{
|
||||
this.index(t);
|
||||
}
|
||||
|
||||
this.byId.generate();
|
||||
this.byName.generate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given item to the search tree.
|
||||
*
|
||||
* @param element The element to add
|
||||
*/
|
||||
public void add(T element)
|
||||
{
|
||||
this.numericContents.put(element, this.contents.size());
|
||||
this.contents.add(element);
|
||||
this.index(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Directly puts the given item into {@link #byId} and {@link #byName}, applying {@link #nameFunc} and {@link
|
||||
* idFunc}.
|
||||
*
|
||||
* @param element The element to add
|
||||
*/
|
||||
private void index(T element)
|
||||
{
|
||||
(this.idFunc.apply(element)).forEach((p_194039_2_) ->
|
||||
{
|
||||
this.byName.add(element, p_194039_2_.toString().toLowerCase(Locale.ROOT));
|
||||
});
|
||||
(this.nameFunc.apply(element)).forEach((p_194041_2_) ->
|
||||
{
|
||||
this.byId.add(element, p_194041_2_.toLowerCase(Locale.ROOT));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches this search tree for the given text.
|
||||
* <p>
|
||||
* If the query does not contain a <code>:</code>, then only {@link #byName} is searched; if it does contain a
|
||||
* colon, both {@link #byName} and {@link #byId} are searched and the results are merged using a {@link
|
||||
* MergingIterator}.
|
||||
* @return A list of all matching items in this search tree.
|
||||
*
|
||||
* @param searchText The text to search for. Must be normalized with <code>toLowerCase(Locale.ROOT)</code> before
|
||||
* calling this method.
|
||||
*/
|
||||
public List<T> search(String searchText)
|
||||
{
|
||||
List<T> list = this.byId.search(searchText);
|
||||
|
||||
if (searchText.indexOf(58) < 0)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<T> list1 = this.byName.search(searchText);
|
||||
return (List<T>)(list1.isEmpty() ? list : Lists.newArrayList(new SearchTree.MergingIterator(list.iterator(), list1.iterator(), this.numericContents)));
|
||||
}
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
static class MergingIterator<T> extends AbstractIterator<T>
|
||||
{
|
||||
private final Iterator<T> leftItr;
|
||||
private final Iterator<T> rightItr;
|
||||
/**
|
||||
* A mapping of objects to unique numeric IDs, used to sort the list.
|
||||
* <p>
|
||||
* Since there's no good place to document how this class works, it basically just interleaves two iterators
|
||||
* together, choosing the entry that has the lower numeric ID in this map.
|
||||
*/
|
||||
private final Object2IntMap<T> numbers;
|
||||
/** Current element from {@link #leftItr} */
|
||||
private T left;
|
||||
/** Current element from {@link #rightItr} */
|
||||
private T right;
|
||||
|
||||
public MergingIterator(Iterator<T> leftIn, Iterator<T> rightIn, Object2IntMap<T> numbersIn)
|
||||
{
|
||||
this.leftItr = leftIn;
|
||||
this.rightItr = rightIn;
|
||||
this.numbers = numbersIn;
|
||||
this.left = (T)(leftIn.hasNext() ? leftIn.next() : null);
|
||||
this.right = (T)(rightIn.hasNext() ? rightIn.next() : null);
|
||||
}
|
||||
|
||||
protected T computeNext()
|
||||
{
|
||||
if (this.left == null && this.right == null)
|
||||
{
|
||||
return (T)this.endOfData();
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
if (this.left == this.right)
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
else if (this.left == null)
|
||||
{
|
||||
i = 1;
|
||||
}
|
||||
else if (this.right == null)
|
||||
{
|
||||
i = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = Integer.compare(this.numbers.getInt(this.left), this.numbers.getInt(this.right));
|
||||
}
|
||||
|
||||
T t = (T)(i <= 0 ? this.left : this.right);
|
||||
|
||||
if (i <= 0)
|
||||
{
|
||||
this.left = (T)(this.leftItr.hasNext() ? this.leftItr.next() : null);
|
||||
}
|
||||
|
||||
if (i >= 0)
|
||||
{
|
||||
this.right = (T)(this.rightItr.hasNext() ? this.rightItr.next() : null);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package net.minecraft.client.util;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.gui.recipebook.RecipeList;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import net.minecraft.client.resources.IResourceManagerReloadListener;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class SearchTreeManager implements IResourceManagerReloadListener
|
||||
{
|
||||
/** The item search tree, used for the creative inventory's search tab */
|
||||
public static final SearchTreeManager.Key<ItemStack> ITEMS = new SearchTreeManager.Key<ItemStack>();
|
||||
/** The recipe search tree, used for the recipe book */
|
||||
public static final SearchTreeManager.Key<RecipeList> RECIPES = new SearchTreeManager.Key<RecipeList>();
|
||||
private final Map < SearchTreeManager.Key<?>, SearchTree<? >> trees = Maps. < SearchTreeManager.Key<?>, SearchTree<? >> newHashMap();
|
||||
|
||||
public void onResourceManagerReload(IResourceManager resourceManager)
|
||||
{
|
||||
for (SearchTree<?> searchtree : this.trees.values())
|
||||
{
|
||||
searchtree.recalculate();
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void register(SearchTreeManager.Key<T> key, SearchTree<T> searchTreeIn)
|
||||
{
|
||||
this.trees.put(key, searchTreeIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ISearchTree} for the given search tree key, returning null if no such tree exists.
|
||||
*/
|
||||
public <T> ISearchTree<T> get(SearchTreeManager.Key<T> key)
|
||||
{
|
||||
return (ISearchTree)this.trees.get(key);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public static class Key<T>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
package net.minecraft.client.util;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import it.unimi.dsi.fastutil.Arrays;
|
||||
import it.unimi.dsi.fastutil.Swapper;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntComparator;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class SuffixArray<T>
|
||||
{
|
||||
/**
|
||||
* A debug property (<code>SuffixArray.printComparisons</code>) that can be specified in the JVM arguments, that
|
||||
* causes debug printing of comparisons as they happen.
|
||||
*/
|
||||
private static final boolean DEBUG_PRINT_COMPARISONS = Boolean.parseBoolean(System.getProperty("SuffixArray.printComparisons", "false"));
|
||||
/**
|
||||
* A debug property (<code>SuffixArray.printArray</code>) that can be specified in the JVM arguments, that causes
|
||||
* the full array to be printed ({@link #printArray()}) after calling {@link #generate()}
|
||||
*/
|
||||
private static final boolean DEBUG_PRINT_ARRAY = Boolean.parseBoolean(System.getProperty("SuffixArray.printArray", "false"));
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
protected final List<T> list = Lists.<T>newArrayList();
|
||||
private final IntList chars = new IntArrayList();
|
||||
private final IntList wordStarts = new IntArrayList();
|
||||
private IntList suffixToT = new IntArrayList();
|
||||
private IntList offsets = new IntArrayList();
|
||||
private int maxStringLength;
|
||||
|
||||
public void add(T p_194057_1_, String p_194057_2_)
|
||||
{
|
||||
this.maxStringLength = Math.max(this.maxStringLength, p_194057_2_.length());
|
||||
int i = this.list.size();
|
||||
this.list.add(p_194057_1_);
|
||||
this.wordStarts.add(this.chars.size());
|
||||
|
||||
for (int j = 0; j < p_194057_2_.length(); ++j)
|
||||
{
|
||||
this.suffixToT.add(i);
|
||||
this.offsets.add(j);
|
||||
this.chars.add(p_194057_2_.charAt(j));
|
||||
}
|
||||
|
||||
this.suffixToT.add(i);
|
||||
this.offsets.add(p_194057_2_.length());
|
||||
this.chars.add(-1);
|
||||
}
|
||||
|
||||
public void generate()
|
||||
{
|
||||
int i = this.chars.size();
|
||||
int[] aint = new int[i];
|
||||
final int[] aint1 = new int[i];
|
||||
final int[] aint2 = new int[i];
|
||||
int[] aint3 = new int[i];
|
||||
IntComparator intcomparator = new IntComparator()
|
||||
{
|
||||
public int compare(int p_compare_1_, int p_compare_2_)
|
||||
{
|
||||
return aint1[p_compare_1_] == aint1[p_compare_2_] ? Integer.compare(aint2[p_compare_1_], aint2[p_compare_2_]) : Integer.compare(aint1[p_compare_1_], aint1[p_compare_2_]);
|
||||
}
|
||||
public int compare(Integer p_compare_1_, Integer p_compare_2_)
|
||||
{
|
||||
return this.compare(p_compare_1_.intValue(), p_compare_2_.intValue());
|
||||
}
|
||||
};
|
||||
Swapper swapper = (p_194054_3_, p_194054_4_) ->
|
||||
{
|
||||
|
||||
if (p_194054_3_ != p_194054_4_)
|
||||
{
|
||||
int i2 = aint1[p_194054_3_];
|
||||
aint1[p_194054_3_] = aint1[p_194054_4_];
|
||||
aint1[p_194054_4_] = i2;
|
||||
i2 = aint2[p_194054_3_];
|
||||
aint2[p_194054_3_] = aint2[p_194054_4_];
|
||||
aint2[p_194054_4_] = i2;
|
||||
i2 = aint3[p_194054_3_];
|
||||
aint3[p_194054_3_] = aint3[p_194054_4_];
|
||||
aint3[p_194054_4_] = i2;
|
||||
}
|
||||
};
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
aint[j] = this.chars.getInt(j);
|
||||
}
|
||||
|
||||
int k1 = 1;
|
||||
|
||||
for (int k = Math.min(i, this.maxStringLength); k1 * 2 < k; k1 *= 2)
|
||||
{
|
||||
for (int l = 0; l < i; aint3[l] = l++)
|
||||
{
|
||||
aint1[l] = aint[l];
|
||||
aint2[l] = l + k1 < i ? aint[l + k1] : -2;
|
||||
}
|
||||
|
||||
Arrays.quickSort(0, i, intcomparator, swapper);
|
||||
|
||||
for (int l1 = 0; l1 < i; ++l1)
|
||||
{
|
||||
if (l1 > 0 && aint1[l1] == aint1[l1 - 1] && aint2[l1] == aint2[l1 - 1])
|
||||
{
|
||||
aint[aint3[l1]] = aint[aint3[l1 - 1]];
|
||||
}
|
||||
else
|
||||
{
|
||||
aint[aint3[l1]] = l1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IntList intlist1 = this.suffixToT;
|
||||
IntList intlist = this.offsets;
|
||||
this.suffixToT = new IntArrayList(intlist1.size());
|
||||
this.offsets = new IntArrayList(intlist.size());
|
||||
|
||||
for (int i1 = 0; i1 < i; ++i1)
|
||||
{
|
||||
int j1 = aint3[i1];
|
||||
this.suffixToT.add(intlist1.getInt(j1));
|
||||
this.offsets.add(intlist.getInt(j1));
|
||||
}
|
||||
|
||||
if (DEBUG_PRINT_ARRAY)
|
||||
{
|
||||
this.printArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the entire array to the logger, on debug level
|
||||
*/
|
||||
private void printArray()
|
||||
{
|
||||
for (int i2 = 0; i2 < this.suffixToT.size(); ++i2)
|
||||
{
|
||||
LOGGER.debug("{} {}", Integer.valueOf(i2), this.getString(i2));
|
||||
}
|
||||
|
||||
LOGGER.debug("");
|
||||
}
|
||||
|
||||
private String getString(int p_194059_1_)
|
||||
{
|
||||
int i2 = this.offsets.getInt(p_194059_1_);
|
||||
int j2 = this.wordStarts.getInt(this.suffixToT.getInt(p_194059_1_));
|
||||
StringBuilder stringbuilder = new StringBuilder();
|
||||
|
||||
for (int k2 = 0; j2 + k2 < this.chars.size(); ++k2)
|
||||
{
|
||||
if (k2 == i2)
|
||||
{
|
||||
stringbuilder.append('^');
|
||||
}
|
||||
|
||||
int l2 = ((Integer)this.chars.get(j2 + k2)).intValue();
|
||||
|
||||
if (l2 == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
stringbuilder.append((char)l2);
|
||||
}
|
||||
|
||||
return stringbuilder.toString();
|
||||
}
|
||||
|
||||
private int compare(String p_194056_1_, int p_194056_2_)
|
||||
{
|
||||
int i2 = this.wordStarts.getInt(this.suffixToT.getInt(p_194056_2_));
|
||||
int j2 = this.offsets.getInt(p_194056_2_);
|
||||
|
||||
for (int k2 = 0; k2 < p_194056_1_.length(); ++k2)
|
||||
{
|
||||
int l2 = this.chars.getInt(i2 + j2 + k2);
|
||||
|
||||
if (l2 == -1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
char c0 = p_194056_1_.charAt(k2);
|
||||
char c1 = (char)l2;
|
||||
|
||||
if (c0 < c1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (c0 > c1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public List<T> search(String p_194055_1_)
|
||||
{
|
||||
int i2 = this.suffixToT.size();
|
||||
int j2 = 0;
|
||||
int k2 = i2;
|
||||
|
||||
while (j2 < k2)
|
||||
{
|
||||
int l2 = j2 + (k2 - j2) / 2;
|
||||
int i3 = this.compare(p_194055_1_, l2);
|
||||
|
||||
if (DEBUG_PRINT_COMPARISONS)
|
||||
{
|
||||
LOGGER.debug("comparing lower \"{}\" with {} \"{}\": {}", p_194055_1_, Integer.valueOf(l2), this.getString(l2), Integer.valueOf(i3));
|
||||
}
|
||||
|
||||
if (i3 > 0)
|
||||
{
|
||||
j2 = l2 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
k2 = l2;
|
||||
}
|
||||
}
|
||||
|
||||
if (j2 >= 0 && j2 < i2)
|
||||
{
|
||||
int i4 = j2;
|
||||
k2 = i2;
|
||||
|
||||
while (j2 < k2)
|
||||
{
|
||||
int j4 = j2 + (k2 - j2) / 2;
|
||||
int j3 = this.compare(p_194055_1_, j4);
|
||||
|
||||
if (DEBUG_PRINT_COMPARISONS)
|
||||
{
|
||||
LOGGER.debug("comparing upper \"{}\" with {} \"{}\": {}", p_194055_1_, Integer.valueOf(j4), this.getString(j4), Integer.valueOf(j3));
|
||||
}
|
||||
|
||||
if (j3 >= 0)
|
||||
{
|
||||
j2 = j4 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
k2 = j4;
|
||||
}
|
||||
}
|
||||
|
||||
int k4 = j2;
|
||||
IntSet intset = new IntOpenHashSet();
|
||||
|
||||
for (int k3 = i4; k3 < k4; ++k3)
|
||||
{
|
||||
intset.add(this.suffixToT.getInt(k3));
|
||||
}
|
||||
|
||||
int[] aint4 = intset.toIntArray();
|
||||
java.util.Arrays.sort(aint4);
|
||||
Set<T> set = Sets.<T>newLinkedHashSet();
|
||||
|
||||
for (int l3 : aint4)
|
||||
{
|
||||
set.add(this.list.get(l3));
|
||||
}
|
||||
|
||||
return Lists.newArrayList(set);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collections.<T>emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Auto generated package-info by MCP
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package net.minecraft.client.util;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
Reference in New Issue
Block a user