Skip to content

Commit

Permalink
add game state machine; extract to module
Browse files Browse the repository at this point in the history
  • Loading branch information
svencc committed Dec 12, 2024
1 parent c697c34 commit 33438c9
Show file tree
Hide file tree
Showing 17 changed files with 232 additions and 43 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@
/services/recom-backend/target/
/services/recom-backend/src/test/resources/test
/services/recom-commander/target/
/libs/statemachine/target/
2 changes: 1 addition & 1 deletion libs/entitycomponentsystem/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>recom-Entity-component-system</artifactId>
<artifactId>recom-entity-component-system</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>RECOM Entity Component System</name>
<description>RECOM Entity Component System</description>
Expand Down
1 change: 1 addition & 0 deletions libs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<module>sharedmodels</module>
<module>tacviewfx</module>
<module>entitycomponentsystem</module>
<module>statemachine</module>
</modules>

<dependencies>
Expand Down
4 changes: 2 additions & 2 deletions libs/sharedmodels/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

<artifactId>recom-sharedmodels</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>RECOM shared Models</name>
<description>RECOM Shared DTOs</description>
<name>RECOM Shared Models</name>
<description>RECOM Shared Models and DTOs</description>

<dependencies>

Expand Down
49 changes: 49 additions & 0 deletions libs/statemachine/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

<parent>
<groupId>com.recom</groupId>
<artifactId>libs</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>recom-state-machine</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>RECOM State Machine</name>
<description>RECOM State Machine</description>

<dependencies>

<!-- NEEDED FOR: import org.springframework.lang.Nullable -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<!-- NEEDED FOR: import org.springframework.lang.Nullable -->

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.recom.statemachine;

