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 events = game.tryMoveTo(position); broadcastEvents(events); } catch (RuntimeException e) { e.printStackTrace(); } }); } @Override public void moveActivePath() { backgroundThread.submit( () -> { try { List events = game.moveActivePath(); broadcastEvents(events); } catch (RuntimeException e) { e.printStackTrace(); } }); } @Override public void endTurn() { backgroundThread.submit( () -> { try { List events = game.endTurn(); broadcastEvents(events); } catch (RuntimeException e) { e.printStackTrace(); } }); } @Override public void waitTurn() { backgroundThread.submit( () -> { try { List events = game.waitTurn(); broadcastEvents(events); } catch (RuntimeException e) { e.printStackTrace(); } }); } @Override public void useCardOn(Point position) { backgroundThread.submit( () -> { try { List events = game.useCardOn(position); broadcastEvents(events); } catch (RuntimeException e) { e.printStackTrace(); } }); } @Override public void swapCards(int first, int second) { backgroundThread.submit( () -> { try { List events = game.swapCards(first, second); broadcastEvents(events); } catch (RuntimeException e) { e.printStackTrace(); } }); } @Override public Optional selectCard(int cardIndex) { try { return backgroundThread .submit( () -> { try { List 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 events = game.removeCard(index); broadcastEvents(events); } catch (RuntimeException e) { e.printStackTrace(); } }); } @Override public void equip(int index) { backgroundThread.submit( () -> { try { List events = game.equip(index); broadcastEvents(events); } catch (RuntimeException e) { e.printStackTrace(); } }); } @Override public void swapEquipment(int first, int second) { backgroundThread.submit( () -> { try { List events = game.swapEquipment(first, second); broadcastEvents(events); } catch (RuntimeException e) { e.printStackTrace(); } }); } @Override public void removeEquipment(int index) { backgroundThread.submit( () -> { try { List events = game.removeEquipment(index); broadcastEvents(events); } catch (RuntimeException e) { e.printStackTrace(); } }); } @Override public void setHighlighted(Point point, boolean highlighted) { backgroundThread.submit( () -> { try { List 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 events) { if (events.size() > 1) { events.getFirst().setDisableControls(true); events.getLast().setEnableControls(true); } for (GameEvent event : events) { eventManager.broadcast(event); } } }