All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.portlek.input.ChatInput Maven / Gradle / Ivy

The newest version!
/*
 * MIT License
 *
 * Copyright (c) 2021 Hasan Demirtaş
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package io.github.portlek.input;

import io.github.portlek.input.event.ChatEvent;
import io.github.portlek.input.event.QuitEvent;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * a class created to get inputs from players.
 *
 * @param  the input type.
 * @param 

the input sender type. */ @RequiredArgsConstructor(access = AccessLevel.PRIVATE) public final class ChatInput { /** * the builder. */ @NotNull private final ChatInput.Builder builder; /** * the platform. */ @NotNull private final ChatPlatform

platform; /** * the started. */ private final AtomicBoolean started = new AtomicBoolean(false); /** * the expire task. */ @Nullable private ChatTask expireTask; /** * creates a new builder instance. * * @param platform the platform to create. * @param sender the sender to create. * @param type of the value. * @param

type of the sender. * * @return a newly created builder instance. */ @NotNull public static Builder builder(@NotNull final ChatPlatform

platform, @NotNull final ChatSender

sender) { return new Builder<>(platform, sender); } /** * stops the chat input sequence. * * @param sender the sender to end. * @param reason the reason to end. */ public void end(@NotNull final P sender, @NotNull final EndReason reason) { this.started.set(false); this.platform.unregisterListeners(); Optional.ofNullable(this.expireTask).ifPresent(ChatTask::cancel); this.builder.getRunAfter().forEach((r, j) -> { if (r == reason) { j.forEach(c -> c.accept(sender)); } }); } /** * runs when the sender push an input. * * @param event the event to apply as a send message event. */ public void onChat(@NotNull final ChatEvent

event) { if (!this.started.get()) { return; } final ChatSender

sender = this.builder.getSender(); if (!sender.getUniqueId().equals(event.getSender().getUniqueId())) { return; } event.cancel(); final String message = event.getMessage(); final P wrapped = sender.getWrapped(); if (message.equalsIgnoreCase(this.builder.getCancel())) { this.builder.getOnCancel().accept(wrapped); this.end(wrapped, EndReason.PLAYER_CANCELS); return; } if (this.builder.getIsValidInput().test(wrapped, message)) { final T value = this.builder.getSetValue().apply(wrapped, message); this.builder.getOnFinish().accept(wrapped, value); this.end(wrapped, EndReason.FINISH); } else { if (this.builder.getOnInvalidInput().test(wrapped, message)) { Optional.ofNullable(this.builder.getInvalidInputMessage()) .ifPresent(sender::sendMessage); Optional.ofNullable(this.builder.getSendValueMessage()) .filter(s -> this.builder.isRepeat()) .ifPresent(sender::sendMessage); } if (!this.builder.isRepeat()) { this.end(wrapped, EndReason.INVALID_INPUT); } } } /** * runs when the send quits from the game. * * @param event the event to apply as a quit event. */ public void onQuit(@NotNull final QuitEvent

event) { if (!this.started.get()) { return; } final ChatSender

sender = this.builder.getSender(); if (event.getSender().getUniqueId().equals(sender.getUniqueId())) { this.builder.getOnDisconnect().accept(sender.getWrapped()); this.end(sender.getWrapped(), EndReason.PLAYER_DISCONNECTS); } } /** * starts the chat input sequence. */ public void start() { this.platform.init(this); final ChatSender

sender = this.builder.getSender(); if (this.builder.getExpire() != -1L) { this.expireTask = this.platform.createRunTaskLater(() -> { if (!this.started.get()) { return; } Optional.ofNullable(this.expireTask) .filter(task -> !task.isCancelled()).map(task -> sender.getWrapped()) .ifPresent(wrapped -> { this.builder.getOnExpire().accept(wrapped); this.end(wrapped, EndReason.EXPIRE); }); }, this.builder.getExpire()); } this.started.set(true); Optional.ofNullable(this.builder.getSendValueMessage()) .ifPresent(sender::sendMessage); } /** * a builder class to create {@link ChatInput} instance. * * @param the value type. * @param

the input sender type. */ @Getter @RequiredArgsConstructor(access = AccessLevel.PRIVATE) public static final class Builder { /** * the platform. */ @NotNull private final ChatPlatform

platform; /** * the run after finish. */ @NotNull private final EnumMap>> runAfter = new EnumMap<>(EndReason.class); /** * the sender. */ @NotNull private final ChatSender

sender; /** * the cancel. */ @NotNull private String cancel = "cancel"; /** * the expire. */ private long expire = -1L; /** * the expire message. */ @Nullable private Function expireMessage; /** * the invalid input message. */ @Nullable private String invalidInputMessage = "That is not a valid input!"; /** * the is valid input. */ @NotNull private BiPredicate isValidInput = (p, mes) -> true; /** * the on cancel. */ @NotNull private Consumer

onCancel = p -> { }; /** * the on disconnect. */ @NotNull private Consumer

onDisconnect = sender -> { }; /** * the on expire. */ @NotNull private Consumer

onExpire = p -> { }; /** * the on finish. */ @NotNull private BiConsumer onFinish = (p, val) -> { }; /** * the on invalid input. */ @NotNull private BiPredicate onInvalidInput = (p, mes) -> true; /** * the repeat. */ private boolean repeat = true; /** * the send value message. */ @Nullable private String sendValueMessage = "Send in the chat the value"; /** * the value. */ @Nullable private T value; /** * the set value. */ @NotNull private BiFunction setValue = (p, mes) -> this.value; /** * puts the given values into {@link #runAfter}. * * @param runAfter the run after to put. * @param reasons the reasons to put. * * @return {@code this}. */ @NotNull public Builder addRunAfter(@NotNull final Consumer

runAfter, @NotNull final EndReason... reasons) { Arrays.stream(reasons) .forEach(reason -> { final Collection> old = this.runAfter.getOrDefault(reason, new HashSet<>()); old.add(runAfter); this.runAfter.put(reason, old); }); return this; } /** * builds the {@link ChatInput} instance. * * @return a {@link ChatInput} instance. */ @NotNull public ChatInput build() { return new ChatInput<>(this, this.platform); } /** * puts the given values into {@link #runAfter}. *

* opens the given builder after finishing the chat input. * * @param builder the run after to put. * @param reasons the reasons to put. * * @return {@code this}. * * @see #chainAfter(ChatInput, EndReason...) */ @NotNull public Builder chainAfter(@NotNull final Builder builder, @NotNull final EndReason... reasons) { return this.chainAfter(builder.build(), reasons); } /** * puts the given values into {@link #runAfter}. *

* opens the given chat input after finishing the chat input. * * @param input the input to put. * @param reasons the reasons to put. * * @return {@code this}. * * @see #addRunAfter(Consumer, EndReason...) */ @NotNull public Builder chainAfter(@NotNull final ChatInput input, @NotNull final EndReason... reasons) { return this.addRunAfter(sender -> input.start(), Arrays.stream(reasons) .filter(reason -> reason != EndReason.PLAYER_DISCONNECTS) .toArray(EndReason[]::new)); } /** * sets {@link #value} and return {@code this}. * * @param value the value to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder defaultValue(@Nullable final T value) { this.value = value; return this; } /** * sets {@link #expire} and return {@code this}. * * @param expire the expire to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder expire(final long expire) { this.expire = expire; return this; } /** * sets {@link #invalidInputMessage} and return {@code this}. * * @param invalidInputMessage the invalid input message to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder invalidInputMessage(@Nullable final String invalidInputMessage) { this.invalidInputMessage = invalidInputMessage; return this; } /** * sets {@link #isValidInput} and return {@code this}. * * @param isValidInput the is valid input to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder isValidInput(@NotNull final BiPredicate isValidInput) { this.isValidInput = isValidInput; return this; } /** * sets {@link #onCancel} and return {@code this}. * * @param onCancel the on cancel to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder onCancel(@NotNull final Consumer

onCancel) { this.onCancel = onCancel; return this; } /** * sets {@link #onDisconnect}. * * @param onDisconnect the on disconnect to set. * * @return {@code this}. */ @NotNull public Builder onDisconnect(@NotNull final Consumer

onDisconnect) { this.onDisconnect = onDisconnect; return this; } /** * sets {@link #onExpire} and return {@code this}. * * @param onExpire the on expire to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder onExpire(@NotNull final Consumer

onExpire) { this.onExpire = onExpire; return this; } /** * sets {@link #onFinish} and return {@code this}. * * @param onFinish the on finish to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder onFinish(@NotNull final BiConsumer onFinish) { this.onFinish = onFinish; return this; } /** * sets {@link #onInvalidInput} and return {@code this}. * * @param onInvalidInput the on invalid input to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder onInvalidInput(@NotNull final BiPredicate onInvalidInput) { this.onInvalidInput = onInvalidInput; return this; } /** * sets {@link #repeat} and return {@code this}. * * @param repeat the repeat to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder repeat(final boolean repeat) { this.repeat = repeat; return this; } /** * sets {@link #sendValueMessage} and return {@code this}. * * @param sendValueMessage the send value message to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder sendValueMessage(@Nullable final String sendValueMessage) { this.sendValueMessage = sendValueMessage; return this; } /** * sets {@link #expireMessage}. * * @param expireMessage the expire message to set. * * @return {@code this}. */ @NotNull public Builder setExpireMessage(@NotNull final Function expireMessage) { this.expireMessage = expireMessage; return this; } /** * sets {@link #setValue} and return {@code this}. * * @param setValue the set value to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder setValue(@NotNull final BiFunction setValue) { this.setValue = setValue; return this; } /** * sets {@link #cancel} and return {@code this}. * * @param cancel the cancel to set. * * @return {@code this}. */ @NotNull public ChatInput.Builder toCancel(@NotNull final String cancel) { this.cancel = cancel; return this; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy