/* * This program 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. * * This program 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 * this program. If not, see . */ package com.l2jserver.gameserver.ai2; import gnu.trove.TIntObjectHashMap; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.List; import java.util.Map; import java.util.Set; import java.util.jar.JarFile; import java.util.logging.Logger; import com.l2jserver.gameserver.ThreadPoolManager; import com.l2jserver.gameserver.ai2.AiInstance.QueueEventRunner; import javolution.util.FastList; import javolution.util.FastMap; import javolution.util.FastSet; /** * This class will load all the AI's and retain all of them. * It is a singleton * @author -Wooden- * */ public class AiManager { protected static final Logger _log = Logger.getLogger(AiManager.class.getName()); private List _aiList; private TIntObjectHashMap _aiMap; private ThreadPoolManager _tpm; private Map _paramcache; public static AiManager getInstance() { return SingletonHolder._instance; } private AiManager() { _aiList = new FastList(); _aiMap = new TIntObjectHashMap(); _tpm = ThreadPoolManager.getInstance(); _paramcache = new FastMap(); load(); } public void load() { try { //TODO redo all the SpecificAiManger loading it's completely messed up: @SuppressWarnings("unused") JarFile jar = new JarFile("./l2jserver.jar"); URL url = Class.class.getResource("/net/sf/l2j/gameserver/ai/managers"); //jar.getJarEntry("/net/sf/l2j/gameserver/ai/managers").get; if (url == null) { _log.severe("Could not open the ai managers folder. No ai will be loaded!"); return; } File directory = new File(url.getFile()); for (String file : directory.list()) { if (file.endsWith(".class")) { try { Class managerClass = Class.forName("com.l2jserver.gameserver.ai.managers." + file.substring(0, file.length() - 6)); Object managerObject = managerClass.newInstance(); if (!(managerObject instanceof ISpecificAiManager)) { _log.info("A class that was not a ISpecificAiManager was found in the ai managers folder."); continue; } ISpecificAiManager managerInstance = (ISpecificAiManager) managerObject; for (EventHandler handler : managerInstance.getEventHandlers()) { AiPlugingParameters pparams = handler.getPlugingParameters(); pparams.convertToIDs(); boolean perfectMatch = false; // let's check if any previously created AiInstance is allready used for the NPC concerned by this handler List intersections = new FastList(); for (AiInstance ai : _aiList) { if (ai.getPluginingParamaters().equals(pparams)) { ai.addHandler(handler); perfectMatch = true; break; } Intersection intersection = new Intersection(ai); for (int id : pparams.getIDs()) { if (ai.getPluginingParamaters().contains(id)) { //intersection with this AI intersection.ids.add(id); } } if (!intersection.isEmpty()) intersections.add(intersection); } if (perfectMatch) continue; for (Intersection i : intersections) { //remove secant ids on both AiInstances pparams.removeIDs(i.ids); i.ai.getPluginingParamaters().removeIDs(i.ids); //TODO if this is extracted to a more general purpose method, dont forget to update linkages to AiIntances //create a new instance with the secant ids that will inherit all the handlers from the secant Ai AiPlugingParameters newAiPparams = new AiPlugingParameters(null, null, null, i.ids, null); AiInstance newAi = new AiInstance(i.ai, newAiPparams); newAi.addHandler(handler); _aiList.add(newAi); } if (pparams.isEmpty()) continue; // create a new instance with the remaining ids AiInstance newAi = new AiInstance(pparams); newAi.addHandler(handler); _aiList.add(newAi); } } catch (ClassCastException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } catch (IOException e1) { e1.printStackTrace(); } // build a mighty map for (AiInstance ai : _aiList) { for (Integer i : ai.getHandledNPCIds()) { _aiMap.put(i, ai); } } } public void executeEventHandler(QueueEventRunner runner) { _tpm.executeAi(runner); } /** * @param instance */ public void addAiInstance(AiInstance instance) { _aiList.add(instance); } /** * @param npcId * @return */ public AiInstance getAiForNPCId(int npcId) { return _aiMap.get(npcId); } public String getParameter(String who, String paramsType, String param1, String param2) { String key = who + ":" + paramsType + ":" + param1 + ":" + param2; String cacheResult = _paramcache.get(key); if (cacheResult != null) return cacheResult; String result = null; // get from SQL _paramcache.put(key, result); return null; } private class Intersection { public AiInstance ai; public Set ids; public Intersection(AiInstance instance) { ai = instance; ids = new FastSet(); } public boolean isEmpty() { return ids.isEmpty(); } } @SuppressWarnings("synthetic-access") private static class SingletonHolder { protected static final AiManager _instance = new AiManager(); } }