Spaces:
Build error
Build error
File size: 8,170 Bytes
d46f4a3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
package net.minecraft.client;
import com.google.common.collect.ImmutableMap;
import com.google.common.math.LongMath;
import com.google.gson.JsonParser;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.mojang.serialization.codecs.RecordCodecBuilder.Instance;
import it.unimi.dsi.fastutil.objects.Object2BooleanFunction;
import java.io.Reader;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import net.minecraft.Util;
import net.minecraft.client.gui.components.toasts.SystemToast;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.SimplePreparableReloadListener;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class PeriodicNotificationManager
extends SimplePreparableReloadListener<Map<String, List<PeriodicNotificationManager.Notification>>>
implements AutoCloseable {
private static final Codec<Map<String, List<PeriodicNotificationManager.Notification>>> CODEC = Codec.unboundedMap(
Codec.STRING,
RecordCodecBuilder.<PeriodicNotificationManager.Notification>create(
p_205303_ -> p_205303_.group(
Codec.LONG.optionalFieldOf("delay", Long.valueOf(0L)).forGetter(PeriodicNotificationManager.Notification::delay),
Codec.LONG.fieldOf("period").forGetter(PeriodicNotificationManager.Notification::period),
Codec.STRING.fieldOf("title").forGetter(PeriodicNotificationManager.Notification::title),
Codec.STRING.fieldOf("message").forGetter(PeriodicNotificationManager.Notification::message)
)
.apply(p_205303_, PeriodicNotificationManager.Notification::new)
)
.listOf()
);
private static final Logger LOGGER = LogUtils.getLogger();
private final ResourceLocation notifications;
private final Object2BooleanFunction<String> selector;
@Nullable
private Timer timer;
@Nullable
private PeriodicNotificationManager.NotificationTask notificationTask;
public PeriodicNotificationManager(ResourceLocation p_205293_, Object2BooleanFunction<String> p_205294_) {
this.notifications = p_205293_;
this.selector = p_205294_;
}
protected Map<String, List<PeriodicNotificationManager.Notification>> prepare(ResourceManager p_205300_, ProfilerFiller p_205301_) {
try {
Map map;
try (Reader reader = p_205300_.openAsReader(this.notifications)) {
map = CODEC.parse(JsonOps.INSTANCE, JsonParser.parseReader(reader)).result().orElseThrow();
}
return map;
} catch (Exception exception) {
LOGGER.warn("Failed to load {}", this.notifications, exception);
return ImmutableMap.of();
}
}
protected void apply(Map<String, List<PeriodicNotificationManager.Notification>> p_205318_, ResourceManager p_205319_, ProfilerFiller p_205320_) {
List<PeriodicNotificationManager.Notification> list = p_205318_.entrySet()
.stream()
.filter(p_205316_ -> this.selector.apply(p_205316_.getKey()))
.map(Entry::getValue)
.flatMap(Collection::stream)
.collect(Collectors.toList());
if (list.isEmpty()) {
this.stopTimer();
} else if (list.stream().anyMatch(p_205326_ -> p_205326_.period == 0L)) {
Util.logAndPauseIfInIde("A periodic notification in " + this.notifications + " has a period of zero minutes");
this.stopTimer();
} else {
long i = this.calculateInitialDelay(list);
long j = this.calculateOptimalPeriod(list, i);
if (this.timer == null) {
this.timer = new Timer();
}
if (this.notificationTask == null) {
this.notificationTask = new PeriodicNotificationManager.NotificationTask(list, i, j);
} else {
this.notificationTask = this.notificationTask.reset(list, j);
}
this.timer.scheduleAtFixedRate(this.notificationTask, TimeUnit.MINUTES.toMillis(i), TimeUnit.MINUTES.toMillis(j));
}
}
@Override
public void close() {
this.stopTimer();
}
private void stopTimer() {
if (this.timer != null) {
this.timer.cancel();
}
}
private long calculateOptimalPeriod(List<PeriodicNotificationManager.Notification> p_205313_, long p_205314_) {
return p_205313_.stream().mapToLong(p_205298_ -> {
long i = p_205298_.delay - p_205314_;
return LongMath.gcd(i, p_205298_.period);
}).reduce(LongMath::gcd).orElseThrow(() -> new IllegalStateException("Empty notifications from: " + this.notifications));
}
private long calculateInitialDelay(List<PeriodicNotificationManager.Notification> p_205311_) {
return p_205311_.stream().mapToLong(p_205305_ -> p_205305_.delay).min().orElse(0L);
}
@OnlyIn(Dist.CLIENT)
public static record Notification(long delay, long period, String title, String message) {
public Notification(final long delay, final long period, final String title, final String message) {
this.delay = delay != 0L ? delay : period;
this.period = period;
this.title = title;
this.message = message;
}
}
@OnlyIn(Dist.CLIENT)
static class NotificationTask extends TimerTask {
private final Minecraft minecraft = Minecraft.getInstance();
private final List<PeriodicNotificationManager.Notification> notifications;
private final long period;
private final AtomicLong elapsed;
public NotificationTask(List<PeriodicNotificationManager.Notification> p_205350_, long p_205351_, long p_205352_) {
this.notifications = p_205350_;
this.period = p_205352_;
this.elapsed = new AtomicLong(p_205351_);
}
public PeriodicNotificationManager.NotificationTask reset(List<PeriodicNotificationManager.Notification> p_205357_, long p_205358_) {
this.cancel();
return new PeriodicNotificationManager.NotificationTask(p_205357_, this.elapsed.get(), p_205358_);
}
@Override
public void run() {
long i = this.elapsed.getAndAdd(this.period);
long j = this.elapsed.get();
for (PeriodicNotificationManager.Notification periodicnotificationmanager$notification : this.notifications) {
if (i >= periodicnotificationmanager$notification.delay) {
long k = i / periodicnotificationmanager$notification.period;
long l = j / periodicnotificationmanager$notification.period;
if (k != l) {
this.minecraft
.execute(
() -> SystemToast.add(
Minecraft.getInstance().getToastManager(),
SystemToast.SystemToastId.PERIODIC_NOTIFICATION,
Component.translatable(periodicnotificationmanager$notification.title, k),
Component.translatable(periodicnotificationmanager$notification.message, k)
)
);
return;
}
}
}
}
}
} |