RuneHive-Tarnish
Neural OSRS Enhancement Framework
Loading...
Searching...
No Matches
RegionDecoder.java
1package com.osroyale.fs.cache.decoder;
2
3import com.osroyale.fs.cache.Cache;
4import com.osroyale.fs.cache.FileSystem;
5import com.osroyale.fs.util.ByteBufferUtil;
6import com.osroyale.fs.util.CompressionUtil;
7import com.osroyale.game.world.World;
8import com.osroyale.game.world.object.*;
9import com.osroyale.game.world.pathfinding.TraversalMap;
10import com.osroyale.game.world.position.Position;
11import com.osroyale.game.world.region.Region;
12import com.osroyale.game.world.region.RegionDefinition;
13import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
14import it.unimi.dsi.fastutil.ints.IntSet;
15import org.apache.logging.log4j.LogManager;
16import org.apache.logging.log4j.Logger;
17
18import java.nio.ByteBuffer;
19import java.util.Optional;
20import java.util.concurrent.atomic.AtomicInteger;
21
59
60* A class which parses static object definitions, which include tool.mapviewer
61 * tiles and landscapes.
62 *
63 * @author Ryley Kimmel <ryley.kimmel@live.com>
64 * @author Artem Batutin <artembatutin@gmail.com>
65 */
66public final class RegionDecoder implements Runnable {
67
68 private static final Logger LOGGER = LogManager.getLogger(RegionDecoder.class);
69
73 private final FileSystem fs;
74
78 private final AtomicInteger decoded = new AtomicInteger();
79
83 private final AtomicInteger errors = new AtomicInteger();
84
91 this.fs = fs;
92 }
93
94 @Override
95 public void run() {
96 LOGGER.info("Loading regional map data.");
97 final Cache mapIndex = fs.getCache(FileSystem.MAP_INDEX);
99 .values()
100 .forEach(def -> load(mapIndex, def));
101 LOGGER.info("Loaded " + decoded + " regions, skipped " + errors + " maps.");
102 }
103
104 public void load(final Cache mapIndex, final RegionDefinition def) {
105 final int hash = def.getHash();
106 final int x = (hash >> 8 & 0xFF) << 6;
107 final int y = (hash & 0xFF) << 6;
108 try {
109 final Region region = World.getRegions().getRegion(x, y);
110
111 ByteBuffer terrainData = mapIndex.get(def.getTerrainFile());
112 if (terrainData == null) {
113 errors.getAndIncrement();
114 return;
115 }
116 ByteBuffer terrainBuffer = ByteBuffer.wrap(CompressionUtil.gunzip(terrainData.array()));
117
118 final IntSet downHeights = new IntOpenHashSet();
119
120 parseTerrain(region, terrainBuffer, downHeights);
121
122 ByteBuffer gameObjectData = mapIndex.get(def.getObjectFile());
123 if (gameObjectData == null) {
124 errors.getAndIncrement();
125 return;
126 }
127 ByteBuffer gameObjectBuffer = ByteBuffer.wrap(CompressionUtil.gunzip(gameObjectData.array()));
128 parseGameObject(region, gameObjectBuffer, x, y, downHeights);
129
130 decoded.getAndIncrement();
131 } catch (Exception e) {
132 e.printStackTrace();
133 errors.getAndIncrement();
134 }
135 }
136
144 private void parseGameObject(Region region, ByteBuffer buf, int x, int y, IntSet downHeights) {
145 int objId = -1;
146 while (true) {
147 int objIdOffset = ByteBufferUtil.getSmart(buf);
148 if (objIdOffset == 0) break;
149
150 objId += objIdOffset;
151 int objPosInfo = 0;
152
153 while (true) {
154 int objPosInfoOffset = ByteBufferUtil.getSmart(buf);
155 if (objPosInfoOffset == 0) break;
156 objPosInfo += objPosInfoOffset - 1;
157
158 int objOtherInfo = buf.get() & 0xFF;
159 int localY = objPosInfo & 0x3f;
160 int localX = objPosInfo >> 6 & 0x3f;
161 int height = objPosInfo >> 12 & 0x3;
162
163 Optional<ObjectType> type = ObjectType.valueOf(objOtherInfo >> 2);
164 Optional<ObjectDirection> face = ObjectDirection.valueOf(objOtherInfo & 0x3);
165
166 if (downHeights.contains(Position.hash(localX, localY, 1))) {
167 if (--height < 0) continue;
168 } else if (downHeights.contains(Position.hash(localX, localY, height))) {
169 height--;
170 }
171
172 if (!type.isPresent() || !face.isPresent()) {
173 continue;
174 }
175
176 Position pos = new Position(localX + x, localY + y, height);
177 GameObjectDefinition def = GameObjectDefinition.forId(objId);
178
179 if (def == null)
180 continue;
181
182 StaticGameObject staticObject = new StaticGameObject(def, pos, type.get(), face.get());
183
184 if (Region.SKIPPED_OBJECTS.contains(pos)) {
185 region.skip(staticObject);
186 } else {
187 TraversalMap.markObject(region, staticObject, true, true);
188 }
189 }
190 }
191 }
192
198 private void parseTerrain(Region region, ByteBuffer mapBuffer, IntSet downHeights) {
199 int[][][] attributes = new int[4][64][64];
200
201 for (int height = 0; height < 4; height++) {
202 for (int localX = 0; localX < 64; localX++) {
203 for (int localY = 0; localY < 64; localY++) {
204 while (true) {
205 int attributeId = mapBuffer.getShort() & 0xFFFF;
206 if (attributeId == 0) {
207 break;
208 }
209 if (attributeId == 1) {
210 int tileHeight = mapBuffer.get() & 0xFF;
211 break;
212 }
213 if (attributeId <= 49) {
214 int overlayId = mapBuffer.getShort() & 0xFFFF;
215 } else if (attributeId <= 81) {
216 attributes[height][localX][localY] = attributeId - 49;
217 }
218 }
219 }
220 }
221 }
222
223 for (int height = 0; height < 4; height++) {
224 for (int localX = 0; localX < 64; localX++) {
225 for (int localY = 0; localY < 64; localY++) {
226
227 if ((attributes[height][localX][localY] & 2) == 2) {
228 downHeights.add(Position.hash(localX, localY, height));
229 }
230
231 if ((attributes[height][localX][localY] & 1) == 1) {
232 int plane = height;
233
234 if ((attributes[1][localX][localY] & 2) == 2) {
235 downHeights.add(Position.hash(localX, localY, 1));
236 plane--;
237 }
238
239 if (plane >= 0) {
240 TraversalMap.block(region, plane, localX, localY);
241 }
242 }
243 }
244 }
245 }
246 }
247
248}
ByteBuffer get(final int indexId)
Definition Cache.java:109
static Int2ObjectMap< RegionDefinition > getDefinitions()