diff --git a/src/main/java/com/minelittlepony/unicopia/AwaitTickQueue.java b/src/main/java/com/minelittlepony/unicopia/AwaitTickQueue.java index aad07fa9..2bfe8422 100644 --- a/src/main/java/com/minelittlepony/unicopia/AwaitTickQueue.java +++ b/src/main/java/com/minelittlepony/unicopia/AwaitTickQueue.java @@ -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> SCHEDULED_TASKS = Queues.newArrayDeque(); - private static List DELAYED_TASKS = Lists.newArrayList(); - private static final Object LOCKER = new Object(); + private static List PENDING_TASKS = new ArrayList<>(); - public static void enqueueTask(Consumer task) { - synchronized (LOCKER) { - SCHEDULED_TASKS.add(task); - } - } - - public static void scheduleTask(Consumer task, int ticksLater) { - synchronized (LOCKER) { - DELAYED_TASKS.add(new DelayedTask(task, ticksLater)); + public static void scheduleTask(World reference, Consumer 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 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 task; + private final WeakReference world; + private int ticks; + + Entry(World world, Consumer 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 tasks) { + World w = this.world.get(); + return w != null && (w != world || ticks-- > 0 || !tasks.add(this)); + } - Consumer 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 task; - - int ticksDelay; - - DelayedTask(Consumer task, int ticks) { - this.task = task; - this.ticksDelay = ticks; - } - - boolean tick() { - if (ticksDelay-- <= 0) { - SCHEDULED_TASKS.add(task); - - return false; - } - - return true; - } - } - } diff --git a/src/main/java/com/minelittlepony/unicopia/container/SpellBookContainer.java b/src/main/java/com/minelittlepony/unicopia/container/SpellBookContainer.java index c777301a..5c8997fb 100644 --- a/src/main/java/com/minelittlepony/unicopia/container/SpellBookContainer.java +++ b/src/main/java/com/minelittlepony/unicopia/container/SpellBookContainer.java @@ -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; } diff --git a/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java b/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java index 7defd614..1f0b597c 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/AlicornAmuletItem.java @@ -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); } diff --git a/src/main/java/com/minelittlepony/unicopia/magic/Caster.java b/src/main/java/com/minelittlepony/unicopia/magic/Caster.java index 348ec89e..1c238057 100644 --- a/src/main/java/com/minelittlepony/unicopia/magic/Caster.java +++ b/src/main/java/com/minelittlepony/unicopia/magic/Caster.java @@ -146,11 +146,11 @@ public interface Caster extends Owned, 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) {