Skip to content
Settlers Journal
Go back

Full-Stack Road Placement and Builder Pattern for the FSM

Edit page

TLDR

Had several hours to work today. Made significant changes to both the frontend and backend. Frontend - added the ability to place roads on the board. This required cleaning up API call logic and reusing / refactoring the existing place settlement code. Backend - reworked the data structures and logic for Finite State Machine now that it is relatively stable. This involved a lot of boilerplate Java code changes.

Builder Pattern

// internal class implementing the steps
private static class BuilderSteps implements StepStartState, StepAction, StepGlide {

  private final Builder builder = new Builder();

  @Override
  public StepAction setStartState(StateEnum startState) {
    builder.startStateEnum = startState;
    return this;
  }

  @Override
  public StepGlide setAction(IAction action) {
    builder.action = action;
    return this;
  }

  @Override
  public StepGlide addGlide(IGlide glide) {
    builder.glides.add(glide);
    return this;
  }

  // TODO this should have a test that checks for a thrown exception
  @SneakyThrows
  @Override
  public Transition build() {
    // throw exception if any glides don't have correct start state
    for(IGlide glide : builder.glides) {
      if (glide.getStartStateEnum() != builder.startStateEnum) {
        throw new Exception("Invalid glide definition in Transition. Starting StateEnum must match parent StateEnum.");
      }
    }

    return new Transition(
        builder.action,
        builder.glides
    );
  }
}

Observable Reuse

// common logic for handling player action success / failure
private handlePlayerAction(playerAction: PlayerAction): {
  next: (value: GameState) => void;
  error?: (error: any) => void;
  complete?: () => void;
} {
  return {
    next: (gameState: GameState) => {
      console.log(`Performed ${playerAction} action.`);
      this.actionState.clearAll();
      this.gameState = gameState;
    },
    error: (e: any) => {
      // Handle errors, such as logging or notifying the user
      console.error(
        `Could not perform ${playerAction} action: ${JSON.stringify(e)}`,
      );
      this.actionState.clearAll();
    },
  };
}

Main work

Challenges

Learnings


Edit page
Share this post on:

Previous Post
Refactoring Graph Data Structures and Loading Board Layout from Files
Next Post
Implementing Place Road Action and Cleaning Up API Call Logic