Fixed chunk load/unload listeners only firing once.

This commit is contained in:
Florian Nücke
2022-02-06 20:48:08 +01:00
parent fb8b9d4c9f
commit e1f51118cd
3 changed files with 50 additions and 32 deletions

View File

@@ -419,16 +419,16 @@ public final class BusCableBlockEntity extends ModBlockEntity {
private void addListener() {
if (level != null && !hasRegisteredListener) {
ServerScheduler.scheduleOnLoad(level, chunkPos, onChunkLoadedStateChanged);
ServerScheduler.scheduleOnUnload(level, chunkPos, onChunkLoadedStateChanged);
ServerScheduler.subscribeOnLoad(level, chunkPos, onChunkLoadedStateChanged);
ServerScheduler.subscribeOnUnload(level, chunkPos, onChunkLoadedStateChanged);
}
hasRegisteredListener = true;
}
private void removeListener() {
if (level != null && hasRegisteredListener) {
ServerScheduler.cancelOnLoad(level, chunkPos, onChunkLoadedStateChanged);
ServerScheduler.cancelOnUnload(level, chunkPos, onChunkLoadedStateChanged);
ServerScheduler.unsubscribeOnLoad(level, chunkPos, onChunkLoadedStateChanged);
ServerScheduler.unsubscribeOnUnload(level, chunkPos, onChunkLoadedStateChanged);
}
hasRegisteredListener = false;
}

View File

@@ -117,8 +117,8 @@ public final class BlockDeviceBusController extends CommonDeviceBusController {
private void addListeners(final Collection<ChunkLocation> trackedChunks) {
for (final ChunkLocation trackedChunk : trackedChunks) {
trackedChunk.tryGetLevel().ifPresent(level -> {
ServerScheduler.scheduleOnLoad(level, trackedChunk.position(), onBusChunkLoadedStateChanged);
ServerScheduler.scheduleOnUnload(level, trackedChunk.position(), onBusChunkLoadedStateChanged);
ServerScheduler.subscribeOnLoad(level, trackedChunk.position(), onBusChunkLoadedStateChanged);
ServerScheduler.subscribeOnUnload(level, trackedChunk.position(), onBusChunkLoadedStateChanged);
});
}
}
@@ -126,8 +126,8 @@ public final class BlockDeviceBusController extends CommonDeviceBusController {
private void removeListeners(final Collection<ChunkLocation> trackedChunks) {
for (final ChunkLocation trackedChunk : trackedChunks) {
trackedChunk.tryGetLevel().ifPresent(level -> {
ServerScheduler.cancelOnLoad(level, trackedChunk.position(), onBusChunkLoadedStateChanged);
ServerScheduler.cancelOnUnload(level, trackedChunk.position(), onBusChunkLoadedStateChanged);
ServerScheduler.unsubscribeOnLoad(level, trackedChunk.position(), onBusChunkLoadedStateChanged);
ServerScheduler.unsubscribeOnUnload(level, trackedChunk.position(), onBusChunkLoadedStateChanged);
});
}
}

View File

@@ -18,8 +18,8 @@ public final class ServerScheduler {
private static final TickScheduler globalTickScheduler = new TickScheduler();
private static final WeakHashMap<LevelAccessor, TickScheduler> levelTickSchedulers = new WeakHashMap<>();
private static final WeakHashMap<LevelAccessor, SimpleScheduler> levelUnloadSchedulers = new WeakHashMap<>();
private static final WeakHashMap<LevelAccessor, HashMap<ChunkPos, SimpleScheduler>> chunkLoadSchedulers = new WeakHashMap<>();
private static final WeakHashMap<LevelAccessor, HashMap<ChunkPos, SimpleScheduler>> chunkUnloadSchedulers = new WeakHashMap<>();
private static final WeakHashMap<LevelAccessor, HashMap<ChunkPos, ListenerCollection>> chunkLoadSchedulers = new WeakHashMap<>();
private static final WeakHashMap<LevelAccessor, HashMap<ChunkPos, ListenerCollection>> chunkUnloadSchedulers = new WeakHashMap<>();
///////////////////////////////////////////////////////////////////
@@ -61,49 +61,49 @@ public final class ServerScheduler {
}
}
public static void scheduleOnLoad(final LevelAccessor level, final ChunkPos chunkPos, final Runnable listener) {
public static void subscribeOnLoad(final LevelAccessor level, final ChunkPos chunkPos, final Runnable listener) {
chunkLoadSchedulers
.computeIfAbsent(level, unused -> new HashMap<>())
.computeIfAbsent(chunkPos, unused -> new SimpleScheduler())
.computeIfAbsent(chunkPos, unused -> new ListenerCollection())
.add(listener);
}
public static void cancelOnLoad(@Nullable final LevelAccessor level, final ChunkPos chunkPos, final Runnable listener) {
public static void unsubscribeOnLoad(@Nullable final LevelAccessor level, final ChunkPos chunkPos, final Runnable listener) {
if (level == null) {
return;
}
final HashMap<ChunkPos, SimpleScheduler> chunkMap = chunkLoadSchedulers.get(level);
final HashMap<ChunkPos, ListenerCollection> chunkMap = chunkLoadSchedulers.get(level);
if (chunkMap == null) {
return;
}
final SimpleScheduler scheduler = chunkMap.get(chunkPos);
if (scheduler != null) {
scheduler.remove(listener);
final ListenerCollection listeners = chunkMap.get(chunkPos);
if (listeners != null) {
listeners.remove(listener);
}
}
public static void scheduleOnUnload(final LevelAccessor level, final ChunkPos chunkPos, final Runnable listener) {
public static void subscribeOnUnload(final LevelAccessor level, final ChunkPos chunkPos, final Runnable listener) {
chunkUnloadSchedulers
.computeIfAbsent(level, unused -> new HashMap<>())
.computeIfAbsent(chunkPos, unused -> new SimpleScheduler())
.computeIfAbsent(chunkPos, unused -> new ListenerCollection())
.add(listener);
}
public static void cancelOnUnload(@Nullable final LevelAccessor level, final ChunkPos chunkPos, final Runnable listener) {
public static void unsubscribeOnUnload(@Nullable final LevelAccessor level, final ChunkPos chunkPos, final Runnable listener) {
if (level == null) {
return;
}
final HashMap<ChunkPos, SimpleScheduler> chunkMap = chunkUnloadSchedulers.get(level);
final HashMap<ChunkPos, ListenerCollection> chunkMap = chunkUnloadSchedulers.get(level);
if (chunkMap == null) {
return;
}
final SimpleScheduler scheduler = chunkMap.get(chunkPos);
if (scheduler != null) {
scheduler.remove(listener);
final ListenerCollection listeners = chunkMap.get(chunkPos);
if (listeners != null) {
listeners.remove(listener);
}
}
@@ -135,27 +135,27 @@ public final class ServerScheduler {
@SubscribeEvent
public static void handleChunkLoad(final ChunkEvent.Load event) {
final HashMap<ChunkPos, SimpleScheduler> chunkMap = chunkLoadSchedulers.get(event.getWorld());
final HashMap<ChunkPos, ListenerCollection> chunkMap = chunkLoadSchedulers.get(event.getWorld());
if (chunkMap == null) {
return;
}
final SimpleScheduler scheduler = chunkMap.get(event.getChunk().getPos());
if (scheduler != null) {
scheduler.run();
final ListenerCollection listeners = chunkMap.get(event.getChunk().getPos());
if (listeners != null) {
listeners.run();
}
}
@SubscribeEvent
public static void handleChunkUnload(final ChunkEvent.Unload event) {
final HashMap<ChunkPos, SimpleScheduler> chunkMap = chunkUnloadSchedulers.get(event.getWorld());
final HashMap<ChunkPos, ListenerCollection> chunkMap = chunkUnloadSchedulers.get(event.getWorld());
if (chunkMap == null) {
return;
}
final SimpleScheduler scheduler = chunkMap.get(event.getChunk().getPos());
if (scheduler != null) {
scheduler.run();
final ListenerCollection listeners = chunkMap.get(event.getChunk().getPos());
if (listeners != null) {
listeners.run();
}
}
@@ -235,4 +235,22 @@ public final class ServerScheduler {
listeners.clear();
}
}
private static final class ListenerCollection {
private final Set<Runnable> listeners = Collections.newSetFromMap(new WeakHashMap<>());
public void add(final Runnable listener) {
listeners.add(listener);
}
public void remove(final Runnable listener) {
listeners.remove(listener);
}
public void run() {
for (final Runnable runnable : listeners) {
runnable.run();
}
}
}
}