diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/internal/teamTasks/TeamTasks.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/internal/teamTasks/TeamTasks.java new file mode 100644 index 0000000..37f66f5 --- /dev/null +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/internal/teamTasks/TeamTasks.java @@ -0,0 +1,52 @@ +package eu.mhsl.craftattack.spawn.varo.appliances.internal.teamTasks; + +import eu.mhsl.craftattack.spawn.core.Main; +import eu.mhsl.craftattack.spawn.core.appliance.Appliance; +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.varo.appliances.metaGameplay.teams.VaroTeam; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class TeamTasks extends Appliance { + public enum Type { + /** + * Task for kicking Team after the desired Playtime + */ + TIME_KICK + } + + private final Map> tasks = new HashMap<>(); + + private Map getTeamTasks(VaroTeam team) { + return this.tasks.computeIfAbsent(team, varoTeam -> new HashMap<>()); + } + + public Map getRunningTeamTasks(VaroTeam team) { + return this.getTeamTasks(team).entrySet().stream() + .filter(entry -> !entry.getValue().isCancelled()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + public void cancelTeamTasks(VaroTeam team) { + Main.logger().info(String.format("All TeamTasks for Team %s were cancelled: %s", team.name, this.getRunningTeamTasks(team))); + this.getTeamTasks(team).forEach((type, bukkitTask) -> bukkitTask.cancel()); + } + + public void addTask(VaroTeam team, Type type, BukkitTask runnable) { + if(this.getTeamTasks(team).containsKey(type) && !this.getTeamTasks(team).get(type).isCancelled()) { + throw new IllegalStateException(String.format("Task %s for Team %s was already running!", type.name(), team.name)); + } + + this.getTeamTasks(team).put(type, runnable); + } + + @Override + protected @NotNull List> commands() { + return List.of(new TeamTasksCommand()); + } +} diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/internal/teamTasks/TeamTasksCommand.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/internal/teamTasks/TeamTasksCommand.java new file mode 100644 index 0000000..fc39f21 --- /dev/null +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/internal/teamTasks/TeamTasksCommand.java @@ -0,0 +1,42 @@ +package eu.mhsl.craftattack.spawn.varo.appliances.internal.teamTasks; + +import eu.mhsl.craftattack.spawn.core.Main; +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.varo.appliances.metaGameplay.teams.Teams; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.stream.Collectors; + +public class TeamTasksCommand extends ApplianceCommand { + public TeamTasksCommand() { + super("teamTasks"); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if(args.length < 1) throw new Error("Please specify Teamname"); + var team = Main.instance().getAppliance(Teams.class).findTeamByName(args[0]); + if(team == null) throw new Error("Team not found!"); + var tasks = this.getAppliance().getRunningTeamTasks(team); + if(tasks.isEmpty()) { + sender.sendMessage("No Tasks found!"); + } else { + sender.sendMessage( + tasks.entrySet() + .stream() + .map(entry -> String.format("%s: %d", entry.getKey().name(), entry.getValue().getTaskId())) + .collect(Collectors.joining("\n")) + ); + } + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + var teams = Main.instance().getAppliance(Teams.class).getAllTeams(); + return teams.stream().map(team -> team.name).toList(); + } +} diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/joinProtection/JoinProtection.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/joinProtection/JoinProtection.java index 621f812..a91a17b 100644 --- a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/joinProtection/JoinProtection.java +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/joinProtection/JoinProtection.java @@ -36,7 +36,7 @@ public class JoinProtection extends Appliance { Bukkit.getScheduler().runTaskTimer( Main.instance(), - this::notifyPlayers, + this::updateStatus, Ticks.TICKS_PER_SECOND, Ticks.TICKS_PER_SECOND ); @@ -57,7 +57,7 @@ public class JoinProtection extends Appliance { event.setCancelled(true); } - public void notifyPlayers() { + public void updateStatus() { IteratorUtil.onlinePlayers(player -> { Options options = this.protectedPlayers.get(player.getUniqueId()); if(options == null) return; diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/teams/Teams.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/teams/Teams.java index 3cf6c7a..dbedcb5 100644 --- a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/teams/Teams.java +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/teams/Teams.java @@ -5,6 +5,7 @@ import eu.mhsl.craftattack.spawn.core.appliance.Appliance; import eu.mhsl.craftattack.spawn.core.util.text.DisconnectInfo; import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.displayName.DisplayName; import eu.mhsl.craftattack.spawn.varo.api.repositories.TeamRepository; +import eu.mhsl.craftattack.spawn.varo.appliances.internal.teamTasks.TeamTasks; import eu.mhsl.craftattack.spawn.varo.appliances.metaGameplay.joinProtection.JoinProtection; import eu.mhsl.craftattack.spawn.varo.appliances.metaGameplay.playTimer.PlayTimer; import net.kyori.adventure.text.Component; @@ -15,6 +16,7 @@ import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.event.Listener; +import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -139,11 +141,14 @@ public class Teams extends Appliance implements DisplayName.Prefixed, DisplayNam .findAny() .ifPresentOrElse( member -> team.kickTeam(teamNotCompleteInfo), - () -> Bukkit.getScheduler().runTaskLater( - Main.instance(), - team::timeOverKick, - Ticks.TICKS_PER_SECOND * 60 * PlayTimer.PLAYTIME_MINUTES - ) + () -> { + BukkitTask kickTask = Bukkit.getScheduler().runTaskLater( + Main.instance(), + team::timeOverKick, + Ticks.TICKS_PER_SECOND * 60 * PlayTimer.PLAYTIME_MINUTES + ); + this.queryAppliance(TeamTasks.class).addTask(team, TeamTasks.Type.TIME_KICK, kickTask); + } ), Ticks.TICKS_PER_SECOND * (JoinProtection.resistanceDuration / 2) ); diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/teams/VaroTeam.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/teams/VaroTeam.java index 290fea9..af3fe66 100644 --- a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/teams/VaroTeam.java +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/metaGameplay/teams/VaroTeam.java @@ -2,10 +2,12 @@ package eu.mhsl.craftattack.spawn.varo.appliances.metaGameplay.teams; import eu.mhsl.craftattack.spawn.core.Main; import eu.mhsl.craftattack.spawn.core.util.text.DisconnectInfo; +import eu.mhsl.craftattack.spawn.varo.appliances.internal.teamTasks.TeamTasks; import eu.mhsl.craftattack.spawn.varo.appliances.metaGameplay.fightDetector.FightDetector; import net.kyori.adventure.util.Ticks; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -59,17 +61,25 @@ public class VaroTeam { )); } - public void kickTeam(DisconnectInfo disconnectInfo) { - this.members.stream() + public List getOnlinePlayers() { + return this.members.stream() .map(member -> Bukkit.getPlayer(member.player.getUniqueId())) .filter(Objects::nonNull) + .toList(); + } + + public void kickTeam(DisconnectInfo disconnectInfo) { + this.getOnlinePlayers() .forEach(player -> player.kick(disconnectInfo.getComponent())); + Main.instance().getAppliance(TeamTasks.class).cancelTeamTasks(this); } public void timeOverKick() { boolean isInFight = Main.instance().getAppliance(FightDetector.class).isInFight(this); if(isInFight) { Main.logger().info(String.format("Cannot kick Team %s because it is in a fight!", this.name)); + this.getOnlinePlayers() + .forEach(player -> player.sendMessage("Du befindest dich in einer Kampfhandlung oder unmittelbar")); Bukkit.getScheduler().runTaskLater( Main.instance(), this::timeOverKick,