Add DimensionScheduler and DimensionScheduleCommand for managing dimension access timings
This commit is contained in:
1 parent
d18ddc7b07
commit
3b43b594f4
3 files changed
+119
No files matched your search
+39
@@ -0,0 +1,39 @@
|
||||
package eu.mhsl.craftattack.spawn.common.appliances.tooling.dimensionScheduler;
|
||||
|
||||
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand;
|
||||
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.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
class DimensionScheduleCommand extends ApplianceCommand<DimensionScheduler> {
|
||||
public DimensionScheduleCommand() {
|
||||
super("dimensionSchedule");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if(!sender.isOp()) throw new Error("Dieser Befehl ist nur für die Konsole und OPs verfügbar.");
|
||||
if(args.length != 1 || !args[0].equalsIgnoreCase("reload")) {
|
||||
throw new Error("Verwendung: /dimensionSchedule reload");
|
||||
}
|
||||
|
||||
try {
|
||||
this.getAppliance().reload();
|
||||
} catch(IOException | InvalidConfigurationException | IllegalArgumentException e) {
|
||||
throw new Error("dimension-schedule.yml konnte nicht neu eingelesen werden: " + e.getMessage());
|
||||
}
|
||||
sender.sendMessage(Component.text("dimension-schedule.yml wurde neu eingelesen.", NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if(!sender.isOp() || args.length != 1) return List.of();
|
||||
return this.tabCompleteReducer(List.of("reload"), args);
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package eu.mhsl.craftattack.spawn.common.appliances.tooling.dimensionScheduler;
|
||||
|
||||
import eu.mhsl.craftattack.spawn.core.Main;
|
||||
import eu.mhsl.craftattack.spawn.core.appliance.Appliance;
|
||||
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/** Reads named times only; applying them to dimension access is handled separately. */
|
||||
public class DimensionScheduler extends Appliance {
|
||||
private static final String FILE_NAME = "dimension-schedule.yml";
|
||||
private final File scheduleFile = new File(Main.instance().getDataFolder(), FILE_NAME);
|
||||
private Map<String, Instant> times = Map.of();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
try {
|
||||
if(!this.scheduleFile.exists()) Main.instance().saveResource(FILE_NAME, false);
|
||||
this.reload();
|
||||
} catch(IOException | InvalidConfigurationException | IllegalArgumentException e) {
|
||||
Main.logger().log(Level.WARNING, "Could not load " + FILE_NAME + "; keeping previous times", e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Validates all entries before replacing the current times. Never creates or writes the file. */
|
||||
public void reload() throws IOException, InvalidConfigurationException {
|
||||
YamlConfiguration configuration = new YamlConfiguration();
|
||||
configuration.load(this.scheduleFile);
|
||||
|
||||
Map<String, Instant> loadedTimes = new HashMap<>();
|
||||
for(Map.Entry<String, Object> entry : configuration.getValues(false).entrySet()) {
|
||||
readTime(entry.getKey(), entry.getValue()).ifPresent(time -> loadedTimes.put(entry.getKey(), time));
|
||||
}
|
||||
this.times = Map.copyOf(loadedTimes);
|
||||
}
|
||||
|
||||
private static Optional<Instant> readTime(String key, Object configured) {
|
||||
if(configured == null) return Optional.empty();
|
||||
if(!(configured instanceof String value)) {
|
||||
throw new IllegalArgumentException(key + " muss null oder ein Datum in Anführungszeichen mit UTC-Offset sein.");
|
||||
}
|
||||
if(value.isBlank()) return Optional.empty();
|
||||
try {
|
||||
return Optional.of(OffsetDateTime.parse(value.trim()).toInstant());
|
||||
} catch(DateTimeParseException e) {
|
||||
throw new IllegalArgumentException("Ungültiger Zeitpunkt für " + key + ". Beispiel: \"2026-11-15T18:00:00+01:00\"", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<Instant> getTime(String name) {
|
||||
return Optional.ofNullable(this.times.get(name));
|
||||
}
|
||||
|
||||
/** Immutable snapshot of all configured, non-empty times. */
|
||||
public Map<String, Instant> getTimes() {
|
||||
return this.times;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull List<ApplianceCommand<?>> commands() {
|
||||
return List.of(new DimensionScheduleCommand());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Datum mit UTC-Offset, z. B. "2026-11-15T18:00:00+01:00"
|
||||
# null bedeutet: kein Termin
|
||||
# Weitere Einträge mit frei wählbaren Namen können ergänzt werden.
|
||||
end-open-at: null
|
||||
outer-end-open-at: null
|
||||
Reference in new issue
Block a user