/* * This file is part of aion-emu <aion-emu.com>. * * aion-emu is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * aion-emu is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with aion-emu. If not, see <http://www.gnu.org/licenses/>. */ package com.aionemu.gameserver.ai; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Future; import com.aionemu.gameserver.ai.desires.Desire; import com.aionemu.gameserver.ai.desires.DesireQueue; import com.aionemu.gameserver.ai.desires.impl.CounterBasedDesireFilter; import com.aionemu.gameserver.ai.desires.impl.GeneralDesireIteratorHandler; import com.aionemu.gameserver.ai.events.Event; import com.aionemu.gameserver.ai.events.handler.EventHandler; import com.aionemu.gameserver.ai.npcai.DummyAi; import com.aionemu.gameserver.ai.state.AIState; import com.aionemu.gameserver.ai.state.handler.StateHandler; import com.aionemu.gameserver.model.gameobjects.Creature; import com.aionemu.gameserver.model.gameobjects.player.Player; import com.aionemu.gameserver.utils.ThreadPoolManager; public abstract class AI<T extends Creature> implements Runnable { /** * Dummy ai that has no any event handlers */ private static final DummyAi dummyAi = new DummyAi(); protected Map<Event, EventHandler> eventHandlers = new HashMap<Event, EventHandler>(); protected Map<AIState, StateHandler> stateHandlers = new HashMap<AIState, StateHandler>(); protected DesireQueue desireQueue = new DesireQueue(); protected Creature owner; protected AIState aiState = AIState.NONE; protected boolean isStateChanged = false; private Future<?> aiTask; /** * * @param event The event that needs to be handled */ public void handleEvent(Event event) { //allow only handling event Event.DIED in dead stats //probably i need to define rules for which events could be handled in which state if(event != Event.DIED && owner.getLifeStats().isAlreadyDead()) return; EventHandler eventHandler = eventHandlers.get(event); if(eventHandler != null) eventHandler.handleEvent(event, this); } /** * Talking with player can be overriden in AI scripts * * @param player */ public void handleTalk(Player player) { } /** * @return owner of this AI */ public Creature getOwner() { return owner; } /** * of the AI * @param owner the owner of the AI */ public void setOwner(Creature owner) { this.owner = owner; } /** * @return the aiState */ public AIState getAiState() { return aiState; } /** * * @param eventHandler */ protected void addEventHandler(EventHandler eventHandler) { this.eventHandlers.put(eventHandler.getEvent(), eventHandler); } /** * * @param stateHandler */ protected void addStateHandler(StateHandler stateHandler) { this.stateHandlers.put(stateHandler.getState(), stateHandler); } /** * @param aiState the aiState to set */ public void setAiState(AIState aiState) { if(this.aiState != aiState) { this.aiState = aiState; isStateChanged = true; } } public void analyzeState() { isStateChanged = false; StateHandler stateHandler = stateHandlers.get(aiState); if(stateHandler != null) stateHandler.handleState(aiState, this); } @Override public void run() { desireQueue.iterateDesires(new GeneralDesireIteratorHandler(this), new CounterBasedDesireFilter()); // TODO: move to home if(desireQueue.isEmpty() || isStateChanged) { analyzeState(); } } public void schedule() { if(!isScheduled()) { aiTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(this, 1000, 1000); } } public void stop() { if(aiTask != null && !aiTask.isCancelled()) { aiTask.cancel(true); aiTask = null; } } public boolean isScheduled() { return aiTask != null && !aiTask.isCancelled(); } public void clearDesires() { this.desireQueue.clear(); } public void addDesire(Desire desire) { this.desireQueue.addDesire(desire); } public int desireQueueSize() { return desireQueue.isEmpty() ? 0 : desireQueue.size(); } /** * @return the dummyai */ public static DummyAi dummyAi() { return dummyAi; } }