124 lines
4.1 KiB
Java
124 lines
4.1 KiB
Java
package net.minecraft.world.level.timers;
|
|
|
|
import com.google.common.collect.HashBasedTable;
|
|
import com.google.common.collect.Table;
|
|
import com.google.common.primitives.UnsignedLong;
|
|
import com.mojang.logging.LogUtils;
|
|
import com.mojang.serialization.Dynamic;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.PriorityQueue;
|
|
import java.util.Queue;
|
|
import java.util.Set;
|
|
import java.util.stream.Stream;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.nbt.ListTag;
|
|
import net.minecraft.nbt.NbtOps;
|
|
import net.minecraft.nbt.Tag;
|
|
import org.slf4j.Logger;
|
|
|
|
public class TimerQueue<T> {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final String CALLBACK_DATA_TAG = "Callback";
|
|
private static final String TIMER_NAME_TAG = "Name";
|
|
private static final String TIMER_TRIGGER_TIME_TAG = "TriggerTime";
|
|
private final TimerCallbacks<T> callbacksRegistry;
|
|
private final Queue<TimerQueue.Event<T>> queue = new PriorityQueue(createComparator());
|
|
private UnsignedLong sequentialId = UnsignedLong.ZERO;
|
|
private final Table<String, Long, TimerQueue.Event<T>> events = HashBasedTable.create();
|
|
|
|
private static <T> Comparator<TimerQueue.Event<T>> createComparator() {
|
|
return Comparator.comparingLong(event -> event.triggerTime).thenComparing(event -> event.sequentialId);
|
|
}
|
|
|
|
public TimerQueue(TimerCallbacks<T> callbacksRegistry, Stream<? extends Dynamic<?>> scheduledEventsDynamic) {
|
|
this(callbacksRegistry);
|
|
this.queue.clear();
|
|
this.events.clear();
|
|
this.sequentialId = UnsignedLong.ZERO;
|
|
scheduledEventsDynamic.forEach(dynamic -> {
|
|
Tag tag = dynamic.convert(NbtOps.INSTANCE).getValue();
|
|
if (tag instanceof CompoundTag compoundTag) {
|
|
this.loadEvent(compoundTag);
|
|
} else {
|
|
LOGGER.warn("Invalid format of events: {}", tag);
|
|
}
|
|
});
|
|
}
|
|
|
|
public TimerQueue(TimerCallbacks<T> callbacksRegistry) {
|
|
this.callbacksRegistry = callbacksRegistry;
|
|
}
|
|
|
|
public void tick(T obj, long gameTime) {
|
|
while (true) {
|
|
TimerQueue.Event<T> event = (TimerQueue.Event<T>)this.queue.peek();
|
|
if (event == null || event.triggerTime > gameTime) {
|
|
return;
|
|
}
|
|
|
|
this.queue.remove();
|
|
this.events.remove(event.id, gameTime);
|
|
event.callback.handle(obj, this, gameTime);
|
|
}
|
|
}
|
|
|
|
public void schedule(String id, long triggerTime, TimerCallback<T> callback) {
|
|
if (!this.events.contains(id, triggerTime)) {
|
|
this.sequentialId = this.sequentialId.plus(UnsignedLong.ONE);
|
|
TimerQueue.Event<T> event = new TimerQueue.Event<>(triggerTime, this.sequentialId, id, callback);
|
|
this.events.put(id, triggerTime, event);
|
|
this.queue.add(event);
|
|
}
|
|
}
|
|
|
|
public int remove(String eventId) {
|
|
Collection<TimerQueue.Event<T>> collection = this.events.row(eventId).values();
|
|
collection.forEach(this.queue::remove);
|
|
int i = collection.size();
|
|
collection.clear();
|
|
return i;
|
|
}
|
|
|
|
public Set<String> getEventsIds() {
|
|
return Collections.unmodifiableSet(this.events.rowKeySet());
|
|
}
|
|
|
|
private void loadEvent(CompoundTag tag) {
|
|
TimerCallback<T> timerCallback = (TimerCallback<T>)tag.read("Callback", this.callbacksRegistry.codec()).orElse(null);
|
|
if (timerCallback != null) {
|
|
String string = tag.getStringOr("Name", "");
|
|
long l = tag.getLongOr("TriggerTime", 0L);
|
|
this.schedule(string, l, timerCallback);
|
|
}
|
|
}
|
|
|
|
private CompoundTag storeEvent(TimerQueue.Event<T> event) {
|
|
CompoundTag compoundTag = new CompoundTag();
|
|
compoundTag.putString("Name", event.id);
|
|
compoundTag.putLong("TriggerTime", event.triggerTime);
|
|
compoundTag.store("Callback", this.callbacksRegistry.codec(), event.callback);
|
|
return compoundTag;
|
|
}
|
|
|
|
public ListTag store() {
|
|
ListTag listTag = new ListTag();
|
|
this.queue.stream().sorted(createComparator()).map(this::storeEvent).forEach(listTag::add);
|
|
return listTag;
|
|
}
|
|
|
|
public static class Event<T> {
|
|
public final long triggerTime;
|
|
public final UnsignedLong sequentialId;
|
|
public final String id;
|
|
public final TimerCallback<T> callback;
|
|
|
|
Event(long triggerTime, UnsignedLong sequentialId, String id, TimerCallback<T> callback) {
|
|
this.triggerTime = triggerTime;
|
|
this.sequentialId = sequentialId;
|
|
this.id = id;
|
|
this.callback = callback;
|
|
}
|
|
}
|
|
}
|