package net.kennux.cubicworld;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import net.kennux.cubicworld.gui.GuiManager;
import net.kennux.cubicworld.input.InputManager;
import net.kennux.cubicworld.pluginapi.APlugin;
import net.kennux.cubicworld.pluginapi.annotations.Event;
import net.kennux.cubicworld.pluginapi.annotations.PluginInfo;
import net.kennux.cubicworld.util.ConsoleHelper;
/**
*
* @author KennuX
*
*/
public class PluginManager
{
/**
* The plugins list loaded in preInitialize().
*/
public ArrayList<APlugin> plugins;
/**
* Contains all methods which were marked as events in the plugin class.
*/
private HashMap<String, ArrayList<AbstractMap.SimpleEntry<APlugin, Method>>> events = new HashMap<String, ArrayList<AbstractMap.SimpleEntry<APlugin, Method>>>();;
private HashMap<APlugin, PluginInfo> pluginInfos = new HashMap<APlugin, PluginInfo>();
private final String[] knownEvents = new String[] { "update" };
public void defineEntityTypes()
{
for (APlugin plugin : plugins)
{
plugin.defineEntityTypes();
}
}
public void defineInputHandlers(InputManager inputManager)
{
for (APlugin plugin : plugins)
{
plugin.defineInputHandlers(inputManager);
}
}
public void defineItemTypes()
{
for (APlugin plugin : plugins)
{
plugin.defineItemTypes();
}
}
public void defineProtocol()
{
for (APlugin plugin : plugins)
{
plugin.defineProtocol();
}
}
public void defineVoxelTypes()
{
for (APlugin plugin : plugins)
{
plugin.defineVoxelTypes();
}
}
/**
* Fires all registered event handlers for the given event name.
*
* @param eventName
* @param params
*/
public void fireEvent(String eventName, Object... params)
{
// Get all methods for this event.
ArrayList<SimpleEntry<APlugin, Method>> methods = events.get(eventName);
for (Entry<APlugin, Method> m : methods)
{
try
{
m.getValue().invoke(m.getKey(), params);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
ConsoleHelper.writeLog("ERROR", "Error while firing event: " + eventName, "PluginManager");
ConsoleHelper.logError(e);
}
}
}
public void initialize(ArrayList<APlugin> plugins)
{
// Set plugins reference
this.plugins = plugins;
// Create event handlers
List<String> knownEventNames = Arrays.asList(knownEvents);
// Prepare events builder list
for (String event : knownEvents)
{
events.put(event, new ArrayList<AbstractMap.SimpleEntry<APlugin, Method>>());
}
for (APlugin plugin : plugins)
{
if (!plugin.getClass().isAnnotationPresent(PluginInfo.class))
{
ConsoleHelper.writeLog("ERROR", "Plugin without plugin annotation registered! Exiting...", "PluginManager");
System.exit(-1);
}
// Write plugin info
PluginInfo pluginInfo = plugin.getClass().getAnnotation(PluginInfo.class);
pluginInfos.put(plugin, pluginInfo);
for (Method m : plugin.getClass().getDeclaredMethods())
{
// Check if this method has the event annotation
if (m.isAnnotationPresent(Event.class))
{
// Get the event annotation
Event eventAnnotation = m.getAnnotation(Event.class);
String eventType = eventAnnotation.eventType();
// Check if this event is allowed / known
if (knownEventNames.contains(eventType))
{
events.get(eventType).add(new AbstractMap.SimpleEntry<APlugin, Method>(plugin, m));
}
else
{
ConsoleHelper.writeLog("ERROR", "Plugin " + pluginInfo.pluginName() + " Tried to register event with unknown type: " + eventType, "PluginManager");
}
}
}
}
}
public void initializeGuiManager(GuiManager guiManager)
{
for (APlugin plugin : plugins)
{
plugin.initializeGuiManager(guiManager);
}
}
public void initializeGuiSystem()
{
for (APlugin plugin : plugins)
{
plugin.initializeGuiSystem();
}
}
public void loadModels()
{
for (APlugin plugin : plugins)
{
plugin.loadModels();
}
}
public void loadSounds()
{
for (APlugin plugin : plugins)
{
plugin.loadSounds();
}
}
// Plugin proxy functions
public void loadTextures()
{
for (APlugin plugin : plugins)
{
plugin.loadTextures();
}
}
}