package com.asteria.game.character.player.dialogue; import java.util.ArrayDeque; import java.util.Optional; import java.util.Queue; import java.util.function.Consumer; import com.asteria.game.character.player.Player; /** * The dialogue chain builder that contains functions for building and managing * dialogues. * * @author lare96 <http://github.com/lare96> */ public final class DialogueChainBuilder { /** * The player that this chain builder is dedicated to. */ private final Player player; /** * The queue of dialogue entries in this chain builder. */ private final Queue<DialogueChain> chain = new ArrayDeque<>(); /** * The option listener for this chain builder. */ private Optional<Consumer<OptionType>> optionListener = Optional.empty(); /** * Creates a new {@link DialogueChainBuilder}. * * @param player * the player that this chain builder is dedicated to. */ public DialogueChainBuilder(Player player) { this.player = player; } /** * Appends {@code entry} to this chain builder. * * @param entry * the dialogue chain to append to this chain builder. * @return an instance of this chain builder. */ public DialogueChainBuilder append(DialogueChain entry) { chain.add(entry); return this; } /** * Appends {@code optionListener} to this chain builder. * * @param optionListener * the option listener to append to this builder. * @return an instance of this chain builder. */ protected void append(Optional<Consumer<OptionType>> optionListener) { this.optionListener = optionListener; } /** * Advances this chain builder by one dialogue chain. * * @throws IllegalStateException * if this dialogue chain builder is empty. */ public void advance() { DialogueChain entry = chain.poll(); if (entry == null) { player.getMessages().sendCloseWindows(); } else { entry.accept(this); } } /** * Interrupts this chain builder by clearing the backing chain list and * resetting the cursor value. */ public void interrupt() { if (!chain.isEmpty()) chain.clear(); optionListener = Optional.empty(); } /** * Executes the dialogue option listener with {@code type} if it is * available. * * @param type * the dialogue option type. * @return {@code true} if the option was executed, {@code false} otherwise. */ public boolean executeOptions(OptionType type) { if (optionListener.isPresent()) { optionListener.get().accept(type); optionListener = Optional.empty(); return true; } return false; } /** * The size of the backing chain list in this chain builder. * * @return the size of this chain builder. */ public int size() { return chain.size(); } /** * Gets the player that this chain builder is dedicated to. * * @return the player for this chain builder. */ public Player getPlayer() { return player; } }