169 lines
5.9 KiB
Java
169 lines
5.9 KiB
Java
package dev.loki.ui;
|
||
|
||
import dev.loki.mdbd;
|
||
import net.kyori.adventure.text.Component;
|
||
import net.kyori.adventure.text.format.NamedTextColor;
|
||
import net.kyori.adventure.text.format.TextDecoration;
|
||
import net.kyori.adventure.title.Title;
|
||
import org.bukkit.entity.Player;
|
||
|
||
import java.time.Duration;
|
||
import java.util.HashMap;
|
||
import java.util.Map;
|
||
import java.util.UUID;
|
||
import java.util.function.Consumer;
|
||
|
||
public class TitleUI {
|
||
private final mdbd plugin;
|
||
private final Map<UUID, SkillCheckState> activeSkillChecks;
|
||
|
||
public TitleUI(mdbd plugin) {
|
||
this.plugin = plugin;
|
||
this.activeSkillChecks = new HashMap<>();
|
||
}
|
||
|
||
public void showGameStart(Player player, boolean isKiller) {
|
||
Title.Times times = Title.Times.times(
|
||
Duration.ofMillis(500),
|
||
Duration.ofSeconds(3),
|
||
Duration.ofMillis(500)
|
||
);
|
||
|
||
Component title;
|
||
Component subtitle;
|
||
|
||
if (isKiller) {
|
||
title = Component.text("KILLER")
|
||
.color(NamedTextColor.DARK_RED)
|
||
.decoration(TextDecoration.BOLD, true);
|
||
subtitle = Component.text("Sacrifice them all")
|
||
.color(NamedTextColor.RED);
|
||
} else {
|
||
title = Component.text("SURVIVOR")
|
||
.color(NamedTextColor.DARK_GREEN)
|
||
.decoration(TextDecoration.BOLD, true);
|
||
subtitle = Component.text("Repair generators and escape")
|
||
.color(NamedTextColor.GREEN);
|
||
}
|
||
|
||
player.showTitle(Title.title(title, subtitle, times));
|
||
}
|
||
|
||
public void showVictory(Player player, boolean escaped) {
|
||
Title.Times times = Title.Times.times(
|
||
Duration.ofMillis(500),
|
||
Duration.ofSeconds(5),
|
||
Duration.ofSeconds(1)
|
||
);
|
||
|
||
Component title = escaped
|
||
? Component.text("ESCAPED!")
|
||
.color(NamedTextColor.GREEN)
|
||
.decoration(TextDecoration.BOLD, true)
|
||
: Component.text("VICTORY!")
|
||
.color(NamedTextColor.DARK_RED)
|
||
.decoration(TextDecoration.BOLD, true);
|
||
|
||
Component subtitle = escaped
|
||
? Component.text("You survived the night")
|
||
.color(NamedTextColor.DARK_GREEN)
|
||
: Component.text("All survivors sacrificed")
|
||
.color(NamedTextColor.RED);
|
||
|
||
player.showTitle(Title.title(title, subtitle, times));
|
||
}
|
||
|
||
public void showDefeat(Player player) {
|
||
Title.Times times = Title.Times.times(
|
||
Duration.ofMillis(500),
|
||
Duration.ofSeconds(5),
|
||
Duration.ofSeconds(1)
|
||
);
|
||
|
||
Component title = Component.text("DEFEAT")
|
||
.color(NamedTextColor.DARK_RED)
|
||
.decoration(TextDecoration.BOLD, true);
|
||
|
||
Component subtitle = Component.text("The Entity claims all")
|
||
.color(NamedTextColor.RED);
|
||
|
||
player.showTitle(Title.title(title, subtitle, times));
|
||
}
|
||
|
||
public void showSkillCheck(Player player, int windowTicks, Consumer<Boolean> callback) {
|
||
UUID uuid = player.getUniqueId();
|
||
|
||
if (activeSkillChecks.containsKey(uuid)) {
|
||
callback.accept(false);
|
||
return;
|
||
}
|
||
|
||
int startTick = plugin.getServer().getCurrentTick();
|
||
int successStart = startTick + (windowTicks / 2);
|
||
int successEnd = successStart + (windowTicks / 2);
|
||
|
||
SkillCheckState state = new SkillCheckState(startTick, successStart, successEnd, callback);
|
||
activeSkillChecks.put(uuid, state);
|
||
|
||
plugin.getServer().getScheduler().runTaskTimer(plugin, task -> {
|
||
int currentTick = plugin.getServer().getCurrentTick();
|
||
SkillCheckState checkState = activeSkillChecks.get(uuid);
|
||
|
||
if (checkState == null || player.isSneaking()) {
|
||
task.cancel();
|
||
boolean success = checkState != null && currentTick >= checkState.successStart
|
||
&& currentTick <= checkState.successEnd;
|
||
activeSkillChecks.remove(uuid);
|
||
callback.accept(success);
|
||
return;
|
||
}
|
||
|
||
if (currentTick > checkState.successEnd + 5) {
|
||
task.cancel();
|
||
activeSkillChecks.remove(uuid);
|
||
callback.accept(false);
|
||
return;
|
||
}
|
||
|
||
renderSkillCheck(player, checkState, currentTick);
|
||
}, 1L, 1L);
|
||
}
|
||
|
||
private void renderSkillCheck(Player player, SkillCheckState state, int currentTick) {
|
||
double progress = (currentTick - state.startTick) / 40.0;
|
||
int position = (int) (progress * 20) % 21;
|
||
|
||
StringBuilder visual = new StringBuilder();
|
||
int successStartPos = (int) ((state.successStart - state.startTick) / 40.0 * 20);
|
||
int successEndPos = (int) ((state.successEnd - state.startTick) / 40.0 * 20);
|
||
|
||
for (int i = 0; i <= 20; i++) {
|
||
if (i == position) {
|
||
visual.append("◆");
|
||
} else if (i >= successStartPos && i <= successEndPos) {
|
||
visual.append("░");
|
||
} else {
|
||
visual.append("─");
|
||
}
|
||
}
|
||
|
||
Component title = Component.text(visual.toString())
|
||
.color(NamedTextColor.WHITE);
|
||
|
||
String subStr = plugin.getConfigManager().getMessages()
|
||
.getString("hook.struggle.subtitle", "&eПрисядь когда будешь в зоне!");
|
||
Component subtitle = dev.loki.util.TextUtil.color(subStr);
|
||
|
||
Title.Times times = Title.Times.times(Duration.ZERO, Duration.ofMillis(100), Duration.ZERO);
|
||
player.showTitle(Title.title(title, subtitle, times));
|
||
}
|
||
|
||
public void clearSkillChecks() {
|
||
for (SkillCheckState state : activeSkillChecks.values()) {
|
||
state.callback().accept(false);
|
||
}
|
||
activeSkillChecks.clear();
|
||
}
|
||
|
||
private record SkillCheckState(int startTick, int successStart, int successEnd, Consumer<Boolean> callback) {}
|
||
}
|