breaking: remove observable pattern, make methods return events directly
This commit is contained in:
parent
4802b0113d
commit
842db2439a
@ -64,4 +64,13 @@ public class NPC extends Entity {
|
|||||||
}
|
}
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "NPC{" +
|
||||||
|
"mp=" + mp +
|
||||||
|
", inventory=" + inventory +
|
||||||
|
", position=" + position +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,6 +167,6 @@ public class EntityManager {
|
|||||||
* @return An array containing every {@link Entity}
|
* @return An array containing every {@link Entity}
|
||||||
*/
|
*/
|
||||||
Entity[] export() {
|
Entity[] export() {
|
||||||
return (Entity[])entities.toArray();
|
return entities.toArray(new Entity[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import uulm.teamname.marvelous.gamelibrary.json.config.ScenarioConfig;
|
|||||||
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
import uulm.teamname.marvelous.gamelibrary.requests.Request;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Observer;
|
|
||||||
|
|
||||||
/** Represents a game instance. */
|
/** Represents a game instance. */
|
||||||
public class GameInstance {
|
public class GameInstance {
|
||||||
@ -21,9 +20,6 @@ public class GameInstance {
|
|||||||
/** The {@link GameStateManager} managing the {@link GameState} of the instance */
|
/** The {@link GameStateManager} managing the {@link GameState} of the instance */
|
||||||
private final GameStateManager manager;
|
private final GameStateManager manager;
|
||||||
|
|
||||||
/** The {@link EventEmitter} for {@link Event}s resulting from {@link Request}s */
|
|
||||||
private final EventEmitter emitter = new EventEmitter();
|
|
||||||
|
|
||||||
/** Constructs a new {@link GameInstance}. */
|
/** Constructs a new {@link GameInstance}. */
|
||||||
public GameInstance(PartyConfig partyConfig, CharacterConfig characterConfig, ScenarioConfig scenarioConfig) {
|
public GameInstance(PartyConfig partyConfig, CharacterConfig characterConfig, ScenarioConfig scenarioConfig) {
|
||||||
_state = new GameState(partyConfig, characterConfig, scenarioConfig);
|
_state = new GameState(partyConfig, characterConfig, scenarioConfig);
|
||||||
@ -34,20 +30,16 @@ public class GameInstance {
|
|||||||
/**
|
/**
|
||||||
* Checks an array of {@link Request}s for validity and automatically applies them if valid.
|
* Checks an array of {@link Request}s for validity and automatically applies them if valid.
|
||||||
* @param requests The requests to check
|
* @param requests The requests to check
|
||||||
* @return Whether or not the given set of requests was valid
|
* @return The list of resulting {@link Event}s or `null` if the check failed
|
||||||
*/
|
*/
|
||||||
public boolean checkRequestsAndApply(Request... requests) {
|
public ArrayList<Event> checkRequestsAndApply(Request... requests) {
|
||||||
if(manager.processRequests(requests, true)) {
|
if(manager.processRequests(requests, true)) {
|
||||||
emit(manager.apply());
|
ArrayList<Event> result = manager.apply();
|
||||||
|
result.addAll(manager.checkPostPhase());
|
||||||
Event[] result = manager.checkPostPhase();
|
return result;
|
||||||
if(result.length > 0) {
|
|
||||||
emit(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return null;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,7 +47,7 @@ public class GameInstance {
|
|||||||
* @param requests The requests to check
|
* @param requests The requests to check
|
||||||
* @return Whether or not the given set of requests is valid
|
* @return Whether or not the given set of requests is valid
|
||||||
*/
|
*/
|
||||||
public boolean checkRequestsSilent(Request... requests) {
|
public boolean checkRequests(Request... requests) {
|
||||||
return manager.processRequests(requests, false);
|
return manager.processRequests(requests, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,10 +55,14 @@ public class GameInstance {
|
|||||||
* Initializes and starts the game. Selected characters are given as a list of indices from the {@link CharacterConfig#characters} array.
|
* Initializes and starts the game. Selected characters are given as a list of indices from the {@link CharacterConfig#characters} array.
|
||||||
* @param selectedCharacters1 The characters selected by player 1
|
* @param selectedCharacters1 The characters selected by player 1
|
||||||
* @param selectedCharacters2 The characters selected by player 2
|
* @param selectedCharacters2 The characters selected by player 2
|
||||||
|
* @return The list of resulting {@link Event}s
|
||||||
*/
|
*/
|
||||||
public void startGame(ArrayList<Integer> selectedCharacters1, ArrayList<Integer> selectedCharacters2) {
|
public ArrayList<Event> startGame(ArrayList<Integer> selectedCharacters1, ArrayList<Integer> selectedCharacters2) {
|
||||||
emit(manager.initGame(selectedCharacters1, selectedCharacters2));
|
ArrayList<Event> result = manager.initGame(selectedCharacters1, selectedCharacters2);
|
||||||
emit(manager.startGame());
|
manager.applyEvents(result);
|
||||||
|
result.addAll(manager.startGame());
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,24 +85,7 @@ public class GameInstance {
|
|||||||
* Applies an array of {@link Event}s to the game state.
|
* Applies an array of {@link Event}s to the game state.
|
||||||
* @param events The events to apply.
|
* @param events The events to apply.
|
||||||
*/
|
*/
|
||||||
public void applyEvents(Event... events) {
|
public void applyEvents(ArrayList<Event> events) {
|
||||||
manager.applyEvents(events);
|
manager.applyEvents(events);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an {@link Observer} for events.
|
|
||||||
* @param observer The observer to add
|
|
||||||
*/
|
|
||||||
public void addObserver(Observer observer) {
|
|
||||||
emitter.addObserver(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instructs the emitter to emit an array of {@link Event}s.
|
|
||||||
* @param events The events to emit
|
|
||||||
*/
|
|
||||||
private void emit(Event... events) {
|
|
||||||
manager.applyEvents(events);
|
|
||||||
emitter.update(events);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ class GameLogic {
|
|||||||
public static Event buildGameStateEvent(GameState state) {
|
public static Event buildGameStateEvent(GameState state) {
|
||||||
return new EventBuilder(EventType.GamestateEvent)
|
return new EventBuilder(EventType.GamestateEvent)
|
||||||
.withEntities(state.entities.export())
|
.withEntities(state.entities.export())
|
||||||
.withTurnOrder((EntityID[])state.turnOrder.toArray())
|
.withTurnOrder(state.turnOrder.toArray(new EntityID[0]))
|
||||||
.withMapSize(state.mapSize)
|
.withMapSize(state.mapSize)
|
||||||
.withActiveCharacter(state.activeCharacter)
|
.withActiveCharacter(state.activeCharacter)
|
||||||
.withStoneCooldowns(state.stoneCooldown.export())
|
.withStoneCooldowns(state.stoneCooldown.export())
|
||||||
@ -562,9 +562,7 @@ class GameLogic {
|
|||||||
for(int x = 0; x < state.mapSize.getX(); x++) {
|
for(int x = 0; x < state.mapSize.getX(); x++) {
|
||||||
for(int y = 0; y < state.mapSize.getY(); y++) {
|
for(int y = 0; y < state.mapSize.getY(); y++) {
|
||||||
if(state.scenarioConfig.scenario[y][x] == FieldType.ROCK) {
|
if(state.scenarioConfig.scenario[y][x] == FieldType.ROCK) {
|
||||||
result.add(new EventBuilder(EventType.SpawnEntityEvent)
|
state.entities.addEntity(new Rock(new EntityID(EntityType.Rocks, rockIndex++), new IntVector2(x, y), 100));
|
||||||
.withEntity(new Rock(new EntityID(EntityType.Rocks, rockIndex++), new IntVector2(x, y), 100))
|
|
||||||
.buildEntityEvent());
|
|
||||||
}else {
|
}else {
|
||||||
free.add(new IntVector2(x, y));
|
free.add(new IntVector2(x, y));
|
||||||
}
|
}
|
||||||
@ -585,8 +583,7 @@ class GameLogic {
|
|||||||
int selected = characters.get(i);
|
int selected = characters.get(i);
|
||||||
|
|
||||||
EntityID id = new EntityID(i < p1 ? EntityType.P1 : EntityType.P2, i % p1);
|
EntityID id = new EntityID(i < p1 ? EntityType.P1 : EntityType.P2, i % p1);
|
||||||
result.add(new EventBuilder(EventType.SpawnEntityEvent)
|
state.entities.addEntity(new Character(
|
||||||
.withEntity(new Character(
|
|
||||||
id, position,
|
id, position,
|
||||||
state.characterConfig.characters[selected].name,
|
state.characterConfig.characters[selected].name,
|
||||||
state.characterConfig.characters[selected].HP,
|
state.characterConfig.characters[selected].HP,
|
||||||
@ -595,12 +592,13 @@ class GameLogic {
|
|||||||
state.characterConfig.characters[selected].attackRange,
|
state.characterConfig.characters[selected].attackRange,
|
||||||
state.characterConfig.characters[selected].rangedDamage,
|
state.characterConfig.characters[selected].rangedDamage,
|
||||||
state.characterConfig.characters[selected].meleeDamage
|
state.characterConfig.characters[selected].meleeDamage
|
||||||
))
|
));
|
||||||
.buildEntityEvent());
|
|
||||||
|
|
||||||
state.turnOrder.add(id);
|
state.turnOrder.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.add(buildGameStateEvent(state));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,7 +847,28 @@ class GameLogic {
|
|||||||
public static ArrayList<Event> handleThanos(GameState state, NPC thanos) {
|
public static ArrayList<Event> handleThanos(GameState state, NPC thanos) {
|
||||||
ArrayList<Event> result = new ArrayList<>();
|
ArrayList<Event> result = new ArrayList<>();
|
||||||
|
|
||||||
|
if(thanos.inventory.getFreeSlots() > 0) {
|
||||||
|
|
||||||
|
IntVector2 picked = null;
|
||||||
|
float lowestDistance = Integer.MAX_VALUE;
|
||||||
|
for(int x = 0; x < state.mapSize.getX(); x++) {
|
||||||
|
for(int y = 0; y < state.mapSize.getY(); y++) {
|
||||||
|
IntVector2 pos = new IntVector2(x, y);
|
||||||
|
for(Entity e: state.entities.findByPosition(pos)) {
|
||||||
|
if(e instanceof InfinityStone || (e instanceof Character && ((Character)e).inventory.getSize() > 0)) {
|
||||||
|
float distance = thanos.getPosition().distanceChebyshev(pos);
|
||||||
|
if(distance < lowestDistance) {
|
||||||
|
picked = pos;
|
||||||
|
lowestDistance = distance;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -49,8 +49,8 @@ class GameStateManager {
|
|||||||
* Handles events that happen after a turn phase.
|
* Handles events that happen after a turn phase.
|
||||||
* @return The optionally resulting {@link Event}s
|
* @return The optionally resulting {@link Event}s
|
||||||
*/
|
*/
|
||||||
public Event[] checkPostPhase() {
|
public ArrayList<Event> checkPostPhase() {
|
||||||
return (Event[])GameLogic.checkTurnEnd(state).toArray();
|
return GameLogic.checkTurnEnd(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,23 +59,23 @@ class GameStateManager {
|
|||||||
* @param selectedCharacters2 The characters selected by player 2
|
* @param selectedCharacters2 The characters selected by player 2
|
||||||
* @return The resulting {@link Event}s
|
* @return The resulting {@link Event}s
|
||||||
*/
|
*/
|
||||||
public Event[] initGame(ArrayList<Integer> selectedCharacters1, ArrayList<Integer> selectedCharacters2) {
|
public ArrayList<Event> initGame(ArrayList<Integer> selectedCharacters1, ArrayList<Integer> selectedCharacters2) {
|
||||||
return GameLogic.startGame(state, selectedCharacters1, selectedCharacters2).toArray(new Event[0]);
|
return GameLogic.startGame(state, selectedCharacters1, selectedCharacters2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the game.
|
* Starts the game.
|
||||||
* @return The resulting {@link Event}s
|
* @return The resulting {@link Event}s
|
||||||
*/
|
*/
|
||||||
public Event[] startGame() {
|
public ArrayList<Event> startGame() {
|
||||||
return GameLogic.handleRoundStart(state).toArray(new Event[0]);
|
return GameLogic.handleRoundStart(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies an array of {@link Event}s to the game state.
|
* Applies an array of {@link Event}s to the game state.
|
||||||
* @param events The events to apply
|
* @param events The events to apply
|
||||||
*/
|
*/
|
||||||
public void applyEvents(Event... events) {
|
public void applyEvents(ArrayList<Event> events) {
|
||||||
for(Event event: events) {
|
for(Event event: events) {
|
||||||
GameLogic.applyEvent(state, event);
|
GameLogic.applyEvent(state, event);
|
||||||
}
|
}
|
||||||
@ -85,13 +85,12 @@ class GameStateManager {
|
|||||||
* Applies the result of the last processRequests call.
|
* Applies the result of the last processRequests call.
|
||||||
* @return A list of applied events
|
* @return A list of applied events
|
||||||
*/
|
*/
|
||||||
public Event[] apply() {
|
public ArrayList<Event> apply() {
|
||||||
Event[] toReturn = new Event[queue.size()];
|
ArrayList<Event> toReturn = new ArrayList<Event>(queue.size());
|
||||||
Event current;
|
Event current;
|
||||||
int i = 0;
|
|
||||||
while ((current = queue.poll()) != null) {
|
while ((current = queue.poll()) != null) {
|
||||||
GameLogic.applyEvent(state, current);
|
GameLogic.applyEvent(state, current);
|
||||||
toReturn[i++] = current;
|
toReturn.add(current);
|
||||||
}
|
}
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
|||||||
import uulm.teamname.marvelous.gamelibrary.entities.*;
|
import uulm.teamname.marvelous.gamelibrary.entities.*;
|
||||||
import uulm.teamname.marvelous.gamelibrary.entities.Character;
|
import uulm.teamname.marvelous.gamelibrary.entities.Character;
|
||||||
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.events.EventBuilder;
|
||||||
|
import uulm.teamname.marvelous.gamelibrary.events.EventType;
|
||||||
import uulm.teamname.marvelous.gamelibrary.json.config.*;
|
import uulm.teamname.marvelous.gamelibrary.json.config.*;
|
||||||
import uulm.teamname.marvelous.gamelibrary.requests.*;
|
import uulm.teamname.marvelous.gamelibrary.requests.*;
|
||||||
|
|
||||||
@ -16,6 +18,7 @@ import java.util.List;
|
|||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
class GameLogicTest {
|
class GameLogicTest {
|
||||||
private static final Iterator<Integer> randomIntegers = ThreadLocalRandom.current().ints().iterator();
|
private static final Iterator<Integer> randomIntegers = ThreadLocalRandom.current().ints().iterator();
|
||||||
@ -24,6 +27,9 @@ class GameLogicTest {
|
|||||||
private static CharacterConfig characterConfig;
|
private static CharacterConfig characterConfig;
|
||||||
private static ScenarioConfig scenarioConfig;
|
private static ScenarioConfig scenarioConfig;
|
||||||
|
|
||||||
|
private static ArrayList<Integer> player1Selection = new ArrayList<>();
|
||||||
|
private static ArrayList<Integer> player2Selection = new ArrayList<>();
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void setUp() {
|
static void setUp() {
|
||||||
partyConfig = new PartyConfig();
|
partyConfig = new PartyConfig();
|
||||||
@ -55,6 +61,14 @@ class GameLogicTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 6; i++) {
|
||||||
|
player1Selection.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 6; i < 12; i++) {
|
||||||
|
player2Selection.add(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String generateName(int length) {
|
private static String generateName(int length) {
|
||||||
@ -87,16 +101,7 @@ class GameLogicTest {
|
|||||||
void testGeneration() {
|
void testGeneration() {
|
||||||
GameInstance game = new GameInstance(partyConfig, characterConfig, scenarioConfig);
|
GameInstance game = new GameInstance(partyConfig, characterConfig, scenarioConfig);
|
||||||
|
|
||||||
ArrayList<Integer> selected1 = new ArrayList<>();
|
game.startGame(player1Selection, player2Selection);
|
||||||
for(int i = 0; i < 6; i++) {
|
|
||||||
selected1.add(i);
|
|
||||||
}
|
|
||||||
ArrayList<Integer> selected2 = new ArrayList<>();
|
|
||||||
for(int i = 6; i < 12; i++) {
|
|
||||||
selected2.add(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
game.startGame(selected1, selected2);
|
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
@ -114,7 +119,7 @@ class GameLogicTest {
|
|||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
||||||
for(Integer i: selected1) {
|
for(Integer i: player1Selection) {
|
||||||
Entity found = game.state.getEntities().findEntity(new EntityID(EntityType.P1, n));
|
Entity found = game.state.getEntities().findEntity(new EntityID(EntityType.P1, n));
|
||||||
assertNotEquals(null, found, "Character Entity "+n+" for Player 1 should exist");
|
assertNotEquals(null, found, "Character Entity "+n+" for Player 1 should exist");
|
||||||
Character c = (Character)found;
|
Character c = (Character)found;
|
||||||
@ -129,7 +134,7 @@ class GameLogicTest {
|
|||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
||||||
for(Integer i: selected2) {
|
for(Integer i: player2Selection) {
|
||||||
Entity found = game.state.getEntities().findEntity(new EntityID(EntityType.P2, n));
|
Entity found = game.state.getEntities().findEntity(new EntityID(EntityType.P2, n));
|
||||||
assertNotEquals(null, found, "Character Entity "+n+" for Player 2 should exist");
|
assertNotEquals(null, found, "Character Entity "+n+" for Player 2 should exist");
|
||||||
Character c = (Character)found;
|
Character c = (Character)found;
|
||||||
@ -165,26 +170,15 @@ class GameLogicTest {
|
|||||||
void testGame() {
|
void testGame() {
|
||||||
GameInstance game = new GameInstance(partyConfig, characterConfig, scenarioConfig);
|
GameInstance game = new GameInstance(partyConfig, characterConfig, scenarioConfig);
|
||||||
|
|
||||||
game.addObserver(new EventObserver() {
|
ArrayList<Event> result = game.startGame(player1Selection, player2Selection);
|
||||||
@Override
|
|
||||||
protected void handle(Event[] events) {
|
|
||||||
|
|
||||||
}
|
assertTrue(result.size() > 0, "Start game should return at least one event");
|
||||||
});
|
|
||||||
|
|
||||||
ArrayList<Integer> selected1 = new ArrayList<>();
|
Event actual = result.get(0);
|
||||||
for(int i = 0; i < 6; i++) {
|
|
||||||
selected1.add(i);
|
|
||||||
}
|
|
||||||
ArrayList<Integer> selected2 = new ArrayList<>();
|
|
||||||
for(int i = 6; i < 12; i++) {
|
|
||||||
selected2.add(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
game.startGame(selected1, selected2);
|
assertEquals(EventType.GamestateEvent, actual.type, "First event should be a GameStateEvent");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// @Provide("gamestate")
|
// @Provide("gamestate")
|
||||||
// Arbitrary<GameState> gamestate() {
|
// Arbitrary<GameState> gamestate() {
|
||||||
// var states = Arbitraries.integers()
|
// var states = Arbitraries.integers()
|
||||||
|
Loading…
Reference in New Issue
Block a user