mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 19:46:42 +01:00
Rewrite the tick queue to be slightly more robust and not trigger actions for worlds they weren't intended to run in
This commit is contained in:
parent
848f6ef66d
commit
b4443e0549
4 changed files with 37 additions and 48 deletions
|
@ -1,44 +1,55 @@
|
|||
package com.minelittlepony.unicopia;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Queues;
|
||||
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class AwaitTickQueue {
|
||||
|
||||
private static final Queue<Consumer<World>> SCHEDULED_TASKS = Queues.newArrayDeque();
|
||||
private static List<DelayedTask> DELAYED_TASKS = Lists.newArrayList();
|
||||
|
||||
private static final Object LOCKER = new Object();
|
||||
private static List<Entry> PENDING_TASKS = new ArrayList<>();
|
||||
|
||||
public static void enqueueTask(Consumer<World> task) {
|
||||
synchronized (LOCKER) {
|
||||
SCHEDULED_TASKS.add(task);
|
||||
}
|
||||
}
|
||||
|
||||
public static void scheduleTask(Consumer<World> task, int ticksLater) {
|
||||
synchronized (LOCKER) {
|
||||
DELAYED_TASKS.add(new DelayedTask(task, ticksLater));
|
||||
public static void scheduleTask(World reference, Consumer<World> task, int ticksLater) {
|
||||
if (!reference.isClient) {
|
||||
synchronized (LOCKER) {
|
||||
PENDING_TASKS.add(new Entry(reference, task, ticksLater));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void tick(World world) {
|
||||
if (world.isClient) {
|
||||
return;
|
||||
if (!world.isClient) {
|
||||
synchronized (LOCKER) {
|
||||
final Queue<Entry> tasks = new ArrayDeque<>();
|
||||
PENDING_TASKS = PENDING_TASKS.stream().filter(e -> e.tick(world, tasks)).collect(Collectors.toList());
|
||||
tasks.forEach(e -> e.run(world));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Entry {
|
||||
private final Consumer<World> task;
|
||||
private final WeakReference<World> world;
|
||||
private int ticks;
|
||||
|
||||
Entry(World world, Consumer<World> task, int ticks) {
|
||||
this.world = new WeakReference<>(world);
|
||||
this.task = task;
|
||||
this.ticks = ticks;
|
||||
}
|
||||
|
||||
synchronized (LOCKER) {
|
||||
DELAYED_TASKS = DELAYED_TASKS.stream().filter(DelayedTask::tick).collect(Collectors.toList());
|
||||
boolean tick(World world, Queue<Entry> tasks) {
|
||||
World w = this.world.get();
|
||||
return w != null && (w != world || ticks-- > 0 || !tasks.add(this));
|
||||
}
|
||||
|
||||
Consumer<World> task;
|
||||
while ((task = SCHEDULED_TASKS.poll()) != null) {
|
||||
void run(World world) {
|
||||
if (this.world.get() == world) {
|
||||
try {
|
||||
task.accept(world);
|
||||
} catch (Exception e) {
|
||||
|
@ -47,26 +58,4 @@ public class AwaitTickQueue {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class DelayedTask {
|
||||
final Consumer<World> task;
|
||||
|
||||
int ticksDelay;
|
||||
|
||||
DelayedTask(Consumer<World> task, int ticks) {
|
||||
this.task = task;
|
||||
this.ticksDelay = ticks;
|
||||
}
|
||||
|
||||
boolean tick() {
|
||||
if (ticksDelay-- <= 0) {
|
||||
SCHEDULED_TASKS.add(task);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ public class SpellBookContainer extends Container {
|
|||
worldObj.createExplosion(null, player.getX(), player.getY(), player.getZ(), 0, DestructionType.NONE);
|
||||
worldObj.addParticle(ParticleTypes.EXPLOSION, player.getX(), player.getY(), player.getZ(), 1, 0, 0);
|
||||
|
||||
AwaitTickQueue.enqueueTask(w -> player.container.close(player));
|
||||
AwaitTickQueue.scheduleTask(player.world, w -> player.container.close(player), 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -234,7 +234,7 @@ public class AlicornAmuletItem extends ArmorItem implements AddictiveMagicitem,
|
|||
|
||||
player.world.createExplosion(player, pos.x, pos.y, pos.z, 10, DestructionType.NONE);
|
||||
|
||||
AwaitTickQueue.scheduleTask(w -> {
|
||||
AwaitTickQueue.scheduleTask(player.world, w -> {
|
||||
w.createExplosion(player, pos.x, pos.y, pos.z, 6, DestructionType.BREAK);
|
||||
}, 50);
|
||||
}
|
||||
|
|
|
@ -146,11 +146,11 @@ public interface Caster<E extends LivingEntity> extends Owned<E>, Levelled, Affi
|
|||
}
|
||||
|
||||
default void notifyNearbySpells(Spell sender, BlockPos origin, double radius, int newState) {
|
||||
AwaitTickQueue.enqueueTask(w -> {
|
||||
AwaitTickQueue.scheduleTask(getWorld(), w -> {
|
||||
VecHelper.findAllEntitiesInRange(getEntity(), getWorld(), origin, radius)
|
||||
.filter(i -> i instanceof EtherialListener)
|
||||
.forEach(i -> ((EtherialListener)i).onNearbySpellChange(this, sender, newState));
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
default void notifyNearbySpells(Spell sender, double radius, int newState) {
|
||||
|
|
Loading…
Reference in a new issue