Skip to content

Commit

Permalink
improve highlight cache world switching handler
Browse files Browse the repository at this point in the history
now handles the different possible cases in which the event is fired correctly
  • Loading branch information
rfresh2 committed Jan 19, 2025
1 parent bf75aa1 commit 2138a4e
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 62 deletions.
14 changes: 13 additions & 1 deletion common/src/main/java/xaeroplus/event/XaeroWorldChangeEvent.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
package xaeroplus.event;

public record XaeroWorldChangeEvent(String worldId, String dimId, String mwId) { }
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;

public record XaeroWorldChangeEvent(WorldChangeType worldChangeType, @Nullable ResourceKey<Level> from, @Nullable ResourceKey<Level> to) {
public enum WorldChangeType {
ENTER_WORLD,
EXIT_WORLD,
SWITCH_TO_ALT_DIMENSION,
SWITCH_BACK_TO_ACTUAL_DIMENSION,
MULTIWORLD_SWITCH
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import it.unimi.dsi.fastutil.longs.LongList;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;
import xaeroplus.event.XaeroWorldChangeEvent;

public interface ChunkHighlightCache {
boolean addHighlight(final int x, final int z);
boolean removeHighlight(final int x, final int z);
boolean isHighlighted(final int x, final int z, ResourceKey<Level> dimensionId);
LongList getHighlightsSnapshot(ResourceKey<Level> dimensionId);
void handleWorldChange();
void handleWorldChange(final XaeroWorldChangeEvent event);
void handleTick();
void onEnable();
void onDisable();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import xaeroplus.XaeroPlus;
import xaeroplus.event.XaeroWorldChangeEvent;
import xaeroplus.util.ChunkUtils;

import java.util.ArrayList;
Expand Down Expand Up @@ -144,7 +145,7 @@ public boolean removeHighlight(final int x, final int z) {
}

@Override
public void handleWorldChange() {}
public void handleWorldChange(final XaeroWorldChangeEvent event) {}

@Override
public void handleTick() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import it.unimi.dsi.fastutil.longs.Long2LongMap;
import xaeroplus.XaeroPlus;
import xaeroplus.event.XaeroWorldChangeEvent;

import java.util.Map;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -48,7 +49,12 @@ private void limitChunksSize() {
}

@Override
public void handleWorldChange() {}
public void handleWorldChange(final XaeroWorldChangeEvent event) {
// intentionally not clearing cache on any world change state
// its somewhat useful for players so they don't lose all date if they get disconnected somehow
// but it does lead to data incoherence if they switch dimensions or servers in the same session
// so its a tradeoff, generally players will always use the database cache anyway
}

@Override
public void handleTick() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import xaero.map.gui.GuiMap;
import xaeroplus.Globals;
import xaeroplus.XaeroPlus;
import xaeroplus.event.XaeroWorldChangeEvent;
import xaeroplus.util.ChunkUtils;

import java.io.Closeable;
Expand All @@ -27,6 +28,7 @@
import java.util.stream.Collectors;

import static net.minecraft.world.level.Level.*;
import static xaeroplus.event.XaeroWorldChangeEvent.WorldChangeType.ENTER_WORLD;
import static xaeroplus.util.ChunkUtils.getActualDimension;
import static xaeroplus.util.GuiMapHelper.*;

Expand Down Expand Up @@ -57,9 +59,9 @@ public ChunkHighlightSavingCache(final @NotNull String databaseName) {
@Override
public boolean addHighlight(final int x, final int z) {
try {
ChunkHighlightCacheDimensionHandler cacheForCurrentDimension = getCacheForCurrentDimension();
if (cacheForCurrentDimension == null) throw new RuntimeException("Didn't find cache for current dimension");
cacheForCurrentDimension.addHighlight(x, z);
ChunkHighlightCacheDimensionHandler cacheForActualDimension = getCacheForActualDimension();
if (cacheForActualDimension == null) throw new RuntimeException("Didn't find cache for current dimension");
cacheForActualDimension.addHighlight(x, z);
return true;
} catch (final Exception e) {
XaeroPlus.LOGGER.debug("Error adding highlight to {} disk cache: {}, {}", databaseName, x, z, e);
Expand All @@ -77,9 +79,9 @@ public void addHighlight(final int x, final int z, final long foundTime, final R
@Override
public boolean removeHighlight(final int x, final int z) {
try {
ChunkHighlightCacheDimensionHandler cacheForCurrentDimension = getCacheForCurrentDimension();
if (cacheForCurrentDimension == null) throw new RuntimeException("Didn't find cache for current dimension");
cacheForCurrentDimension.removeHighlight(x, z);
ChunkHighlightCacheDimensionHandler cacheForActualDimension = getCacheForActualDimension();
if (cacheForActualDimension == null) throw new RuntimeException("Didn't find cache for current dimension");
cacheForActualDimension.removeHighlight(x, z);
return true;
} catch (final Exception e) {
XaeroPlus.LOGGER.debug("Error removing highlight from {} disk cache: {}, {}", databaseName, x, z, e);
Expand Down Expand Up @@ -110,22 +112,33 @@ public LongList getHighlightsSnapshot(final ResourceKey<Level> dimensionId) {
}

@Override
public void handleWorldChange() {
public void handleWorldChange(final XaeroWorldChangeEvent event) {
parentExecutor.execute(() -> {
// make sure we mark as unready to prevent further mutations
if (cacheReady.compareAndSet(true, false)) {
try {
Futures.allAsList(flushAllChunks()).get(30, TimeUnit.SECONDS);
} catch (final Exception e) {
XaeroPlus.LOGGER.error("Error saving all chunks before world change", e);
switch (event.worldChangeType()) {
case ENTER_WORLD -> {
cacheReady.set(false);
reset();
if (initializeWorld()) {
cacheReady.set(true);
}
}
case EXIT_WORLD -> {
// make sure we mark as unready to prevent further mutations
if (cacheReady.compareAndSet(true, false)) {
try {
Futures.allAsList(flushAllChunks()).get(30, TimeUnit.SECONDS);
} catch (final Exception e) {
XaeroPlus.LOGGER.error("Error saving all chunks before world change", e);
}
}
reset();
}
case SWITCH_TO_ALT_DIMENSION -> {
loadChunksInCurrentDimension();
}
case SWITCH_BACK_TO_ACTUAL_DIMENSION -> {
loadChunksInActualDimension();
}
} else {
// will happen on initial world load, i.e. not switching dimensions
cacheReady.set(false);
}
reset();
if (initializeWorld()) {
cacheReady.set(true);
}
});
}
Expand All @@ -152,7 +165,7 @@ private List<ListenableFuture<?>> flushAllChunks() {
.collect(Collectors.toList());
}

public ChunkHighlightCacheDimensionHandler getCacheForCurrentDimension() {
public ChunkHighlightCacheDimensionHandler getCacheForActualDimension() {
if (!cacheReady.get()) return null;
return getCacheForDimension(ChunkUtils.getActualDimension(), true);
}
Expand Down Expand Up @@ -228,6 +241,7 @@ private synchronized boolean initializeWorld() {
initializeDimensionCacheHandler(OVERWORLD);
initializeDimensionCacheHandler(NETHER);
initializeDimensionCacheHandler(END);
loadChunksInCurrentDimension();
loadChunksInActualDimension();
return true;
} catch (final Exception e) {
Expand All @@ -238,15 +252,22 @@ private synchronized boolean initializeWorld() {
}

private void loadChunksInActualDimension() {
ChunkHighlightCacheDimensionHandler cacheForCurrentDimension = getCacheForCurrentDimension();
var cacheForActualDimension = getCacheForActualDimension();
if (cacheForActualDimension == null) return;
cacheForActualDimension
.setWindow(ChunkUtils.actualPlayerRegionX(), ChunkUtils.actualPlayerRegionZ(), getMinimapRegionWindowSize());
}

private void loadChunksInCurrentDimension() {
var cacheForCurrentDimension = getCacheForActualDimension();
if (cacheForCurrentDimension == null) return;
cacheForCurrentDimension
.setWindow(ChunkUtils.actualPlayerRegionX(), ChunkUtils.actualPlayerRegionZ(), getMinimapRegionWindowSize());
.setWindow(ChunkUtils.getPlayerRegionX(), ChunkUtils.getPlayerRegionZ(), getMinimapRegionWindowSize());
}

@Override
public void onEnable() {
handleWorldChange();
handleWorldChange(new XaeroWorldChangeEvent(ENTER_WORLD, null, ChunkUtils.getActualDimension()));
}

@Override
Expand Down Expand Up @@ -296,39 +317,35 @@ public void handleTick() {
final ResourceKey<Level> mapDimension = Globals.getCurrentDimensionId();
final ResourceKey<Level> actualDimension = ChunkUtils.getActualDimension();

final int windowSize;
final int actualPlayerRegionX = ChunkUtils.actualPlayerRegionX();
final int actualPlayerRegionZ = ChunkUtils.actualPlayerRegionZ();
final int windowCenterX;
final int windowCenterZ;

Optional<GuiMap> guiMapOptional = getGuiMap();
if (guiMapOptional.isPresent()) { // viewing worldmap
final GuiMap guiMap = guiMapOptional.get();
final int mapCenterX = getGuiMapCenterRegionX(guiMap);
final int mapCenterZ = getGuiMapCenterRegionZ(guiMap);
final int mapSize = getGuiMapRegionSize(guiMap);
final ChunkHighlightCacheDimensionHandler viewedDimCache = getCacheForDimension(mapDimension, true);
if (viewedDimCache != null) viewedDimCache.setWindow(mapCenterX, mapCenterZ, mapSize);
if (mapDimension == actualDimension) {
getCachesExceptDimension(mapDimension)
.forEach(cache -> cache.setWindow(0, 0, 0));
} else {
final ChunkHighlightCacheDimensionHandler actualDimCache = getCacheForDimension(actualDimension, true);
if (actualDimCache != null) {
actualDimCache.setWindow(ChunkUtils.getPlayerRegionX(), ChunkUtils.getPlayerRegionZ(), mapSize);
}
getCachesExceptDimensions(List.of(mapDimension, actualDimension))
.forEach(cache -> cache.setWindow(0, 0, 0));
}
} else { // viewing minimap
final ChunkHighlightCacheDimensionHandler cacheForDimension = getCacheForDimension(mapDimension, true);
if (cacheForDimension != null) cacheForDimension.setWindow(ChunkUtils.getPlayerRegionX(), ChunkUtils.getPlayerRegionZ(), getMinimapRegionWindowSize());
if (mapDimension == actualDimension) {
getCachesExceptDimension(mapDimension)
.forEach(cache -> cache.setWindow(0, 0, 0));
} else {
final ChunkHighlightCacheDimensionHandler actualDimCache = getCacheForDimension(actualDimension, true);
if (actualDimCache != null) {
actualDimCache.setWindow(ChunkUtils.getPlayerRegionX(), ChunkUtils.getPlayerRegionZ(), getMinimapRegionWindowSize());
}
getCachesExceptDimensions(List.of(mapDimension, actualDimension))
.forEach(cache -> cache.setWindow(0, 0, 0));
if (guiMapOptional.isPresent()) {
var guiMap = guiMapOptional.get();
windowSize = getGuiMapRegionSize(guiMap);
windowCenterX = getGuiMapCenterRegionX(guiMap);
windowCenterZ = getGuiMapCenterRegionZ(guiMap);
} else {
windowSize = getMinimapRegionWindowSize();
windowCenterX = ChunkUtils.getPlayerRegionX();
windowCenterZ = ChunkUtils.getPlayerRegionZ();
}
var cacheForDimension = getCacheForDimension(mapDimension, true);
if (cacheForDimension != null) cacheForDimension.setWindow(windowCenterX, windowCenterZ, windowSize);
if (mapDimension == actualDimension) {
getCachesExceptDimension(mapDimension)
.forEach(cache -> cache.setWindow(0, 0, 0));
} else {
var actualDimCache = getCacheForDimension(actualDimension, true);
if (actualDimCache != null) {
actualDimCache.setWindow(actualPlayerRegionX, actualPlayerRegionZ, windowSize);
}
getCachesExceptDimensions(List.of(mapDimension, actualDimension))
.forEach(cache -> cache.setWindow(0, 0, 0));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public synchronized void setDiskCache(final boolean disk, final boolean enabled)
@EventHandler
public void onXaeroWorldChange(XaeroWorldChangeEvent event) {
try {
cache.handleWorldChange();
cache.handleWorldChange(event);
} catch (final Exception e) {
XaeroPlus.LOGGER.error("Error handling world change event for cache: {} event: {}", dbName, event, e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.UUID;

@Mixin(value = MapProcessor.class, remap = false)
Expand Down Expand Up @@ -107,7 +108,34 @@ public Path replaceLockPath(final Path instance, final String other) {
ordinal = 0
))
public void fireWorldChangedEvent(final CallbackInfo ci) {
XaeroPlus.EVENT_BUS.call(new XaeroWorldChangeEvent(this.currentWorldId, this.currentDimId, this.currentMWId));
var customDimensionId = mapWorld != null ? mapWorld.getCustomDimensionId() : null;
var mapWorldDim = this.mapWorld != null ? this.mapWorld.getCurrentDimensionId() : null;
XaeroWorldChangeEvent.WorldChangeType type;
ResourceKey<Level> from, to;
if (xaeroPlus$prevWorldId == null) {
type = XaeroWorldChangeEvent.WorldChangeType.ENTER_WORLD;
from = null;
to = mapWorldDim;
} else if (currentWorldId == null) {
type = XaeroWorldChangeEvent.WorldChangeType.EXIT_WORLD;
from = mapWorldDim;
to = null;
} else if (!Objects.equals(xaeroPlus$prevMWId, currentMWId) && mapWorldDim == ChunkUtils.getActualDimension()) {
type = XaeroWorldChangeEvent.WorldChangeType.MULTIWORLD_SWITCH;
from = null;
to = null;
} else if (customDimensionId != ChunkUtils.getActualDimension()) {
type = XaeroWorldChangeEvent.WorldChangeType.SWITCH_TO_ALT_DIMENSION;
from = mapWorldDim;
to = customDimensionId;
} else {
type = XaeroWorldChangeEvent.WorldChangeType.SWITCH_BACK_TO_ACTUAL_DIMENSION;
from = null;
to = mapWorldDim;
}
// XaeroPlus.LOGGER.info("Firing world change event: {} from {} to {}", type, from, to);
var event = new XaeroWorldChangeEvent(type, from, to);
XaeroPlus.EVENT_BUS.call(event);
}

@Inject(method = "getCurrentDimension", at = @At("HEAD"), cancellable = true)
Expand Down
4 changes: 3 additions & 1 deletion common/src/main/java/xaeroplus/module/impl/WaystoneSync.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import java.util.Locale;

import static xaero.common.settings.ModSettings.COLORS;
import static xaeroplus.event.XaeroWorldChangeEvent.WorldChangeType.ENTER_WORLD;
import static xaeroplus.event.XaeroWorldChangeEvent.WorldChangeType.EXIT_WORLD;

public class WaystoneSync extends Module {
private final BlayWaystonesHelper blayWaystonesHelper = new BlayWaystonesHelper();
Expand All @@ -51,7 +53,7 @@ public void onDisable() {

@EventHandler
public void onXaeroWorldChangeEvent(final XaeroWorldChangeEvent event) {
if (event.worldId() == null) {
if (event.worldChangeType() == EXIT_WORLD || event.worldChangeType() == ENTER_WORLD) {
blayWaystonesHelper.toSyncWaystones = Collections.emptyList();
}
}
Expand Down

0 comments on commit 2138a4e

Please sign in to comment.