Enhance DimensionScheduler and EndOpeningSchedule with load time tracking and state restoration logic
This commit is contained in:
1 parent
45685c0c13
commit
f3f19a3370
3 files changed
+30
-9
No files matched your search
+7
@@ -23,6 +23,7 @@ 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();
|
||||
private Instant loadedAt = Instant.now();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
@@ -44,6 +45,7 @@ public class DimensionScheduler extends Appliance {
|
||||
readTime(entry.getKey(), entry.getValue()).ifPresent(time -> loadedTimes.put(entry.getKey(), time));
|
||||
}
|
||||
this.times = Map.copyOf(loadedTimes);
|
||||
this.loadedAt = Instant.now();
|
||||
}
|
||||
|
||||
private static Optional<Instant> readTime(String key, Object configured) {
|
||||
@@ -68,6 +70,11 @@ public class DimensionScheduler extends Appliance {
|
||||
return this.times;
|
||||
}
|
||||
|
||||
/** Wall-clock time of the last successful load, before consumers check the new times. */
|
||||
public Instant getLoadedAt() {
|
||||
return this.loadedAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull List<ApplianceCommand<?>> commands() {
|
||||
return List.of(new DimensionScheduleCommand());
|
||||
|
||||
+5
@@ -60,6 +60,11 @@ setzen die bereits behandelten Stufen nicht zurück. Bei Verzögerungen wird hö
|
||||
zuletzt fällige Vorankündigung ausgegeben. Ist die Öffnung bereits fällig, entfallen alte Teaser.
|
||||
Während einer manuellen Freigabe fällige Teaser werden still als behandelt markiert.
|
||||
|
||||
Für einen geänderten Termin gilt der erfolgreiche Ladezeitpunkt als Grenze für verpasste
|
||||
Stufen. Wird eine Ankündigung erst zwischen dem Reload und der nächsten Sekundenprüfung
|
||||
fällig, wird sie regulär ausgeführt. Dasselbe gilt für eine in diesem Zeitraum fällige Öffnung.
|
||||
Beim erneuten Aktivieren von EndPrevent gilt frühestens dessen Startzeitpunkt als Grenze.
|
||||
|
||||
Ein Rechtsklick mit Enderauge auf einen leeren, gesperrten Endportalrahmen wird für beide Hände
|
||||
abgebrochen. Nur der auslösende Spieler erhält einen der fünf zufälligen Texte in der Actionbar,
|
||||
höchstens einmal pro Server-Tick. Die Spieler-Zuordnung wird beim Verlassen entfernt.
|
||||
|
||||
+18
-9
@@ -26,6 +26,7 @@ final class EndOpeningSchedule {
|
||||
private Optional<Instant> previousOuterEndOpenAt = Optional.empty();
|
||||
private @Nullable EndPrevent.State previousScheduledState;
|
||||
private boolean initialized;
|
||||
private Instant startedAt = Instant.EPOCH;
|
||||
|
||||
EndOpeningSchedule(EndPrevent endPrevent, DimensionScheduler scheduler, EndOpeningEffects effects) {
|
||||
this.endPrevent = endPrevent;
|
||||
@@ -35,6 +36,7 @@ final class EndOpeningSchedule {
|
||||
|
||||
void start() {
|
||||
this.stop();
|
||||
this.startedAt = Instant.now();
|
||||
// Wait until the next tick so all appliances have finished loading, regardless of order.
|
||||
this.task = Bukkit.getScheduler().runTaskTimer(Main.instance(), this::checkOpeningTimes, 1L, 20L);
|
||||
}
|
||||
@@ -52,7 +54,9 @@ final class EndOpeningSchedule {
|
||||
boolean endTimeChanged = !endOpenAt.equals(this.previousEndOpenAt);
|
||||
boolean restoreSchedule = !this.initialized || endTimeChanged
|
||||
|| !outerEndOpenAt.equals(this.previousOuterEndOpenAt);
|
||||
if(!this.initialized || endTimeChanged) this.resetAnnouncements(endOpenAt, now);
|
||||
Instant restoreAt = this.scheduler.getLoadedAt();
|
||||
if(!this.initialized && this.startedAt.isAfter(restoreAt)) restoreAt = this.startedAt;
|
||||
if(!this.initialized || endTimeChanged) this.resetAnnouncements(endOpenAt, restoreAt);
|
||||
this.previousEndOpenAt = endOpenAt;
|
||||
this.previousOuterEndOpenAt = outerEndOpenAt;
|
||||
this.initialized = true;
|
||||
@@ -62,20 +66,19 @@ final class EndOpeningSchedule {
|
||||
return;
|
||||
}
|
||||
|
||||
EndPrevent.State scheduledState;
|
||||
if(endOpenAt.isPresent() && now.isBefore(endOpenAt.get())) {
|
||||
scheduledState = EndPrevent.State.CLOSED;
|
||||
} else if(outerEndOpenAt.isPresent() && now.isBefore(outerEndOpenAt.get())) {
|
||||
scheduledState = EndPrevent.State.NO_OUTER;
|
||||
} else {
|
||||
scheduledState = EndPrevent.State.OPEN;
|
||||
EndPrevent.State scheduledState = stateAt(now, endOpenAt, outerEndOpenAt);
|
||||
EndPrevent.State restoredState = stateAt(restoreAt, endOpenAt, outerEndOpenAt);
|
||||
boolean crossedAfterLoad = restoreSchedule && restoredState != scheduledState;
|
||||
if(crossedAfterLoad) {
|
||||
// Restore the state at load time silently, then execute the newly due live transition.
|
||||
this.endPrevent.restoreEndState(restoredState);
|
||||
}
|
||||
|
||||
// Remember the schedule's state, not the current manual state: commands remain effective
|
||||
// until the next scheduled transition or a change to the relevant opening times.
|
||||
if(restoreSchedule || scheduledState != this.previousScheduledState) {
|
||||
if(this.endPrevent.getEndPreventState() != scheduledState) {
|
||||
if(restoreSchedule) {
|
||||
if(restoreSchedule && !crossedAfterLoad) {
|
||||
this.endPrevent.restoreEndState(scheduledState);
|
||||
} else {
|
||||
this.endPrevent.setEndState(scheduledState);
|
||||
@@ -89,6 +92,12 @@ final class EndOpeningSchedule {
|
||||
this.announceDueStages(endOpenAt, now);
|
||||
}
|
||||
|
||||
private static EndPrevent.State stateAt(Instant at, Optional<Instant> endOpenAt, Optional<Instant> outerEndOpenAt) {
|
||||
if(endOpenAt.isPresent() && at.isBefore(endOpenAt.get())) return EndPrevent.State.CLOSED;
|
||||
if(outerEndOpenAt.isPresent() && at.isBefore(outerEndOpenAt.get())) return EndPrevent.State.NO_OUTER;
|
||||
return EndPrevent.State.OPEN;
|
||||
}
|
||||
|
||||
/** A new opening time starts a new cycle; announcements already in the past are consumed. */
|
||||
private void resetAnnouncements(Optional<Instant> endOpenAt, Instant now) {
|
||||
this.handledAnnouncements.clear();
|
||||
|
||||
Reference in new issue
Block a user