Merge branch 'master-shrinkingBorder'

This commit is contained in:
2025-04-11 20:44:00 +02:00
8 changed files with 383 additions and 7 deletions

View File

@ -0,0 +1,109 @@
package eu.mhsl.craftattack.spawn.varo.appliances.metaGameplay.shrinkingBorder;
import eu.mhsl.craftattack.core.Main;
import eu.mhsl.craftattack.core.appliance.Appliance;
import eu.mhsl.craftattack.core.appliance.ApplianceCommand;
import eu.mhsl.craftattack.core.config.Configuration;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.Settings;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldBorder;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.time.LocalTime;
import java.util.*;
public class ShrinkingBorder extends Appliance {
private final String shrinkPerDayKey = "shrinkPerDay";
private final String shrinkTimeKey = "shrinkTime";
private final String minimumSizeKey = "minimumSize";
public int shrinkPerDay;
public LocalTime shrinkTime;
public int minimumSize;
private final Timer timer = new Timer();
private final Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
private final WorldBorder overworldBorder = Bukkit.getWorlds().stream()
.filter(world -> world.getEnvironment().equals(World.Environment.NORMAL))
.findFirst().orElseThrow().getWorldBorder();
private final WorldBorder netherBorder = Bukkit.getWorlds().stream()
.filter(world -> world.getEnvironment().equals(World.Environment.NETHER))
.findFirst().orElseThrow().getWorldBorder();
private class ShrinkBorderTask extends TimerTask {
@Override
public void run() {
Bukkit.getScheduler().runTask(Main.instance(), ShrinkingBorder.this::shrinkBorder);
}
}
@Override
public void onEnable() {
Settings.instance().declareSetting(ShrinkingBorderSetting.class);
}
public ShrinkingBorder() {
super("shrinkingBorder");
this.shrinkPerDay = this.localConfig().getInt(this.shrinkPerDayKey, 10);
this.shrinkTime = LocalTime.parse(this.localConfig().getString(this.shrinkTimeKey, LocalTime.of(3, 0, 0).toString()));
this.minimumSize = this.localConfig().getInt(this.minimumSizeKey, 10);
this.calendar.set(Calendar.HOUR_OF_DAY, this.shrinkTime.getHour());
this.calendar.set(Calendar.MINUTE, this.shrinkTime.getMinute());
this.calendar.set(Calendar.SECOND, this.shrinkTime.getSecond());
if(this.calendar.getTime().before(new Date(System.currentTimeMillis()))) {
this.calendar.add(Calendar.DAY_OF_MONTH, 1);
}
this.timer.schedule(new ShrinkBorderTask(), this.calendar.getTime());
}
private void shrinkBorder() {
this.overworldBorder.setSize(Math.max(this.overworldBorder.getSize()-this.shrinkPerDay, this.minimumSize));
this.netherBorder.setSize(Math.max(this.netherBorder.getSize()-this.shrinkPerDay, this.minimumSize));
this.calendar.add(Calendar.DAY_OF_MONTH, 1);
this.timer.schedule(new ShrinkBorderTask(), this.calendar.getTime());
}
public void changeOption(ShrinkingBorderCommand.Argument option, int value) {
switch (option) {
case MINIMUM_SIZE -> {
this.minimumSize = value;
this.localConfig().set(this.minimumSizeKey, value);
}
case SHRINK_PER_DAY -> {
this.shrinkPerDay = value;
this.localConfig().set(this.shrinkPerDayKey, value);
}
}
Configuration.saveChanges();
}
public int getOption(ShrinkingBorderCommand.Argument option) {
switch (option) {
case MINIMUM_SIZE -> {
return this.minimumSize;
}
case SHRINK_PER_DAY -> {
return this.shrinkPerDay;
}
default -> {
return 0;
}
}
}
@Override
protected @NotNull List<ApplianceCommand<?>> commands() {
return List.of(new ShrinkingBorderCommand());
}
@Override
protected @NotNull List<Listener> listeners() {
return List.of(new ShrinkingBorderListener());
}
}

View File

