package vooga.towerdefense.gameeditor.controller; import java.awt.BorderLayout; import java.awt.Dimension; import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.swing.JFrame; import vooga.towerdefense.gameeditor.gamemaker.editorscreens.GameEditorScreen; import vooga.towerdefense.gameeditor.gamemaker.editorscreens.StartUpScreen; import vooga.towerdefense.gameeditor.gamemaker.xmlwriters.XMLWriter; /** * Controls the game editor & makes the XML * file based on input from the game editor. * * @author Angelica Schwartz * @author Leonard Ng'eno */ public class GameEditorController extends JFrame { private static final long serialVersionUID = 1L; private static final String TITLE_KEYWORD = "GAME EDITOR"; private static final String FACTORY_INDICATOR = "Factory"; private static final Dimension SIZE = new Dimension(700, 700); private static final String CLASS_INDICATOR_STRING = ".class"; private Dimension mySize; private Dimension myMapSize; private String myName; private XMLWriter myXMLWriter; /** * Constructor. * * @param size The preferred size of this game editor. */ public GameEditorController (Dimension size) { setTitle(TITLE_KEYWORD); mySize = size; setSize(mySize); setPreferredSize(mySize); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); initializeXML(); initializeGUI(); } /** * Starts a new XML file & initializes the main parent elements */ private void initializeXML () { myXMLWriter = new XMLWriter(); } /** * Starts the visual for the game editor. */ private void initializeGUI () { StartUpScreen screen = new StartUpScreen(SIZE, this); getContentPane().add(screen, BorderLayout.CENTER); pack(); setVisible(true); } /** * Saves the XML file. */ public void saveFile () { myXMLWriter.saveFile(myName); } /** * Sets the name of this game. * * @param name The desired name of the game. */ public void setNameOfGame (String name) { myName = name; } /** * Creates a new level in the game and adds it to the XML file. * * @param name The name of the level * @param rules A map of rules, which controls different instructions for updating scores and * determining other game states * @param actions Any action present in the game. */ public void addLevelToGame (String name, String rules, String actions) { myXMLWriter.addLevelToGame(name, rules, actions); } /** * Adds a map to the XML file. * * @param name The name of the map, used as a tag. This name will be formatted. * @param image A string URL to the background image * @param width The width determined by the user * @param height The height of the map determined by the user * @param tile Size The size of a tile * @param map The grid */ public void addMapToGame (String name, String image, String width, String height, String tileSize, String map) { myXMLWriter.addMapToGame(name, image, width, height, tileSize, map); } /** * adds the player information to the game. * @param attributes is the map of the attributes */ public void addPlayerToGame(Map<String, String> attributes) { myXMLWriter.addPlayerToGame(attributes); } /** * Creates a new game element based on user input and adds it to the game. * * @param type Determines the type of element * @param name is the game element's name * @param path is the image path * @param attributes is the map of attribute name to value * @param actions is the map of action name to value */ public void addGameElementToGame (String type, String name, String path, String dimension, Map<String, String> attributes, String actions) { myXMLWriter.addGameElementToGame(type, name, path, dimension, attributes, actions); } /** * adds the rules to the game. * * @param rulesText */ public void addRulesToGame (String rulesText) { myXMLWriter.addRulesToGame(rulesText); } /** * Gets the list of already created units. * * @return a list of unit names as strings. */ public List<String> getUnits () { return myXMLWriter.getUnits(); } /** * * @param dimension * @param viewInfo * @param map */ public void addViewToGame (String dimension, List<String> viewInfo, Map<String, List<String>> map) { myXMLWriter.addViewToGame(dimension, viewInfo, map); } /** * sets the map size for this game. * * @param mapSize */ public void setMapSize (Dimension mapSize) { myMapSize = mapSize; } /** * gets the map size for this game. * * @return Dimension that is the map size */ public Dimension getMapSize () { return myMapSize; } /** * uses reflection to display the next screen in the sequence. * * @param nextScreenName is the next screen */ @SuppressWarnings({ "rawtypes", "unchecked" }) public void displayNextScreen (String nextScreenName) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException { if (nextScreenName != null) { Class[] args = { Dimension.class, GameEditorController.class }; Class theClass = Class.forName(nextScreenName); Constructor cons = theClass.getConstructor(args); GameEditorScreen screen = (GameEditorScreen) cons.newInstance(mySize, this); getContentPane().add(screen); screen.display(); pack(); setVisible(true); } else { System.exit(0); } } /** * returns the parameters of the constructor in the desired class. * * @param className the class path * @return a list of parameters as strings * @throws ClassNotFoundException */ @SuppressWarnings("rawtypes") public List<String> getParametersForAction (String className) throws ClassNotFoundException { List<String> parameters = new ArrayList<String>(); Class c = Class.forName(className + FACTORY_INDICATOR); Constructor cons = c.getConstructors()[0]; Class[] parameterClasses = cons.getParameterTypes(); for (Class parameterClass : parameterClasses) { parameters.add(parameterClass.getSimpleName().toString()); } return parameters; } /** * gets the available actions for the gam developer. * * @param actionPackageName is the package where the action factories are. * @return * @throws IOException * @throws ClassNotFoundException */ public List<String> getAvailableActions (String packageName) throws IOException, ClassNotFoundException { List<String> actions = new ArrayList<String>(); List<Class> actionClasses = getClassesInPackage(packageName); for (Class actionClass : actionClasses) { String action = actionClass.getSimpleName().toString(); action = action.substring(0, action.length() - FACTORY_INDICATOR.length()); actions.add(action); } return actions; } /** * Get the classes in this package. * * @param packageName * @return list of classes in the package * @throws IOException * @throws ClassNotFoundException */ @SuppressWarnings("rawtypes") public static List<Class> getClassesInPackage (String packageName) { List<Class> classes = new ArrayList<Class>(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); String path = packageName.replace(".", "/"); URL resource = classLoader.getResource(path); path = resource.toString().replaceAll("%20", " "); try { resource = new URL(path); } catch (MalformedURLException e1) { e1.printStackTrace(); } File directory = new File(resource.getFile()); if (directory.exists()) { File[] files = directory.listFiles(); for (File file : files) { if (file.getName().endsWith(CLASS_INDICATOR_STRING)) { try { classes.add(Class .forName(packageName + "." + file.getName().subSequence(0, file.getName().length() - CLASS_INDICATOR_STRING .length()))); } catch (ClassNotFoundException e) { } } } } return classes; } /** * gets the list of class names in the desired package. * * @param packageName * @return a list of strings * @throws ClassNotFoundException * @throws IOException */ @SuppressWarnings("rawtypes") public List<String> getClassNamesInPackage (String packageName) throws IOException, ClassNotFoundException { List<String> names = new ArrayList<String>(); List<Class> classes = getClassesInPackage(packageName); for (Class c : classes) { if (!c.getName().contains("$")) { names.add(c.getName().substring(packageName.length() + 1, c.getName().length())); } names.add(c.getName().substring(packageName.length() + 1, c.getName().length())); } return names; } /** * gets the attributes as strings for the game developer. * * @return the attributes as a list of strings * @throws ClassNotFoundException */ public List<String> getAttributes (String attributeClassName) throws ClassNotFoundException { List<String> fields = new ArrayList<String>(); Field[] fieldList = getFieldsInClass(attributeClassName); for (Field field : fieldList) { fields.add(field.getName()); } return fields; } /** * gets the list of field names in the desired class. * * @param packageName * @return * @throws ClassNotFoundException */ @SuppressWarnings("rawtypes") private Field[] getFieldsInClass (String className) throws ClassNotFoundException { Class attributesClass = Class.forName(className); Field fieldList[] = attributesClass.getDeclaredFields(); return fieldList; } public List<String> getFiles(String packagePath) { List<String> fileNames = new ArrayList<String>(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); String path = packagePath.replace(".", "/"); URL resource = classLoader.getResource(path); path = resource.toString().replaceAll("%20", " "); try { resource = new URL(path); } catch (MalformedURLException e1) { e1.printStackTrace(); } File directory = new File(resource.getFile()); if (directory.exists()) { File[] files = directory.listFiles(); for (File file : files) { fileNames.add(file.getName()); } } return fileNames; } }