Cleanup and simplification

This commit is contained in:
nico3000 2022-08-30 23:52:20 +02:00
parent 75eb4771c3
commit 976acb8d41
13 changed files with 198 additions and 365 deletions

View File

@ -1,6 +1,5 @@
import java.io.IOException; import java.io.IOException;
import javax.script.Invocable;
import javax.script.ScriptEngine; import javax.script.ScriptEngine;
import javax.script.ScriptException; import javax.script.ScriptException;
@ -35,7 +34,6 @@ public class Main {
e.printStackTrace(); e.printStackTrace();
} }
System.exit(0);
Parser parser = new Parser(); Parser parser = new Parser();
try (GameLogic logic = new GameLogic(parser)) { try (GameLogic logic = new GameLogic(parser)) {
logic.loadGameState("games/damnCoolTextAdventureFTW.json"); logic.loadGameState("games/damnCoolTextAdventureFTW.json");

View File

@ -6,13 +6,8 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate;
import game.logic.actionsystem.Action;
import game.logic.actionsystem.PlayerAction; import game.logic.actionsystem.PlayerAction;
import game.logic.actionsystem.actions.GoDirection;
import game.logic.actionsystem.actions.Open;
import game.logic.actionsystem.actions.TakeFrom;
import game.state.CircularLocationException; import game.state.CircularLocationException;
import game.state.Entity; import game.state.Entity;
import game.state.EntitySet; import game.state.EntitySet;
@ -35,135 +30,136 @@ public class GameLogic implements Closeable {
// TODO setup code, load from json or so // TODO setup code, load from json or so
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// final String NORTH = "north"; Entity east = this.state.createEntity("east");
// final String SOUTH = "south"; Entity west = this.state.createEntity("west");
final String EAST = "east"; Entity inside = this.state.createEntity("inside");
final String WEST = "west"; Entity outside = this.state.createEntity("outside");
final String INSIDE = "inside"; EntitySet genericDirections = EntitySet.createPersistent("genericDirections");
final String OUTSIDE = "outside"; genericDirections.add(east, west);
EntitySet houseDirections = EntitySet.createPersistent("houseDirections");
houseDirections.add(inside, outside);
Entity forestPath01 = this.state.createEntity("forest_path_01"); Entity forestPath01 = this.state.createEntity("forest_path_01");
Entity clearing = this.state.createEntity("clearing"); Entity clearing = this.state.createEntity("clearing");
Entity houseOutside = this.state.createEntity("house_outside"); Entity houseOutside = this.state.createEntity("house_outside");
Entity houseInside = this.state.createEntity("house_inside"); Entity houseInside = this.state.createEntity("house_inside");
Entity houseMainDoor = this.state.createEntity("house_main_door"); Entity houseMainDoor = this.state.createEntity("house_main_door");
houseMainDoor.setClosed(true);
forestPath01.connectBidirectional(EAST, null, WEST, clearing); EntitySet locations = EntitySet.createPersistent("locations");
forestPath01.connectBidirectional(WEST, null, EAST, houseOutside); locations.add(forestPath01, clearing, houseInside, houseOutside);
houseOutside.connectBidirectional(INSIDE, houseMainDoor, OUTSIDE, houseInside);
this.player = this.state.createEntity("player"); forestPath01.connectBidirectional(east, west, clearing);
Entity apple01 = this.state.createEntity("apple_01", "green"); forestPath01.connectBidirectional(west, east, houseOutside);
Entity apple02 = this.state.createEntity("apple_02", "red"); houseOutside.connectBidirectional(inside, outside, houseInside);
this.player.setLocation(clearing); this.player = clearing.createContainedEntity(this, "player");
apple01.setLocation(forestPath01); Entity apple01 = forestPath01.createContainedEntity(this, "apple_01");
apple02.setLocation(forestPath01); Entity apple02 = forestPath01.createContainedEntity(this, "apple_02");
//////////////////////////////////////////////////////////////////////// EntitySet collectibles = EntitySet.createPersistent("collectibles");
// TODO game specific action parsers collectibles.add(apple01, apple02);
////////////////////////////////////////////////////////////////////////
this.parser.pushActionParser(userInput -> userInput.get(0).equals("go") collectibles.pushPlayerAction("take", (logic, args) -> {
? new GoDirection(userInput.size() < 2 ? null : userInput.get(1)) Entity collectible = args[0];
: null); if (logic.getPlayer().getLocation() == collectible.getLocation()) {
this.parser.pushActionParser(userInput -> { try {
if (userInput.get(0).equals("take")) { collectible.setLocation(logic.getPlayer());
int fromIdx = userInput.indexOf("from"); logic.printRaw("Du nimmst %s, du Schuft.\n", collectible);
List<EntityDescription> whatToTake = this } catch (CircularLocationException ex) {
.parseDescriptionList(userInput.subList(1, fromIdx == -1 ? userInput.size() : fromIdx)); // Should not happpen
List<EntityDescription> whereToTakeFrom = fromIdx == -1 ? null ex.printStackTrace();
: this.parseDescriptionList(userInput.subList(fromIdx + 1, userInput.size())); }
return new TakeFrom(whatToTake, whereToTakeFrom);
} else {
return null;
} }
return true;
}); });
this.parser.pushActionParser(userInput -> {
if (userInput.get(0).equals("open")) { // this.player becomes first argument by calling pushPlayerAction on it
return new Open(this.parseDescriptionList(userInput.subList(1, userInput.size()))); 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 { } else {
return null; 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() { public Entity getPlayer() {
return this.player; return this.player;
} }
public EntitySet searchForEntity(EntityDescription description) {
return this.state.searchForEntity(description);
}
public EntitySet searchForEntity(EntityDescription description, Predicate<Entity> acceptFunction) {
return this.state.searchForEntity(description).getFiltered(acceptFunction);
}
public EntitySet searchForNearbyEntity(EntityDescription description) {
return this.searchForEntity(description, e -> {
if (this.player == null) {
return false;
} else if (this.player.contains(e, false)) {
return true;
} else if (this.player.getLocation() != null && this.player.getLocation().contains(e, false)) {
return true;
} else {
for (Entity.EntityConnection c : this.player.getLocation().getConnections().stream()
.map(this.player.getLocation()::getConnection).toList()) {
if (c.associatedEntity() == e) {
return true;
}
}
}
return false;
});
}
public void mainLoop() { public void mainLoop() {
while (!this.discontinue) { while (!this.discontinue) {
Action action = this.parser.readAction(); this.parser.executeUserInput(this);
if (action != null) {
action.execute(this);
}
} }
} }
private List<EntityDescription> parseDescriptionList(List<String> words) { public void printRaw(String rawMessage, Object... args) {
List<EntityDescription> descriptions = new LinkedList<>(); System.out.printf(rawMessage, args);
List<String> desc = new LinkedList<>();
for (String word : words) {
if (word.equals("and")) {
descriptions.add(new EntityDescription(desc));
desc = new LinkedList<>();
} else {
desc.add(word);
}
}
if (!desc.isEmpty()) {
descriptions.add(new EntityDescription(desc));
}
return descriptions;
}
public void printToUser(String messageId, Object... args) {
System.out.print(messageId);
for (int i = 0; i < args.length; ++i) {
System.out.print(i == 0 ? " " : ", ");
System.out.print(args[i]);
}
System.out.println();
}
public boolean canPlayerOpen(Entity entity) {
// TODO
return true;
}
public boolean canPlayerTake(Entity entity) {
// TODO
return true;
} }
public void registerPlayerAction(PlayerAction action) { public void registerPlayerAction(PlayerAction action) {

View File

@ -2,33 +2,53 @@ package game.logic;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Scanner; import java.util.Scanner;
import game.logic.actionsystem.Action; import game.state.Entity;
import game.logic.actionsystem.ActionParser; import game.state.EntitySet;
import startup.Environment; import startup.Environment;
import util.Commands; import util.Commands;
import util.TextColors; import util.TextColors;
public class Parser implements Closeable { public class Parser implements Closeable {
private final Scanner scanner = new Scanner(System.in); private final Scanner scanner = new Scanner(System.in);
private final List<ActionParser> actionParsers = new LinkedList<>();
public Action readAction() { public void executeUserInput(GameLogic logic) {
// Big TODO
// currently just reads an action id followed by entity ids
String greenPrompt = TextColors.BLUE.colorize(">"); String greenPrompt = TextColors.BLUE.colorize(">");
System.out.printf("%s ", greenPrompt); System.out.printf("%s ", greenPrompt);
List<String> input = Arrays.stream(scanner.nextLine().split("\\s+")).map(String::toLowerCase).toList(); List<String> input = Arrays.stream(scanner.nextLine().split("\\s+")).map(String::toLowerCase).toList();
if (!input.isEmpty()) {
for (ActionParser actionParser : this.actionParsers) { String actionId = input.get(0);
Action action = actionParser.parseAction(input); List<Entity> args = new ArrayList<>(input.size() - 1);
if (action != null) { for (int i = 1; i < input.size(); ++i) {
return action; Entity e = logic.getState().getEntityById(input.get(i));
if (e == null) {
logic.printRaw("Keine Ahnung, was du mit %s meinst, du Tölpel.\n", input.get(i));
return;
}
args.add(e);
}
Entity primaryEntity = this.getPrimaryEntity(logic, actionId, args);
if (primaryEntity != null) {
primaryEntity.tryExecutePlayerAction(actionId, EntitySet.createTemporary(args), logic);
} else if(logic.tryExecutePlayerAction(actionId, EntitySet.createTemporary(args))) {
logic.printRaw("Das geht doch so nicht.\n", args);
} }
} }
return null; }
private Entity getPrimaryEntity(GameLogic logic, String actionId, List<Entity> arguments) {
return switch (actionId) {
case "go" -> logic.getPlayer();
case "take", "open", "close" -> arguments.remove(0);
default -> null;
};
} }
public void parse(List<String> parameter) { public void parse(List<String> parameter) {
@ -40,10 +60,6 @@ public class Parser implements Closeable {
} }
} }
public void pushActionParser(ActionParser actionParser) {
this.actionParsers.add(actionParser);
}
@Override @Override
public void close() throws IOException { public void close() throws IOException {
this.scanner.close(); this.scanner.close();

View File

@ -1,22 +0,0 @@
package game.logic.actionsystem;
import game.logic.GameLogic;
public abstract class Action {
public enum Type {
TAKE, DROP,
COMBINE_WITH, USE,
GIVE_TO, TAKE_FROM,
PUT_ON,
PUSH, PULL, ROLL, ROLL_TO,
TRACE_RAY_TO,
KILL, KILL_WITH,
SEARCH, SEARCH_FOR,
TALK_TO, TELL_TO, ANNOY,
LOOK_AT, EXAMINE, READ, WRITE_ON_WITH,
HIT, HIT_WITH,
GO_TO,
}
public abstract void execute(GameLogic logic);
}

View File

@ -1,7 +0,0 @@
package game.logic.actionsystem;
import java.util.List;
public interface ActionParser {
public Action parseAction(List<String> userInput);
}

View File

@ -116,7 +116,6 @@ public class PlayerAction {
if (Arrays.stream(entitiesToUse).anyMatch(Objects::isNull)) { if (Arrays.stream(entitiesToUse).anyMatch(Objects::isNull)) {
return false; return false;
} }
this.executor.execute(logic, entitiesToUse); return this.executor.execute(logic, entitiesToUse);
return true;
} }
} }

View File

@ -7,7 +7,7 @@ import game.state.Entity;
* A player action executor provides specific instructions how to manipulate the * A player action executor provides specific instructions how to manipulate the
* game logic. * game logic.
*/ */
public class PlayerActionExecutor { public interface PlayerActionExecutor {
/** /**
* Executes the game logic manupulation. * Executes the game logic manupulation.
@ -15,7 +15,5 @@ public class PlayerActionExecutor {
* @param logic The game logic * @param logic The game logic
* @param args Arguments * @param args Arguments
*/ */
public void execute(GameLogic logic, Entity... args) { public boolean execute(GameLogic logic, Entity... args);
// TODO
}
} }

View File

@ -1,44 +0,0 @@
package game.logic.actionsystem.actions;
import game.logic.GameLogic;
import game.logic.actionsystem.Action;
import game.state.CircularLocationException;
import game.state.Entity;
public class GoDirection extends Action {
private final String directionId;
public GoDirection(String directionId) {
this.directionId = directionId;
}
public String getDirectionId() {
return this.directionId;
}
@Override
public void execute(GameLogic logic) {
if (logic.getPlayer() == null) {
logic.printToUser("go.player.null");
} else {
Entity location = logic.getPlayer().getLocation();
if (location == null) {
logic.printToUser("go.player.location.null", logic.getPlayer());
} else {
Entity.EntityConnection connection = location.getConnection(this.directionId);
if (connection == null || connection.to() == null) {
logic.printToUser("go.direction.unknown", logic.getPlayer().getLocation(), this.directionId);
} else if (connection.associatedEntity() != null && connection.associatedEntity().isClosed()) {
logic.printToUser("go.location.closed", connection.associatedEntity());
} else {
try {
logic.getPlayer().setLocation(connection.to());
logic.printToUser("go.success", location, connection.to());
} catch (CircularLocationException ex) {
logic.printToUser("go.locationCircular", ex);
}
}
}
}
}
}

View File

@ -1,32 +0,0 @@
package game.logic.actionsystem.actions;
import java.util.List;
import game.logic.EntityDescription;
import game.logic.GameLogic;
import game.logic.actionsystem.Action;
import game.state.Entity;
import game.state.EntitySet;
public class Open extends Action {
private final List<EntityDescription> descriptions;
public Open(List<EntityDescription> descriptions) {
this.descriptions = descriptions;
}
@Override
public void execute(GameLogic logic) {
for (EntitySet set : this.descriptions.stream().map(logic::searchForNearbyEntity).toList()) {
Entity e = set.collapse(logic);
if(e == null) {
logic.printToUser("open.noEntity");
} else if (logic.canPlayerOpen(e)) {
e.setClosed(false);
logic.printToUser("open.success", e);
} else {
logic.printToUser("open.failed", e);
}
}
}
}

View File

@ -1,50 +0,0 @@
package game.logic.actionsystem.actions;
import java.util.List;
import game.logic.EntityDescription;
import game.logic.GameLogic;
import game.logic.actionsystem.Action;
import game.state.CircularLocationException;
import game.state.Entity;
import game.state.EntitySet;
public class TakeFrom extends Action {
private final List<EntityDescription> what;
private final List<EntityDescription> fromWhere;
public TakeFrom(List<EntityDescription> what, List<EntityDescription> fromWhere) {
this.what = what;
this.fromWhere = fromWhere;
}
public List<EntityDescription> getWhat() {
return this.what;
}
public List<EntityDescription> getFromWhere() {
return this.fromWhere;
}
@Override
public void execute(GameLogic logic) {
// TODO incorporate fromWhere
for (EntityDescription ed : this.what) {
EntitySet es = logic.searchForNearbyEntity(ed);
if(es.isEmpty()) {
logic.printToUser("entity.notFound", ed);
}
Entity e = es.collapse(logic);
if (e != null && logic.canPlayerTake(e)) {
try {
e.setLocation(logic.getPlayer());
logic.printToUser("take.success", e);
} catch (CircularLocationException ex) {
logic.printToUser("take.error", ex);
}
} else {
logic.printToUser("take.failed", e);
}
}
}
}

View File

@ -1,6 +1,5 @@
package game.state; package game.state;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -24,21 +23,16 @@ import game.logic.actionsystem.PlayerActionExecutor;
* can store generic attributes. * can store generic attributes.
*/ */
public class Entity { public class Entity {
public record EntityConnection(Entity to, Entity associatedEntity) {
}
private final String id; private final String id;
private final Set<String> attributes = new HashSet<>();
private Entity location;
private boolean closed = false;
private final EntitySet contents;
private final Map<String, EntityConnection> connections = new HashMap<>();
private final Map<String, List<PlayerAction>> playerActions = new HashMap<>();
final Set<EntitySet> containingPersistentSets = new HashSet<>(); final Set<EntitySet> containingPersistentSets = new HashSet<>();
private final Map<String, String> attributes = new HashMap<>();
private Entity location;
private final EntitySet contents;
private final Map<Entity, Entity> connections = new HashMap<>();
private final Map<String, List<PlayerAction>> playerActions = new HashMap<>();
public Entity(String id, String... attributes) { public Entity(String id) {
this.id = id; this.id = id;
this.attributes.addAll(Arrays.asList(attributes));
this.contents = EntitySet.createPersistent(this.id + "::contents"); this.contents = EntitySet.createPersistent(this.id + "::contents");
} }
@ -46,30 +40,25 @@ public class Entity {
return this.id; return this.id;
} }
public Set<String> getAttributes() { public String getAttribute(String key) {
return Collections.unmodifiableSet(this.attributes); String value = this.attributes.get(key);
return value == null ? "" : value;
} }
public boolean addAttribute(String attribute) { public boolean getBoolAttribute(String key) {
return this.attributes.add(attribute); return Boolean.parseBoolean(this.getAttribute(key));
} }
public boolean removeAttribute(String attribute) { public void setAttribute(String key, Object value) {
return this.attributes.remove(attribute); if (value == null) {
} this.attributes.remove(key);
} else {
public void toggleAttribute(String attribute) { this.attributes.put(key, value.toString());
if (!this.attributes.remove(attribute)) {
this.attributes.add(attribute);
} }
} }
public void switchAttribute(String attr1, String attr2) { public void removeAttribute(String key) {
if (this.attributes.remove(attr1)) { this.setAttribute(key, null);
this.attributes.add(attr2);
} else if (this.attributes.remove(attr2)) {
this.attributes.add(attr1);
}
} }
public void setLocation(Entity location) throws CircularLocationException { public void setLocation(Entity location) throws CircularLocationException {
@ -88,18 +77,21 @@ public class Entity {
} }
} }
public boolean isClosed() {
return this.closed;
}
public void setClosed(boolean closed) {
this.closed = closed;
}
public boolean contains(Entity other, boolean recursive) { public boolean contains(Entity other, boolean recursive) {
return this.contents.getAll().stream().anyMatch(e -> e == other || (recursive && e.contains(other, true))); return this.contents.getAll().stream().anyMatch(e -> e == other || (recursive && e.contains(other, true)));
} }
public Entity createContainedEntity(GameLogic logic, String id) {
Entity e = logic.getState().createEntity(id);
try {
e.setLocation(this);
} catch (CircularLocationException ex) {
// should not happen
ex.printStackTrace();
}
return e;
}
public Entity getLocation() { public Entity getLocation() {
return this.location; return this.location;
} }
@ -108,32 +100,31 @@ public class Entity {
return this.contents.getAll(); return this.contents.getAll();
} }
public void connectUnidirectional(String directionId, Entity to, Entity associatedEntity) { public void connectUnidirectional(Entity direction, Entity to) {
this.connections.put(directionId, new EntityConnection(to, associatedEntity)); this.connections.put(direction, to);
} }
public void connectBidirectional(String dirIdFromThisToOther, Entity associatedEntity, String dirIdFromOtherToThis, public void connectBidirectional(Entity dirFromThisToOther, Entity dirFromOtherToThis, Entity other) {
Entity to) { this.connections.put(dirFromThisToOther, other);
this.connections.put(dirIdFromThisToOther, new EntityConnection(to, associatedEntity)); other.connections.put(dirFromOtherToThis, this);
to.connections.put(dirIdFromOtherToThis, new EntityConnection(this, associatedEntity));
} }
public void removeSingleConnection(String directionId) { public void removeSingleConnection(Entity direction) {
this.connections.remove(directionId); this.connections.remove(direction);
} }
public void removeBidirectionalConnection(String dirIdFromThisToOther, String dirIdFromOtherToThis) { public void removeBidirectionalConnection(Entity dirFromThisToOther, Entity dirFromOtherToThis) {
EntityConnection c = this.connections.remove(dirIdFromThisToOther); Entity other = this.connections.remove(dirFromThisToOther);
if (c != null) { if (other != null && other.connections.get(dirFromOtherToThis) == this) {
c.to.connections.remove(dirIdFromOtherToThis); other.connections.remove(dirFromOtherToThis);
} }
} }
public EntityConnection getConnection(String directionId) { public Entity getConnectedEntity(Entity direction) {
return this.connections.get(directionId); return this.connections.get(direction);
} }
public Set<String> getConnections() { public Set<Entity> getConnectionDirections() {
return Collections.unmodifiableSet(this.connections.keySet()); return Collections.unmodifiableSet(this.connections.keySet());
} }

View File

@ -33,15 +33,12 @@ public class EntitySet {
} }
private final String name; private final String name;
private final Set<Entity> entities; private final Set<Entity> entities = new HashSet<>();
private final Map<String, List<PlayerAction>> playerActions = new HashMap<>(); private final Map<String, List<PlayerAction>> playerActions = new HashMap<>();
private EntitySet(String name, Collection<Entity> entities) { private EntitySet(String name, Collection<Entity> entities) {
this.name = name; this.name = name;
this.entities = new HashSet<>(entities); this.add(entities.toArray(new Entity[0]));
if (this.name != null) {
this.entities.forEach(e -> e.containingPersistentSets.add(this));
}
} }
public boolean isEmpty() { public boolean isEmpty() {
@ -56,24 +53,20 @@ public class EntitySet {
return this.entities.size(); return this.entities.size();
} }
public boolean add(Entity entity) { public void add(Entity... entities) {
if (this.entities.add(entity)) { for (Entity e : entities) {
if (this.name != null) { if (this.entities.add(e) && this.name != null) {
entity.containingPersistentSets.add(this); e.containingPersistentSets.add(this);
} }
return true;
} }
return false;
} }
public boolean remove(Entity entity) { public void remove(Entity... entities) {
if(this.entities.remove(entity)) { for (Entity e : entities) {
if(this.name != null) { if (this.entities.remove(e) && this.name != null) {
entity.containingPersistentSets.remove(this); e.containingPersistentSets.remove(this);
} }
return true;
} }
return false;
} }
public boolean contains(Entity entity) { public boolean contains(Entity entity) {

View File

@ -1,25 +1,22 @@
package game.state; package game.state;
import java.util.LinkedList; import java.util.HashMap;
import java.util.List; import java.util.Map;
import game.logic.EntityDescription;
public class GameState { public class GameState {
private final List<Entity> entities = new LinkedList<>(); private final Map<String, Entity> entities = new HashMap<>();
public GameState() { public GameState() {
} }
public Entity createEntity(String id, String... attributes) { public Entity createEntity(String id) {
Entity e = new Entity(id, attributes); Entity e = new Entity(id);
this.entities.add(e); this.entities.put(id, e);
return e; return e;
} }
public EntitySet searchForEntity(EntityDescription description) { public Entity getEntityById(String id) {
return EntitySet.createTemporary(this.entities.stream().filter(e -> e.getId().equals(description.getMainWord()) return this.entities.get(id);
&& e.getAttributes().containsAll(description.getAttributes())).toList());
} }
} }