untitledTextAdventure/src/main/java/game/logic/GameLogic.java

209 lines
8.1 KiB
Java

package game.logic;
import java.io.Closeable;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import game.logic.actionsystem.PlayerAction;
import game.state.CircularLocationException;
import game.state.Entity;
import game.state.EntitySet;
import game.state.GameState;
public class GameLogic implements Closeable {
private final Parser parser;
private GameState state;
private Entity player;
private boolean discontinue = false;
private Map<String, List<PlayerAction>> playerActions = new HashMap<>();
public GameLogic(Parser parser) {
this.parser = parser;
this.state = new GameState();
}
public void loadGameState(String stateDescJsonFilePath) throws CircularLocationException {
////////////////////////////////////////////////////////////////////////
// TODO setup code, load from json or so
////////////////////////////////////////////////////////////////////////
Entity east = this.state.createEntity("east");
Entity west = this.state.createEntity("west");
Entity inside = this.state.createEntity("inside");
Entity outside = this.state.createEntity("outside");
EntitySet genericDirections = EntitySet.createPersistent("genericDirections");
genericDirections.add(east, west);
EntitySet houseDirections = EntitySet.createPersistent("houseDirections");
houseDirections.add(inside, outside);
Entity forestPath01 = this.state.createEntity("forest_path_01");
Entity clearing = this.state.createEntity("clearing");
Entity houseOutside = this.state.createEntity("house_outside");
Entity houseInside = this.state.createEntity("house_inside");
Entity houseMainDoor = this.state.createEntity("house_main_door");
EntitySet locations = EntitySet.createPersistent("locations");
locations.add(forestPath01, clearing, houseInside, houseOutside);
forestPath01.connectBidirectional(east, west, clearing);
forestPath01.connectBidirectional(west, east, houseOutside);
houseOutside.connectBidirectional(inside, outside, houseInside);
this.player = clearing.createContainedEntity(this, "player");
Entity apple01 = forestPath01.createContainedEntity(this, "apple_01");
Entity apple02 = forestPath01.createContainedEntity(this, "apple_02");
EntitySet collectibles = EntitySet.createPersistent("collectibles");
collectibles.add(apple01, apple02);
collectibles.pushPlayerAction("take", (logic, args) -> {
Entity collectible = args[0];
if (logic.getPlayer().getLocation() == collectible.getLocation()) {
try {
collectible.setLocation(logic.getPlayer());
logic.printRaw("Du nimmst %s, du Schuft.\n", collectible);
} catch (CircularLocationException ex) {
// Should not happpen
ex.printStackTrace();
}
}
return true;
});
// this.player becomes first argument by calling pushPlayerAction on it
PlayerAction goAction = this.player.pushPlayerAction("go", (logic, args) -> {
Entity character = args[0];
Entity direction = args[1];
Entity newLocation = character.getLocation().getConnectedEntity(direction);
if (newLocation != null) {
try {
logic.getPlayer().setLocation(newLocation);
logic.printRaw("Du gehst Richtung %s und landest hier: %s, du Lutscher!\n", direction, newLocation);
} catch (CircularLocationException ex) {
ex.printStackTrace();
}
} else {
logic.printRaw("Hier geht es nicht nach %s, du Nichtsnutz.\n", direction);
}
return true;
});
// second argument must be exactly 1 of the entites contained in genericDirections
goAction.pushVaryingNeededEntites(genericDirections, 1);
// again first argument becomes this.player by calling pushPlayerAction on it
PlayerAction goHouseAction = this.player.pushPlayerAction("go", (logic, args) -> {
Entity character = args[0];
Entity direction = args[1];
Entity newLocation = character.getLocation().getConnectedEntity(direction);
if (newLocation != null && character.getLocation() == houseInside
|| character.getLocation() == houseOutside) {
if (houseMainDoor.getBoolAttribute("open")) {
try {
character.setLocation(newLocation);
} catch (CircularLocationException ex) {
ex.printStackTrace();
}
logic.printRaw("Du gehst durch die Tür, du Eumel.\n");
} else {
logic.printRaw("Die Tür ist zu, du Dödel.\n");
}
return true;
}
return false;
});
// second argument must be exactly 1 of the entites contained in houseDirections
goHouseAction.pushVaryingNeededEntites(houseDirections, 1);
houseMainDoor.pushPlayerAction("open", (logic, args) -> {
if (logic.getPlayer().getLocation() == houseInside || logic.getPlayer().getLocation() == houseOutside) {
if (houseMainDoor.getBoolAttribute("open")) {
logic.printRaw("Die Tür ist schon offen, du Hammel.\n");
} else {
houseMainDoor.setAttribute("open", true);
logic.printRaw("Du öffnest die Tür, du Dummbatz.\n");
}
return true;
}
return false;
});
houseMainDoor.pushPlayerAction("close", (logic, args) -> {
if (logic.getPlayer().getLocation() == houseInside || logic.getPlayer().getLocation() == houseOutside) {
if (!houseMainDoor.getBoolAttribute("open")) {
logic.printRaw("Die Tür ist schon geschlossen, du Mummenschanz.\n");
} else {
houseMainDoor.setAttribute("open", false);
logic.printRaw("Du schließt die Tür, du Angsthase.\n");
}
return true;
}
return false;
});
}
public GameState getState() {
return this.state;
}
public Entity getPlayer() {
return this.player;
}
public void mainLoop() {
while (!this.discontinue) {
this.parser.executeUserInput(this);
}
}
public void printRaw(String rawMessage, Object... args) {
System.out.printf(rawMessage, args);
}
public void registerPlayerAction(PlayerAction action) {
List<PlayerAction> l = this.playerActions.get(action.getId());
if (l == null) {
this.playerActions.put(action.getId(), l = new LinkedList<>());
}
l.add(action);
}
/**
* Searches for the first player action that does not use any entity and
* executes it if one is found.
*
* @param id The action id
* @return <code>true</code>, if an action was found and executed
*/
public boolean tryExecutePlayerAction(String id) {
return this.tryExecutePlayerAction(id, null);
}
/**
* Searches for the first player action that can operate on the given set of
* entities and executes it if one is found.
*
* @param id The action id
* @param entities The entities on which the action shoud operate
* @return <code>true</code>, if an action was found and executed
*/
public boolean tryExecutePlayerAction(String id, EntitySet entities) {
List<PlayerAction> l = this.playerActions.get(id);
if (l != null) {
for (PlayerAction a : l) {
if (a.tryExecute(null, entities, this)) {
return true;
}
}
}
return false;
}
@Override
public void close() throws IOException {
this.parser.close();
}
}