package amidst.map; import java.awt.AlphaComposite; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import amidst.Options; import amidst.logging.Log; import amidst.minecraft.MinecraftUtil; public class Fragment { public static final int SIZE = 512, SIZE_SHIFT = 9, MAX_OBJECTS_PER_FRAGMENT = 32, BIOME_SIZE = SIZE >> 2; private static AffineTransform drawMatrix = new AffineTransform(); public int blockX, blockY; public short[] biomeData = new short[BIOME_SIZE * BIOME_SIZE]; private ImageLayer[] imageLayers; private LiveLayer[] liveLayers; private IconLayer[] iconLayers; private Object loadLock = new Object(); private BufferedImage[] images; public MapObject[] objects; public int objectsLength = 0; private float alpha = 0.0f; public boolean isActive = false; public boolean isLoaded = false; public Fragment nextFragment = null, prevFragment = null; public boolean hasNext = false; public boolean endOfLine = false; private static int[] dataCache = new int[SIZE*SIZE]; public Fragment(ImageLayer... layers) { this(layers, null, null); } public Fragment(ImageLayer[] imageLayers, LiveLayer[] liveLayers, IconLayer[] iconLayers) { this.imageLayers = imageLayers; this.liveLayers = liveLayers; images = new BufferedImage[imageLayers.length]; for (int i = 0; i < imageLayers.length; i++) images[imageLayers[i].getLayerId()] = new BufferedImage(imageLayers[i].size, imageLayers[i].size, BufferedImage.TYPE_INT_ARGB); this.iconLayers = iconLayers; objects = new MapObject[MAX_OBJECTS_PER_FRAGMENT]; } public void load() { synchronized (loadLock) { if (isLoaded) Log.w("This should never happen!"); int[] data = MinecraftUtil.getBiomeData(blockX >> 2, blockY >> 2, BIOME_SIZE, BIOME_SIZE, true); for (int i = 0; i < BIOME_SIZE * BIOME_SIZE; i++) biomeData[i] = (short)data[i]; for (int i = 0; i < imageLayers.length; i++) imageLayers[i].load(this); for (int i = 0; i < iconLayers.length; i++) iconLayers[i].generateMapObjects(this); alpha = Options.instance.mapFading.get()?0.0f:1.0f; isLoaded = true; } } public void recycle() { isActive = false; isLoaded = false; } public void clearData() { for (IconLayer layer : iconLayers) layer.clearMapObjects(this); isLoaded = false; } public void clear() { for (IconLayer layer : iconLayers) layer.clearMapObjects(this); hasNext = false; endOfLine = false; isActive = true; } public void drawLiveLayers(float time, Graphics2D g, AffineTransform mat) { for (int i = 0; i < liveLayers.length; i++) { if (liveLayers[i].isVisible()) { liveLayers[i].drawLive(this, g, mat); } } } public void drawImageLayers(float time, Graphics2D g, AffineTransform mat) { if (!isLoaded) return; alpha = Math.min(1.0f, time*3.0f + alpha); for (int i = 0; i < images.length; i++) { if (imageLayers[i].isVisible()) { g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha * imageLayers[i].getAlpha())); // TOOD: FIX THIS g.setTransform(imageLayers[i].getScaledMatrix(mat)); if (g.getTransform().getScaleX() < 1.0f) g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); else g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); g.drawImage(images[i], 0, 0, null); } } g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f)); } public void drawObjects(Graphics2D g, AffineTransform inMatrix) { if (alpha != 1.0f) g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); for (int i = 0; i < objectsLength; i++) { if (objects[i].parentLayer.isVisible()) { drawMatrix.setTransform(inMatrix); drawMatrix.translate(objects[i].x, objects[i].y); double invZoom = 1.0 / objects[i].parentLayer.map.getZoom(); drawMatrix.scale(invZoom, invZoom); g.setTransform(drawMatrix); g.drawImage(objects[i].getImage(), -(objects[i].getWidth() >> 1), -(objects[i].getHeight() >> 1), objects[i].getWidth(), objects[i].getHeight(), null); } } if (alpha != 1.0f) g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f)); } public void addObject(MapObject object) { object.rx = object.x + this.blockX; object.ry = object.y + this.blockY; if (objectsLength >= objects.length) { MapObject[] tempObjects = new MapObject[objects.length << 1]; for (int i = 0; i < objects.length; i++) tempObjects[i] = objects[i]; objects = tempObjects; } objects[objectsLength] = object; objectsLength++; } public void setImageData(int layerId, int[] data) { images[layerId].setRGB(0, 0, imageLayers[layerId].size, imageLayers[layerId].size, data, 0, imageLayers[layerId].size); } public int getBlockX() { return blockX; } public int getBlockY() { return blockY; } public int getChunkX() { return blockX >> 4; } public int getChunkY() { return blockY >> 4; } public int getFragmentX() { return blockX >> SIZE_SHIFT; } public int getFragmentY() { return blockY >> SIZE_SHIFT; } public void setNext(Fragment frag) { nextFragment = frag; frag.prevFragment = this; hasNext = true; } public void remove() { if (hasNext) prevFragment.setNext(nextFragment); else prevFragment.hasNext = false; } public static int[] getIntArray() { return dataCache; } public void removeObject(MapObjectPlayer player) { for (int i = 0; i < objectsLength; i++) { if (objects[i] == player) { objects[i] = objects[objectsLength - 1]; objectsLength--; } } } public BufferedImage getBufferedImage(int layer) { return images[layer]; } public void reset() { objectsLength = 0; isActive = false; isLoaded = false; nextFragment = null; prevFragment = null; hasNext = false; endOfLine = false; } public void repaint() { synchronized (loadLock) { if (isLoaded) for (int i = 0; i < imageLayers.length; i++) imageLayers[i].load(this); } } public void repaintImageLayer(int id) { synchronized (loadLock) { if (isLoaded) imageLayers[id].load(this); } } }