diff --git a/cache/src/main/java/net/runelite/cache/AreaManager.java b/cache/src/main/java/net/runelite/cache/AreaManager.java new file mode 100644 index 0000000000..3f45072fec --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/AreaManager.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.AreaDefinition; +import net.runelite.cache.definitions.loaders.AreaLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Store; + +public class AreaManager +{ + private final Store store; + private final Map areas = new HashMap<>(); + + public AreaManager(Store store) + { + this.store = store; + } + + public void load() + { + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.AREA.getId()); + + for (FSFile file : archive.getFiles()) + { + AreaLoader loader = new AreaLoader(); + AreaDefinition area = loader.load(file.getContents(), file.getFileId()); + areas.put(area.id, area); + } + } + + public Collection getAreas() + { + return Collections.unmodifiableCollection(areas.values()); + } + + public AreaDefinition getArea(int areaId) + { + return areas.get(areaId); + } +} diff --git a/cache/src/main/java/net/runelite/cache/MapImageDumper.java b/cache/src/main/java/net/runelite/cache/MapImageDumper.java index 0cfe3c3bad..04d73c43d4 100644 --- a/cache/src/main/java/net/runelite/cache/MapImageDumper.java +++ b/cache/src/main/java/net/runelite/cache/MapImageDumper.java @@ -24,8 +24,6 @@ */ package net.runelite.cache; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; @@ -35,6 +33,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import net.runelite.cache.definitions.AreaDefinition; import net.runelite.cache.definitions.ObjectDefinition; import net.runelite.cache.definitions.OverlayDefinition; import net.runelite.cache.definitions.SpriteDefinition; @@ -69,13 +68,13 @@ public class MapImageDumper private final List underlays = new ArrayList<>(); private final List overlays = new ArrayList<>(); private final List textures = new ArrayList<>(); - private final Multimap sprites = HashMultimap.create(); private final Map averageColors = new HashMap<>(); private final Map scaledMapIcons = new HashMap<>(); private final Map objects = new HashMap<>(); - private final Map mapFunctions = new HashMap<>(); // quest, water, etc private RegionLoader regionLoader; + private final AreaManager areas; + private final SpriteManager sprites; private boolean labelRegions; private boolean outlineRegions; @@ -83,6 +82,8 @@ public class MapImageDumper public MapImageDumper(Store store) { this.store = store; + this.areas = new AreaManager(store); + this.sprites = new SpriteManager(store); } public void load() throws IOException @@ -90,10 +91,12 @@ public class MapImageDumper loadUnderlays(store); loadOverlays(store); loadTextures(store); - loadSprites(store); loadObjects(store); loadRegions(store); + areas.load(); + sprites.load(); + loadSprites(); } public BufferedImage drawMap(int z) throws IOException @@ -131,7 +134,7 @@ public class MapImageDumper int drawBaseY = regionLoader.getHighestY().getBaseY() - baseY; Graphics2D graphics = image.createGraphics(); - + drawObjects(graphics, region, z, drawBaseX, drawBaseY); graphics.dispose(); @@ -172,7 +175,7 @@ public class MapImageDumper return image; } - + private void drawUnderlay(BufferedImage image, int z) { // pass 1 @@ -199,7 +202,7 @@ public class MapImageDumper int overlayId = region.getOverlayId(z, x, y) - 1; int underlayId = region.getUnderlayId(z, x, y) - 1; int rgb = 0; - + if (overlayId > -1) { OverlayDefinition overlay = findOverlay(overlayId); @@ -220,7 +223,7 @@ public class MapImageDumper } } } - + private void drawOverlay(BufferedImage image, int z) { for (Region region : regionLoader.getRegions()) @@ -265,7 +268,7 @@ public class MapImageDumper TextureDefinition texture = findTexture(overlay.getTexture()); assert texture.getFileIds().length == 1; - SpriteDefinition sprite = findSprite(texture.getFileIds()[0], 0); + SpriteDefinition sprite = sprites.findSprite(texture.getFileIds()[0], 0); assert sprite != null; rgb = averageColors.get(sprite); @@ -336,14 +339,22 @@ public class MapImageDumper int drawX = drawBaseX + localX; int drawY = drawBaseY + (Region.Y - 1 - localY); - if (od.getMapIconID() != -1) + if (od.getMapAreaId() != -1) { - Image iconImage = mapFunctions.get(od.getMapIconID()); + AreaDefinition area = areas.getArea(od.getMapAreaId()); + assert area != null; + + int spriteId = area.spriteId; + + SpriteDefinition sprite = sprites.findSprite(spriteId, 0); + assert sprite != null; + + BufferedImage iconImage = sprites.getSpriteImage(sprite); graphics.drawImage(iconImage, drawX * MAP_SCALE, drawY * MAP_SCALE, null); } } } - + private void loadRegions(Store store) throws IOException { regionLoader = new RegionLoader(store); @@ -435,11 +446,10 @@ public class MapImageDumper return null; } - private void loadSprites(Store store) + private void loadSprites() { Index index = store.getIndex(IndexType.SPRITES); final int mapsceneHash = Djb2.hash("mapscene"); - final int mapfunctionHash = Djb2.hash("mapfunction"); for (Archive a : index.getArchives()) { @@ -460,8 +470,6 @@ public class MapImageDumper continue; } - this.sprites.put(sprite.getId(), sprite); - averageColors.put(sprite, getAverageColor(sprite.getPixels())); if (a.getNameHash() == mapsceneHash) @@ -475,30 +483,10 @@ public class MapImageDumper assert scaledMapIcons.containsKey(sprite.getFrame()) == false; scaledMapIcons.put(sprite.getFrame(), scaledImage); } - else if (a.getNameHash() == mapfunctionHash) - { - BufferedImage spriteImage = new BufferedImage(sprite.getWidth(), sprite.getHeight(), BufferedImage.TYPE_INT_ARGB); - spriteImage.setRGB(0, 0, sprite.getWidth(), sprite.getHeight(), sprite.getPixels(), 0, sprite.getWidth()); - - assert mapFunctions.containsKey(sprite.getFrame()) == false; - mapFunctions.put(sprite.getFrame(), spriteImage); - } } } } - private SpriteDefinition findSprite(int id, int frame) - { - for (SpriteDefinition def : sprites.get(id)) - { - if (def.getFrame() == frame) - { - return def; - } - } - return null; - } - private int getAverageColor(int[] pixels) { int redTotal = 0; diff --git a/cache/src/main/java/net/runelite/cache/SpriteManager.java b/cache/src/main/java/net/runelite/cache/SpriteManager.java index 52633ac019..653a84b748 100644 --- a/cache/src/main/java/net/runelite/cache/SpriteManager.java +++ b/cache/src/main/java/net/runelite/cache/SpriteManager.java @@ -24,10 +24,13 @@ */ package net.runelite.cache; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.List; import net.runelite.cache.definitions.SpriteDefinition; import net.runelite.cache.definitions.exporters.SpriteExporter; @@ -40,7 +43,7 @@ import net.runelite.cache.fs.Store; public class SpriteManager { private final Store store; - private final List sprites = new ArrayList<>(); + private final Multimap sprites = HashMultimap.create(); public SpriteManager(Store store) { @@ -61,20 +64,42 @@ public class SpriteManager byte[] contents = file.getContents(); SpriteLoader loader = new SpriteLoader(); - SpriteDefinition[] sprites = loader.load(a.getArchiveId(), contents); + SpriteDefinition[] defs = loader.load(a.getArchiveId(), contents); - this.sprites.addAll(Arrays.asList(sprites)); + for (SpriteDefinition sprite : defs) + { + sprites.put(sprite.getId(), sprite); + } } } - public List getSprites() + public Collection getSprites() { - return sprites; + return Collections.unmodifiableCollection(sprites.values()); + } + + public SpriteDefinition findSprite(int spriteId, int frameId) + { + for (SpriteDefinition sprite : sprites.get(spriteId)) + { + if (sprite.getFrame() == frameId) + { + return sprite; + } + } + return null; + } + + public BufferedImage getSpriteImage(SpriteDefinition sprite) + { + BufferedImage image = new BufferedImage(sprite.getWidth(), sprite.getHeight(), BufferedImage.TYPE_INT_ARGB); + image.setRGB(0, 0, sprite.getWidth(), sprite.getHeight(), sprite.getPixels(), 0, sprite.getWidth()); + return image; } public void export(File outDir) throws IOException { - for (SpriteDefinition sprite : sprites) + for (SpriteDefinition sprite : sprites.values()) { // I don't know why this happens if (sprite.getHeight() <= 0 || sprite.getWidth() <= 0) diff --git a/cache/src/main/java/net/runelite/cache/definitions/ObjectDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/ObjectDefinition.java index b7dc1d4744..44ba1189fb 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/ObjectDefinition.java +++ b/cache/src/main/java/net/runelite/cache/definitions/ObjectDefinition.java @@ -37,7 +37,7 @@ public class ObjectDefinition private int[] objectModels; private int[] objectTypes; private short[] recolorToFind; - private int mapIconID = -1; + private int mapAreaId = -1; private short[] textureToReplace; private int sizeX = 1; private int sizeY = 1; @@ -154,14 +154,14 @@ public class ObjectDefinition this.recolorToFind = recolorToFind; } - public int getMapIconID() + public int getMapAreaId() { - return mapIconID; + return mapAreaId; } - public void setMapIconID(int mapIconID) + public void setMapAreaId(int mapAreaId) { - this.mapIconID = mapIconID; + this.mapAreaId = mapAreaId; } public short[] getTextureToReplace() diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/ObjectLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/ObjectLoader.java index ac191b9893..edd038a995 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/loaders/ObjectLoader.java +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/ObjectLoader.java @@ -59,7 +59,7 @@ public class ObjectLoader private void processOp(int opcode, ObjectDefinition def, InputStream is) { - if (1 == opcode) + if (opcode == 1) { int length = is.readUnsignedByte(); if (length > 0) @@ -101,7 +101,7 @@ public class ObjectLoader { def.setSizeX(is.readUnsignedByte()); } - else if (15 == opcode) + else if (opcode == 15) { def.setSizeY(is.readUnsignedByte()); } @@ -122,7 +122,7 @@ public class ObjectLoader { def.setAnInt2105(0); } - else if (22 == opcode) + else if (opcode == 22) { def.setNonFlatShading(false); } @@ -130,7 +130,7 @@ public class ObjectLoader { def.setaBool2111(true); } - else if (24 == opcode) + else if (opcode == 24) { def.setAnimationID(is.readUnsignedShort()); if (def.getAnimationID() == 0xFFFF) @@ -193,7 +193,7 @@ public class ObjectLoader def.setRetextureToFind(retextureToFind); def.setTextureToReplace(textureToReplace); } - else if (62 == opcode) + else if (opcode == 62) { def.setIsRotated(true); } @@ -209,7 +209,7 @@ public class ObjectLoader { def.setModelSizeHeight(is.readUnsignedShort()); } - else if (67 == opcode) + else if (opcode == 67) { def.setModelSizeY(is.readUnsignedShort()); } @@ -221,7 +221,7 @@ public class ObjectLoader { is.readByte(); } - else if (70 == opcode) + else if (opcode == 70) { def.setOffsetX(is.readUnsignedShort()); } @@ -303,7 +303,7 @@ public class ObjectLoader } else if (opcode == 82) { - def.setMapIconID(is.readUnsignedShort()); + def.setMapAreaId(is.readUnsignedShort()); } else if (opcode == 92) { diff --git a/cache/src/test/java/net/runelite/cache/AreaDumper.java b/cache/src/test/java/net/runelite/cache/AreaDumper.java index 079730ac25..b789d78a0d 100644 --- a/cache/src/test/java/net/runelite/cache/AreaDumper.java +++ b/cache/src/test/java/net/runelite/cache/AreaDumper.java @@ -31,10 +31,6 @@ import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import net.runelite.cache.definitions.AreaDefinition; -import net.runelite.cache.definitions.loaders.AreaLoader; -import net.runelite.cache.fs.Archive; -import net.runelite.cache.fs.FSFile; -import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Store; import org.junit.Rule; import org.junit.Test; @@ -63,15 +59,12 @@ public class AreaDumper { store.load(); - Index index = store.getIndex(IndexType.CONFIGS); - Archive archive = index.getArchive(ConfigType.AREA.getId()); + AreaManager areaManager = new AreaManager(store); + areaManager.load(); - for (FSFile file : archive.getFiles()) + for (AreaDefinition area : areaManager.getAreas()) { - AreaLoader loader = new AreaLoader(); - AreaDefinition area = loader.load(file.getContents(), file.getFileId()); - - Files.write(gson.toJson(area), new File(outDir, file.getFileId() + ".json"), Charset.defaultCharset()); + Files.write(gson.toJson(area), new File(outDir, area.id + ".json"), Charset.defaultCharset()); ++count; } }