/**
* 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.weaponry.core.ctrl;
import java.util.Map;
import java.util.WeakHashMap;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.server.MinecraftServer;
import cn.annoreg.core.Registrant;
import cn.annoreg.mc.RegEventHandler;
import cn.annoreg.mc.RegEventHandler.Bus;
import cn.liutils.registry.KeyHandlerRegistration.RegKeyHandler;
import cn.weaponry.api.ctrl.IItemCtrlListener;
import cn.weaponry.api.ctrl.KeyEventType;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
import cpw.mods.fml.common.gameevent.TickEvent.ServerTickEvent;
/**
* @author WeAthFolD
*/
@Registrant
@RegEventHandler(Bus.FML)
public class WeaponControllerServer {
static Map<EntityPlayer, PlayerCtrlState> states = new WeakHashMap();
public static void sendEvent(EntityPlayer player, int keyID, SyncEventType type) {
check(player).onSyncEvent(keyID, type);
}
private static PlayerCtrlState check(EntityPlayer player) {
PlayerCtrlState ret = states.get(player);
if(ret == null || ret.player != player) {
ret = new PlayerCtrlState(player);
states.put(player, ret);
}
return ret;
}
@SubscribeEvent
public void serverTick(ServerTickEvent event) {
if(event.phase == Phase.END)
return;
for(Object p : MinecraftServer.getServer().getConfigurationManager().playerEntityList) {
EntityPlayer player = (EntityPlayer) p;
if(states.containsKey(player)) //TODO: May be faster if we remove the 'silent' CtrlStates.
check(player).tick();
}
}
private static class PlayerCtrlState {
final EntityPlayer player;
public PlayerCtrlState(EntityPlayer _p) {
player = _p;
}
boolean kdArray[] = new boolean[3];
int kaTimeouts[] = new int[3];
public void onSyncEvent(int keyID, SyncEventType type) {
boolean kd = kdArray[keyID];
int timeout = kaTimeouts[keyID];
switch(type) {
case DOWN:
if(!kd) {
kd = true;
timeout = 0;
locateAndSend(keyID, KeyEventType.DOWN);
}
break;
case UP:
if(kd) {
kd = false;
locateAndSend(keyID, KeyEventType.UP);
}
break;
case ABORT:
if(kd) {
kd = false;
locateAndSend(keyID, KeyEventType.ABORT);
}
break;
case KEEPALIVE:
if(kd) {
timeout = 0;
}
break;
default:
break;
}
kdArray[keyID] = kd;
kaTimeouts[keyID] = timeout;
}
private void locateAndSend(int keyID, KeyEventType event) {
ItemStack stack = player.getCurrentEquippedItem();
if(stack != null && stack.getItem() instanceof IItemCtrlListener) {
((IItemCtrlListener) stack.getItem()).onKeyEvent(player, keyID, event);
}
}
public void tick() {
for(int i = 0; i < 3; ++i) {
if(kdArray[i]) {
if(++kaTimeouts[i] == 20) {
kdArray[i] = false;
locateAndSend(i, KeyEventType.ABORT);
} else {
locateAndSend(i, KeyEventType.TICK);
}
}
}
}
}
}