photos in item frames are read from their renderer or index cache without loading the map view (a wall of 1000 frames with not yet loaded photos took 830 ms on the main thread, now 490 ms cold / 60 ms warm)
This commit is contained in:
1 parent
faeda0e0da
commit
3a064a5ffa
3 files changed
+49
-10
No files matched your search
+9
-3
@@ -2,6 +2,7 @@ package eu.mhsl.minecraft.pixelpics.render.snapshot;
|
||||
|
||||
import eu.mhsl.minecraft.pixelpics.render.entity.DecorationState;
|
||||
import eu.mhsl.minecraft.pixelpics.render.entity.ItemSpec;
|
||||
import eu.mhsl.minecraft.pixelpics.utils.MapManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -51,9 +52,14 @@ public final class DecorationSnapshotBuilder {
|
||||
ItemStack stack = frame.getItem();
|
||||
item = ItemSpecs.of(stack);
|
||||
if (stack.getType() == Material.FILLED_MAP) {
|
||||
MapView view = MapPixels.view(stack);
|
||||
map = MapPixels.of(view);
|
||||
if (map != null) markers = MapPixels.markers(view);
|
||||
int id = MapPixels.mapId(stack);
|
||||
if (id >= 0 && MapManager.isManaged(id)) {
|
||||
map = MapPixels.photo(id); // photos have no markers
|
||||
} else {
|
||||
MapView view = MapPixels.view(stack);
|
||||
map = MapPixels.of(view);
|
||||
if (map != null) markers = MapPixels.markers(view);
|
||||
}
|
||||
}
|
||||
rotation = frame.getRotation().ordinal();
|
||||
glow = e instanceof GlowItemFrame;
|
||||
|
||||
@@ -36,22 +36,45 @@ final class MapPixels {
|
||||
}
|
||||
}
|
||||
|
||||
/** The stack's map id without loading its view, or -1. */
|
||||
static int mapId(ItemStack stack) {
|
||||
try {
|
||||
return stack.getItemMeta() instanceof MapMeta meta && meta.hasMapId() ? meta.getMapId() : -1;
|
||||
} catch (Throwable t) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A PixelPics photo ({@link MapManager#isManaged}) without loading the server's map data (a wall of photos not
|
||||
* loaded yet cost ~4 ms per map on the main thread): its renderer's indices, else the stored index cache, else
|
||||
* blank film like its map shows meanwhile.
|
||||
*/
|
||||
static int[][] photo(int mapId) {
|
||||
ImageMapRenderer renderer = MapManager.renderer(mapId);
|
||||
byte[] colors = renderer != null ? renderer.getIndices() : MapManager.readIndices(mapId);
|
||||
return argb(colors != null ? colors : film());
|
||||
}
|
||||
|
||||
/** ARGB {@code [y][x]}, or null without map data (vanilla then draws the item). */
|
||||
static int[][] of(MapView view) {
|
||||
if (view == null) return null;
|
||||
try {
|
||||
byte[] colors = colors(view);
|
||||
if (colors == null || colors.length != SIZE * SIZE) return null;
|
||||
int[][] out = new int[SIZE][SIZE];
|
||||
for (int y = 0; y < SIZE; y++) {
|
||||
for (int x = 0; x < SIZE; x++) out[y][x] = MapColorPalette.argb(colors[y * SIZE + x]);
|
||||
}
|
||||
return out;
|
||||
return argb(colors(view));
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static int[][] argb(byte[] colors) {
|
||||
if (colors == null || colors.length != SIZE * SIZE) return null;
|
||||
int[][] out = new int[SIZE][SIZE];
|
||||
for (int y = 0; y < SIZE; y++) {
|
||||
for (int x = 0; x < SIZE; x++) out[y][x] = MapColorPalette.argb(colors[y * SIZE + x]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static byte[] colors(MapView view) throws ReflectiveOperationException {
|
||||
for (MapRenderer r : view.getRenderers()) {
|
||||
if (r instanceof ImageMapRenderer image) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -37,6 +38,8 @@ public class MapManager {
|
||||
private static File folder;
|
||||
// Views carrying one of our renderers; weak, the server owns them.
|
||||
private static final Map<MapView, Boolean> attached = new WeakHashMap<>();
|
||||
// The renderer of each attached photo by map id (main thread), so a photo can be read without loading its view.
|
||||
private static final Map<Integer, ImageMapRenderer> renderers = new HashMap<>();
|
||||
|
||||
private MapManager() {}
|
||||
|
||||
@@ -73,6 +76,12 @@ public class MapManager {
|
||||
mapView.addRenderer(renderer);
|
||||
mapView.setTrackingPosition(false);
|
||||
attached.put(mapView, Boolean.TRUE);
|
||||
renderers.put(mapView.getId(), renderer);
|
||||
}
|
||||
|
||||
/** The renderer attached to photo map {@code id} in this session, or null when its view is not loaded (yet). */
|
||||
public static ImageMapRenderer renderer(int id) {
|
||||
return renderers.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,6 +97,7 @@ public class MapManager {
|
||||
ids.add(Integer.toString(view.getId()));
|
||||
}
|
||||
attached.clear();
|
||||
renderers.clear();
|
||||
try {
|
||||
Files.write(new File(Main.getInstance().getDataFolder(), RELOAD_FILE).toPath(), ids);
|
||||
} catch (IOException e) {
|
||||
|
||||
Reference in new issue
Block a user