diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/ProjectStart.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/ProjectStart.java new file mode 100644 index 0000000..ea0b0d0 --- /dev/null +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/ProjectStart.java @@ -0,0 +1,173 @@ +package eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart; + +import eu.mhsl.craftattack.spawn.core.appliance.Appliance; +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.core.config.Configuration; +import eu.mhsl.craftattack.spawn.core.util.IteratorUtil; +import eu.mhsl.craftattack.spawn.core.util.entity.PlayerUtils; +import eu.mhsl.craftattack.spawn.core.util.text.ComponentUtil; +import eu.mhsl.craftattack.spawn.core.util.text.Countdown; +import eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.command.ProjectStartCancelCommand; +import eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.command.ProjectStartCommand; +import eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.command.ProjectStartResetCommand; +import eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.listener.NoAdvancementsListener; +import eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.listener.PlayerInvincibleListener; +import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.*; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static java.util.Map.entry; +import static org.bukkit.Sound.MUSIC_DISC_PRECIPICE; + +public class ProjectStart extends Appliance { + private final int startMusicAt = 293; + private final World startWorld = Bukkit.getWorld("world"); + + private final Countdown countdown = new Countdown( + this.localConfig().getInt("countdown"), + this::format, + this::announce, + this::startProject + ); + + private final Map, Boolean> gameRulesAfterStart = Map.ofEntries( + entry(GameRule.DO_DAYLIGHT_CYCLE, true), + entry(GameRule.DO_INSOMNIA, true), + entry(GameRule.DISABLE_RAIDS, false), + entry(GameRule.DO_FIRE_TICK, true), + entry(GameRule.DO_ENTITY_DROPS, true), + entry(GameRule.DO_PATROL_SPAWNING, true), + entry(GameRule.DO_TRADER_SPAWNING, true), + entry(GameRule.DO_WEATHER_CYCLE, true), + entry(GameRule.FALL_DAMAGE, true), + entry(GameRule.FIRE_DAMAGE, true) + ); + + public ProjectStart() { + super("countdown"); + + this.countdown.addCustomAnnouncement( + new Countdown.CustomAnnouncements( + counter -> counter == this.startMusicAt, + counter -> { + Objects.requireNonNull(this.startWorld); + this.startWorld.playSound(new Location(this.startWorld, 152, 77, 179), MUSIC_DISC_PRECIPICE, SoundCategory.RECORDS, 500f, 1f); + } + ) + ); + } + + private Component format(Countdown.AnnouncementData data) { + return Component.text() + .append(ComponentUtil.createRainbowText("Varo", 10)) + .append(Component.text(" startet in ", NamedTextColor.GOLD)) + .append(Component.text(data.count(), NamedTextColor.AQUA)) + .append(Component.text(" " + data.unit() + "!", NamedTextColor.GOLD)) + .build(); + } + + private void announce(Component message) { + IteratorUtil.onlinePlayers(player -> player.sendMessage(message)); + } + + private void resetAdvancements() { + Bukkit.getServer().advancementIterator().forEachRemaining( + advancement -> Bukkit.getOnlinePlayers().forEach( + player -> player.getAdvancementProgress(advancement).getAwardedCriteria().forEach( + criteria -> player.getAdvancementProgress(advancement).revokeCriteria(criteria) + ) + ) + ); + } + + public void startCountdown() { + if(!this.isEnabled()) return; + this.countdown.start(); + } + + public void cancelCountdown() { + this.countdown.cancel(); + this.restoreBeforeStart(); + } + + public void startProject() { + this.setEnabled(false); + + IteratorUtil.worlds(World::getWorldBorder, worldBorder -> worldBorder.setSize(5000)); + IteratorUtil.worlds(world -> IteratorUtil.setGameRules(this.gameRulesAfterStart, false)); + IteratorUtil.worlds(world -> world.setFullTime(0)); + + Bukkit.getOnlinePlayers().forEach(player -> { + player.setFoodLevel(20); + player.setHealth(20); + player.getInventory().clear(); + player.setGameMode(GameMode.SURVIVAL); + player.setExp(0); + player.setLevel(0); + + player.playSound(Sound.sound(org.bukkit.Sound.ITEM_GOAT_HORN_SOUND_5, Sound.Source.MASTER, 500f, 1f)); + + player.sendMessage(Component.text("Viel Spaß bei Varo!", NamedTextColor.GREEN)); + + player.setStatistic(Statistic.TIME_SINCE_REST, 0); + PlayerUtils.resetStatistics(player); + }); + + this.resetAdvancements(); + } + + public void restoreBeforeStart() { + this.setEnabled(true); + + IteratorUtil.onlinePlayers(Player::stopAllSounds); + + IteratorUtil.worlds(World::getWorldBorder, worldBorder -> { + worldBorder.setSize(this.localConfig().getLong("worldborder-before")); + worldBorder.setWarningDistance(0); + worldBorder.setDamageAmount(0); + }); + + IteratorUtil.worlds(world -> world, world -> IteratorUtil.setGameRules(this.gameRulesAfterStart, true)); + this.resetAdvancements(); + } + + public boolean isEnabled() { + return this.localConfig().getBoolean("enabled"); + } + + public void setEnabled(boolean enabled) { + this.localConfig().set("enabled", enabled); + Configuration.saveChanges(); + } + + public Countdown getCountdown() { + return this.countdown; + } + + @Override + @NotNull + protected List listeners() { + return List.of( + new PlayerInvincibleListener(), + new NoAdvancementsListener() + ); + } + + @Override + @NotNull + protected List> commands() { + return List.of( + new ProjectStartCommand(), + new ProjectStartCancelCommand(), + new ProjectStartResetCommand() + ); + } +} diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/command/ProjectStartCancelCommand.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/command/ProjectStartCancelCommand.java new file mode 100644 index 0000000..b58042f --- /dev/null +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/command/ProjectStartCancelCommand.java @@ -0,0 +1,25 @@ +package eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.command; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.ProjectStart; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class ProjectStartCancelCommand extends ApplianceCommand { + public ProjectStartCancelCommand() { + super("projectStartCancel"); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if(this.getAppliance().getCountdown().isRunning()) { + this.getAppliance().cancelCountdown(); + sender.sendMessage(Component.text("Countdown cancelled successfully!").color(NamedTextColor.GREEN)); + } else { + sender.sendMessage(Component.text("Countdown is not running!").color(NamedTextColor.RED)); + } + } +} diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/command/ProjectStartCommand.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/command/ProjectStartCommand.java new file mode 100644 index 0000000..921bf10 --- /dev/null +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/command/ProjectStartCommand.java @@ -0,0 +1,30 @@ +package eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.command; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.ProjectStart; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class ProjectStartCommand extends ApplianceCommand { + public ProjectStartCommand() { + super("projectStart"); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if(!this.getAppliance().isEnabled()) { + sender.sendMessage(Component.text("Countdown not enabled or executed once before!").color(NamedTextColor.RED)); + return; + } + + if(this.getAppliance().getCountdown().isRunning()) { + sender.sendMessage(Component.text("Countdown already running!").color(NamedTextColor.RED)); + return; + } + + this.getAppliance().startCountdown(); + } +} diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/command/ProjectStartResetCommand.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/command/ProjectStartResetCommand.java new file mode 100644 index 0000000..2abfade --- /dev/null +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/command/ProjectStartResetCommand.java @@ -0,0 +1,18 @@ +package eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.command; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.ProjectStart; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class ProjectStartResetCommand extends ApplianceCommand { + public ProjectStartResetCommand() { + super("projectStartReset"); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + this.getAppliance().restoreBeforeStart(); + } +} diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/listener/NoAdvancementsListener.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/listener/NoAdvancementsListener.java new file mode 100644 index 0000000..ecbb120 --- /dev/null +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/listener/NoAdvancementsListener.java @@ -0,0 +1,22 @@ +package eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.listener; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener; +import eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.ProjectStart; +import org.bukkit.advancement.Advancement; +import org.bukkit.advancement.AdvancementProgress; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerAdvancementDoneEvent; + +public class NoAdvancementsListener extends ApplianceListener { + @EventHandler + public void onAdvancement(PlayerAdvancementDoneEvent event) { + if(!this.getAppliance().isEnabled()) return; + event.message(null); + + Advancement advancement = event.getAdvancement(); + AdvancementProgress progress = event.getPlayer().getAdvancementProgress(advancement); + for(String criteria : progress.getAwardedCriteria()) { + progress.revokeCriteria(criteria); + } + } +} diff --git a/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/listener/PlayerInvincibleListener.java b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/listener/PlayerInvincibleListener.java new file mode 100644 index 0000000..829bcc1 --- /dev/null +++ b/varo/src/main/java/eu/mhsl/craftattack/spawn/varo/appliances/tooling/projectStart/listener/PlayerInvincibleListener.java @@ -0,0 +1,27 @@ +package eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.listener; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener; +import eu.mhsl.craftattack.spawn.varo.appliances.tooling.projectStart.ProjectStart; +import io.papermc.paper.event.player.PrePlayerAttackEntityEvent; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; + +public class PlayerInvincibleListener extends ApplianceListener { + @EventHandler + public void onDamage(EntityDamageEvent event) { + if(!(event.getEntity() instanceof Player)) return; + if(this.getAppliance().isEnabled()) event.setCancelled(true); + } + + @EventHandler + public void onHunger(FoodLevelChangeEvent event) { + if(this.getAppliance().isEnabled()) event.setCancelled(true); + } + + @EventHandler + public void onHit(PrePlayerAttackEntityEvent event) { + if(this.getAppliance().isEnabled()) event.setCancelled(true); + } +}