/** * eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the * <e-UCM> research group. * * Copyright 2005-2010 <e-UCM> research group. * * You can access a list of all the contributors to eAdventure at: * http://e-adventure.e-ucm.es/contributors * * <e-UCM> is a research group of the Department of Software Engineering * and Artificial Intelligence at the Complutense University of Madrid * (School of Computer Science). * * C Profesor Jose Garcia Santesmases sn, * 28040 Madrid (Madrid), Spain. * * For more info please visit: <http://e-adventure.e-ucm.es> or * <http://www.e-ucm.es> * * **************************************************************************** * * This file is part of eAdventure, version 2.0 * * eAdventure is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * eAdventure 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with eAdventure. If not, see <http://www.gnu.org/licenses/>. */ package es.eucm.ead.engine.debugger; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.Action; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Event; import com.badlogic.gdx.scenes.scene2d.Group; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.utils.Array; import com.google.inject.Inject; import com.google.inject.Singleton; import es.eucm.ead.engine.game.Game; import es.eucm.ead.engine.game.GameLoader; import es.eucm.ead.engine.game.interfaces.EffectsHandler.EffectsListener; import es.eucm.ead.engine.gameobjects.sceneelements.SceneGO; import es.eucm.ead.model.Commands; import es.eucm.ead.model.elements.BasicElement; import es.eucm.ead.model.elements.effects.ChangeChapterEf; import es.eucm.ead.model.elements.effects.ChangeSceneEf; import es.eucm.ead.model.elements.effects.Effect; import es.eucm.ead.model.elements.effects.ToggleSoundEf; import es.eucm.ead.model.elements.scenes.SceneElement; import es.eucm.ead.reader.model.Manifest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.IOException; import java.util.Map; @Singleton public class CommandInterpreter implements EffectsListener { private static final Logger logger = LoggerFactory .getLogger(CommandInterpreter.class); private Game game; private GameLoader gameLoader; private Array<String> effects; private int waiting = 0; private Vector2 aux = new Vector2(); @Inject public CommandInterpreter(Game game, GameLoader gameLoader) { this.game = game; game.getEffectsHandler().addEffectListener(this); this.gameLoader = gameLoader; this.effects = new Array<String>(); } public boolean isWaiting() { return waiting > 0; } public void effectLaunched(Effect e, Event action, SceneElement parent) { if (effects.size > 0 && effects.get(0).equals(e.getId())) { effects.removeIndex(0); } } public String interpret(String command) { String result = "Invalid command."; try { command = command.trim(); if (command.equals(Commands.NOTIFY)) { waiting--; result = "Notified."; } else if (command.equals(Commands.WAIT)) { waiting++; result = "Waiting."; } else if (command.equals(Commands.PASS)) { result = "OK."; } else if (command.equals("scene")) { result = game.getGUI().getScene().getElement().getId(); } else if (command.startsWith(Commands.GO_CHAPTER)) { String[] parts = command.split(" "); game.addEffect(new ChangeChapterEf(parts[1])); } else if (command.equals(Commands.CHAPTER)) { result = gameLoader.getCurrentChapterId(); } else if (command.startsWith(Commands.GO)) { String[] parts = command.split(" "); game.addEffect(new ChangeSceneEf(new BasicElement(parts[1]))); result = "OK."; } else if (command.startsWith(Commands.LIST)) { String[] parts = command.split(" "); if (parts[1].equals("scenes")) { Manifest m = gameLoader.loadManifest(); result = m.getChaptersScenes().get( gameLoader.getCurrentChapterId()).toString(); } else if (parts[1].equals("chapters")) { Manifest m = gameLoader.loadManifest(); result = m.getChaptersScenes().keySet().toString(); } else if (parts[1].equals("elements")) { SceneGO scene = game.getGUI().getScene(); result = addGroup(scene); } else if (parts[1].equals("variables")) { Map<String, Object> vars = game.getGameState() .getElementVars(parts[2]); result = vars == null ? "[]" : vars.toString(); } } else if (command.startsWith(Commands.LOAD)) { String[] parts = command.split(" "); result = runCommands(parts[1]); } else if (command.startsWith(Commands.SET)) { String[] parts = command.split(" "); String[] field = parts[1].split("\\."); Object value = parseValue(parts[2]); game.getGameState().setValue(field[0], field[1], value); result = "OK."; } else if (command.startsWith(Commands.GET)) { String[] parts = command.split(" "); String[] field = parts[1].split("\\."); result = game.getGameState().getValue(field[0], field[1], null) + ""; } else if (command.startsWith(Commands.PING)) { String[] parts = command.split(" "); ping(parts[1]); result = "OK."; } else if (command.startsWith(Commands.SOUND)) { game.addEffect(new ToggleSoundEf()); result = "OK."; } else if (command.startsWith(Commands.WATCHING)) { String[] parts = command.split(" "); result = game.getGameState().countWatchers(parts[1]) + " watchers."; } else if (command.startsWith(Commands.WHOIS)) { result = game.getGUI().getGameObjectUnderPointer() + ""; } else if (command.startsWith("is")) { String[] parts = command.split(" "); result = game.getGUI().getScene().findActor(parts[1]) == null ? "false" : "true"; } else if (command.startsWith(Commands.MOVE)) { String[] parts = command.split(" "); int x = Integer.parseInt(parts[1]); int y = Integer.parseInt(parts[2]); Gdx.input.setCursorPosition(x, Gdx.graphics.getHeight() - y); result = "OK."; } else if (command.startsWith(Commands.WHERE)) { result = "(" + Gdx.input.getX() + ", " + (Gdx.graphics.getHeight() - Gdx.input.getY()) + ")"; } else if (command.startsWith(Commands.CLICK)) { String[] parts = command.split(" "); int x = Integer.parseInt(parts[1]); int y = Integer.parseInt(parts[2]); Gdx.input.setCursorPosition(x, Gdx.graphics.getHeight() - y); Stage s = gameLoader.getEngine().getStage(); aux.set(x, y); aux = s.screenToStageCoordinates(aux); Actor a = s.hit(aux.x, aux.y, true); gameLoader.getEngine().getStage().touchDown(x, y, 0, Input.Buttons.LEFT); result = a == null ? "" : a.getName(); } else if (command.startsWith(Commands.EXIT)) { Gdx.app.exit(); } else if (command.startsWith(Commands.LOG)) { logger.debug(command.substring(Math .max(0, command.indexOf(' ')))); result = "OK."; } else if (command.startsWith(Commands.WAIT_EFFECTS)) { String[] parts = command.split(" "); for (int i = 1; i < parts.length; i++) { effects.add(parts[i]); } result = effects.size + " effects waiting"; } else if (command.startsWith(Commands.CLEAR_EFFECTS)) { result = effects.size + " effects cleared."; effects.clear(); } else if (command.startsWith(Commands.EFFECTS)) { result = effects.toString(); } } catch (Exception e) { logger.error("{}", e); result = "Wrong parameters"; } return result; } private void ping(String part) { Actor a = game.getGUI().getScene().findActor(part); if (a != null) { a.addAction(new PingAction()); } } private String addGroup(Group g) { String result = ""; for (Actor a : g.getChildren()) { if (a.getName() != null) { result += a.getName() + ","; } if (a instanceof Group) { result += addGroup((Group) a); } } return result; } private Object parseValue(String part) { if (part.equals("true")) { return true; } else if (part.equals("false")) { return false; } else if (part.contains("\"")) { return part.substring(1, part.length() - 1); } else { Object value = null; if (part.contains(".")) { try { value = Float.parseFloat(part); } catch (Exception e) { } } if (value == null) { try { value = Integer.parseInt(part); } catch (Exception e) { } } return value == null ? part : value; } } private String runCommands(String file) { String result = ""; FileHandle fh = Gdx.files.internal(file); if (fh != null) { BufferedReader reader = null; try { reader = new BufferedReader(fh.reader()); String line; while ((line = reader.readLine()) != null) { // Ignore comments if (!line.startsWith("#")) { result = interpret(line); } } } catch (Exception e) { logger.error("Error reading text file {}", file, e); } finally { try { if (reader != null) { reader.close(); } } catch (IOException e) { logger.error("Error reading text file {}", e); } } } return result; } public class PingAction extends Action { private boolean going; private float time = 10.0f; private Color prevColor; @Override public boolean act(float delta) { if (!going) { this.prevColor = this.actor.getColor().cpy(); actor.setColor(Color.GREEN); time = 2000; going = true; } if (going) { time -= delta; } if (time < 0) { this.actor.setColor(prevColor); } return time < 0; } } }