From c4bee1127c0fe4b7cf0c86213d9522b7003d48ba Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 28 Dec 2017 21:07:24 -0500 Subject: [PATCH] cache: add map and location definition, convert Region loading to use it --- .../definitions/LocationsDefinition.java | 38 ++++ .../cache/definitions/MapDefinition.java | 51 ++++++ .../definitions/loaders/LocationsLoader.java | 73 ++++++++ .../cache/definitions/loaders/MapLoader.java | 91 ++++++++++ .../cache/definitions/savers/MapSaver.java | 74 ++++++++ .../net/runelite/cache/region/Location.java | 83 +-------- .../net/runelite/cache/region/Region.java | 163 +++++++----------- .../runelite/cache/region/RegionLoader.java | 13 +- .../net/runelite/cache/MapDumperTest.java | 48 ++++-- .../net/runelite/modelviewer/ModelViewer.java | 12 +- 10 files changed, 444 insertions(+), 202 deletions(-) create mode 100644 cache/src/main/java/net/runelite/cache/definitions/LocationsDefinition.java create mode 100644 cache/src/main/java/net/runelite/cache/definitions/MapDefinition.java create mode 100644 cache/src/main/java/net/runelite/cache/definitions/loaders/LocationsLoader.java create mode 100644 cache/src/main/java/net/runelite/cache/definitions/loaders/MapLoader.java create mode 100644 cache/src/main/java/net/runelite/cache/definitions/savers/MapSaver.java diff --git a/cache/src/main/java/net/runelite/cache/definitions/LocationsDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/LocationsDefinition.java new file mode 100644 index 0000000000..435cdd4746 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/LocationsDefinition.java @@ -0,0 +1,38 @@ +/* + * 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.definitions; + +import java.util.ArrayList; +import java.util.List; +import lombok.Data; +import net.runelite.cache.region.Location; + +@Data +public class LocationsDefinition +{ + private int regionX; + private int regionY; + private List locations = new ArrayList<>(); +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/MapDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/MapDefinition.java new file mode 100644 index 0000000000..b695b24cbe --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/MapDefinition.java @@ -0,0 +1,51 @@ +/* + * 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.definitions; + +import lombok.Data; + +@Data +public class MapDefinition +{ + public static final int X = 64; + public static final int Y = 64; + public static final int Z = 4; + + @Data + public static class Tile + { + public Integer height; + public int attrOpcode; + public byte settings; + public byte overlayId; + public byte overlayPath; + public byte overlayRotation; + public byte underlayId; + } + + private int regionX; + private int regionY; + private Tile[][][] tiles = new Tile[Z][X][Y]; +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/LocationsLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/LocationsLoader.java new file mode 100644 index 0000000000..4dfa2ab360 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/LocationsLoader.java @@ -0,0 +1,73 @@ +/* + * 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.definitions.loaders; + +import net.runelite.cache.definitions.LocationsDefinition; +import net.runelite.cache.io.InputStream; +import net.runelite.cache.region.Location; +import net.runelite.cache.region.Position; + +public class LocationsLoader +{ + public LocationsDefinition load(int regionX, int regionY, byte[] b) + { + LocationsDefinition loc = new LocationsDefinition(); + loc.setRegionX(regionX); + loc.setRegionY(regionY); + loadLocations(loc, b); + return loc; + } + + private void loadLocations(LocationsDefinition loc, byte[] b) + { + InputStream buf = new InputStream(b); + + int id = -1; + int idOffset; + + while ((idOffset = buf.readUnsignedShortSmart()) != 0) + { + id += idOffset; + + int position = 0; + int positionOffset; + + while ((positionOffset = buf.readUnsignedShortSmart()) != 0) + { + position += positionOffset - 1; + + int localY = position & 0x3F; + int localX = position >> 6 & 0x3F; + int height = position >> 12 & 0x3; + + int attributes = buf.readUnsignedByte(); + int type = attributes >> 2; + int orientation = attributes & 0x3; + + loc.getLocations().add(new Location(id, type, orientation, new Position(localX, localY, height))); + } + } + } +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/MapLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/MapLoader.java new file mode 100644 index 0000000000..3224536388 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/MapLoader.java @@ -0,0 +1,91 @@ +/* + * 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.definitions.loaders; + +import net.runelite.cache.definitions.MapDefinition; +import net.runelite.cache.definitions.MapDefinition.Tile; +import net.runelite.cache.io.InputStream; +import static net.runelite.cache.region.Region.X; +import static net.runelite.cache.region.Region.Y; +import static net.runelite.cache.region.Region.Z; + +public class MapLoader +{ + public MapDefinition load(int regionX, int regionY, byte[] b) + { + MapDefinition map = new MapDefinition(); + map.setRegionX(regionX); + map.setRegionY(regionY); + loadTerrain(map, b); + return map; + } + + private void loadTerrain(MapDefinition map, byte[] buf) + { + Tile[][][] tiles = map.getTiles(); + + InputStream in = new InputStream(buf); + + for (int z = 0; z < Z; z++) + { + for (int x = 0; x < X; x++) + { + for (int y = 0; y < Y; y++) + { + Tile tile = tiles[z][x][y] = new Tile(); + while (true) + { + int attribute = in.readUnsignedByte(); + if (attribute == 0) + { + break; + } + else if (attribute == 1) + { + int height = in.readUnsignedByte(); + tile.height = height; + break; + } + else if (attribute <= 49) + { + tile.attrOpcode = attribute; + tile.overlayId = in.readByte(); + tile.overlayPath = (byte) ((attribute - 2) / 4); + tile.overlayRotation = (byte) (attribute - 2 & 3); + } + else if (attribute <= 81) + { + tile.settings = (byte) (attribute - 49); + } + else + { + tile.underlayId = (byte) (attribute - 81); + } + } + } + } + } + } +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/savers/MapSaver.java b/cache/src/main/java/net/runelite/cache/definitions/savers/MapSaver.java new file mode 100644 index 0000000000..855ccd413c --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/savers/MapSaver.java @@ -0,0 +1,74 @@ +/* + * 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.definitions.savers; + +import net.runelite.cache.definitions.MapDefinition; +import net.runelite.cache.definitions.MapDefinition.Tile; +import net.runelite.cache.io.OutputStream; +import static net.runelite.cache.region.Region.X; +import static net.runelite.cache.region.Region.Y; +import static net.runelite.cache.region.Region.Z; + +public class MapSaver +{ + public byte[] save(MapDefinition map) + { + Tile[][][] tiles = map.getTiles(); + OutputStream out = new OutputStream(); + for (int z = 0; z < Z; z++) + { + for (int x = 0; x < X; x++) + { + for (int y = 0; y < Y; y++) + { + Tile tile = tiles[z][x][y]; + if (tile.attrOpcode != 0) + { + out.writeByte(tile.attrOpcode); + out.writeByte(tile.overlayId); + } + if (tile.settings != 0) + { + out.writeByte(tile.settings + 49); + } + if (tile.underlayId != 0) + { + out.writeByte(tile.underlayId + 81); + } + if (tile.height == null) + { + out.writeByte(0); + } + else + { + out.writeByte(1); + out.writeByte(tile.height); + } + } + } + } + return out.flip(); + } +} diff --git a/cache/src/main/java/net/runelite/cache/region/Location.java b/cache/src/main/java/net/runelite/cache/region/Location.java index 5cb14fd0cc..7cf59f8e1c 100644 --- a/cache/src/main/java/net/runelite/cache/region/Location.java +++ b/cache/src/main/java/net/runelite/cache/region/Location.java @@ -25,92 +25,13 @@ package net.runelite.cache.region; -import java.util.Objects; +import lombok.Value; +@Value public class Location { private final int id; private final int type; private final int orientation; private final Position position; - - public Location(int id, int type, int orientation, Position position) - { - this.id = id; - this.type = type; - this.orientation = orientation; - this.position = position; - } - - @Override - public String toString() - { - return "GamwObject{" + "id=" + id + ", type=" + type + ", orientation=" + orientation + ", position=" + position + '}'; - } - - @Override - public int hashCode() - { - int hash = 5; - hash = 83 * hash + this.id; - hash = 83 * hash + this.type; - hash = 83 * hash + this.orientation; - hash = 83 * hash + Objects.hashCode(this.position); - return hash; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (getClass() != obj.getClass()) - { - return false; - } - final Location other = (Location) obj; - if (this.id != other.id) - { - return false; - } - if (this.type != other.type) - { - return false; - } - if (this.orientation != other.orientation) - { - return false; - } - if (!Objects.equals(this.position, other.position)) - { - return false; - } - return true; - } - - public int getId() - { - return id; - } - - public int getType() - { - return type; - } - - public int getOrientation() - { - return orientation; - } - - public Position getPosition() - { - return position; - } } diff --git a/cache/src/main/java/net/runelite/cache/region/Region.java b/cache/src/main/java/net/runelite/cache/region/Region.java index 8b746ae33d..7dbda27534 100644 --- a/cache/src/main/java/net/runelite/cache/region/Region.java +++ b/cache/src/main/java/net/runelite/cache/region/Region.java @@ -1,35 +1,35 @@ -/** - * Copyright (c) 2015 Kyle Friz +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. + * 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. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * 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.region; import java.util.ArrayList; import java.util.List; -import net.runelite.cache.io.InputStream; +import net.runelite.cache.definitions.LocationsDefinition; +import net.runelite.cache.definitions.MapDefinition; +import net.runelite.cache.definitions.MapDefinition.Tile; -/** - * - * @author Kyle Friz - * @since Jun 30, 2015 - */ public class Region { @@ -42,7 +42,7 @@ public class Region private final int baseY; private final int[][][] tileHeights = new int[Z][X][Y]; - private final byte[][][] renderRules = new byte[Z][X][Y]; + private final byte[][][] tileSettings = new byte[Z][X][Y]; private final byte[][][] overlayIds = new byte[Z][X][Y]; private final byte[][][] overlayPaths = new byte[Z][X][Y]; private final byte[][][] overlayRotations = new byte[Z][X][Y]; @@ -64,99 +64,66 @@ public class Region this.baseY = y << 6; } - public void loadTerrain(byte[] buf) + public void loadTerrain(MapDefinition map) { - InputStream in = new InputStream(buf); - + Tile[][][] tiles = map.getTiles(); for (int z = 0; z < Z; z++) { for (int x = 0; x < X; x++) { for (int y = 0; y < Y; y++) { - while (true) + Tile tile = tiles[z][x][y]; + + if (tile.height == null) { - int attribute = in.readUnsignedByte(); - if (attribute == 0) + if (z == 0) { - if (z == 0) - { - tileHeights[0][x][y] = -HeightCalc.calculate(baseX + x + 0xe3b7b, baseY + y + 0x87cce) * 8; - } - else - { - tileHeights[z][x][y] = tileHeights[z - 1][x][y] - 240; - } - - break; - } - else if (attribute == 1) - { - int height = in.readUnsignedByte(); - if (height == 1) - { - height = 0; - } - - if (z == 0) - { - tileHeights[0][x][y] = -height * 8; - } - else - { - tileHeights[z][x][y] = tileHeights[z - 1][x][y] - height * 8; - } - - break; - } - else if (attribute <= 49) - { - overlayIds[z][x][y] = in.readByte(); - overlayPaths[z][x][y] = (byte) ((attribute - 2) / 4); - overlayRotations[z][x][y] = (byte) (attribute - 2 & 3); - } - else if (attribute <= 81) - { - renderRules[z][x][y] = (byte) (attribute - 49); + tileHeights[0][x][y] = -HeightCalc.calculate(baseX + x + 0xe3b7b, baseY + y + 0x87cce) * 8; } else { - underlayIds[z][x][y] = (byte) (attribute - 81); + tileHeights[z][x][y] = tileHeights[z - 1][x][y] - 240; } } + else + { + int height = tile.getHeight(); + if (height == 1) + { + height = 0; + } + + if (z == 0) + { + tileHeights[0][x][y] = -height * 8; + } + else + { + tileHeights[z][x][y] = tileHeights[z - 1][x][y] - height * 8; + } + } + + overlayIds[z][x][y] = tile.getOverlayId(); + overlayPaths[z][x][y] = tile.getOverlayPath(); + overlayRotations[z][x][y] = tile.getOverlayRotation(); + + tileSettings[z][x][y] = tile.getSettings(); + underlayIds[z][x][y] = tile.getUnderlayId(); } } } } - public void loadLocations(byte[] b) + public void loadLocations(LocationsDefinition locs) { - InputStream buf = new InputStream(b); - - int id = -1; - int idOffset; - - while ((idOffset = buf.readUnsignedShortSmart()) != 0) + for (Location loc : locs.getLocations()) { - id += idOffset; - - int position = 0; - int positionOffset; - - while ((positionOffset = buf.readUnsignedShortSmart()) != 0) - { - position += positionOffset - 1; - - int localY = position & 0x3F; - int localX = position >> 6 & 0x3F; - int height = position >> 12 & 0x3; - - int attributes = buf.readUnsignedByte(); - int type = attributes >> 2; - int orientation = attributes & 0x3; - - locations.add(new Location(id, type, orientation, new Position(getBaseX() + localX, getBaseY() + localY, height))); - } + Location newLoc = new Location(loc.getId(), loc.getType(), loc.getOrientation(), + new Position(getBaseX() + loc.getPosition().getX(), + getBaseY() + loc.getPosition().getY(), + loc.getPosition().getZ())); + locations.add(newLoc); } } @@ -180,9 +147,9 @@ public class Region return tileHeights[z][x][y]; } - public byte getRenderRule(int z, int x, int y) + public byte getTileSetting(int z, int x, int y) { - return renderRules[z][x][y]; + return tileSettings[z][x][y]; } public int getOverlayId(int z, int x, int y) diff --git a/cache/src/main/java/net/runelite/cache/region/RegionLoader.java b/cache/src/main/java/net/runelite/cache/region/RegionLoader.java index 6395ccc707..cc346a9265 100644 --- a/cache/src/main/java/net/runelite/cache/region/RegionLoader.java +++ b/cache/src/main/java/net/runelite/cache/region/RegionLoader.java @@ -28,6 +28,10 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import net.runelite.cache.IndexType; +import net.runelite.cache.definitions.LocationsDefinition; +import net.runelite.cache.definitions.MapDefinition; +import net.runelite.cache.definitions.loaders.LocationsLoader; +import net.runelite.cache.definitions.loaders.MapLoader; import net.runelite.cache.fs.Archive; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Storage; @@ -64,7 +68,9 @@ public class RegionLoader { Region region = this.loadRegionFromArchive(i); if (region != null) + { regions.add(region); + } } } @@ -86,8 +92,10 @@ public class RegionLoader byte[] data = map.decompress(storage.loadArchive(map)); + MapDefinition mapDef = new MapLoader().load(x, y, data); + Region region = new Region(i); - region.loadTerrain(data); + region.loadTerrain(mapDef); int[] keys = keyManager.getKeys(i); if (keys != null) @@ -95,7 +103,8 @@ public class RegionLoader try { data = land.decompress(storage.loadArchive(land), keys); - region.loadLocations(data); + LocationsDefinition locDef = new LocationsLoader().load(x, y, data); + region.loadLocations(locDef); } catch (IOException ex) { diff --git a/cache/src/test/java/net/runelite/cache/MapDumperTest.java b/cache/src/test/java/net/runelite/cache/MapDumperTest.java index 91395b0bcd..163ab2932d 100644 --- a/cache/src/test/java/net/runelite/cache/MapDumperTest.java +++ b/cache/src/test/java/net/runelite/cache/MapDumperTest.java @@ -29,14 +29,19 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import net.runelite.cache.definitions.LocationsDefinition; +import net.runelite.cache.definitions.MapDefinition; +import net.runelite.cache.definitions.loaders.LocationsLoader; +import net.runelite.cache.definitions.loaders.MapLoader; import net.runelite.cache.fs.Archive; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Storage; import net.runelite.cache.fs.Store; -import net.runelite.cache.region.Region; import net.runelite.cache.util.XteaKeyManager; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -53,9 +58,8 @@ public class MapDumperTest @Rule public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); - private final List regions = new ArrayList<>(); - - //@Test + @Test + @Ignore public void dumpRaw() throws IOException { File base = StoreLocation.LOCATION, @@ -111,8 +115,9 @@ public class MapDumperTest } } - private void loadRegions(Store store) throws IOException + private Map loadRegions(Store store) throws IOException { + Map mapMap = new HashMap<>(); Storage storage = store.getStorage(); Index index = store.getIndex(IndexType.MAPS); XteaKeyManager keyManager = new XteaKeyManager(); @@ -134,9 +139,8 @@ public class MapDumperTest } byte[] data = map.decompress(storage.loadArchive(map)); - - Region region = new Region(i); - region.loadTerrain(data); + MapDefinition mapDef = new MapLoader().load(x, y, data); + LocationsDefinition locDef = null; int[] keys = keyManager.getKeys(i); if (keys != null) @@ -150,11 +154,13 @@ public class MapDumperTest continue; } - region.loadLocations(data); + locDef = new LocationsLoader().load(x, y, data); } - regions.add(region); + mapMap.put(mapDef, locDef); } + + return mapMap; } @Test @@ -167,16 +173,20 @@ public class MapDumperTest { store.load(); - loadRegions(store); + Map regions = loadRegions(store); - for (Region region : regions) + for (Entry entry : regions.entrySet()) { - if (region.getLocations().isEmpty()) - { - continue; - } + MapDefinition key = entry.getKey(); + LocationsDefinition value = entry.getValue(); - Files.write(gson.toJson(region).getBytes(), new File(outDir, region.getBaseX() + "_" + region.getBaseY() + ".json")); + int x = key.getRegionX(); + int y = key.getRegionY(); + Files.write(gson.toJson(key).getBytes(), new File(outDir, "m" + x + "_" + y + ".json")); + if (value != null) + { + Files.write(gson.toJson(value).getBytes(), new File(outDir, "l" + x + "_" + y + ".json")); + } } } diff --git a/model-viewer/src/main/java/net/runelite/modelviewer/ModelViewer.java b/model-viewer/src/main/java/net/runelite/modelviewer/ModelViewer.java index d8fc9d6058..51d180df3c 100644 --- a/model-viewer/src/main/java/net/runelite/modelviewer/ModelViewer.java +++ b/model-viewer/src/main/java/net/runelite/modelviewer/ModelViewer.java @@ -39,12 +39,16 @@ import java.util.List; import java.util.Map; import javax.imageio.ImageIO; import net.runelite.cache.definitions.KitDefinition; +import net.runelite.cache.definitions.LocationsDefinition; +import net.runelite.cache.definitions.MapDefinition; import net.runelite.cache.definitions.ModelDefinition; import net.runelite.cache.definitions.NpcDefinition; import net.runelite.cache.definitions.ObjectDefinition; import net.runelite.cache.definitions.OverlayDefinition; import net.runelite.cache.definitions.TextureDefinition; import net.runelite.cache.definitions.UnderlayDefinition; +import net.runelite.cache.definitions.loaders.LocationsLoader; +import net.runelite.cache.definitions.loaders.MapLoader; import net.runelite.cache.models.Vector3f; import net.runelite.cache.models.VertexNormal; import net.runelite.cache.region.Location; @@ -163,17 +167,21 @@ public class ModelViewer int x = Integer.parseInt(s[0]), y = Integer.parseInt(s[1]); region = new Region(x, y); + MapLoader mapLoader = new MapLoader(); + LocationsLoader locationsLoader = new LocationsLoader(); try (FileInputStream fin = new FileInputStream(mapdir + "/m" + x + "_" + y + ".dat")) { byte[] b = IOUtils.toByteArray(fin); - region.loadTerrain(b); + MapDefinition mapDef = mapLoader.load(x, y, b); + region.loadTerrain(mapDef); } try (FileInputStream fin = new FileInputStream(mapdir + "/l" + x + "_" + y + ".dat")) { byte[] b = IOUtils.toByteArray(fin); - region.loadLocations(b); + LocationsDefinition locDef = locationsLoader.load(x, y, b); + region.loadLocations(locDef); } catch (FileNotFoundException ex) {