68 private static final Logger LOGGER = LogManager.getLogger(
RegionDecoder.class);
78 private final AtomicInteger decoded =
new AtomicInteger();
83 private final AtomicInteger errors =
new AtomicInteger();
96 LOGGER.info(
"Loading regional map data.");
100 .forEach(def -> load(mapIndex, def));
101 LOGGER.info(
"Loaded " + decoded +
" regions, skipped " + errors +
" maps.");
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;
111 ByteBuffer terrainData = mapIndex.
get(def.getTerrainFile());
112 if (terrainData ==
null) {
113 errors.getAndIncrement();
116 ByteBuffer terrainBuffer = ByteBuffer.wrap(CompressionUtil.gunzip(terrainData.array()));
118 final IntSet downHeights =
new IntOpenHashSet();
120 parseTerrain(region, terrainBuffer, downHeights);
122 ByteBuffer gameObjectData = mapIndex.
get(def.getObjectFile());
123 if (gameObjectData ==
null) {
124 errors.getAndIncrement();
127 ByteBuffer gameObjectBuffer = ByteBuffer.wrap(CompressionUtil.gunzip(gameObjectData.array()));
128 parseGameObject(region, gameObjectBuffer, x, y, downHeights);
130 decoded.getAndIncrement();
131 }
catch (Exception e) {
133 errors.getAndIncrement();
144 private void parseGameObject(Region region, ByteBuffer buf,
int x,
int y, IntSet downHeights) {
147 int objIdOffset = ByteBufferUtil.getSmart(buf);
148 if (objIdOffset == 0)
break;
150 objId += objIdOffset;
154 int objPosInfoOffset = ByteBufferUtil.getSmart(buf);
155 if (objPosInfoOffset == 0)
break;
156 objPosInfo += objPosInfoOffset - 1;
158 int objOtherInfo = buf.get() & 0xFF;
159 int localY = objPosInfo & 0x3f;
160 int localX = objPosInfo >> 6 & 0x3f;
161 int height = objPosInfo >> 12 & 0x3;
163 Optional<ObjectType> type = ObjectType.valueOf(objOtherInfo >> 2);
164 Optional<ObjectDirection> face = ObjectDirection.valueOf(objOtherInfo & 0x3);
166 if (downHeights.contains(Position.hash(localX, localY, 1))) {
167 if (--height < 0)
continue;
168 }
else if (downHeights.contains(Position.hash(localX, localY, height))) {
172 if (!type.isPresent() || !face.isPresent()) {
176 Position pos =
new Position(localX + x, localY + y, height);
177 GameObjectDefinition def = GameObjectDefinition.forId(objId);
182 StaticGameObject staticObject =
new StaticGameObject(def, pos, type.get(), face.get());
184 if (Region.SKIPPED_OBJECTS.contains(pos)) {
185 region.skip(staticObject);
187 TraversalMap.markObject(region, staticObject,
true,
true);
198 private void parseTerrain(Region region, ByteBuffer mapBuffer, IntSet downHeights) {
199 int[][][] attributes =
new int[4][64][64];
201 for (
int height = 0; height < 4; height++) {
202 for (
int localX = 0; localX < 64; localX++) {
203 for (
int localY = 0; localY < 64; localY++) {
205 int attributeId = mapBuffer.getShort() & 0xFFFF;
206 if (attributeId == 0) {
209 if (attributeId == 1) {
210 int tileHeight = mapBuffer.get() & 0xFF;
213 if (attributeId <= 49) {
214 int overlayId = mapBuffer.getShort() & 0xFFFF;
215 }
else if (attributeId <= 81) {
216 attributes[height][localX][localY] = attributeId - 49;
223 for (
int height = 0; height < 4; height++) {
224 for (
int localX = 0; localX < 64; localX++) {
225 for (
int localY = 0; localY < 64; localY++) {
227 if ((attributes[height][localX][localY] & 2) == 2) {
228 downHeights.add(Position.hash(localX, localY, height));
231 if ((attributes[height][localX][localY] & 1) == 1) {
234 if ((attributes[1][localX][localY] & 2) == 2) {
235 downHeights.add(Position.hash(localX, localY, 1));
240 TraversalMap.block(region, plane, localX, localY);