tweak List algorithm further

This commit is contained in:
asiekierka 2015-07-01 17:05:15 +02:00
parent 325cef4a58
commit 96fc5df707
4 changed files with 177 additions and 94 deletions

View file

@ -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());

View file

@ -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);
}
}

View file

@ -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;
}
}

View 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);
}
}