mirror of
https://github.com/GTNewHorizons/Botania.git
synced 2026-11-14 01:04:16 +00:00
Item Autocomplete system
This commit is contained in:
1 parent
fc4ea7e4fc
commit
176fa1f5b5
6 files changed
+260
-2
No files matched your search
@@ -29,7 +29,8 @@ public final class CorporeaHelper {
|
||||
|
||||
private static final List<IInventory> empty = Collections.unmodifiableList(new ArrayList());
|
||||
private static final WeakHashMap<List<ICorporeaSpark>, List<IInventory>> cachedNetworks = new WeakHashMap();
|
||||
|
||||
private static final List<ICorporeaAutoCompleteController> autoCompleteControllers = new ArrayList<ICorporeaAutoCompleteController>();
|
||||
|
||||
public static final String[] WILDCARD_STRINGS = new String[] {
|
||||
"...", "~", "+", "?" , "*"
|
||||
};
|
||||
@@ -319,4 +320,21 @@ public final class CorporeaHelper {
|
||||
public static boolean equalOrContain(String s1, String s2, boolean contain) {
|
||||
return contain ? s1.contains(s2) : s1.equals(s2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a ICorporeaAutoCompleteController
|
||||
*/
|
||||
public static void registerAutoCompleteController(ICorporeaAutoCompleteController controller) {
|
||||
autoCompleteControllers.add(controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the auto complete helper should run
|
||||
*/
|
||||
public static boolean shouldAutoComplete() {
|
||||
for(ICorporeaAutoCompleteController controller : autoCompleteControllers)
|
||||
if(controller.shouldAutoComplete())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* This class was created by <SoundLogic>. It's distributed as
|
||||
* part of the Botania Mod. Get the Source Code in github:
|
||||
* https://github.com/Vazkii/Botania
|
||||
*
|
||||
* Botania is Open Source and distributed under the
|
||||
* Botania License: http://botaniamod.net/license.php
|
||||
*
|
||||
* File Created @ [June 8, 2015, 1:04:05 PM (GMT)]
|
||||
*/
|
||||
package vazkii.botania.api.corporea;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
/**
|
||||
* An interface for systems which may control if the item auto complete system should be active
|
||||
*/
|
||||
public interface ICorporeaAutoCompleteController {
|
||||
|
||||
/**
|
||||
* Return true if auto completion should be enabled.
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public boolean shouldAutoComplete();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* This class was created by <SoundLogic>. It's distributed as
|
||||
* part of the Botania Mod. Get the Source Code in github:
|
||||
* https://github.com/Vazkii/Botania
|
||||
*
|
||||
* Botania is Open Source and distributed under the
|
||||
* Botania License: http://botaniamod.net/license.php
|
||||
*
|
||||
* File Created @ [June 8, 2015, 12:55:20 AM (GMT)]
|
||||
*/
|
||||
package vazkii.botania.client.core.handler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiChat;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import vazkii.botania.api.corporea.CorporeaHelper;
|
||||
import vazkii.botania.common.lib.LibObfuscation;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||
|
||||
public class CorporeaAutoCompleteHandler {
|
||||
|
||||
boolean isAutoCompleted = false;
|
||||
String originalString = "";
|
||||
List<CompletionData> completions = new ArrayList<CompletionData>();
|
||||
int position;
|
||||
|
||||
static TreeSet<String> itemNames = new TreeSet<String>(
|
||||
new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String arg0, String arg1) {
|
||||
return arg0.compareToIgnoreCase(arg1);
|
||||
}
|
||||
});
|
||||
|
||||
private boolean tabLastTick = false;
|
||||
|
||||
public static void updateItemList() {
|
||||
itemNames.clear();
|
||||
Iterator<Item> iterator = Item.itemRegistry.iterator();
|
||||
ArrayList<ItemStack> curList = new ArrayList<ItemStack>();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
Item item = iterator.next();
|
||||
|
||||
if(item != null && item.getCreativeTab() != null) {
|
||||
curList.clear();
|
||||
try {
|
||||
item.getSubItems(item, (CreativeTabs) null, curList);
|
||||
for(ItemStack stack : curList)
|
||||
itemNames.add(stack.getDisplayName().trim());
|
||||
}
|
||||
catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onTick(ClientTickEvent event) {
|
||||
if(event.phase != Phase.END)
|
||||
return;
|
||||
GuiScreen screen = Minecraft.getMinecraft().currentScreen;
|
||||
if(!(screen instanceof GuiChat)) {
|
||||
isAutoCompleted = false;
|
||||
return;
|
||||
}
|
||||
GuiChat chat = (GuiChat) screen;
|
||||
if(isAutoCompleted) {
|
||||
boolean valid = ReflectionHelper.getPrivateValue(GuiChat.class, chat, LibObfuscation.COMPLETE_FLAG);
|
||||
if(!valid)
|
||||
isAutoCompleted = false;
|
||||
}
|
||||
if(Keyboard.isKeyDown(15)) {
|
||||
if(tabLastTick)
|
||||
return;
|
||||
tabLastTick = true;
|
||||
} else {
|
||||
tabLastTick = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CorporeaHelper.shouldAutoComplete())
|
||||
return;
|
||||
|
||||
GuiTextField inputField = ReflectionHelper.getPrivateValue(GuiChat.class, chat, LibObfuscation.INPUT_FIELD);
|
||||
if(!isAutoCompleted && GuiScreen.isShiftKeyDown())
|
||||
buildAutoCompletes(inputField, chat);
|
||||
if(isAutoCompleted && !completions.isEmpty())
|
||||
advanceAutoComplete(inputField, chat);
|
||||
}
|
||||
|
||||
private void advanceAutoComplete(GuiTextField inputField, GuiChat chat) {
|
||||
this.position++;
|
||||
if(this.position >= completions.size())
|
||||
this.position -= completions.size();
|
||||
CompletionData data = completions.get(position);
|
||||
String str = originalString.substring(0, originalString.length() - data.prefixLength) + data.string;
|
||||
inputField.setText(str);
|
||||
}
|
||||
|
||||
private void buildAutoCompletes(GuiTextField inputField, GuiChat chat) {
|
||||
String leftOfCursor;
|
||||
if(inputField.getCursorPosition() == 0)
|
||||
leftOfCursor = "";
|
||||
else
|
||||
leftOfCursor = inputField.getText().substring(0, inputField.getCursorPosition());
|
||||
if(leftOfCursor.length() == 0 || leftOfCursor.charAt(0) == '/')
|
||||
return;
|
||||
this.completions = getNames(leftOfCursor);
|
||||
if(completions.isEmpty())
|
||||
return;
|
||||
this.position = -1;
|
||||
ReflectionHelper.setPrivateValue(GuiChat.class, chat, true, LibObfuscation.COMPLETE_FLAG);
|
||||
StringBuilder stringbuilder = new StringBuilder();
|
||||
CompletionData data;
|
||||
for(Iterator<CompletionData> iterator = completions.iterator(); iterator.hasNext(); stringbuilder.append(data.string)) {
|
||||
data = iterator.next();
|
||||
if(stringbuilder.length() > 0)
|
||||
stringbuilder.append(", ");
|
||||
}
|
||||
|
||||
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText(stringbuilder.toString()), 1);
|
||||
isAutoCompleted = true;
|
||||
originalString = inputField.getText();
|
||||
}
|
||||
|
||||
private ArrayList<CompletionData> getNames(String prefix) {
|
||||
TreeSet<CompletionData> result = new TreeSet<CompletionData>();
|
||||
String[] words = prefix.split(" ");
|
||||
int i = words.length - 1;
|
||||
String curPrefix = words[i];
|
||||
while(i >= 0) {
|
||||
result.addAll(getNamesStartingWith(curPrefix.toLowerCase()));
|
||||
i--;
|
||||
if(i >= 0)
|
||||
curPrefix = words[i] + " " + curPrefix;
|
||||
}
|
||||
return new ArrayList<CompletionData>(result);
|
||||
}
|
||||
|
||||
private List<CompletionData> getNamesStartingWith(String prefix) {
|
||||
ArrayList<CompletionData> result = new ArrayList<CompletionData>();
|
||||
int length = prefix.length();
|
||||
SortedSet<String> after = itemNames.tailSet(prefix);
|
||||
for(String str : after) {
|
||||
if(str.toLowerCase().startsWith(prefix))
|
||||
result.add(new CompletionData(str, length));
|
||||
else return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class CompletionData implements Comparable<CompletionData> {
|
||||
|
||||
private String string;
|
||||
private int prefixLength;
|
||||
|
||||
public CompletionData(String string, int prefixLength) {
|
||||
this.string = string;
|
||||
this.prefixLength = prefixLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(CompletionData arg0) {
|
||||
return string.compareTo(arg0.string);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,6 +39,7 @@ import vazkii.botania.client.core.handler.BaubleRenderHandler;
|
||||
import vazkii.botania.client.core.handler.BotaniaPlayerController;
|
||||
import vazkii.botania.client.core.handler.BoundTileRenderer;
|
||||
import vazkii.botania.client.core.handler.ClientTickHandler;
|
||||
import vazkii.botania.client.core.handler.CorporeaAutoCompleteHandler;
|
||||
import vazkii.botania.client.core.handler.DebugHandler;
|
||||
import vazkii.botania.client.core.handler.HUDHandler;
|
||||
import vazkii.botania.client.core.handler.LightningHandler;
|
||||
@@ -143,6 +144,7 @@ import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.Optional;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||
|
||||
public class ClientProxy extends CommonProxy {
|
||||
@@ -162,6 +164,7 @@ public class ClientProxy extends CommonProxy {
|
||||
MinecraftForge.EVENT_BUS.register(new BaubleRenderHandler());
|
||||
MinecraftForge.EVENT_BUS.register(new DebugHandler());
|
||||
MinecraftForge.EVENT_BUS.register(new SubTileRadiusRenderHandler());
|
||||
FMLCommonHandler.instance().bus().register(new CorporeaAutoCompleteHandler());
|
||||
|
||||
if(ConfigHandler.versionCheckEnabled)
|
||||
new VersionChecker().init();
|
||||
@@ -174,6 +177,11 @@ public class ClientProxy extends CommonProxy {
|
||||
|
||||
initRenderers();
|
||||
}
|
||||
@Override
|
||||
public void postInit(FMLPostInitializationEvent event) {
|
||||
super.postInit(event);
|
||||
CorporeaAutoCompleteHandler.updateItemList();
|
||||
}
|
||||
|
||||
private void initRenderers() {
|
||||
LibRenderIDs.idAltar = RenderingRegistry.getNextAvailableRenderId();
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.WeakHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -32,6 +33,7 @@ import net.minecraftforge.event.ServerChatEvent;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
|
||||
import vazkii.botania.api.corporea.CorporeaHelper;
|
||||
import vazkii.botania.api.corporea.ICorporeaAutoCompleteController;
|
||||
import vazkii.botania.api.corporea.ICorporeaSpark;
|
||||
import vazkii.botania.common.achievement.ModAchievements;
|
||||
import vazkii.botania.common.core.helper.MathHelper;
|
||||
@@ -213,8 +215,12 @@ public class TileCorporeaIndex extends TileCorporeaBase {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class InputHandler {
|
||||
public static final class InputHandler implements ICorporeaAutoCompleteController {
|
||||
|
||||
public InputHandler() {
|
||||
CorporeaHelper.registerAutoCompleteController(this);
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
public void onChatMessage(ServerChatEvent event) {
|
||||
List<TileCorporeaIndex> nearbyIndexes = getNearbyIndexes(event.player);
|
||||
@@ -270,6 +276,11 @@ public class TileCorporeaIndex extends TileCorporeaBase {
|
||||
return indexList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldAutoComplete() {
|
||||
return !getNearbyIndexes(Minecraft.getMinecraft().thePlayer).isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static interface IRegexStacker {
|
||||
|
||||
@@ -72,5 +72,9 @@ public final class LibObfuscation {
|
||||
|
||||
// GuiContainer
|
||||
public static final String[] THE_SLOT = new String[] { "theSlot", "field_147006_u", "u" };
|
||||
|
||||
// GuiChat
|
||||
public static final String[] INPUT_FIELD = new String[] { "inputField", "field_146415_a", "a" };
|
||||
public static final String[] COMPLETE_FLAG = new String[] { "field_146414_r", "r" };
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user