/**
* Copyright (c) Lambda Innovation, 2013-2015
* 本作品版权由Lambda Innovation所有。
* http://www.li-dev.cn/
*
* This project is open-source, and it is distributed under
* the terms of GNU General Public License. You can modify
* and distribute freely as long as you follow the license.
* 本项目是一个开源项目,且遵循GNU通用公共授权协议。
* 在遵照该协议的情况下,您可以自由传播和修改。
* http://www.gnu.org/licenses/gpl.html
*/
package cn.liutils.util.helper;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import cn.liutils.util.client.ClientUtils;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent;
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
/**
* The instance of this class handles a set of KeyHandlers, and restore their key bindings
* from a configuration. (If any)
* @author WeAthFolD
*/
public class KeyManager {
/**
* The most commonly used KeyManager. Use this if you don't want to use any config on keys.
*/
public static final KeyManager dynamic = new KeyManager();
public static final int
MOUSE_LEFT = -100, MOUSE_MIDDLE = -98, MOUSE_RIGHT = -99,
MWHEELDOWN = -50, MWHEELUP = -49;
private boolean activated = true;
public KeyManager() {
activate();
FMLCommonHandler.instance().bus().register(this);
}
public void deactivate() {
activated = false;
}
public void activate() {
activated = true;
}
Map<String, KeyBinding> nameMap = new HashMap();
public void addKeyHandler(String name, int defKeyID, KeyHandler handler) {
addKeyHandler(name, "", defKeyID, false, handler);
}
public void addKeyHandler(String name, String keyDesc, int defKeyID, KeyHandler handler) {
addKeyHandler(name, keyDesc, defKeyID, false, handler);
}
private KeyBinding getKeyBinding(KeyHandler handler) {
for(KeyBinding kb : nameMap.values()) {
if(kb.handler == handler)
return kb;
}
return null;
}
public int getKeyID(KeyHandler handler) {
KeyBinding kb = getKeyBinding(handler);
return kb == null ? -1 : kb.keyID;
}
/**
* Add a key handler.
* @param name
* @param keyDesc Description of the key in the configuration file
* @param defKeyID Default key ID in config file
* @param global If global=true, this key will have callback even if opening GUI.
* @param handler
*/
public void addKeyHandler(String name, String keyDesc, int defKeyID, boolean global, KeyHandler handler) {
if(nameMap.containsKey(name))
throw new RuntimeException("Duplicate key: " + name + " of object " + handler);
Configuration conf = getConfig();
int keyID = defKeyID;
if(conf != null) {
keyID = conf.getInt(name, "keys", defKeyID, -1000, 1000, keyDesc);
}
KeyBinding kb = new KeyBinding(handler, keyID, global);
nameMap.put(name, kb);
}
public void resetBindingKey(String name, int newKey) {
KeyBinding kb = nameMap.get(name);
if(kb != null) {
Configuration cfg = getConfig();
if(cfg != null) {
Property p = cfg.get("keys", name, kb.keyID);
p.set(newKey);
}
kb.keyID = newKey;
if(kb.keyDown)
kb.handler.onKeyAbort();
kb.keyDown = false;
}
}
/**
* Removes a key handler from map, if exists.
*/
public void removeKeyHandler(String name) {
KeyBinding kb = nameMap.get(name);
if(kb != null)
kb.dead = true;
}
private void tick() {
Iterator< Entry<String, KeyBinding> > iter = nameMap.entrySet().iterator();
boolean inGame = ClientUtils.isPlayerInGame();
while(iter.hasNext()) {
Entry<String, KeyBinding> entry = iter.next();
KeyBinding kb = entry.getValue();
if(kb.dead) {
iter.remove();
} else {
boolean down = getKeyDown(kb.keyID);
if(down) {
if(!kb.isGlobal && !inGame) {
kb.keyAborted = true;
if(kb.keyDown) {
kb.handler.onKeyAbort();
}
} else if(!kb.keyAborted) {
if(!kb.keyDown) {
kb.handler.onKeyDown();
} else {
kb.handler.onKeyTick();
}
}
} else {
if(kb.keyDown) {
kb.handler.onKeyUp();
}
kb.keyAborted = false;
}
kb.keyDown = down;
}
}
}
private boolean getKeyDown(int keyID) {
if(keyID > 0) {
return Keyboard.isKeyDown(keyID);
}
return Mouse.isButtonDown(keyID + 100);
}
private class KeyBinding {
KeyHandler handler;
boolean isGlobal;
int keyID;
boolean keyDown;
boolean keyAborted;
boolean dead;
public KeyBinding(KeyHandler h, int k, boolean g) {
handler = h;
keyID = k;
isGlobal = g;
}
}
@SubscribeEvent
public void onEvent(ClientTickEvent event) {
if(event.phase == Phase.START && activated) {
tick();
}
}
protected Configuration getConfig() {
return null;
}
public static String getKeyName(int keyid) {
if(keyid >= 0) {
String ret = Keyboard.getKeyName(keyid);
return ret == null ? "undefined" : ret;
} else {
String ret = Mouse.getButtonName(keyid + 100);
return ret == null ? "undefined" : ret;
}
}
}