diff options
| author | Mike Vink <mike1994vink@gmail.com> | 2021-07-29 17:37:06 +0200 |
|---|---|---|
| committer | Mike Vink <mike1994vink@gmail.com> | 2021-07-29 17:37:06 +0200 |
| commit | c0004768de6695e2acfa48c392765b03b81ba9d0 (patch) | |
| tree | b48160c635b2a9d423ebbda2b101a50578d386f4 | |
| parent | 935c4676165fc2cf8cc938725ff473643acd0077 (diff) | |
refactor(): making battles is now easy
30 files changed, 556 insertions, 382 deletions
diff --git a/api/src/main/java/akkamon/api/EventSocket.java b/api/src/main/java/akkamon/api/EventSocket.java index 77950ed..0f92878 100644 --- a/api/src/main/java/akkamon/api/EventSocket.java +++ b/api/src/main/java/akkamon/api/EventSocket.java @@ -1,5 +1,6 @@ package akkamon.api; +import akkamon.domain.actors.AkkamonNexus; import akkamon.domain.AkkamonSession; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketAdapter; @@ -10,7 +11,7 @@ import java.util.concurrent.CountDownLatch; public class EventSocket extends WebSocketAdapter implements AkkamonSession { private final CountDownLatch closureLatch = new CountDownLatch(1); - private String trainerId; + private AkkamonNexus.TrainerID trainerID; @Override public void onWebSocketConnect(Session sess) @@ -59,12 +60,12 @@ public class EventSocket extends WebSocketAdapter implements AkkamonSession { } @Override - public void setTrainerId(String trainerId) { - this.trainerId = trainerId; + public void settrainerID(AkkamonNexus.TrainerID trainerID) { + this.trainerID = trainerID; } @Override - public String getTrainerId() { - return trainerId; + public AkkamonNexus.TrainerID gettrainerID() { + return this.trainerID; } } diff --git a/api/src/main/java/akkamon/api/MessagingEngine.java b/api/src/main/java/akkamon/api/MessagingEngine.java index 957ad6e..fb913ca 100644 --- a/api/src/main/java/akkamon/api/MessagingEngine.java +++ b/api/src/main/java/akkamon/api/MessagingEngine.java @@ -4,7 +4,7 @@ import akka.actor.typed.ActorRef; import akka.actor.typed.ActorSystem; import akkamon.api.models.*; import akkamon.domain.AkkamonMessageEngine; -import akkamon.domain.AkkamonNexus; +import akkamon.domain.actors.AkkamonNexus; import akkamon.domain.AkkamonSession; import akkamon.domain.InteractionHandshaker; import com.google.gson.Gson; @@ -15,15 +15,17 @@ import java.util.concurrent.TimeUnit; public class MessagingEngine implements AkkamonMessageEngine { + // nexus: a connection or series of connections linking two or more things. + private ActorRef<AkkamonNexus.Command> nexus; + private Map<String, Set<AkkamonSession>> sceneIdToAkkamonSessions = new HashMap<>(); - private Map<String, AkkamonSession> trainerIdToAkkamonSessions = new HashMap<>(); + private Map<AkkamonNexus.TrainerID, AkkamonSession> trainerIDToAkkamonSessions = new HashMap<>(); private Map<String, ActorRef<InteractionHandshaker.Command>> pendingInteractioRequestToHandshaker = new HashMap<>(); - private Gson gson = new Gson(); - private ActorRef<AkkamonNexus.Command> system; + private Gson gson = new Gson(); public MessagingEngine() { - this.system = ActorSystem.create(AkkamonNexus.create(this), "akkamon-system"); + this.nexus = ActorSystem.create(AkkamonNexus.create(this), "akkamon-system"); ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2); executor.scheduleAtFixedRate(new Runnable() { @@ -36,27 +38,29 @@ public class MessagingEngine implements AkkamonMessageEngine { } private void heartBeat() { - system.tell(new AkkamonNexus.RequestHeartBeat( + nexus.tell(new AkkamonNexus.RequestHeartBeat( UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE, - system + nexus )); } @Override - public void broadCastHeartBeatToScene(String sceneId, - Map<String, AkkamonNexus.MovementQueueReading> trainerPositions) { + public void broadCastHeartBeatToScene(String sceneId, Map<AkkamonNexus.TrainerID, AkkamonNexus.MovementQueueReading> trainerPositions) { + Set<AkkamonSession> sceneSessions = sceneIdToAkkamonSessions.get(sceneId); // System.out.println(sceneSessions); // System.out.println(sceneIdToAkkamonSessions.keySet()); if (sceneSessions != null) { for (AkkamonSession session : sceneSessions) { - Map<String, AkkamonNexus.MovementQueueReading> withoutSelf = new HashMap<>(trainerPositions); - withoutSelf.remove(session.getTrainerId()); + Map<AkkamonNexus.TrainerID, AkkamonNexus.MovementQueueReading> withoutSelf = new HashMap<>(trainerPositions); + withoutSelf.remove(session.gettrainerID()); + HeartBeatEvent heartBeat = new HeartBeatEvent( withoutSelf ); + String heartBeatMessage = gson.toJson(heartBeat); - // System.out.println("Sending to " + session.getTrainerId()); + // System.out.println("Sending to " + session.gettrainerID()); // System.out.println(heartBeatMessage); session.send( heartBeatMessage @@ -66,14 +70,21 @@ public class MessagingEngine implements AkkamonMessageEngine { } @Override - public void broadCastInteractionRequestToSessionWithTrainerIds(List<String> trainerIds, String type, String trainerId, String requestName, ActorRef<InteractionHandshaker.Command> handshaker) { + public void broadCastInteractionRequestToSessionWithtrainerIDs( + List<AkkamonNexus.TrainerID> trainerIDs, + String type, + AkkamonNexus.TrainerID trainerID, + String requestName, + ActorRef<InteractionHandshaker.Command> handshaker) { + System.out.println("Sending interaction request " + requestName); this.pendingInteractioRequestToHandshaker.put(requestName, handshaker); - trainerIds.add(trainerId); - for (String id : trainerIds) { - AkkamonSession session = trainerIdToAkkamonSessions.get(id); + trainerIDs.add(trainerID); + + for (AkkamonNexus.TrainerID id : trainerIDs) { + AkkamonSession session = trainerIDToAkkamonSessions.get(id); if (session != null) { - session.send(gson.toJson(new InteractionRequest( + session.send(gson.toJson(new OutgoingInteractionRequest( type, id, requestName @@ -86,33 +97,35 @@ public class MessagingEngine implements AkkamonMessageEngine { @Override - public void registerTrainerSessionToSceneAndTrainerIdMaps(String sceneId, AkkamonSession session) { - System.out.println("Registering session to scene " + sceneId); - Set<AkkamonSession> sceneIdMapping = sceneIdToAkkamonSessions.get(sceneId); - AkkamonSession trainerIdMapping = trainerIdToAkkamonSessions.get(session.getTrainerId()); + public void registerTrainerSessionToSceneAndtrainerIDMaps(AkkamonNexus.TrainerID trainerID, AkkamonSession session) { + System.out.println("Registering session to scene " + trainerID.scene); + + Set<AkkamonSession> sceneIdMapping = sceneIdToAkkamonSessions.get(trainerID.scene); + // AkkamonSession trainerIDMapping = trainerIDToAkkamonSessions.get(session.gettrainerID()); + if (sceneIdMapping != null) { sceneIdMapping.add(session); } else { sceneIdMapping = new HashSet<>(); sceneIdMapping.add(session); - sceneIdToAkkamonSessions.put(sceneId, + sceneIdToAkkamonSessions.put(trainerID.scene, sceneIdMapping ); System.out.println(sceneIdToAkkamonSessions.keySet()); } - trainerIdToAkkamonSessions.put(session.getTrainerId(), session); - System.out.println(trainerIdToAkkamonSessions); + trainerIDToAkkamonSessions.put(session.gettrainerID(), session); + System.out.println(trainerIDToAkkamonSessions); - System.out.println("Sending trainerId: " + session.getTrainerId()); + System.out.println("Sending trainerID: " + session.gettrainerID()); // TODO what if registration goes wrong ... session.send( - gson.toJson(new TrainerRegistrationReplyEvent(session.getTrainerId())) + gson.toJson(new TrainerRegistrationReplyEvent(session.gettrainerID())) ); } @Override - public void removeTrainerSessionFromScene(String sceneId, AkkamonSession session) { + public void removeTrainerSessionFromScene(AkkamonNexus.TrainerID sceneId, AkkamonSession session) { this.sceneIdToAkkamonSessions.get(sceneId).remove(session); } @@ -123,12 +136,12 @@ public class MessagingEngine implements AkkamonMessageEngine { if (entry.getValue().contains(session)) sceneId = entry.getKey(); } - system.tell(new AkkamonNexus.RequestTrainerOffline( + nexus.tell(new AkkamonNexus.RequestTrainerOffline( UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE, - session.getTrainerId(), + session.gettrainerID(), sceneId, session, - system + nexus )); } @@ -138,9 +151,10 @@ public class MessagingEngine implements AkkamonMessageEngine { } @Override - public void broadCastInteractionStart(String requestName, String interactionType, Set<String> waitingToStartInteraction) { - for (String trainerId : waitingToStartInteraction) { - AkkamonSession session = trainerIdToAkkamonSessions.get(trainerId); + public void broadCastInteractionStart(String requestName, String interactionType, Set<AkkamonNexus.TrainerID> waitingToStartInteraction) { + for (AkkamonNexus.TrainerID trainerID : waitingToStartInteraction) { + + AkkamonSession session = trainerIDToAkkamonSessions.get(trainerID); session.send(gson.toJson( new InteractionStartEvent( requestName, @@ -152,75 +166,74 @@ public class MessagingEngine implements AkkamonMessageEngine { } @Override - public void broadCastHandshakeFail(String requestName, Set<String> waitingToStartInteraction) { + public void broadCastHandshakeFail(String requestName, Set<AkkamonNexus.TrainerID> waitingToStartInteraction) { System.out.println("Handshake fail not implemented yet!"); } void incoming(AkkamonSession session, String message) { + System.out.println(message); Event event = gson.fromJson(message, Event.class); if (event == null) { System.out.println("Received non-supported message DTO."); return; } - // TODO use session trainerId + // TODO use session trainerID String sceneId = "DemoScene"; switch (event.type) { case INTERACTION_REPLY: System.out.println("received interaction reply!"); - sendToHandshaker(event.requestName, event.trainerId, event.sceneId, event.value); + sendToHandshaker(event.requestName, event.trainerID, event.value); break; case INTERACTION_REQUEST: System.out.println("received interaction request"); System.out.println(event.interaction); - system.tell(new AkkamonNexus.RequestInteraction( + nexus.tell(new AkkamonNexus.RequestInteraction( UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE, event.interaction.type, - event.sceneId, - event.interaction.requestingTrainerId, - event.interaction.receivingTrainerIds, - system + event.trainerID, + event.interaction.receivingtrainerIDs, + nexus )); break; case START_MOVING: - system.tell(new AkkamonNexus.RequestStartMoving( + System.out.println(message); + nexus.tell(new AkkamonNexus.RequestStartMoving( UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE, - session.getTrainerId(), - event.sceneId, + event.trainerID, event.direction, - system + nexus )); break; case NEW_TILE_POS: - system.tell( + nexus.tell( new AkkamonNexus.RequestNewTilePos( UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE, - session.getTrainerId(), - event.sceneId, + event.trainerID, event.tilePos, - system + nexus ) ); break; case STOP_MOVING: - system.tell( + nexus.tell( new AkkamonNexus.RequestStopMoving( UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE, - session.getTrainerId(), - event.sceneId, + event.trainerID, event.direction, - system + nexus ) ); break; case TRAINER_REGISTRATION_REQUEST: - String trainerId = String.valueOf(sceneIdToAkkamonSessions.get(sceneId) == null ? 1 : sceneIdToAkkamonSessions.get(sceneId).size() + 1); - system.tell(new AkkamonNexus.RequestTrainerRegistration( - trainerId, + // Here we make the trainerID and the scene is hard coded! + String trainerName = String.valueOf(sceneIdToAkkamonSessions.get(sceneId) == null ? 1 : sceneIdToAkkamonSessions.get(sceneId).size() + 1); + nexus.tell(new AkkamonNexus.RequestTrainerRegistration( + trainerName, sceneId, session, - system + nexus )); break; case HEART_BEAT: @@ -230,11 +243,11 @@ public class MessagingEngine implements AkkamonMessageEngine { } - private void sendToHandshaker(String requestName, String trainerId, String sceneId, boolean value) { + private void sendToHandshaker(String requestName, AkkamonNexus.TrainerID trainerID, boolean value) { ActorRef<InteractionHandshaker.Command> handshaker = pendingInteractioRequestToHandshaker.get(requestName); if (handshaker != null) { handshaker.tell( - new InteractionHandshaker.InteractionReply(requestName, trainerId, sceneId, value) + new InteractionHandshaker.InteractionReply(requestName, trainerID, value) ); } } diff --git a/api/src/main/java/akkamon/api/models/Event.java b/api/src/main/java/akkamon/api/models/Event.java index 4743453..06ca8d0 100644 --- a/api/src/main/java/akkamon/api/models/Event.java +++ b/api/src/main/java/akkamon/api/models/Event.java @@ -1,13 +1,13 @@ package akkamon.api.models; +import akkamon.domain.actors.AkkamonNexus; import akkamon.domain.Direction; import akkamon.domain.TilePos; public class Event { public EventType type; - public String trainerId; + public AkkamonNexus.TrainerID trainerID; public Direction direction; - public String sceneId; public TilePos tilePos; public Interaction interaction; public String requestName; diff --git a/api/src/main/java/akkamon/api/models/HeartBeatEvent.java b/api/src/main/java/akkamon/api/models/HeartBeatEvent.java index b795feb..2ec98ad 100644 --- a/api/src/main/java/akkamon/api/models/HeartBeatEvent.java +++ b/api/src/main/java/akkamon/api/models/HeartBeatEvent.java @@ -1,13 +1,13 @@ package akkamon.api.models; -import akkamon.domain.AkkamonNexus; +import akkamon.domain.actors.AkkamonNexus; import java.util.Map; public class HeartBeatEvent extends Event { - public Map<String, AkkamonNexus.MovementQueueReading> remoteMovementQueues; + public Map<AkkamonNexus.TrainerID, AkkamonNexus.MovementQueueReading> remoteMovementQueues; - public HeartBeatEvent(Map<String, AkkamonNexus.MovementQueueReading> remoteMovementQueues) { + public HeartBeatEvent(Map<AkkamonNexus.TrainerID, AkkamonNexus.MovementQueueReading> remoteMovementQueues) { this.type = EventType.HEART_BEAT; this.remoteMovementQueues = remoteMovementQueues; } diff --git a/api/src/main/java/akkamon/api/models/Interaction.java b/api/src/main/java/akkamon/api/models/Interaction.java index 5bc9d17..ad947e9 100644 --- a/api/src/main/java/akkamon/api/models/Interaction.java +++ b/api/src/main/java/akkamon/api/models/Interaction.java @@ -1,21 +1,22 @@ package akkamon.api.models; +import akkamon.domain.actors.AkkamonNexus; + import java.util.List; public class Interaction { public String type; - public String requestingTrainerId; - public List<String> receivingTrainerIds; + public String requestingtrainerID; + public List<AkkamonNexus.TrainerID> receivingtrainerIDs; - public Interaction(String type, String requestingTrainerId, List<String> receivingTrainerIds) { + public Interaction(String type, String requestingtrainerID, List<AkkamonNexus.TrainerID> receivingtrainerIDs) { this.type = type; - this.requestingTrainerId = requestingTrainerId; - this.receivingTrainerIds = receivingTrainerIds; + this.receivingtrainerIDs = receivingtrainerIDs; } public String toString() { return "interaction={\n\ttype: " + this.type + ",\n" + - "\trequestingTrainerId: " + this.requestingTrainerId + ",\n" + - "\treceivingTrainerIds: " + this.receivingTrainerIds + "\n}"; + "\trequestingtrainerID: " + this.requestingtrainerID + ",\n" + + "\treceivingtrainerIDs: " + this.receivingtrainerIDs + "\n}"; } } diff --git a/api/src/main/java/akkamon/api/models/InteractionRequest.java b/api/src/main/java/akkamon/api/models/InteractionRequest.java deleted file mode 100644 index ae91972..0000000 --- a/api/src/main/java/akkamon/api/models/InteractionRequest.java +++ /dev/null @@ -1,13 +0,0 @@ -package akkamon.api.models; - -public class InteractionRequest extends Event { - - public String interactionType; - - public InteractionRequest(String interactionType, String trainerId, String requestName) { - this.type = EventType.INTERACTION_REQUEST; - this.interactionType = interactionType; - this.trainerId = trainerId; - this.requestName = requestName; - } -} diff --git a/api/src/main/java/akkamon/api/models/OutgoingInteractionRequest.java b/api/src/main/java/akkamon/api/models/OutgoingInteractionRequest.java new file mode 100644 index 0000000..9360384 --- /dev/null +++ b/api/src/main/java/akkamon/api/models/OutgoingInteractionRequest.java @@ -0,0 +1,15 @@ +package akkamon.api.models; + +import akkamon.domain.actors.AkkamonNexus; + +public class OutgoingInteractionRequest extends Event { + + public String interactionType; + + public OutgoingInteractionRequest(String interactionType, AkkamonNexus.TrainerID trainerID, String requestName) { + this.type = EventType.INTERACTION_REQUEST; + this.interactionType = interactionType; + this.trainerID = trainerID; + this.requestName = requestName; + } +} diff --git a/api/src/main/java/akkamon/api/models/TrainerRegistrationReplyEvent.java b/api/src/main/java/akkamon/api/models/TrainerRegistrationReplyEvent.java index 107b722..2120e45 100644 --- a/api/src/main/java/akkamon/api/models/TrainerRegistrationReplyEvent.java +++ b/api/src/main/java/akkamon/api/models/TrainerRegistrationReplyEvent.java @@ -1,13 +1,12 @@ package akkamon.api.models; -import akkamon.domain.AkkamonNexus; - -import java.util.Map; +import akkamon.domain.actors.AkkamonNexus; public class TrainerRegistrationReplyEvent extends Event { - public TrainerRegistrationReplyEvent(String sessionTrainerId) { + + public TrainerRegistrationReplyEvent(AkkamonNexus.TrainerID sessiontrainerID) { this.type = EventType.TRAINER_REGISTRATION_REPLY; - this.trainerId = sessionTrainerId; + this.trainerID = sessiontrainerID; } } diff --git a/client/src/akkamon/client/Client.ts b/client/src/akkamon/client/Client.ts index 0e7e8c3..4adaec5 100644 --- a/client/src/akkamon/client/Client.ts +++ b/client/src/akkamon/client/Client.ts @@ -39,7 +39,10 @@ import { HeartBeatReplyEvent, Interaction, OutgoingInteractionRequestEvent, - InteractionReplyEvent + InteractionReplyEvent, + StartMovingEvent, + NewTilePosEvent, + StopMovingEvent } from './OutgoingEvents'; @@ -85,9 +88,10 @@ export class Client implements AkkamonClient this.send(new HeartBeatReplyEvent()); break; case EventType.TRAINER_REGISTRATION_REPLY: - if (event.trainerId !== undefined) { - console.log("setting Session trainerId to: " + event.trainerId); - this.session.trainerId = event.trainerId; + if (event.trainerID !== undefined) { + console.log("setting Session trainerID to: "); + console.log(event.trainerID); + this.session.trainerID = event.trainerID; } break; case EventType.INTERACTION_REQUEST: @@ -213,23 +217,19 @@ export class Client implements AkkamonClient sendInteractionRequest(interaction: Interaction) { console.log("sent an interaction request!"); - console.log(this.getCurrentSceneKey()); + console.log(this.getTrainerID()); console.log(JSON.stringify(interaction)); this.interactionEngine!.setAwaitingInteractionRequestInitiation(true); this.send(new OutgoingInteractionRequestEvent( - this.getCurrentSceneKey(), + this.getTrainerID()!, interaction )); } - getSessionTrainerId() { - return this.session.trainerId; - } - - getCurrentSceneKey() { - return this.scene!.scene.key; + getTrainerID() { + return this.session.trainerID; } sendInteractionReply(value: boolean, requestName: string) { @@ -237,10 +237,30 @@ export class Client implements AkkamonClient this.interactionEngine!.setAnswering(false); this.interactionEngine!.setWaitingForInteractionToStart(true); this.send(new InteractionReplyEvent( - this.getSessionTrainerId()!, - this.getCurrentSceneKey()!, + this.getTrainerID()!, requestName, value )); } + + sendStartMove(direction: Direction) { + this.send(new StartMovingEvent(this.getTrainerID()!, direction)); + } + + sendNewTilePos(tilePos: {x: number, y: number}) { + this.send(new NewTilePosEvent( + this.getTrainerID()!, tilePos + ) + ); + } + + sendStopMoving(direction: Direction) { + this.send( + new StopMovingEvent( + this.getTrainerID()!, + direction + ) + ); + + } } diff --git a/client/src/akkamon/client/IncomingEvents.ts b/client/src/akkamon/client/IncomingEvents.ts index 1145b4c..be02bf9 100644 --- a/client/src/akkamon/client/IncomingEvents.ts +++ b/client/src/akkamon/client/IncomingEvents.ts @@ -2,10 +2,11 @@ import { EventType, AkkamonEvent } from './EventType'; import type { Direction } from '../render/Direction'; +type TrainerID = {id: string, scene: string} export interface IncomingEvent extends AkkamonEvent { - remoteMovementQueues?:{[trainerId: string]: { value: Array<Direction> }} - trainerId?: string + remoteMovementQueues?:{[trainerID: string]: { value: Array<Direction> }} + trainerID?: TrainerID requestId?: number requestName?: string interactionType?: string @@ -17,7 +18,7 @@ export class IncomingInteractionRequest implements IncomingEvent { constructor( public interactionType: string, - public trainerId: string, + public trainerID: TrainerID, public requestName: string ) { } } @@ -35,7 +36,7 @@ export class PlayerRegistrationReplyEvent implements IncomingEvent { public type: EventType = EventType.TRAINER_REGISTRATION_REPLY; constructor( - public trainerId: string + public trainerID: TrainerID ) { } } diff --git a/client/src/akkamon/client/InteractionEngine.ts b/client/src/akkamon/client/InteractionEngine.ts index f54ced4..ee5b4ac 100644 --- a/client/src/akkamon/client/InteractionEngine.ts +++ b/client/src/akkamon/client/InteractionEngine.ts @@ -47,7 +47,7 @@ export class InteractionEngine extends AkkamonEngine { this.answering = true; this.scene.pushMenu(new InteractionRequestDialogue(this.scene, ["YES", "NO"], - {name: message!.trainerId, + {name: message!.trainerID.id, requestType: message!.interactionType, requestName: message!.requestName} )); @@ -59,7 +59,7 @@ export class InteractionEngine extends AkkamonEngine { } push(event: IncomingInteractionRequest) { - // check trainerId + // check trainerID if (this.awaitingInit) { this.waitingForResponseOf = event.requestName; diff --git a/client/src/akkamon/client/OutgoingEvents.ts b/client/src/akkamon/client/OutgoingEvents.ts index 9feb49b..6c19b07 100644 --- a/client/src/akkamon/client/OutgoingEvents.ts +++ b/client/src/akkamon/client/OutgoingEvents.ts @@ -2,20 +2,33 @@ import type { Direction } from '../render/Direction'; import { EventType, AkkamonEvent } from './EventType'; +export type TrainerID = { + id: string, + scene: string +} + +interface OutgoingEvent extends AkkamonEvent { + trainerID: TrainerID; +} + export type RemoteMovementQueues = { - [trainerId: string]: { value: Array<Direction> } + [trainerID: string]: { value: Array<Direction> } } export type Interaction = { type: string, - requestingTrainerId: string, - receivingTrainerIds: string[] + receivingtrainerIDs: TrainerID[] } -export interface InteractionEvent extends AkkamonEvent { +export interface InteractionEvent extends OutgoingEvent { interaction: Interaction } + + + + + export class HeartBeatReplyEvent implements AkkamonEvent { public type: EventType = EventType.HEART_BEAT; @@ -34,54 +47,53 @@ export class PlayerRegistrationRequestEvent implements AkkamonEvent { } -export class StartMovingEvent implements AkkamonEvent { +export class StartMovingEvent implements OutgoingEvent { public type: EventType = EventType.START_MOVING; constructor( - public sceneId: string, + public trainerID: TrainerID, public direction: Direction, ) { } } -export class StopMovingEvent implements AkkamonEvent { +export class StopMovingEvent implements OutgoingEvent { public type: EventType = EventType.STOP_MOVING; constructor( - public sceneId: string, + public trainerID: TrainerID, public direction: Direction, ) { } } -export class NewTilePosEvent implements AkkamonEvent { +export class NewTilePosEvent implements OutgoingEvent { public type: EventType = EventType.NEW_TILE_POS; constructor( - public sceneId: string, + public trainerID: TrainerID, public tilePos: {x: number, y: number} ) { } } -export class OutgoingInteractionRequestEvent implements InteractionEvent { +export class OutgoingInteractionRequestEvent implements OutgoingEvent { public type: EventType = EventType.INTERACTION_REQUEST; constructor( - public sceneId: string, + public trainerID: TrainerID, public interaction: Interaction, ) { } } -export class InteractionReplyEvent implements AkkamonEvent { +export class InteractionReplyEvent implements OutgoingEvent { public type: EventType = EventType.INTERACTION_REPLY; constructor( - public trainerId: string, - public sceneId: string, + public trainerID: TrainerID, public requestName: string, public value: boolean ) { } diff --git a/client/src/akkamon/client/Session.ts b/client/src/akkamon/client/Session.ts index 6b6f5ec..7357743 100644 --- a/client/src/akkamon/client/Session.ts +++ b/client/src/akkamon/client/Session.ts @@ -1,11 +1,7 @@ -import type Player from './player'; +import type { + TrainerID +} from './OutgoingEvents'; export default interface AkkamonSession extends WebSocket { - trainerId?: string - -} - -interface User { - name: string - password: string + trainerID?: TrainerID; } diff --git a/client/src/akkamon/client/Socket.ts b/client/src/akkamon/client/Socket.ts index b46c73f..3184416 100644 --- a/client/src/akkamon/client/Socket.ts +++ b/client/src/akkamon/client/Socket.ts @@ -7,7 +7,7 @@ import { export class Socket extends WebSocket implements AkkamonSession { - public trainerId?: string; + public trainerID?: {id: string, scene: string}; constructor( url: string, diff --git a/client/src/akkamon/render/engine/GridPhysics.ts b/client/src/akkamon/render/engine/GridPhysics.ts index 7c266bf..4a7d1e1 100644 --- a/client/src/akkamon/render/engine/GridPhysics.ts +++ b/client/src/akkamon/render/engine/GridPhysics.ts @@ -66,9 +66,7 @@ export class GridPhysics extends AkkamonEngine { private startMoving(direction: Direction): void { console.log("Sending startMovingEvent"); - this.client.send( - new StartMovingEvent(this.playerSprite.getScene(), direction) - ); + this.client.sendStartMove(direction); this.playerSprite.startAnimation(direction); this.movementDirection = direction; this.updatePlayerSpriteTilePosition(); @@ -96,12 +94,7 @@ export class GridPhysics extends AkkamonEngine { } private updatePlayerSpriteTilePosition() { - this.client.send( - new NewTilePosEvent( - this.playerSprite.getScene(), - this.playerSprite.getTilePos() - ) - ); + this.client.sendNewTilePos(this.playerSprite.getTilePos()); this.playerSprite.setTilePos( this.playerSprite .getTilePos() @@ -149,12 +142,7 @@ export class GridPhysics extends AkkamonEngine { } private stopMoving(): void { - this.client.send( - new StopMovingEvent( - this.playerSprite.getScene(), - this.movementDirection - ) - ); + this.client.sendStopMoving(this.movementDirection); this.playerSprite.stopAnimation(this.movementDirection); this.movementDirection = Direction.NONE; } diff --git a/client/src/akkamon/render/engine/RemotePlayerEngine.ts b/client/src/akkamon/render/engine/RemotePlayerEngine.ts index 7ce5fa9..037b26c 100644 --- a/client/src/akkamon/render/engine/RemotePlayerEngine.ts +++ b/client/src/akkamon/render/engine/RemotePlayerEngine.ts @@ -24,7 +24,7 @@ export class RemotePlayerEngine extends AkkamonEngine { private scene: WorldScene; - private trainerIdToRemotePlayerSprite: Map<string, RemotePlayerSprite> = new Map(); + private trainerIDToRemotePlayerSprite: Map<string, RemotePlayerSprite> = new Map(); constructor(scene: WorldScene) { super(); @@ -37,13 +37,13 @@ export class RemotePlayerEngine extends AkkamonEngine { } pushMovesToSprites(remoteMovementQueues: RemoteMovementQueues) { - this.trainerIdToRemotePlayerSprite.forEach((remoteSprite: RemotePlayerSprite, key: string) => { + this.trainerIDToRemotePlayerSprite.forEach((remoteSprite: RemotePlayerSprite, key: string) => { remoteSprite.push(remoteMovementQueues[key].value); }); } update(delta: number): void { - this.trainerIdToRemotePlayerSprite.forEach((remoteSprite: RemotePlayerSprite, key: string) => { + this.trainerIDToRemotePlayerSprite.forEach((remoteSprite: RemotePlayerSprite, key: string) => { if (remoteSprite.isMoving()) { console.log("remote player currently walking"); remoteSprite.updatePixelPosition(delta); @@ -55,18 +55,18 @@ export class RemotePlayerEngine extends AkkamonEngine { } updateMembers(newRemoteMovementQueues: RemoteMovementQueues) { - const traineridToQueueValue = newRemoteMovementQueues; + const trainerIDToQueueValue = newRemoteMovementQueues; Object.keys(newRemoteMovementQueues).forEach((key: string) => { - var moveQueue = traineridToQueueValue[key].value; + var moveQueue = trainerIDToQueueValue[key].value; if (moveQueue !== undefined) { // console.log("-> key: " + key + " has position " + newTilePos.x + ", " + newTilePos.y); - if (!this.trainerIdToRemotePlayerSprite.has(key)) { + if (!this.trainerIDToRemotePlayerSprite.has(key)) { // console.log("adding remote player sprite for " + key); - this.trainerIdToRemotePlayerSprite.set(key, + this.trainerIDToRemotePlayerSprite.set(key, new RemotePlayerSprite({ scene: this.scene, tilePos: new Phaser.Math.Vector2(this.scene.spawnPointTilePos!), @@ -82,11 +82,11 @@ export class RemotePlayerEngine extends AkkamonEngine { }); - this.trainerIdToRemotePlayerSprite.forEach((value: RemotePlayerSprite, key: string) => { + this.trainerIDToRemotePlayerSprite.forEach((value: RemotePlayerSprite, key: string) => { if (!(key in newRemoteMovementQueues)) { // console.log("removing remote player sprite for " + key); - this.trainerIdToRemotePlayerSprite.get(key)!.destroy(); - this.trainerIdToRemotePlayerSprite.delete(key); + this.trainerIDToRemotePlayerSprite.get(key)!.destroy(); + this.trainerIDToRemotePlayerSprite.delete(key); } else { // console.log("Player " + key + " was not removed!"); } @@ -94,6 +94,6 @@ export class RemotePlayerEngine extends AkkamonEngine { } getData() { - return this.trainerIdToRemotePlayerSprite; + return this.trainerIDToRemotePlayerSprite; } } diff --git a/client/src/akkamon/scenes/AkkamonWorldScene.ts b/client/src/akkamon/scenes/AkkamonWorldScene.ts index 002b4b5..9912145 100644 --- a/client/src/akkamon/scenes/AkkamonWorldScene.ts +++ b/client/src/akkamon/scenes/AkkamonWorldScene.ts @@ -147,8 +147,8 @@ export function akkamonBaseWorldScene(key: string): WorldScene { requestBattle: function (remotePlayerName: string | string[]): void { this.client.sendInteractionRequest({ type: "battle", - requestingTrainerId: this.client.getSessionTrainerId()!, - receivingTrainerIds: Array.isArray(remotePlayerName) ? remotePlayerName : [remotePlayerName] + requestingtrainerID: this.client.getSessiontrainerID()!, + receivingtrainerIDs: Array.isArray(remotePlayerName) ? remotePlayerName : [remotePlayerName] }); }, @@ -265,8 +265,8 @@ export function akkamonBaseWorldScene(key: string): WorldScene { // requestBattle(remotePlayerName: string | string[]): void { // this.client.sendInteractionRequest({ // type: "battle", -// requestingTrainerId: this.client.getSessionTrainerId()!, -// receivingTrainerIds: Array.isArray(remotePlayerName) ? remotePlayerName : [remotePlayerName] +// requestingtrainerID: this.client.getSessiontrainerID()!, +// receivingtrainerIDs: Array.isArray(remotePlayerName) ? remotePlayerName : [remotePlayerName] // }); // } // diff --git a/client/src/akkamon/scenes/UIElement.ts b/client/src/akkamon/scenes/UIElement.ts index c77503e..1c87ef4 100644 --- a/client/src/akkamon/scenes/UIElement.ts +++ b/client/src/akkamon/scenes/UIElement.ts @@ -163,12 +163,6 @@ class Menu extends Phaser.GameObjects.Image implements AkkamonMenu { return index * this.ySpacing! + this.yOffsetFromTop! + 7 + this.y; } - setButtons(buttonTextArray: Array<string>) { - for (let i = 0; i < buttonTextArray.length; i++) { - this.buttons!.push(new MenuText(this.scene, this.group!, this.groupDepth!, this.x - this.xOffsetFromRight!, this.y + this.yOffsetFromTop! + i * this.ySpacing!, buttonTextArray[i])); - } - } - clearButtons() { for (let button of this.buttons!) { button.destroy(); @@ -202,6 +196,13 @@ export class PauseMenu extends Menu implements AkkamonMenu { this.group!.setDepth(this.groupDepth!); } + setButtons(buttonTextArray: Array<string>) { + for (let i = 0; i < buttonTextArray.length; i++) { + this.buttons!.push(new MenuText(this.scene, this.group!, this.groupDepth!, this.x - this.xOffsetFromRight!, this.y + this.yOffsetFromTop! + i * this.ySpacing!, buttonTextArray[i])); + } + } + + confirm() { if (this.buttons![this.index!].text === 'PHONE') { this.akkamonScene.pushMenu(new RemotePlayerList(this.akkamonScene, this.akkamonScene.getRemotePlayerNames())); @@ -210,7 +211,7 @@ export class PauseMenu extends Menu implements AkkamonMenu { } class ListMenu extends Menu implements AkkamonMenu { - options: Array<string> + options: Array<any> viewTop: number = 0; @@ -218,7 +219,7 @@ class ListMenu extends Menu implements AkkamonMenu { constructor( scene: WorldScene, - options: Array<string> + options: any[] ) { super(scene, "pause-menu") let camera = scene.cameras.main; @@ -232,28 +233,14 @@ class ListMenu extends Menu implements AkkamonMenu { this.xOffsetFromRight = 210; this.yOffsetFromTop = 50; - let contacts = new MenuText( - this.scene, - this.group!, - this.groupDepth!, - this.x - this.xOffsetFromRight, - this.y + 20, - "Nearby trainers:") - // this.yOffsetFromTop - // this.ySpacing - this.setPicker(0); - this.setButtons( - this.options.slice( - this.viewTop, - this.viewBot - ) - ); this.groupDepth = 30; this.group!.setDepth(this.groupDepth); } + setButtons(visibleOptions: any[]) {} + selectButton(direction: Direction) { if (direction === Direction.UP) { if (this.index! !== 0) { @@ -292,12 +279,51 @@ class ListMenu extends Menu implements AkkamonMenu { class RemotePlayerList extends ListMenu implements AkkamonMenu { + constructor( + scene: WorldScene, + options: {id: string, scene: string}[] + ) { + super(scene, options) + + let title = new MenuText( + this.scene, + this.group!, + this.groupDepth!, + this.x - this.xOffsetFromRight!, + this.y + 20, + "Nearby trainers:") + + this.setButtons( + this.options.slice( + this.viewTop, + this.viewBot + ) + ); + + // this.yOffsetFromTop + // this.ySpacing + + } + + setButtons(visibleOptions: {id: string, scene: string}[]) { + for (let i = 0; i < visibleOptions.length; i++) { + + this.buttons!.push(new MenuText( + this.scene, + this.group!, + this.groupDepth!, + this.x - this.xOffsetFromRight!, + this.y + this.yOffsetFromTop! + i * this.ySpacing!, + visibleOptions[i].id)); + } + } + confirm() { this.akkamonScene.pushMenu(new ChallengeDialogue( this.akkamonScene, ['YES', 'NO'], { - 'trainerName': this.buttons![this.index! + this.viewTop].text + 'trainerID': this.options![this.index! + this.viewTop] })); } } @@ -307,7 +333,7 @@ class ConfirmationDialogue extends Menu implements AkkamonMenu { options?: Array<string> dialogueBox?: Dialogue - constructor(scene: WorldScene, options: Array<string>, dialogueData: {[key: string]: string} | string) { + constructor(scene: WorldScene, options: Array<string>, dialogueData: {[key: string]: string} | string | {}) { super(scene, "confirmation-dialogue"); let camera = scene.cameras.main; this.setDisplaySize(200, 0.83 * 200) @@ -323,6 +349,14 @@ class ConfirmationDialogue extends Menu implements AkkamonMenu { this.dialogueBox = new Dialogue(scene, this.group!, this.groupDepth); } + + setButtons(buttonTextArray: Array<string>) { + for (let i = 0; i < buttonTextArray.length; i++) { + this.buttons!.push(new MenuText(this.scene, this.group!, this.groupDepth!, this.x - this.xOffsetFromRight!, this.y + this.yOffsetFromTop! + i * this.ySpacing!, buttonTextArray[i])); + } + } + + } class Dialogue extends Phaser.GameObjects.Image implements AkkamonMenu { @@ -416,19 +450,21 @@ class Dialogue extends Phaser.GameObjects.Image implements AkkamonMenu { } class ChallengeDialogue extends ConfirmationDialogue implements AkkamonMenu { - challengedTrainerName: string; - constructor(scene: WorldScene, options: Array<string>, dialogueData: {[key: string]: string}) { + challengedTrainerID: {id: string, scene: string}; + + constructor(scene: WorldScene, options: Array<string>, dialogueData: {trainerID: {id: string, scene: string}}) { + super(scene, options, dialogueData); - this.challengedTrainerName = dialogueData['trainerName']; + this.challengedTrainerID = dialogueData.trainerID; this.dialogueBox!.push( - `Do you want to challenge ${this.challengedTrainerName} to a battle?` + `Do you want to challenge ${this.challengedTrainerID.id} to a battle?` ); this.dialogueBox!.displayNextDialogue(); } confirm() { if (this.buttons![this.index!].text === "YES") { - this.akkamonScene.requestBattle(this.challengedTrainerName); + this.akkamonScene.requestBattle(this.challengedTrainerID); this.akkamonScene.clearMenus(); this.akkamonScene.pushMenu(new WaitingDialogue(this.akkamonScene, new Phaser.GameObjects.Group(this.scene), 20, 'Awaiting request initialisation...')); } else { diff --git a/client/src/akkamon/scenes/WorldScene.ts b/client/src/akkamon/scenes/WorldScene.ts index f125a0e..f570cde 100644 --- a/client/src/akkamon/scenes/WorldScene.ts +++ b/client/src/akkamon/scenes/WorldScene.ts @@ -40,9 +40,9 @@ export interface WorldScene extends Phaser.Scene { getPlayerPixelPosition: () => Phaser.Math.Vector2 - getRemotePlayerNames: () => string[] + getRemotePlayerNames: () => {id: string, scene: string}[] - requestBattle: (remotePlayerData: string | string[]) => void + requestBattle: (remotePlayerData: {id: string, scene: string}) => void clearMenus: () => void @@ -136,20 +136,26 @@ export function createWorldScene<PhaserScene extends BasePhaserScene>(scene: Pha return client.requestPlayerPixelPosition(); } - getRemotePlayerNames(): Array<string> { + getRemotePlayerNames(): Array<{id: string, scene: string}> { let remotePlayerData = client.requestRemotePlayerData(); if (remotePlayerData.size === 0) { - return ['Nobody Online']; + return [{id: 'Nobody Online', scene: ''}]; } else { - return Array.from(remotePlayerData.keys()); + let keys = remotePlayerData.keys(); + let trainerIDs: {id: string, scene: string}[] = []; + + for (let key of keys) { + let trainerID: { id: string, scene: string } = JSON.parse(key); + trainerIDs.push(trainerID); + } + return trainerIDs; } } - requestBattle(remotePlayerName: string | string[]): void { + requestBattle(remoteTrainerID: {id: string, scene: string}): void { client.sendInteractionRequest({ type: "battle", - requestingTrainerId: client.getSessionTrainerId()!, - receivingTrainerIds: Array.isArray(remotePlayerName) ? remotePlayerName : [remotePlayerName] + receivingtrainerIDs: Array.isArray(remoteTrainerID) ? remoteTrainerID : [remoteTrainerID] }); } diff --git a/client/src/app.ts b/client/src/app.ts index 7a80442..82fdc81 100644 --- a/client/src/app.ts +++ b/client/src/app.ts @@ -39,8 +39,8 @@ function delay(ms: number) { async function awaitRegistrationReplyAndStart() { if (!game) { - while (client.getSessionTrainerId() === undefined) { - console.log("can't start game, this trainerId is still undefined"); + while (client.getTrainerID() === undefined) { + console.log("can't start game, this trainerID is still undefined"); await delay(1000); } newGame(); diff --git a/domain/src/main/java/akkamon/domain/AkkamonMessageEngine.java b/domain/src/main/java/akkamon/domain/AkkamonMessageEngine.java index df5402f..0172770 100644 --- a/domain/src/main/java/akkamon/domain/AkkamonMessageEngine.java +++ b/domain/src/main/java/akkamon/domain/AkkamonMessageEngine.java @@ -1,6 +1,7 @@ package akkamon.domain; import akka.actor.typed.ActorRef; +import akkamon.domain.actors.AkkamonNexus; import java.util.List; import java.util.Map; @@ -8,19 +9,19 @@ import java.util.Set; public interface AkkamonMessageEngine { // broadcasts position info to WebSocket Clients - void broadCastHeartBeatToScene(String sceneId, Map<String, AkkamonNexus.MovementQueueReading> trainerPositions); + void broadCastHeartBeatToScene(String sceneId, Map<AkkamonNexus.TrainerID, AkkamonNexus.MovementQueueReading> trainerPositions); - void broadCastInteractionRequestToSessionWithTrainerIds(List<String> trainerIds, String type, String trainerId, String requestName, ActorRef<InteractionHandshaker.Command> handshaker); + void broadCastInteractionRequestToSessionWithtrainerIDs(List<AkkamonNexus.TrainerID> trainerIDs, String type, AkkamonNexus.TrainerID trainerID, String requestName, ActorRef<InteractionHandshaker.Command> handshaker); - void registerTrainerSessionToSceneAndTrainerIdMaps(String sceneId, AkkamonSession session); + void registerTrainerSessionToSceneAndtrainerIDMaps(AkkamonNexus.TrainerID trainerID, AkkamonSession session); - void removeTrainerSessionFromScene(String sceneId, AkkamonSession session); + void removeTrainerSessionFromScene(AkkamonNexus.TrainerID trainerID, AkkamonSession session); void trainerDisconnected(AkkamonSession session); void removeInteractionHandshaker(String requestName); - void broadCastInteractionStart(String requestName, String interactionType, Set<String> waitingToStartInteraction); + void broadCastInteractionStart(String requestName, String interactionType, Set<AkkamonNexus.TrainerID> waitingToStartInteraction); - void broadCastHandshakeFail(String requestName, Set<String> waitingToStartInteraction); + void broadCastHandshakeFail(String requestName, Set<AkkamonNexus.TrainerID> waitingToStartInteraction); } diff --git a/domain/src/main/java/akkamon/domain/AkkamonSession.java b/domain/src/main/java/akkamon/domain/AkkamonSession.java index 68aa1fc..d44e6db 100644 --- a/domain/src/main/java/akkamon/domain/AkkamonSession.java +++ b/domain/src/main/java/akkamon/domain/AkkamonSession.java @@ -1,9 +1,11 @@ package akkamon.domain; +import akkamon.domain.actors.AkkamonNexus; + public interface AkkamonSession { void send(String event); - void setTrainerId(String trainerId); + void settrainerID(AkkamonNexus.TrainerID trainerID); - String getTrainerId(); + AkkamonNexus.TrainerID gettrainerID(); } diff --git a/domain/src/main/java/akkamon/domain/HeartBeatQuery.java b/domain/src/main/java/akkamon/domain/HeartBeatQuery.java index aa201c3..45d6e38 100644 --- a/domain/src/main/java/akkamon/domain/HeartBeatQuery.java +++ b/domain/src/main/java/akkamon/domain/HeartBeatQuery.java @@ -3,10 +3,14 @@ package akkamon.domain; import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.*; +import akkamon.domain.actors.AkkamonNexus; +import akkamon.domain.actors.Trainer; import java.time.Duration; import java.util.*; +import static akkamon.domain.actors.AkkamonNexus.*; + public class HeartBeatQuery extends AbstractBehavior<HeartBeatQuery.Command> { public interface Command {} @@ -26,15 +30,15 @@ public class HeartBeatQuery extends AbstractBehavior<HeartBeatQuery.Command> { } private static class TrainerOffline implements Command { - final String trainerId; + final TrainerID trainerID; - private TrainerOffline(String trainerId) { - this.trainerId = trainerId; + private TrainerOffline(TrainerID trainerID) { + this.trainerID = trainerID; } } public static Behavior<Command> create( - Map<String, ActorRef<Trainer.Command>> trainerIdToActor, + Map<TrainerID, ActorRef<Trainer.Command>> trainerIDToActor, long requestId, String sceneId, ActorRef<AkkamonNexus.Command> requester, @@ -44,7 +48,7 @@ public class HeartBeatQuery extends AbstractBehavior<HeartBeatQuery.Command> { context -> Behaviors.withTimers( timers -> new HeartBeatQuery( - trainerIdToActor, + trainerIDToActor, requestId, sceneId, requester, @@ -59,11 +63,11 @@ public class HeartBeatQuery extends AbstractBehavior<HeartBeatQuery.Command> { private final long requestId; private final String sceneId; private final ActorRef<AkkamonNexus.Command> requester; - private Map<String, AkkamonNexus.MovementQueueReading> repliesSoFar = new HashMap<String, AkkamonNexus.MovementQueueReading>(); - private final Set<String> stillWaiting; + private Map<TrainerID, MovementQueueReading> repliesSoFar = new HashMap<>(); + private final Set<TrainerID> stillWaiting; public HeartBeatQuery( - Map<String, ActorRef<Trainer.Command>> trainerIdToActor, + Map<TrainerID, ActorRef<Trainer.Command>> trainerIDToActor, long requestId, String sceneId, ActorRef<AkkamonNexus.Command> requester, @@ -80,7 +84,7 @@ public class HeartBeatQuery extends AbstractBehavior<HeartBeatQuery.Command> { ActorRef<Trainer.RespondMovementQueue> respondTrainerPositionAdapter = context.messageAdapter(Trainer.RespondMovementQueue.class, WrappedRespondMovementQueue::new); - for (Map.Entry<String, ActorRef<Trainer.Command>> entry : trainerIdToActor.entrySet()) { + for (Map.Entry<TrainerID, ActorRef<Trainer.Command>> entry : trainerIDToActor.entrySet()) { context.watchWith(entry.getValue(), new TrainerOffline(entry.getKey())); entry.getValue().tell( new Trainer.ReadMovementQueue( @@ -88,7 +92,7 @@ public class HeartBeatQuery extends AbstractBehavior<HeartBeatQuery.Command> { respondTrainerPositionAdapter )); } - stillWaiting = new HashSet<>(trainerIdToActor.keySet()); + stillWaiting = new HashSet<>(trainerIDToActor.keySet()); } @Override @@ -99,25 +103,25 @@ public class HeartBeatQuery extends AbstractBehavior<HeartBeatQuery.Command> { } private Behavior<Command> onRespondMovementQueue(WrappedRespondMovementQueue r) { - AkkamonNexus.MovementQueueReading movementQueueRead = null; + MovementQueueReading movementQueueRead = null; if (r.response.value.size() != 0) { - movementQueueRead = new AkkamonNexus.MovementQueue(r.response.value); + movementQueueRead = new MovementQueue(r.response.value); } else { Queue<Direction> queue = new LinkedList<>(); queue.add(Direction.NONE); - movementQueueRead = new AkkamonNexus.MovementQueue(queue); + movementQueueRead = new MovementQueue(queue); } - String trainerId = r.response.trainerId; - repliesSoFar.put(trainerId, movementQueueRead); - stillWaiting.remove(trainerId); + TrainerID trainerID = r.response.trainerID; + repliesSoFar.put(trainerID, movementQueueRead); + stillWaiting.remove(trainerID); return respondWhenAllCollected(); } private Behavior<Command> respondWhenAllCollected() { if (stillWaiting.isEmpty()) { - requester.tell(new AkkamonNexus.RespondHeartBeatQuery( + requester.tell(new RespondHeartBeatQuery( requestId, sceneId, repliesSoFar)); diff --git a/domain/src/main/java/akkamon/domain/InteractionHandshaker.java b/domain/src/main/java/akkamon/domain/InteractionHandshaker.java index 43c0c2e..9817be1 100644 --- a/domain/src/main/java/akkamon/domain/InteractionHandshaker.java +++ b/domain/src/main/java/akkamon/domain/InteractionHandshaker.java @@ -3,12 +3,15 @@ package akkamon.domain; import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.*; +import akkamon.domain.actors.AkkamonNexus; import java.time.Duration; import java.util.HashSet; import java.util.List; import java.util.Set; +import static akkamon.domain.actors.AkkamonNexus.*; + public class InteractionHandshaker extends AbstractBehavior<InteractionHandshaker.Command> { public interface Command { @@ -21,23 +24,20 @@ public class InteractionHandshaker extends AbstractBehavior<InteractionHandshake public static class InteractionReply implements Command { public String requestName; - public String trainerId; - public String sceneId; + public TrainerID trainerID; public boolean value; - public InteractionReply(String requestName, String trainerId, String sceneId, boolean value) { + public InteractionReply(String requestName, TrainerID trainerID, boolean value) { this.requestName = requestName; - this.trainerId = trainerId; - this.sceneId = sceneId; + this.trainerID = trainerID; this.value = value; } } public static Behavior<Command> create( - String trainerId, + TrainerID trainerID, String type, - List<String> needingConfirmation, - String sceneId, + List<TrainerID> needingConfirmation, String requestName, ActorRef<AkkamonNexus.Command> replyTo, Duration timeout) { @@ -46,10 +46,9 @@ public class InteractionHandshaker extends AbstractBehavior<InteractionHandshake context -> Behaviors.withTimers( timers -> new InteractionHandshaker( context, - trainerId, + trainerID, type, new HashSet(needingConfirmation), - sceneId, requestName, replyTo, timeout, @@ -58,20 +57,19 @@ public class InteractionHandshaker extends AbstractBehavior<InteractionHandshake )); } - private Set<String> stillWaiting; + private Set<TrainerID> stillWaiting; private ActorRef<AkkamonNexus.Command> replyTo; private String requestName; private String type; - private Set<String> waitingToStartInteraction = new HashSet<>(); + private Set<TrainerID> waitingToStartInteraction = new HashSet<>(); public InteractionHandshaker(ActorContext<Command> context, - String trainerId, + TrainerID trainerID, String type, - Set<String> needingToShakeHands, - String sceneId, + Set<TrainerID> needingToShakeHands, String requestName, ActorRef<AkkamonNexus.Command> replyTo, Duration timeout, @@ -85,7 +83,7 @@ public class InteractionHandshaker extends AbstractBehavior<InteractionHandshake this.requestName = requestName; this.type = type; - waitingToStartInteraction.add(trainerId); + waitingToStartInteraction.add(trainerID); stillWaiting = needingToShakeHands; } @@ -101,7 +99,7 @@ public class InteractionHandshaker extends AbstractBehavior<InteractionHandshake getContext().getLog().info("Received fail instance due to timeout!"); replyTo.tell( - new AkkamonNexus.RespondInteractionHandshaker( + new RespondInteractionHandshaker( requestName, type, HandshakeResult.FAIL, @@ -113,13 +111,15 @@ public class InteractionHandshaker extends AbstractBehavior<InteractionHandshake private Behavior<Command> onReply(InteractionReply r) { - getContext().getLog().info("received reply from {} with value {}!", r.trainerId, r.value); - stillWaiting.remove(r.trainerId); - this.waitingToStartInteraction.add(r.trainerId); + getContext().getLog().info("received reply from {} with value {}!", r.trainerID, r.value); + getContext().getLog().info(String.valueOf(stillWaiting)); + stillWaiting.remove(r.trainerID); + getContext().getLog().info(String.valueOf(stillWaiting)); + this.waitingToStartInteraction.add(r.trainerID); if (r.value) { return respondIfAllRepliesReceived(); } else { - replyTo.tell(new AkkamonNexus.RespondInteractionHandshaker( + replyTo.tell(new RespondInteractionHandshaker( requestName, type, HandshakeResult.FAIL, @@ -130,8 +130,10 @@ public class InteractionHandshaker extends AbstractBehavior<InteractionHandshake } private Behavior<Command> respondIfAllRepliesReceived() { + getContext().getLog().info(String.valueOf(stillWaiting)); if (this.stillWaiting.isEmpty()) { - replyTo.tell(new AkkamonNexus.RespondInteractionHandshaker( + getContext().getLog().info("Sending out interaction Start!"); + replyTo.tell(new RespondInteractionHandshaker( requestName, type, HandshakeResult.SUCCESS, diff --git a/domain/src/main/java/akkamon/domain/InteractionTypes.java b/domain/src/main/java/akkamon/domain/InteractionTypes.java new file mode 100644 index 0000000..b915893 --- /dev/null +++ b/domain/src/main/java/akkamon/domain/InteractionTypes.java @@ -0,0 +1,5 @@ +package akkamon.domain; + +public enum InteractionTypes { + BATTLE +} diff --git a/domain/src/main/java/akkamon/domain/actors/AkkamonBattle.java b/domain/src/main/java/akkamon/domain/actors/AkkamonBattle.java new file mode 100644 index 0000000..6f65845 --- /dev/null +++ b/domain/src/main/java/akkamon/domain/actors/AkkamonBattle.java @@ -0,0 +1,36 @@ +package akkamon.domain.actors; + +import akka.actor.typed.ActorRef; +import akka.actor.typed.javadsl.ActorContext; +import akka.actor.typed.Behavior; +import akka.actor.typed.javadsl.AbstractBehavior; +import akka.actor.typed.javadsl.Behaviors; +import akka.actor.typed.javadsl.Receive; + +public class AkkamonBattle extends AbstractBehavior<AkkamonBattle.Command> { + + public interface Command { } + + public static class BattleCreatedResponse implements AkkamonNexus.Command { + + } + + public static Behavior<Command> create( + ActorRef<AkkamonNexus.Command> replyTo + ) { + return Behaviors.setup( + context -> new AkkamonBattle(context) + ); + } + + public AkkamonBattle(ActorContext<Command> context) { + super(context); + } + + + @Override + public Receive<Command> createReceive() { + return null; + } + +} diff --git a/domain/src/main/java/akkamon/domain/AkkamonNexus.java b/domain/src/main/java/akkamon/domain/actors/AkkamonNexus.java index 949e5c5..e560a69 100644 --- a/domain/src/main/java/akkamon/domain/AkkamonNexus.java +++ b/domain/src/main/java/akkamon/domain/actors/AkkamonNexus.java @@ -1,4 +1,4 @@ -package akkamon.domain; +package akkamon.domain.actors; import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; @@ -6,6 +6,7 @@ import akka.actor.typed.javadsl.AbstractBehavior; import akka.actor.typed.javadsl.ActorContext; import akka.actor.typed.javadsl.Behaviors; import akka.actor.typed.javadsl.Receive; +import akkamon.domain.*; import java.time.Duration; import java.util.*; @@ -15,18 +16,52 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { public interface Command {} + public static class TrainerID { + public String id; + public String scene; + + public TrainerID(String id, String scene) { + this.id = id; + this.scene = scene; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TrainerID trainerID = (TrainerID) o; + return Objects.equals(id, trainerID.id) && Objects.equals(scene, trainerID.scene); + } + + @Override + public int hashCode() { + return Objects.hash(id, scene); + } + + @Override + public String toString() { + return "{ " + + "\"id\": \"" + id + "\"," + + "\"scene\": \"" + scene + "\"" + + " }"; + } + } + + public static class BattleStart implements SceneTrainerGroup.Command, Trainer.Command { + + } public static class RespondInteractionHandshaker implements Command { public String requestName; public String interactionType; public InteractionHandshaker.HandshakeResult result; - public Set<String> waitingToStartInteraction; + public Set<TrainerID> waitingToStartInteraction; public RespondInteractionHandshaker(String requestName, String interactionType, InteractionHandshaker.HandshakeResult result, - Set<String> waitingToStartInteraction) { + Set<TrainerID> waitingToStartInteraction) { this.requestName = requestName; this.interactionType = interactionType; this.result = result; @@ -40,15 +75,14 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { public long requestId; public String type; public String sceneId; - public String trainerId; - public List<String> forwardTo; + public TrainerID trainerID; + public List<TrainerID> forwardTo; public ActorRef<Command> replyTo; - public RequestInteraction(long requestId, String type, String sceneId, String trainerId, List<String> forwardTo, ActorRef<Command> replyTo) { + public RequestInteraction(long requestId, String type, TrainerID trainerID, List<TrainerID> forwardTo, ActorRef<Command> replyTo) { this.requestId = requestId; this.type = type; - this.sceneId = sceneId; - this.trainerId = trainerId; + this.trainerID = trainerID; this.forwardTo = forwardTo; this.replyTo = replyTo; } @@ -56,18 +90,18 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { public static class RequestTrainerRegistration implements AkkamonNexus.Command, SceneTrainerGroup.Command { - public String trainerId; + public String trainerName; public String sceneId; public AkkamonSession session; public ActorRef<Command> replyTo; public RequestTrainerRegistration( - String trainerId, + String trainerName, String sceneId, AkkamonSession session, ActorRef<Command> replyTo ) { - this.trainerId = trainerId; + this.trainerName = trainerName; this.sceneId = sceneId; this.session = session; this.replyTo = replyTo; @@ -75,17 +109,14 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { } public static class TrainerRegistered implements Command { - private String trainerId; - private String sceneId; + private TrainerID trainerID; private AkkamonSession session; public TrainerRegistered( - String trainerId, - String sceneId, + TrainerID trainerID, AkkamonSession session ) { - this.trainerId = trainerId; - this.sceneId = sceneId; + this.trainerID = trainerID; this.session = session; } } @@ -93,15 +124,13 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { public static class RequestStartMoving implements Command, SceneTrainerGroup.Command, Trainer.Command { public long requestId; - public String trainerId; - public String sceneId; + public TrainerID trainerID; public Direction direction; public ActorRef<AkkamonNexus.Command> replyTo; - public RequestStartMoving(long requestId, String trainerId, String sceneId, Direction direction, ActorRef<AkkamonNexus.Command> replyTo) { + public RequestStartMoving(long requestId, AkkamonNexus.TrainerID trainerID, Direction direction, ActorRef<Command> replyTo) { this.requestId = requestId; - this.trainerId = trainerId; - this.sceneId = sceneId; + this.trainerID = trainerID; this.direction = direction; this.replyTo = replyTo; } @@ -110,20 +139,17 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { public static class RequestStopMoving implements Command, SceneTrainerGroup.Command, Trainer.Command { public long requestId; - public String trainerId; - public String sceneId; + public TrainerID trainerID; public Direction direction; public ActorRef<AkkamonNexus.Command> replyTo; public RequestStopMoving( long requestId, - String trainerId, - String sceneId, + TrainerID trainerID, Direction direction, ActorRef<AkkamonNexus.Command> replyTo) { this.requestId = requestId; - this.trainerId = trainerId; - this.sceneId = sceneId; + this.trainerID = trainerID; this.direction = direction; this.replyTo = replyTo; } @@ -132,15 +158,13 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { public static class RequestNewTilePos implements Command, SceneTrainerGroup.Command, Trainer.Command { public long requestId; - public String trainerId; - public String sceneId; + public TrainerID trainerID; public TilePos tilePos; public ActorRef<AkkamonNexus.Command> replyTo; - public RequestNewTilePos(long requestId, String trainerId, String sceneId, TilePos tilePos, ActorRef<Command> replyTo) { + public RequestNewTilePos(long requestId, TrainerID trainerID, TilePos tilePos, ActorRef<Command> replyTo) { this.requestId = requestId; - this.trainerId = trainerId; - this.sceneId = sceneId; + this.trainerID = trainerID; this.tilePos = tilePos; this.replyTo = replyTo; } @@ -167,15 +191,13 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { public static class RequestTrainerOffline implements Command, SceneTrainerGroup.Command, Trainer.Command { public long requestId; - public String trainerId; - public String sceneId; + public TrainerID trainerID; public AkkamonSession session; public ActorRef<AkkamonNexus.Command> replyTo; - public RequestTrainerOffline(long requestId, String trainerId, String sceneId, AkkamonSession session, ActorRef<Command> replyTo) { + public RequestTrainerOffline(long requestId, TrainerID trainerID, String sceneId, AkkamonSession session, ActorRef<Command> replyTo) { this.requestId = requestId; - this.trainerId = trainerId; - this.sceneId = sceneId; + this.trainerID = trainerID; this.session = session; this.replyTo = replyTo; } @@ -184,12 +206,12 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { public static class RespondTrainerOffline implements Command { public long requestId; - public String sceneId; + public TrainerID trainerID; public AkkamonSession session; - public RespondTrainerOffline(long requestId, String sceneId, AkkamonSession session) { + public RespondTrainerOffline(long requestId, TrainerID trainerID, AkkamonSession session) { this.requestId = requestId; - this.sceneId = sceneId; + this.trainerID = trainerID; this.session = session; } } @@ -198,12 +220,12 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { public final long requestId; public final String sceneId; - public final Map<String, MovementQueueReading> trainerMovementQueues; + public final Map<TrainerID, MovementQueueReading> trainerMovementQueues; public RespondHeartBeatQuery( long requestId, String sceneId, - Map<String, MovementQueueReading> trainerPositions) { + Map<TrainerID, MovementQueueReading> trainerPositions) { this.requestId = requestId; this.sceneId = sceneId; this.trainerMovementQueues = trainerPositions; @@ -250,24 +272,44 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { return newReceiveBuilder() .onMessage(RequestTrainerRegistration.class, this::onTrainerRegistration) .onMessage(TrainerRegistered.class, this::onTrainerRegistered) + .onMessage(RequestTrainerOffline.class, this::onTrainerOfflineRequest) .onMessage(RespondTrainerOffline.class, this::onTrainerOffline) + .onMessage(RequestHeartBeat.class, this::onHeartBeat) .onMessage(RespondHeartBeatQuery.class, this::onHeartBeatQueryResponse) + .onMessage(RequestStartMoving.class, this::onStartMoving) .onMessage(RequestStopMoving.class, this::onStopMoving) .onMessage(RequestNewTilePos.class, this::onNewTilePos) + .onMessage(RequestInteraction.class, this::onInteractionRequest) .onMessage(RespondInteractionHandshaker.class, this::onInteractionHandshakerResponse) + + .onMessage(AkkamonBattle.BattleCreatedResponse.class, this::onBattleCreatedResponse) .build(); } + private AkkamonNexus onBattleCreatedResponse(AkkamonBattle.BattleCreatedResponse r) { + getContext().getLog().info("Created battle between {} and {}, they should now only be listening to battle commands!"); + return this; + } + private Behavior<Command> onInteractionHandshakerResponse(RespondInteractionHandshaker r) { this.messageEngine.removeInteractionHandshaker(r.requestName); if (r.result.equals(InteractionHandshaker.HandshakeResult.SUCCESS)) { messageEngine.broadCastInteractionStart(r.requestName, r.interactionType, r.waitingToStartInteraction); + switch (r.interactionType) { + case "battle": + getContext().spawn(AkkamonBattle.create( + getContext().getSelf() + ), + r.requestName); + break; + } + } else if (r.result.equals(InteractionHandshaker.HandshakeResult.FAIL)) { messageEngine.broadCastHandshakeFail(r.requestName, r.waitingToStartInteraction); } @@ -275,40 +317,39 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { } private AkkamonNexus onInteractionRequest(RequestInteraction interactionRequest) { - List<String> needConfirmation = interactionRequest.forwardTo; + List<TrainerID> needConfirmation = interactionRequest.forwardTo; - getContext().getLog().info("Creating interactionHandshaker of type {} from {} to {} ", interactionRequest.type, interactionRequest.trainerId, interactionRequest.forwardTo); + getContext().getLog().info("Creating interactionHandshaker of type {} from {} to {} ", interactionRequest.type, interactionRequest.trainerID, needConfirmation); - String requestName = "interaction-handshaker-" + interactionRequest.type + "-" + interactionRequest.trainerId + "-" + interactionRequest.requestId; + String requestName = "interaction-handshaker-" + interactionRequest.type + "-" + interactionRequest.trainerID.id + "-" + interactionRequest.requestId; ActorRef<InteractionHandshaker.Command> handshaker = getContext().spawn(InteractionHandshaker.create( - interactionRequest.trainerId, + interactionRequest.trainerID, interactionRequest.type, interactionRequest.forwardTo, - interactionRequest.sceneId, requestName, interactionRequest.replyTo, Duration.ofSeconds(60) ), requestName); - messageEngine.broadCastInteractionRequestToSessionWithTrainerIds(needConfirmation, interactionRequest.type, interactionRequest.trainerId, requestName, handshaker); + messageEngine.broadCastInteractionRequestToSessionWithtrainerIDs(new ArrayList<>(needConfirmation), interactionRequest.type, interactionRequest.trainerID, requestName, handshaker); return this; } private AkkamonNexus onTrainerOffline(RespondTrainerOffline trainerOfflineMsg) { - getContext().getLog().info("Removing {} from akkamon sessions!", trainerOfflineMsg.session.getTrainerId()); - messageEngine.removeTrainerSessionFromScene(trainerOfflineMsg.sceneId, trainerOfflineMsg.session); + getContext().getLog().info("Removing {} from akkamon sessions!", trainerOfflineMsg.session.gettrainerID()); + messageEngine.removeTrainerSessionFromScene(trainerOfflineMsg.trainerID, trainerOfflineMsg.session); return this; } private AkkamonNexus onTrainerOfflineRequest(RequestTrainerOffline trainerOfflineRequest) { ActorRef<SceneTrainerGroup.Command> sceneTrainerGroup = sceneIdToActor.get( - trainerOfflineRequest.sceneId + trainerOfflineRequest.trainerID.scene ); if (sceneTrainerGroup != null) { sceneTrainerGroup.tell(trainerOfflineRequest); } else { - getContext().getLog().info("Ignoring trainerOffline request in scene {}, it isn't mapped to a sceneTrainerActor.", trainerOfflineRequest.sceneId); + getContext().getLog().info("Ignoring trainerOffline request in scene {}, it isn't mapped to a sceneTrainerActor.", trainerOfflineRequest.trainerID.scene); } return this; } @@ -340,59 +381,59 @@ public class AkkamonNexus extends AbstractBehavior<AkkamonNexus.Command> { private AkkamonNexus onNewTilePos(RequestNewTilePos newTilePosRequest) { ActorRef<SceneTrainerGroup.Command> sceneTrainerGroup = sceneIdToActor.get( - newTilePosRequest.sceneId + newTilePosRequest.trainerID.scene ); if (sceneTrainerGroup != null) { sceneTrainerGroup.tell(newTilePosRequest); } else { - getContext().getLog().info("Ignoring newTilePos request in scene {}, it isn't mapped to a sceneTrainerActor.", newTilePosRequest.sceneId); + getContext().getLog().info("Ignoring newTilePos request in scene {}, it isn't mapped to a sceneTrainerActor.", newTilePosRequest.trainerID.scene); } return this; } private AkkamonNexus onStopMoving(RequestStopMoving stopMovingRequest) { ActorRef<SceneTrainerGroup.Command> sceneTrainerGroup = sceneIdToActor.get( - stopMovingRequest.sceneId + stopMovingRequest.trainerID.scene ); if (sceneTrainerGroup != null) { sceneTrainerGroup.tell(stopMovingRequest); } else { - getContext().getLog().info("Ignoring stopMove request in scene {}, it isn't mapped to a sceneTrainerActor.", stopMovingRequest.sceneId); + getContext().getLog().info("Ignoring stopMove request in scene {}, it isn't mapped to a sceneTrainerActor.", stopMovingRequest.trainerID.scene); } return this; } private AkkamonNexus onStartMoving(RequestStartMoving startMovingRequest) { ActorRef<SceneTrainerGroup.Command> sceneTrainerGroup = sceneIdToActor.get( - startMovingRequest.sceneId + startMovingRequest.trainerID.scene ); if (sceneTrainerGroup != null) { sceneTrainerGroup.tell(startMovingRequest); } else { - getContext().getLog().info("Ignoring startMove request in scene {}, it isn't mapped to a sceneTrainerActor.", startMovingRequest.sceneId); + getContext().getLog().info("Ignoring startMove request in scene {}, it isn't mapped to a sceneTrainerActor.", startMovingRequest.trainerID.scene); } return this; } private AkkamonNexus onTrainerRegistered(TrainerRegistered reply) { // TODO test when registration fails? - getContext().getLog().info("Adding {} to scene {} Live AkkamonSessions in Messaging Engine", reply.trainerId, reply.sceneId); - reply.session.setTrainerId(reply.trainerId); - messageEngine.registerTrainerSessionToSceneAndTrainerIdMaps(reply.sceneId, reply.session); + getContext().getLog().info("Adding {} to scene {} Live AkkamonSessions in Messaging Engine", reply.trainerID, reply.trainerID.scene); + reply.session.settrainerID(reply.trainerID); + messageEngine.registerTrainerSessionToSceneAndtrainerIDMaps(reply.trainerID, reply.session); return this; } private AkkamonNexus onTrainerRegistration(RequestTrainerRegistration registrationRequest) { String sceneId = registrationRequest.sceneId; - String trainerId = registrationRequest.trainerId; + String trainerName = registrationRequest.trainerName; - getContext().getLog().info("Nexus received registration request for {} in {}", trainerId, sceneId); + getContext().getLog().info("Nexus received registration request for {} in {}", trainerName, sceneId); ActorRef<SceneTrainerGroup.Command> sceneTrainerGroup = sceneIdToActor.get(sceneId); if (sceneTrainerGroup != null) { sceneTrainerGroup.tell(registrationRequest); } else { - getContext().getLog().info("Creating sceneTrainerGroup {} for trainer {}", sceneId, trainerId); + getContext().getLog().info("Creating sceneTrainerGroup {} for trainer {}", sceneId, trainerName); ActorRef<SceneTrainerGroup.Command> sceneActor = getContext().spawn(SceneTrainerGroup.create(sceneId), "scene-" + sceneId); diff --git a/domain/src/main/java/akkamon/domain/SceneTrainerGroup.java b/domain/src/main/java/akkamon/domain/actors/SceneTrainerGroup.java index e8ace82..31f53b5 100644 --- a/domain/src/main/java/akkamon/domain/SceneTrainerGroup.java +++ b/domain/src/main/java/akkamon/domain/actors/SceneTrainerGroup.java @@ -1,4 +1,4 @@ -package akkamon.domain; +package akkamon.domain.actors; import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; @@ -6,6 +6,7 @@ import akka.actor.typed.javadsl.AbstractBehavior; import akka.actor.typed.javadsl.ActorContext; import akka.actor.typed.javadsl.Behaviors; import akka.actor.typed.javadsl.Receive; +import akkamon.domain.HeartBeatQuery; import java.time.Duration; import java.util.HashMap; @@ -19,13 +20,13 @@ public class SceneTrainerGroup extends AbstractBehavior<SceneTrainerGroup.Comman implements Command, AkkamonNexus.Command { public ActorRef<Trainer.Command> trainer; public String sceneId; - public String trainerId; + public String trainerID; public ActorRef<AkkamonNexus.Command> replyTo; - public TrainerOffline(ActorRef<Trainer.Command> trainerActor, String sceneId, String trainerId, ActorRef<AkkamonNexus.Command> replyTo) { + public TrainerOffline(ActorRef<Trainer.Command> trainerActor, String sceneId, String trainerID, ActorRef<AkkamonNexus.Command> replyTo) { this.trainer = trainerActor; this.sceneId = sceneId; - this.trainerId = trainerId; + this.trainerID = trainerID; this.replyTo = replyTo; } } @@ -35,7 +36,7 @@ public class SceneTrainerGroup extends AbstractBehavior<SceneTrainerGroup.Comman } private final String sceneId; - private final Map<String, ActorRef<Trainer.Command>> trainerIdToActor= new HashMap(); + private final Map<AkkamonNexus.TrainerID, ActorRef<Trainer.Command>> trainerIDToActor= new HashMap(); public SceneTrainerGroup(ActorContext<Command> context, String sceneId) { super(context); @@ -81,26 +82,26 @@ public class SceneTrainerGroup extends AbstractBehavior<SceneTrainerGroup.Comman private SceneTrainerGroup onWatchedTrainerOffline(TrainerOffline trainerOfflineMsg) { trainerOfflineMsg.replyTo.tell(trainerOfflineMsg); - trainerIdToActor.remove(trainerOfflineMsg.trainerId); + trainerIDToActor.remove(trainerOfflineMsg.trainerID); return this; } private SceneTrainerGroup onTrainerOfflineRequest(AkkamonNexus.RequestTrainerOffline trainerOfflineRequest) { - if (this.sceneId.equals(trainerOfflineRequest.sceneId)) { - ActorRef<Trainer.Command> trainerActor = trainerIdToActor.get(trainerOfflineRequest.trainerId); + if (this.sceneId.equals(trainerOfflineRequest.trainerID.scene)) { + ActorRef<Trainer.Command> trainerActor = trainerIDToActor.get(trainerOfflineRequest.trainerID); if (trainerActor != null) { trainerActor.tell(trainerOfflineRequest); trainerOfflineRequest.replyTo.tell(new AkkamonNexus.RespondTrainerOffline( trainerOfflineRequest.requestId, - trainerOfflineRequest.sceneId, + trainerOfflineRequest.trainerID, trainerOfflineRequest.session )); } else { getContext() .getLog() .warn( - "Ignoring trainerOffline for trainerId {}. There is no actor mapped to it.", - trainerOfflineRequest.trainerId + "Ignoring trainerOffline for trainerID {}. There is no actor mapped to it.", + trainerOfflineRequest.trainerID ); } } else { @@ -108,18 +109,18 @@ public class SceneTrainerGroup extends AbstractBehavior<SceneTrainerGroup.Comman .getLog() .warn( "Ignoring trainerOffline for {}. This actor is responsible for {}.", - trainerOfflineRequest.sceneId, + trainerOfflineRequest.trainerID.scene, this.sceneId); } return this; } private SceneTrainerGroup onHeartBeat(AkkamonNexus.RequestHeartBeat heartBeatRequest) { - Map<String, ActorRef<Trainer.Command>> trainerIdToActorCopy = new HashMap<>(this.trainerIdToActor); + Map<AkkamonNexus.TrainerID, ActorRef<Trainer.Command>> trainerIDToActorCopy = new HashMap<>(this.trainerIDToActor); getContext() .spawnAnonymous( HeartBeatQuery.create( - trainerIdToActorCopy, + trainerIDToActorCopy, heartBeatRequest.requestId, sceneId, heartBeatRequest.replyTo, @@ -130,16 +131,16 @@ public class SceneTrainerGroup extends AbstractBehavior<SceneTrainerGroup.Comman } private SceneTrainerGroup onNewTilePos(AkkamonNexus.RequestNewTilePos newTilePosRequest) { - if (this.sceneId.equals(newTilePosRequest.sceneId)) { - ActorRef<Trainer.Command> trainerActor = trainerIdToActor.get(newTilePosRequest.trainerId); + if (this.sceneId.equals(newTilePosRequest.trainerID.scene)) { + ActorRef<Trainer.Command> trainerActor = trainerIDToActor.get(newTilePosRequest.trainerID); if (trainerActor != null) { trainerActor.tell(newTilePosRequest); } else { getContext() .getLog() .warn( - "Ignoring newTilePos for trainerId {}. There is no actor mapped to it.", - newTilePosRequest.trainerId + "Ignoring newTilePos for trainerID {}. There is no actor mapped to it.", + newTilePosRequest.trainerID ); } } else { @@ -147,23 +148,23 @@ public class SceneTrainerGroup extends AbstractBehavior<SceneTrainerGroup.Comman .getLog() .warn( "Ignoring newTilePos for {}. This actor is responsible for {}.", - newTilePosRequest.sceneId, + newTilePosRequest.trainerID.scene, this.sceneId); } return this; } private SceneTrainerGroup onStopMoving(AkkamonNexus.RequestStopMoving stopMovingRequest) { - if (this.sceneId.equals(stopMovingRequest.sceneId)) { - ActorRef<Trainer.Command> trainerActor = trainerIdToActor.get(stopMovingRequest.trainerId); + if (this.sceneId.equals(stopMovingRequest.trainerID.scene)) { + ActorRef<Trainer.Command> trainerActor = trainerIDToActor.get(stopMovingRequest.trainerID); if (trainerActor != null) { trainerActor.tell(stopMovingRequest); } else { getContext() .getLog() .warn( - "Ignoring stopMovingRequest for trainerId {}. There is no actor mapped to it.", - stopMovingRequest.trainerId + "Ignoring stopMovingRequest for trainerID {}. There is no actor mapped to it.", + stopMovingRequest.trainerID ); } } else { @@ -171,23 +172,23 @@ public class SceneTrainerGroup extends AbstractBehavior<SceneTrainerGroup.Comman .getLog() .warn( "Ignoring stopMovingRequest for {}. This actor is responsible for {}.", - stopMovingRequest.sceneId, + stopMovingRequest.trainerID, this.sceneId); } return this; } private SceneTrainerGroup onStartMoving(AkkamonNexus.RequestStartMoving startMovingRequest) { - if (this.sceneId.equals(startMovingRequest.sceneId)) { - ActorRef<Trainer.Command> trainerActor = trainerIdToActor.get(startMovingRequest.trainerId); + if (this.sceneId.equals(startMovingRequest.trainerID.scene)) { + ActorRef<Trainer.Command> trainerActor = trainerIDToActor.get(startMovingRequest.trainerID); if (trainerActor != null) { trainerActor.tell(startMovingRequest); } else { getContext() .getLog() .warn( - "Ignoring startMovingRequest for trainerId {}. There is no actor mapped to it.", - startMovingRequest.trainerId + "Ignoring startMovingRequest for trainerID {}. There is no actor mapped to it.", + startMovingRequest.trainerID ); } } else { @@ -195,33 +196,36 @@ public class SceneTrainerGroup extends AbstractBehavior<SceneTrainerGroup.Comman .getLog() .warn( "Ignoring startMovingRequest for {}. This actor is responsible for {}.", - startMovingRequest.sceneId, + startMovingRequest.trainerID.scene, this.sceneId); } return this; } private SceneTrainerGroup onTrainerRegistration(AkkamonNexus.RequestTrainerRegistration registrationRequest) { + + AkkamonNexus.TrainerID existingOrNewTrainerID = new AkkamonNexus.TrainerID(registrationRequest.trainerName, this.sceneId); + if (this.sceneId.equals(registrationRequest.sceneId)) { - ActorRef<Trainer.Command> trainerActor = trainerIdToActor.get(registrationRequest.trainerId); + ActorRef<Trainer.Command> trainerActor = trainerIDToActor.get(existingOrNewTrainerID); if (trainerActor != null) { // TODO add optional already registered? registrationRequest.replyTo.tell(new AkkamonNexus.TrainerRegistered( - registrationRequest.trainerId, - sceneId, + existingOrNewTrainerID, registrationRequest.session )); } else { - getContext().getLog().info("Creating trainer actor for {}", registrationRequest.trainerId); + getContext().getLog().info("Creating trainer actor for {}", registrationRequest.trainerName); trainerActor = getContext() - .spawn(Trainer.create(sceneId, registrationRequest.trainerId), "trainer-" + registrationRequest.trainerId); + .spawn(Trainer.create(existingOrNewTrainerID), "trainer-" + existingOrNewTrainerID.id); getContext() - .watchWith(trainerActor, new SceneTrainerGroup.TrainerOffline(trainerActor, sceneId, registrationRequest.trainerId, registrationRequest.replyTo)); - trainerIdToActor.put(registrationRequest.trainerId, trainerActor); + .watchWith(trainerActor, new TrainerOffline(trainerActor, sceneId, registrationRequest.trainerName, registrationRequest.replyTo)); + + trainerIDToActor.put(existingOrNewTrainerID, trainerActor); + registrationRequest.replyTo.tell(new AkkamonNexus.TrainerRegistered( - registrationRequest.trainerId, - sceneId, + existingOrNewTrainerID, registrationRequest.session )); } diff --git a/domain/src/main/java/akkamon/domain/Trainer.java b/domain/src/main/java/akkamon/domain/actors/Trainer.java index caad860..4d4d9c5 100644 --- a/domain/src/main/java/akkamon/domain/Trainer.java +++ b/domain/src/main/java/akkamon/domain/actors/Trainer.java @@ -1,4 +1,4 @@ -package akkamon.domain; +package akkamon.domain.actors; import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; @@ -6,11 +6,15 @@ import akka.actor.typed.javadsl.AbstractBehavior; import akka.actor.typed.javadsl.ActorContext; import akka.actor.typed.javadsl.Behaviors; import akka.actor.typed.javadsl.Receive; +import akkamon.domain.Direction; +import akkamon.domain.TilePos; import java.util.LinkedList; import java.util.Optional; import java.util.Queue; +import static akkamon.domain.actors.AkkamonNexus.*; + public class Trainer extends AbstractBehavior<Trainer.Command> { public interface Command { } @@ -27,26 +31,25 @@ public class Trainer extends AbstractBehavior<Trainer.Command> { public static final class RespondMovementQueue { final long requestId; - final String trainerId; + final TrainerID trainerID; final Queue<Direction> value; public RespondMovementQueue( long requestId, - String trainerId, + TrainerID trainerID, Queue<Direction> value ) { this.requestId = requestId; - this.trainerId = trainerId; + this.trainerID = trainerID; this.value = value; } } - public static Behavior<Command> create(String sceneId, String trainerId) { - return Behaviors.setup(context -> new Trainer(context, sceneId, trainerId)); + public static Behavior<Command> create(TrainerID trainerID) { + return Behaviors.setup(context -> new Trainer(context, trainerID)); } - private String sceneId; - private String trainerId; + private TrainerID trainerID; private Queue<Direction> movementQueue = new LinkedList<>(); @@ -54,10 +57,9 @@ public class Trainer extends AbstractBehavior<Trainer.Command> { private Optional<TilePos> lastValidTilePos = Optional.empty(); - public Trainer(ActorContext<Command> context, String sceneId, String trainerId) { + public Trainer(ActorContext<Command> context, TrainerID trainerID) { super(context); - this.sceneId = sceneId; - this.trainerId = trainerId; + this.trainerID = trainerID; } @Override @@ -68,24 +70,24 @@ public class Trainer extends AbstractBehavior<Trainer.Command> { this::onReadMovementQueue ) .onMessage( - AkkamonNexus.RequestTrainerOffline.class, + RequestTrainerOffline.class, this::onTrainerOffline ) .onMessage( - AkkamonNexus.RequestStartMoving.class, + RequestStartMoving.class, this::onStartMoving ) .onMessage( - AkkamonNexus.RequestStopMoving.class, + RequestStopMoving.class, this::onStopMoving) .onMessage( - AkkamonNexus.RequestNewTilePos.class, + RequestNewTilePos.class, this::onNewTilePos ) .build(); } - private Behavior<Command> onTrainerOffline(AkkamonNexus.RequestTrainerOffline trainerOfflineRequest) { + private Behavior<Command> onTrainerOffline(RequestTrainerOffline trainerOfflineRequest) { getContext().getLog().info("Trainer {} went offline, the actor has stopped! My supervisor should handle closing my connection!"); return Behaviors.stopped(); } @@ -93,29 +95,29 @@ public class Trainer extends AbstractBehavior<Trainer.Command> { private Trainer onReadMovementQueue(ReadMovementQueue readTrainerPositionRequest) { readTrainerPositionRequest.replyTo.tell(new RespondMovementQueue( readTrainerPositionRequest.requestId, - trainerId, + trainerID, new LinkedList<>(movementQueue) )); this.movementQueue.clear(); return this; } - private Trainer onNewTilePos(AkkamonNexus.RequestNewTilePos newTilePosRequest) { - // getContext().getLog().info("Trainer {} has new {}.", trainerId, newTilePosRequest.tilePos); + private Trainer onNewTilePos(RequestNewTilePos newTilePosRequest) { + // getContext().getLog().info("Trainer {} has new {}.", trainerID, newTilePosRequest.tilePos); if (isMoving()) { this.movementQueue.add(this.movementDirection); } return this; } - private Trainer onStopMoving(AkkamonNexus.RequestStopMoving stopMovingRequest) { - // getContext().getLog().info("Trainer {} stops to move {}.", trainerId, stopMovingRequest.direction); + private Trainer onStopMoving(RequestStopMoving stopMovingRequest) { + // getContext().getLog().info("Trainer {} stops to move {}.", trainerID, stopMovingRequest.direction); this.movementDirection = Direction.NONE; return this; } - private Trainer onStartMoving(AkkamonNexus.RequestStartMoving startMovingRequest) { - // getContext().getLog().info("Trainer {} starts to move {}.", trainerId, startMovingRequest.direction); + private Trainer onStartMoving(RequestStartMoving startMovingRequest) { + // getContext().getLog().info("Trainer {} starts to move {}.", trainerID, startMovingRequest.direction); this.movementDirection = startMovingRequest.direction; return this; } diff --git a/domain/src/test/java/akkamon/domain/AkkamonNexusTest.java b/domain/src/test/java/akkamon/domain/AkkamonNexusTest.java index d83bdcb..0ece974 100644 --- a/domain/src/test/java/akkamon/domain/AkkamonNexusTest.java +++ b/domain/src/test/java/akkamon/domain/AkkamonNexusTest.java @@ -3,6 +3,8 @@ package akkamon.domain; import akka.actor.testkit.typed.javadsl.TestKitJunitResource; import akka.actor.testkit.typed.javadsl.TestProbe; import akka.actor.typed.ActorRef; +import akkamon.domain.actors.AkkamonNexus; +import akkamon.domain.actors.SceneTrainerGroup; import org.junit.ClassRule; import org.junit.Test; |