@ -0,0 +1,61 @@
package eu.mhsl.craftattack.spawn.varo.appliances.metaGameplay.shrinkingBorder;
import eu.mhsl.craftattack.core.appliance.ApplianceCommand;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
public class ShrinkingBorderCommand extends ApplianceCommand<ShrinkingBorder> {
public enum Argument {
SHRINK_PER_DAY("shrinkPerDay"),
MINIMUM_SIZE("minimumSize");
public final String name;
Argument(String friendlyName) {
this.name = friendlyName;
}
static Argument fromString(String argument) {
return Arrays.stream(values()).filter(argument1 -> argument1.name.equals(argument)).findFirst().orElseThrow();
}
}
public ShrinkingBorderCommand() {
super("shrinkingBorder");
}
@Override
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if(args.length < 1 || args.length > 2) throw new Error("shrinkingBorder command needs one or two arguments");
if(Arrays.stream(Argument.values()).noneMatch(argument -> argument.name.equals(args[0]))) throw new Error(String.format("argument %s does not exist", args[0]));
Argument option = Argument.fromString(args[0]);
switch (args.length) {
case 1:
sender.sendMessage(String.format("%s is currently set to %d", args[0], this.getAppliance().getOption(option)));
break;
case 2:
try {
int value = Integer.parseInt(args[1]);
this.getAppliance().changeOption(option, value);
sender.sendMessage(String.format("%s is now set to %d", args[0], this.getAppliance().getOption(option)));
} catch (NumberFormatException e) {
throw new Error("second argument has to be an integer");
}
break;
default:
throw new Error("shrinkingBorder command needs one or two arguments");
}
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if(args.length > 1) return List.of();
return Arrays.stream(Argument.values()).map(argument -> argument.name).toList();
}
}

View File

@ -0,0 +1,55 @@
package eu.mhsl.craftattack.spawn.varo.appliances.metaGameplay.shrinkingBorder;
import eu.mhsl.craftattack.core.appliance.ApplianceListener;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.Settings;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.WorldBorder;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerMoveEvent;
public class ShrinkingBorderListener extends ApplianceListener<ShrinkingBorder> {
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
if(!event.hasChangedPosition()) return;
if(event.getTo().getWorld().getEnvironment().equals(World.Environment.THE_END)) return;
if(this.isSave(event.getTo())) return;
int remainingDays = this.daysUntilBorder(event.getTo());
int maxDaysShown = Settings.instance().getSetting(event.getPlayer(), Settings.Key.BorderWarning, Integer.class);
if(remainingDays > maxDaysShown) return;
String actionBarText;
if(remainingDays <= 0) {
actionBarText = "Du befindest dich in der Worldborder!";
} else {
actionBarText = String.format("In %d Tagen ist die Worldborder hier!", remainingDays);
}
event.getPlayer().sendActionBar(Component.text(
actionBarText,
TextColor.color(255, 0, 0)
));
}
private int daysUntilBorder(Location playerLocation) {
WorldBorder worldBorder = playerLocation.getWorld().getWorldBorder();
Location relativeLocation = playerLocation.clone().subtract(worldBorder.getCenter());
double playerBorderDistanceX = worldBorder.getSize()/2 - Math.abs(relativeLocation.getX());
double playerBorderDistanceZ = worldBorder.getSize()/2 - Math.abs(relativeLocation.getZ());
int xSteps = (int) Math.ceil(playerBorderDistanceX / this.getAppliance().getOption(ShrinkingBorderCommand.Argument.SHRINK_PER_DAY));
int zSteps = (int) Math.ceil(playerBorderDistanceZ / this.getAppliance().getOption(ShrinkingBorderCommand.Argument.SHRINK_PER_DAY));
return Math.min(xSteps, zSteps);
}
private boolean isSave(Location playerLocation) {
WorldBorder worldBorder = playerLocation.getWorld().getWorldBorder();
Location relativeLocation = playerLocation.clone().subtract(worldBorder.getCenter());
if(Math.abs(relativeLocation.getX()) > this.getAppliance().getOption(ShrinkingBorderCommand.Argument.MINIMUM_SIZE)) return false;
if(Math.abs(relativeLocation.getZ()) > this.getAppliance().getOption(ShrinkingBorderCommand.Argument.MINIMUM_SIZE)) return false;
return true;
}
}

View File

@ -0,0 +1,43 @@
package eu.mhsl.craftattack.spawn.varo.appliances.metaGameplay.shrinkingBorder;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.CategorizedSetting;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.SettingCategory;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.Settings;
import eu.mhsl.craftattack.spawn.common.appliances.metaGameplay.settings.datatypes.IntegerSetting;
import org.bukkit.Material;
import java.util.List;
public class ShrinkingBorderSetting extends IntegerSetting implements CategorizedSetting {
public ShrinkingBorderSetting() {
super(
Settings.Key.BorderWarning,
List.of(0, 1, 2, 3)
);
}
@Override
public SettingCategory category() {
return SettingCategory.Gameplay;
}
@Override
protected String title() {
return "Warnung vor der Worldborder";
}
@Override
protected String description() {
return "Warnt vor der Worldborder";
}
@Override
protected Material icon() {
return Material.BARRIER;
}
@Override
protected Integer defaultValue() {
return 1;
}
}