public interface FSMEventable {
public interface BaseFSMEvent {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.recom.statemachine;

import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import org.springframework.lang.Nullable;

import java.time.Duration;
import java.time.Instant;

abstract public class BaseStateMachine<STATES extends Enum, TRANSITIONS extends BaseTransition<? extends BaseStateMachine, STATES>, EVENT extends BaseFSMEvent> {

@Getter
@Setter
@Nullable
protected STATES currentMachineState;
protected TRANSITIONS transitions;
@NonNull
private Instant lastEvent = Instant.now();

protected BaseStateMachine() {
currentMachineState = null;
transitions = initTransitions();
}

@NonNull
protected abstract TRANSITIONS initTransitions();

private boolean triggerReRun = false;

public abstract void start();

public abstract void stop();

protected void trackEventTime() {
lastEvent = Instant.now();
}

@NonNull
private Duration calculateDeltaTime() {
final Duration deltaTime = Duration.between(lastEvent, Instant.now());
trackEventTime();

return deltaTime;
}

protected void triggerReRun() {
triggerReRun = true;
}

public void nextEvent(@NonNull final EVENT event) throws IllegalStateException {
do {
triggerReRun = false;
final Duration deltaTime = calculateDeltaTime();
handleEvent(event, deltaTime);
} while (triggerReRun);
}

protected abstract void handleEvent(
@NonNull final EVENT event,
@NonNull final Duration deltaTime
) throws IllegalStateException;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.recom.statemachine;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
abstract public class BaseTransition<MACHINE extends BaseStateMachine, STATES extends Enum> {

protected final MACHINE machine;

@NonNull
protected IllegalStateException getFsmIsNotStarted() {
return new IllegalStateException("FSM is not started");
}

}
6 changes: 6 additions & 0 deletions services/recom-backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.recom</groupId>
<artifactId>recom-state-machine</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<!-- RECOM SHARED LIBRARY -->

<!-- SPRING BOOT WEB -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@RequiredArgsConstructor
public class ColorCalculatorConfiguration {

@Bean()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.recom.model;

import com.recom.security.account.RECOMAccount;
import com.recom.statemachine.game.GameEvent;
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
Expand All @@ -11,7 +12,7 @@
@Data
@Builder
@RequiredArgsConstructor
public class HeartbeatModel {
public class HeartbeatModel extends GameEvent {

@NonNull
private final RECOMAccount account;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
package com.recom.service.game;

import com.recom.service.map.GameMapService;
import com.recom.service.messagebus.MessageBusService;
import com.recom.statemachine.game.GameMachine;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class GameMachineService {

@NonNull
private final GameMapService gameMapService;
@NonNull
private final MessageBusService messageBusService;

@NonNull
private final Map<String, GameMachine> runningGameMachines = new HashMap<>();

@NonNull
public GameMachine provideMachine(@NonNull final String gameId) {
return runningGameMachines.computeIfAbsent(gameId, k -> {
final GameMachine newGameMachine = new GameMachine();
final GameMachine newGameMachine = new GameMachine(gameMapService, messageBusService);
newGameMachine.start();

return newGameMachine;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.recom.statemachine.game;

import com.recom.statemachine.FSMEventable;
import com.recom.statemachine.BaseFSMEvent;

public class GameEvent implements FSMEventable {
public class GameEvent implements BaseFSMEvent {

public final static GameEvent HEARTBEAT = new GameEvent();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,65 @@
package com.recom.statemachine.game;

import com.recom.model.HeartbeatModel;
import com.recom.service.map.GameMapService;
import com.recom.service.messagebus.MessageBusService;
import com.recom.statemachine.BaseStateMachine;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

import java.time.Duration;
import java.time.Instant;

public class GameMachine extends BaseStateMachine<GameStates, GameEvent> {
@RequiredArgsConstructor
public class GameMachine extends BaseStateMachine<GameStates, GameTransitions, GameEvent> {

@NonNull
private Instant lastEvent = Instant.now();
private final GameMapService gameMapService;
@NonNull
private final MessageBusService messageBusService;

@NonNull
@Override
protected GameTransitions initTransitions() {
return new GameTransitions(this);
}

@Override
public void start() {
currentMachineState = GameStates.CHECK_MAP;
lastEvent = Instant.now();
trackEventTime();
}

@Override
public void stop() {
currentMachineState = GameStates.STOPPED;
lastEvent = Instant.now();
trackEventTime();
}

@Override
public void nextEvent(@NonNull final GameEvent event) {
final Duration deltaTime = calculateDeltaTime();
protected void handleEvent(
@NonNull final GameEvent event,
@NonNull final Duration deltaTime

) throws IllegalStateException {
switch (currentMachineState) {
case CHECK_MAP:
if (event instanceof HeartbeatModel heartbeat) {
if (gameMapService.provideGameMap(heartbeat.getMapName()).isPresent()) {
transitions.map_is_ready();
triggerReRun();
} else {
transitions.map_is_not_ready();
triggerReRun();
}
}
break;
case SCAN_MAP:

// 1. request map_meta_creation if not exists
// 2. wait for map_meta_creation in state
// 3. trigger map_meta_is_created

// messageBusService.sendMessage();
break;
case IN_GAME:
break;
Expand All @@ -46,12 +76,4 @@ public void nextEvent(@NonNull final GameEvent event) {
}
}

@NonNull
private Duration calculateDeltaTime() {
final Duration deltaTime = Duration.between(lastEvent, Instant.now());
lastEvent = Instant.now();

return deltaTime;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ footer RECOM.one
CHECK_MAP --> SCAN_MAP :map_is_not_ready
CHECK_MAP --> IN_GAME :map_is_ready

SCAN_MAP --> SCAN_MAP :create_map
SCAN_MAP --> REQUEST_MAP_META :request_map_meta
REQUEST_MAP_META --> SCAN_MAP :map_meta_created
REQUEST_MAP_META --> REQUEST_MAP_META :map_meta_not_created
SCAN_MAP --> SCAN_MAP :scan_sector
SCAN_MAP --> IN_GAME :map_is_scanned

Expand All @@ -26,7 +28,7 @@ legend left
__**ALPHABET**__
| **Symbol** | **Description** |
| start | on start() |
| stop | on autoclosable close() |
| stop | on close() |
| map_is_ready | ... |
| map_is_not_ready | ... |
| create_map | ... |
Expand Down
Loading

0 comments on commit 33438c9

Please sign in to comment.