tweak List algorithm further
This commit is contained in:
parent
325cef4a58
commit
96fc5df707
4 changed files with 177 additions and 94 deletions
|
@ -126,7 +126,7 @@ import buildcraft.core.lib.engines.TileEngineBase;
|
|||
import buildcraft.core.lib.network.ChannelHandler;
|
||||
import buildcraft.core.lib.utils.ColorUtils;
|
||||
import buildcraft.core.lib.utils.NBTUtils;
|
||||
import buildcraft.core.lib.utils.OreDictionaryCache;
|
||||
import buildcraft.core.list.ListOreDictionaryCache;
|
||||
import buildcraft.core.lib.utils.Utils;
|
||||
import buildcraft.core.lib.utils.XorShift128Random;
|
||||
import buildcraft.core.list.ListMatchHandlerClass;
|
||||
|
@ -475,6 +475,7 @@ public class BuildCraftCore extends BuildCraftMod {
|
|||
|
||||
@Mod.EventHandler
|
||||
public void postInit(FMLPostInitializationEvent event) {
|
||||
OreDictionary.registerOre("dustTinyRedstone", Blocks.fence_gate);
|
||||
BCLog.logger.info("BuildCraft's fake player: UUID = " + gameProfile.getId().toString() + ", name = '" + gameProfile.getName() + "'!");
|
||||
|
||||
for (Object o : Block.blockRegistry) {
|
||||
|
@ -520,9 +521,9 @@ public class BuildCraftCore extends BuildCraftMod {
|
|||
}
|
||||
}
|
||||
|
||||
MinecraftForge.EVENT_BUS.register(OreDictionaryCache.INSTANCE);
|
||||
MinecraftForge.EVENT_BUS.register(ListOreDictionaryCache.INSTANCE);
|
||||
for (String s : OreDictionary.getOreNames()) {
|
||||
OreDictionaryCache.INSTANCE.registerName(s);
|
||||
ListOreDictionaryCache.INSTANCE.registerName(s);
|
||||
}
|
||||
|
||||
ListRegistry.registerHandler(new ListMatchHandlerOreDictionary());
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
package buildcraft.core.lib.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
public final class OreDictionaryCache {
|
||||
public static final OreDictionaryCache INSTANCE = new OreDictionaryCache();
|
||||
|
||||
private final Map<String, Set<Integer>> namingCache = new HashMap<String, Set<Integer>>();
|
||||
private final Set<String> registeredNames = new HashSet<String>();
|
||||
|
||||
private OreDictionaryCache() {
|
||||
|
||||
}
|
||||
|
||||
public Set<Integer> getListOfPartialMatches(String part) {
|
||||
return namingCache.get(part);
|
||||
}
|
||||
|
||||
private void addToNamingCache(String s, int id) {
|
||||
if (s == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<Integer> ll = namingCache.get(s);
|
||||
|
||||
if (ll == null) {
|
||||
ll = new HashSet<Integer>();
|
||||
ll.add(id);
|
||||
namingCache.put(s, ll);
|
||||
} else {
|
||||
ll.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getSplitLocation(String name) {
|
||||
int splitLocation = 0;
|
||||
while (splitLocation < name.length()) {
|
||||
if (!Character.isUpperCase(name.codePointAt(splitLocation))) {
|
||||
splitLocation++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return splitLocation;
|
||||
}
|
||||
|
||||
public static String getFirstHalf(String name) {
|
||||
int splitLocation = getSplitLocation(name);
|
||||
return splitLocation < name.length() ? name.substring(0, splitLocation) : name; // No null - this handles things like "record".
|
||||
}
|
||||
|
||||
public static String getSecondHalf(String name) {
|
||||
int splitLocation = getSplitLocation(name);
|
||||
return splitLocation < name.length() ? name.substring(splitLocation) : null;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void oreRegister(OreDictionary.OreRegisterEvent event) {
|
||||
registerName(event.Name);
|
||||
}
|
||||
|
||||
public void registerName(String name) {
|
||||
if (registeredNames.contains(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int oreID = OreDictionary.getOreID(name);
|
||||
|
||||
addToNamingCache(getFirstHalf(name), oreID);
|
||||
addToNamingCache(getSecondHalf(name), oreID);
|
||||
|
||||
registeredNames.add(name);
|
||||
}
|
||||
}
|
|
@ -4,15 +4,34 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import buildcraft.core.lib.utils.OreDictionaryCache;
|
||||
import buildcraft.core.lib.inventory.StackHelper;
|
||||
|
||||
public class ListMatchHandlerOreDictionary extends ListMatchHandler {
|
||||
private int getUppercaseCount(String s) {
|
||||
int j = 0;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (Character.isUpperCase(s.codePointAt(i))) {
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Type type, ItemStack stack, ItemStack target, boolean precise) {
|
||||
int[] oreIds = OreDictionary.getOreIDs(stack);
|
||||
|
||||
if (oreIds.length == 0) {
|
||||
// No ore IDs? Time for the best effort plan of METADATA!
|
||||
if (type == Type.TYPE) {
|
||||
return StackHelper.isMatchingItem(stack, target, false, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int[] matchesIds = OreDictionary.getOreIDs(target);
|
||||
|
||||
if (type == Type.CLASS) {
|
||||
|
@ -24,10 +43,13 @@ public class ListMatchHandlerOreDictionary extends ListMatchHandler {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (int i : oreIds) {
|
||||
String s = OreDictionary.getOreName(i);
|
||||
Set<Integer> stackIds = OreDictionaryCache.INSTANCE.getListOfPartialMatches(
|
||||
type == Type.MATERIAL ? OreDictionaryCache.getSecondHalf(s) : OreDictionaryCache.getFirstHalf(s)
|
||||
// Always pick only the longest OreDictionary string for matching.
|
||||
// It's ugly, but should give us the most precise result for the
|
||||
// cases in which a given stone is also used for crafting equivalents.
|
||||
String s = getBestOreString(oreIds);
|
||||
if (s != null) {
|
||||
Set<Integer> stackIds = ListOreDictionaryCache.INSTANCE.getListOfPartialMatches(
|
||||
type == Type.MATERIAL ? ListOreDictionaryCache.getMaterial(s) : ListOreDictionaryCache.getType(s)
|
||||
);
|
||||
if (stackIds != null) {
|
||||
for (int j : stackIds) {
|
||||
|
@ -44,20 +66,48 @@ public class ListMatchHandlerOreDictionary extends ListMatchHandler {
|
|||
return false;
|
||||
}
|
||||
|
||||
private String getBestOreString(int[] oreIds) {
|
||||
String s = null, st;
|
||||
int suc = 0, suct;
|
||||
for (int i : oreIds) {
|
||||
st = OreDictionary.getOreName(i);
|
||||
suct = getUppercaseCount(st);
|
||||
if (s == null || suct > suc) {
|
||||
s = st;
|
||||
suc = suct;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getClientExamples(Type type, ItemStack stack) {
|
||||
int[] oreIds = OreDictionary.getOreIDs(stack);
|
||||
List<ItemStack> stacks = new ArrayList<ItemStack>();
|
||||
|
||||
if (oreIds.length == 0) {
|
||||
// No ore IDs? Time for the best effort plan of METADATA!
|
||||
if (type == Type.TYPE) {
|
||||
List<ItemStack> tempStack = new ArrayList<ItemStack>();
|
||||
stack.getItem().getSubItems(stack.getItem(), CreativeTabs.tabMisc, tempStack);
|
||||
for (ItemStack is : tempStack) {
|
||||
if (is.getItem() == stack.getItem()) {
|
||||
stacks.add(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
return stacks;
|
||||
}
|
||||
|
||||
if (type == Type.CLASS) {
|
||||
for (int i : oreIds) {
|
||||
stacks.addAll(OreDictionary.getOres(i));
|
||||
}
|
||||
} else {
|
||||
for (int i : oreIds) {
|
||||
String s = OreDictionary.getOreName(i);
|
||||
Set<Integer> stackIds = OreDictionaryCache.INSTANCE.getListOfPartialMatches(
|
||||
type == Type.MATERIAL ? OreDictionaryCache.getSecondHalf(s) : OreDictionaryCache.getFirstHalf(s)
|
||||
String s = getBestOreString(oreIds);
|
||||
if (s != null) {
|
||||
Set<Integer> stackIds = ListOreDictionaryCache.INSTANCE.getListOfPartialMatches(
|
||||
type == Type.MATERIAL ? ListOreDictionaryCache.getMaterial(s) : ListOreDictionaryCache.getType(s)
|
||||
);
|
||||
if (stackIds != null) {
|
||||
for (int j : stackIds) {
|
||||
|
@ -67,6 +117,22 @@ public class ListMatchHandlerOreDictionary extends ListMatchHandler {
|
|||
}
|
||||
}
|
||||
|
||||
List<ItemStack> wildcard = new ArrayList<ItemStack>();
|
||||
|
||||
for (ItemStack is : stacks) {
|
||||
if (is != null && is.getItemDamage() == OreDictionary.WILDCARD_VALUE && is.getHasSubtypes()) {
|
||||
wildcard.add(is);
|
||||
}
|
||||
}
|
||||
for (ItemStack is : wildcard) {
|
||||
List<ItemStack> wll = new ArrayList<ItemStack>();
|
||||
is.getItem().getSubItems(is.getItem(), CreativeTabs.tabMisc, wll);
|
||||
if (wll.size() > 0) {
|
||||
stacks.remove(is);
|
||||
stacks.addAll(wll);
|
||||
}
|
||||
}
|
||||
|
||||
return stacks;
|
||||
}
|
||||
}
|
||||
|
|
97
common/buildcraft/core/list/ListOreDictionaryCache.java
Normal file
97
common/buildcraft/core/list/ListOreDictionaryCache.java
Normal file
|
@ -0,0 +1,97 @@
|
|||
package buildcraft.core.list;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
public final class ListOreDictionaryCache {
|
||||
public static final ListOreDictionaryCache INSTANCE = new ListOreDictionaryCache();
|
||||
private static final String[] TYPE_KEYWORDS = {
|
||||
"Tiny", "Dense", "Small"
|
||||
};
|
||||
private final Map<String, Set<Integer>> namingCache = new HashMap<String, Set<Integer>>();
|
||||
private final Set<String> registeredNames = new HashSet<String>();
|
||||
|
||||
private ListOreDictionaryCache() {
|
||||
|
||||
}
|
||||
|
||||
public Set<Integer> getListOfPartialMatches(String part) {
|
||||
return namingCache.get(part);
|
||||
}
|
||||
|
||||
private void addToNamingCache(String s, int id) {
|
||||
if (s == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<Integer> ll = namingCache.get(s);
|
||||
|
||||
if (ll == null) {
|
||||
ll = new HashSet<Integer>();
|
||||
ll.add(id);
|
||||
namingCache.put(s, ll);
|
||||
} else {
|
||||
ll.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getType(String name) {
|
||||
// Rules for finding type:
|
||||
// - Split just before the last uppercase character found.
|
||||
int splitLocation = name.length() - 1;
|
||||
while (splitLocation >= 0) {
|
||||
if (Character.isUpperCase(name.codePointAt(splitLocation))) {
|
||||
break;
|
||||
} else {
|
||||
splitLocation--;
|
||||
}
|
||||
}
|
||||
return splitLocation >= 0 ? name.substring(0, splitLocation) : name; // No null - this handles things like "record".
|
||||
}
|
||||
|
||||
public static String getMaterial(String name) {
|
||||
// Rules for finding material:
|
||||
// - For every uppercase character, check if the character is not in
|
||||
// TYPE_KEYWORDS. This is used to skip things like "plate[DenseIron]"
|
||||
// or "dust[TinyRedstone]". That part should be the material still.
|
||||
int splitLocation = 0;
|
||||
String t = null;
|
||||
while (splitLocation < name.length()) {
|
||||
if (!Character.isUpperCase(name.codePointAt(splitLocation))) {
|
||||
splitLocation++;
|
||||
} else {
|
||||
t = name.substring(splitLocation);
|
||||
for (String s : TYPE_KEYWORDS) {
|
||||
if (t.startsWith(s)) {
|
||||
t = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (t != null) {
|
||||
break;
|
||||
} else {
|
||||
splitLocation++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return splitLocation < name.length() ? t : null;
|
||||
}
|
||||
|
||||
public void registerName(String name) {
|
||||
if (registeredNames.contains(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int oreID = OreDictionary.getOreID(name);
|
||||
|
||||
addToNamingCache(getType(name), oreID);
|
||||
addToNamingCache(getMaterial(name), oreID);
|
||||
|
||||
registeredNames.add(name);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue