mourning-ember / src / main / java / dev / llan / model / GameContainer.java
GameContainer.java
Raw
package dev.llan.model;

import dev.llan.model.board.Point;
import dev.llan.events.GameEvent;
import dev.llan.events.GameInitializedEvent;
import dev.llan.model.cards.Card;
import dev.llan.receivers.Receiver;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static dev.llan.model.Constants.*;

public final class GameContainer implements Model {
  private static GameContainer instance;

  public static GameContainer getInstance() {
    if (instance == null) {
      instance = new GameContainer();
    }
    return instance;
  }

  private final ExecutorService backgroundThread = Executors.newSingleThreadExecutor();

  private Game game;
  private final EventManager eventManager;

  private GameContainer() {
    eventManager = new EventManager();
  }

  @Override
  public Game initGame() {
    try {
      return backgroundThread
          .submit(
              () -> {
                try {
                  game = new Game(GAME_SIZE);
                  broadcastEvents(List.of(new GameInitializedEvent()));
                  return game;
                } catch (RuntimeException e) {
                  e.printStackTrace();
                  throw e;
                }
              })
          .get();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public Game getCurrentGame() {
    return game;
  }

  @Override
  public void registerReceiver(Receiver receiver) {
    eventManager.registerReceiver(receiver);
  }

  @Override
  public void removeReceiver(Receiver receiver) {
    eventManager.removeReceiver(receiver);
  }

  @Override
  public void tryMoveTo(Point position) {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.tryMoveTo(position);
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public void moveActivePath() {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.moveActivePath();
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public void endTurn() {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.endTurn();
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public void waitTurn() {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.waitTurn();
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public void useCardOn(Point position) {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.useCardOn(position);
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public void swapCards(int first, int second) {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.swapCards(first, second);
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public Optional<Card> selectCard(int cardIndex) {
    try {
      return backgroundThread
          .submit(
              () -> {
                try {
                  List<GameEvent> events = game.selectCard(cardIndex);
                  broadcastEvents(events);
                  return game.getPlayer().getSelectedCard();
                } catch (RuntimeException e) {
                  e.printStackTrace();
                  throw e;
                }
              })
          .get();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public void removeCard(int index) {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.removeCard(index);
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public void equip(int index) {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.equip(index);
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public void swapEquipment(int first, int second) {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.swapEquipment(first, second);
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public void removeEquipment(int index) {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.removeEquipment(index);
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public void setHighlighted(Point point, boolean highlighted) {
    backgroundThread.submit(
        () -> {
          try {
            List<GameEvent> events = game.setHighlighted(point, highlighted);
            broadcastEvents(events);
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        });
  }

  @Override
  public boolean isInRange(Point point) {
    return game.getPlayer().isInRange(point);
  }

  private void broadcastEvents(List<GameEvent> events) {
    if (events.size() > 1) {
      events.getFirst().setDisableControls(true);
      events.getLast().setEnableControls(true);
    }
    for (GameEvent event : events) {
      eventManager.broadcast(event);
    }
  }
}