Created
December 7, 2023 22:31
-
-
Save ekmillard/e8400a2ed2b8f0dc0c24586e529ace30 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ps.eden.server.cache.editor.emperor.wm; | |
import java.io.IOException; | |
import java.nio.ByteBuffer; | |
import java.util.ArrayList; | |
import java.util.List; | |
import ps.eden.server.ServerConstants; | |
import ps.eden.server.cache.editor.dragonkk.store.Store; | |
import ps.eden.server.cache.editor.dragonkk.tools.clientCacheUpdater.RSXteas; | |
import ps.eden.server.cache.editor.dragonkk.utils.ByteBufferUtils; | |
import ps.eden.server.cache.editor.mgi.tools.rseditor.core.cache.Cache; | |
import ps.eden.server.cache.editor.mgi.tools.rseditor.core.cache.File; | |
import ps.eden.server.cache.editor.mgi.tools.rseditor.core.cache.Folder; | |
import static ps.eden.server.ServerConstants.CUSTOM_ISLAND_NAME; | |
/** | |
* Used for packing new regions on the world map (not "game map"). | |
* | |
* @author Emperor - mostly everything | |
* @author Clayton Williams - just finishing up some wall icons and piers //TODO pier walls | |
*/ | |
public final class WorldMapPacker { | |
/** | |
* The cache index. | |
*/ | |
private static final int INDEX = 23; | |
/** | |
* The world map planes available. | |
*/ | |
private static List<WorldMapPlane> planes = new ArrayList<>(); | |
/** | |
* The main method, sets things going. | |
* | |
* @param args The arguments cast on runtime. | |
*/ | |
public static void main(String[] args) { | |
long time = System.currentTimeMillis(); | |
Cache cache = Cache.openCache(ServerConstants.CACHE_530_DIR); | |
if (false) { | |
parseWorldMap(cache); | |
System.out.println("Took = "+(System.currentTimeMillis() - time)); | |
return; | |
} | |
//RSXteas.loadUnpackedXteas(store.getRevision()); | |
//store.getIndexes()[23].packIndex(new Store("./old530/", 530)); | |
//if (true) | |
// return; | |
//parseWorldMap(new Store("./530/", 530)); | |
//parseDetails(cache); | |
//planes.get(0).setName(ServerConstants.GAME_NAME + " surface"); | |
//3968, 3521 | |
//planes.clear(); | |
cache.getFilesSystem(INDEX).deleteAllFolders(); | |
WorldMapPlane plane = new WorldMapPlane(ServerConstants.GAME_NAME + " surface", "main"); | |
//3087, 3502 | |
plane.setCenterX(3087 >> 6); | |
plane.setCenterY(3502 >> 6); | |
plane.setVisible(true); | |
/*plane.addBoundaries(new ZoneBorders(2800, 2900, 4000, 3932)); | |
plane.addBoundaries(new ZoneBorders(2100, 2500, 3428, 4132)); | |
plane.addBoundaries(new ZoneBorders(3428, 2500, 4031, 3642)); | |
plane.addBoundaries(new ZoneBorders(1799, 2463, 2268, 4885));*/ | |
// below is the ENTIRE visible map region on world map - will take longest but the BEST results! :) | |
//plane.addBoundaries(new ZoneBorders(1158, 2111, 4857, 5654)); | |
plane.addBoundaries(new ZoneBorders(2800, 2900, 4000, 3932)); | |
plane.setDefault(cache); | |
/*plane.getDetails().add(new RegionDetails(CUSTOM_ISLAND_NAME, (byte) 8, 3968, 3518, -1)); | |
plane.getDetails().add(new RegionDetails("Donator Islands", (byte) 8, 3918, 3585, -1)); | |
plane.getDetails().add(new RegionDetails("Deadman Island", (byte) 8, 2962, 2787, -1)); | |
plane.getDetails().add(new RegionDetails("Resource Area", (byte) 8, 3188, 3934, -1)); | |
plane.getDetails().add(new RegionDetails("Wilderness Hub", (byte) 8, 3043, 3768, -1));*/ | |
planes.add(plane); | |
packWMPlane(planes.get(0), cache); | |
packDetails(cache); | |
System.out.println("Took = "+(System.currentTimeMillis() - time)); | |
try { | |
cache.close(); | |
} catch (Throwable t) { | |
System.err.println("Failed 2 complete write"); | |
t.printStackTrace(); | |
} | |
} | |
/** | |
* Parses all world map information. | |
* | |
* @param cache The store. | |
*/ | |
private static void parseWorldMap(Cache cache) { | |
parseDetails(cache); | |
for (WorldMapPlane plane : planes) { | |
parseWMPlane(cache, plane); | |
} | |
} | |
/** | |
* Parses the world map details. | |
* | |
* @param cache The store. | |
*/ | |
private static void parseDetails(Cache cache) { | |
if (cache.getIndicesCount() <= INDEX) { | |
throw new IllegalStateException("No world map cache file found! Amount of files: " + cache.getIndicesCount()); | |
} | |
Folder archiveId = cache.getFilesSystem(INDEX).findFolderByName("details"); | |
if (archiveId == null) { | |
System.err.println("No world map details found!"); | |
return; | |
} | |
int length = archiveId.filesCount(); | |
for (int i = 0; i < length; i++) { | |
File file = archiveId.findFileByID(i); | |
if (file == null) { | |
System.err.println("World map plane " + i + " is invalid!"); | |
continue; | |
} | |
ByteBuffer buffer = ByteBuffer.wrap(file.getData().getBuffer()); | |
String archive = ByteBufferUtils.getString(buffer); | |
String name = ByteBufferUtils.getString(buffer); | |
int regionX = buffer.getShort(); | |
int regionY = buffer.getShort(); | |
int value = buffer.getInt(); //? | |
boolean visible = buffer.get() == 1; //? | |
int type = buffer.get(); //? | |
WorldMapPlane plane = new WorldMapPlane(name, archive); | |
plane.setCenterX(regionX); | |
plane.setCenterY(regionY); | |
plane.setVisible(visible); | |
plane.setType(type); | |
plane.setValue(value); | |
planes.add(plane); | |
int amount = buffer.get() & 0xFF; | |
for (int j = 0; j < amount; j++) { | |
plane.addBoundaries(new ZoneBorders(buffer.getShort(), buffer.getShort(), buffer.getShort(), buffer.getShort())); | |
} | |
System.out.println("Found plane id: " + i + ", name: " + name + ", archive: " + archive + ", center loc: [" + regionX + "," + regionY + "], zones (" + amount + "): " + plane.getBoundaries() + "."); | |
} | |
} | |
/** | |
* Parses the world map details. | |
* | |
* @param cache The store. | |
*/ | |
private static void packDetails(Cache cache) { | |
if (cache.getIndicesCount() <= INDEX) { | |
throw new IllegalStateException("No world map cache file found! Amount of files: " + cache.getIndicesCount()); | |
} | |
Folder archiveId = cache.getFilesSystem(INDEX).findFolderByName("details"); | |
if (archiveId == null) { | |
archiveId = new Folder("details", new File[] {}); | |
} | |
archiveId.deleteAllFiles(); | |
for (int i = 0; i < planes.size(); i++) { | |
WorldMapPlane plane = planes.get(i); | |
if (plane == null) { | |
System.err.println("World map plane " + i + " is invalid."); | |
continue; | |
} | |
ByteBuffer buffer = ByteBuffer.allocate(65535); | |
ByteBufferUtils.putString(plane.getArchive(), buffer); | |
ByteBufferUtils.putString(plane.getName(), buffer); | |
buffer.putShort((short) plane.getCenterX()); | |
buffer.putShort((short) plane.getCenterY()); | |
buffer.putInt(plane.getValue()); | |
buffer.put((byte) (plane.isVisible() ? 1 : 0)); | |
buffer.put((byte) plane.getType()); | |
buffer.put((byte) plane.getBoundaries().size()); | |
for (ZoneBorders z : plane.getBoundaries()) { | |
buffer.putShort((short) z.getSouthWestX()); | |
buffer.putShort((short) z.getSouthWestY()); | |
buffer.putShort((short) z.getNorthEastX()); | |
buffer.putShort((short) z.getNorthEastY()); | |
} | |
buffer.flip(); | |
byte[] bs = new byte[buffer.remaining()]; | |
buffer.get(bs); | |
archiveId.addFile(new File(new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs))); | |
System.out.println("Packed world map details for plane " + plane.getName() + "!"); | |
} | |
cache.getFilesSystem(INDEX).addFolder(archiveId); | |
} | |
/** | |
* Parses all data for a world map plane. | |
* | |
* @param cache The store to get the data from. | |
* @param plane The plane we're parsing. | |
*/ | |
private static void parseWMPlane(Cache cache, WorldMapPlane plane) { | |
parseUnderlay(cache, plane); | |
parseOverlay(cache, plane); | |
parseOverlay2(cache, plane); //Overlays above overlays, used for platforms you can walk on etc. | |
parseObjects(cache, plane); | |
parseLabels(cache, plane); | |
} | |
/** | |
* Packs data for a world map plane on the cache store. | |
* | |
* @param cache The store to pack on. | |
* @param plane The plane we're packing. | |
*/ | |
private static void packWMPlane(WorldMapPlane plane, Cache cache) { | |
try { | |
packUnderlay(cache, plane); | |
} catch (Throwable t) { | |
System.err.println("Failed 2 pack underlay"); | |
t.printStackTrace(); | |
} | |
try { | |
packOverlay(cache, plane); | |
} catch (Throwable t) { | |
System.err.println("Failed 2 pack overlay"); | |
t.printStackTrace(); | |
} | |
try { | |
packOverlay2(cache, plane); | |
} catch (Throwable t) { | |
System.err.println("Failed 2 pack overlay2"); | |
t.printStackTrace(); | |
} | |
try { | |
packObjects(cache, plane); | |
} catch (Throwable t) { | |
System.err.println("Failed 2 pack objects"); | |
t.printStackTrace(); | |
} | |
try { | |
packLabels(cache, plane); | |
} catch (Throwable t) { | |
System.err.println("Failed 2 pack labels"); | |
t.printStackTrace(); | |
} | |
} | |
/** | |
* Parses the underlays for the given world map plane. | |
* | |
* @param cache The cache store. | |
* @param plane The world map plane. | |
*/ | |
private static void parseUnderlay(Cache cache, WorldMapPlane plane) { | |
File file = cache.getFilesSystem(INDEX).findFolderByName(plane.getArchive()).findFileByName("underlay"); | |
if (file == null) { | |
System.err.println("Underlays for world map plane " + plane.getName() + " (archive " + plane.getArchive() + ") not found!"); | |
return; | |
} | |
ByteBuffer buffer = ByteBuffer.wrap(file.getData().getBuffer()); | |
byte[][][] data = plane.getUnderlay(); | |
if (data == null) { | |
plane.setUnderlay(data = new byte[plane.getSizeX()][plane.getSizeY()][]); | |
} | |
int count = 0; | |
while (buffer.hasRemaining()) { | |
boolean chunk = buffer.get() == 1; | |
int chunkX = 0; //Chunk x-coordinate | |
int chunkY = 0; //Chunk y-coordinate | |
if (chunk) { //Not used in 530 so far. | |
chunkX = buffer.get() & 0xFF; | |
chunkY = buffer.get() & 0xFF; | |
System.out.println("Parsing chunk instead of region!"); | |
} | |
int regionX = buffer.get() & 0xFF; | |
int regionY = buffer.get() & 0xFF; | |
int offsetX = ((regionX << 6) - plane.getBaseX()) >> 6; | |
int offsetY = ((regionY << 6) - plane.getBaseY()) >> 6; | |
if (data[offsetX][offsetY] == null) { | |
data[offsetX][offsetY] = new byte[4096]; | |
} | |
if (offsetX >= 0 && offsetY >= 0 && offsetX < data.length && offsetY < data[offsetX].length) { | |
for (int x = 0; x < 64; ++x) { | |
for (int y = 0; y < 64; ++y) { | |
if (!chunk || x >= 8 * chunkX && 8 + 8 * chunkX > x && y >= chunkY * 8 && y < 8 + 8 * chunkY) { | |
data[offsetX][offsetY][x + (63 - y << 6)] = buffer.get(); | |
count++; | |
} | |
} | |
} | |
} else if (!chunk) { | |
buffer.position(buffer.position() + 4096); //64x64=4096 | |
} else { | |
buffer.position(buffer.position() + 64); //8x8=64 | |
} | |
} | |
System.out.println("Parsed " + count + " underlays for plane " + plane.getName() + "!"); | |
} | |
/** | |
* Packs underlays for a map plane on the cache store. | |
* | |
* @param cache The store to pack on. | |
* @param plane The world map plane to pack. | |
*/ | |
private static void packUnderlay(Cache cache, WorldMapPlane plane) { | |
if (plane.getUnderlay() == null) { | |
System.err.println("Underlay is null for world map plane " + plane.getName() + "!"); | |
return; | |
} | |
int count = 0; | |
ByteBuffer buffer = ByteBuffer.allocate(4099 * 5000); //Currently supports up to 5000 regions | |
for (ZoneBorders z : plane.getBoundaries()) { | |
for (int regionX = z.getSouthWestX() >> 6; regionX < (z.getNorthEastX() >> 6) + 1; regionX++) { | |
for (int regionY = z.getSouthWestY() >> 6; regionY < (z.getNorthEastY() >> 6) + 1; regionY++) { | |
int offsetX = ((regionX << 6) - plane.getBaseX()) >> 6; | |
int offsetY = ((regionY << 6) - plane.getBaseY()) >> 6; | |
buffer.put((byte) 0); //No support for chunk based packing yet! | |
buffer.put((byte) regionX); | |
buffer.put((byte) regionY); | |
for (int x = 0; x < 64; x++) { | |
for (int y = 0; y < 64; y++) { | |
byte[] data = plane.getUnderlay()[offsetX][offsetY]; | |
if (data != null && offsetX >= 0 && offsetY >= 0 && offsetX < plane.getUnderlay().length && offsetY < plane.getUnderlay()[offsetX].length) { | |
buffer.put((byte) (plane.getUnderlay()[offsetX][offsetY][x + (63 - y << 6)])); | |
count++; | |
} else { | |
// System.out.println("Array " + arrX + "," + arrY); | |
buffer.put((byte) 0); | |
} | |
} | |
} | |
} | |
} | |
} | |
buffer.flip(); | |
byte[] bs = new byte[buffer.remaining()]; | |
buffer.get(bs); | |
Folder folder = null; | |
try { | |
folder = cache.getFilesSystem(INDEX).findFolderByName(plane.getArchive()); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
String fileName = "underlay"; | |
if (folder == null) { | |
folder = new Folder(plane.getArchive(), new File[] {new File(fileName, new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs))}); | |
} else { | |
File file = folder.findFileByName(fileName); | |
if (file != null) { | |
file.setData(new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs)); | |
} else { | |
file = new File(fileName, new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs)); | |
folder.addFile(file); | |
} | |
} | |
folder.finish(); | |
cache.getFilesSystem(INDEX).addFolder(folder); | |
cache.getFilesSystem(INDEX).finish(); | |
System.out.println("Packed " + count + " underlays for plane " + plane.getName() + "!"); | |
} | |
/** | |
* Parses the overlays for the given world map plane. | |
* | |
* @param cache The cache store. | |
* @param plane The world map plane. | |
*/ | |
private static void parseOverlay(Cache cache, WorldMapPlane plane) { | |
File file = cache.getFilesSystem(INDEX).findFolderByName(plane.getArchive()).findFileByName("overlay"); | |
if (file == null) { | |
System.err.println("Overlays for world map plane " + plane.getName() + " (archive " + plane.getArchive() + ") not found!"); | |
return; | |
} | |
ByteBuffer buffer = ByteBuffer.wrap(file.getData().getBuffer()); | |
byte[][][] data = plane.getOverlay(); | |
if (data == null) { | |
plane.setOverlay(data = new byte[plane.getSizeX() >> 6][plane.getSizeY() >> 6][]); | |
} | |
byte[][][] shapes = plane.getOverlayShapes(); | |
if (shapes == null) { | |
plane.setOverlayShapes(shapes = new byte[plane.getSizeX() >> 6][plane.getSizeY() >> 6][]); | |
} | |
int count = 0; | |
while (buffer.hasRemaining()) { | |
boolean chunk = buffer.get() == 1; | |
int chunkX = 0; //Chunk x-coordinate | |
int chunkY = 0; //Chunk y-coordinate | |
if (chunk) { //Not used in 530 so far. | |
chunkX = buffer.get() & 0xFF; | |
chunkY = buffer.get() & 0xFF; | |
System.out.println("Parsing chunk instead of region!"); | |
} | |
int regionX = buffer.get() & 0xFF; | |
int regionY = buffer.get() & 0xFF; | |
// System.out.println("Parsing region " + regionX + "," + regionY + " (" + (regionX << 6) + "," + (regionY << 6) + ")."); | |
int offsetX = ((regionX << 6) - plane.getBaseX()) >> 6; | |
int offsetY = ((regionY << 6) - plane.getBaseY()) >> 6; | |
if (offsetX >= 0 && offsetY >= 0 && offsetX < data.length && offsetY < data[offsetX].length) { | |
for (int x = 0; x < 64; ++x) { | |
for (int y = 0; y < 64; ++y) { | |
if (!chunk || x >= 8 * chunkX && 8 + 8 * chunkX > x && y >= chunkY * 8 && y < 8 + 8 * chunkY) { | |
int overlayId = buffer.get() & 0xFF; | |
if (overlayId != 0) { | |
if (data[offsetX][offsetY] == null) { | |
data[offsetX][offsetY] = new byte[4096]; | |
} | |
data[offsetX][offsetY][x + (63 - y << 6)] = (byte) overlayId; | |
if (shapes[offsetX][offsetY] == null) { | |
shapes[offsetX][offsetY] = new byte[4096]; | |
} | |
shapes[offsetX][offsetY][x + (63 - y << 6)] = buffer.get(); | |
count++; | |
} | |
} | |
} | |
} | |
} else { | |
for (int i = 0; i < (chunk ? 64 : 4096); ++i) { | |
int b = buffer.get(); | |
if (b != 0) { | |
buffer.position(buffer.position() + 1); | |
} | |
} | |
} | |
} | |
System.out.println("Parsed " + count + " overlay for plane " + plane.getName() + "!"); | |
} | |
/** | |
* Packs the overlay data. | |
* | |
* @param cache The store. | |
* @param plane The world map plane to pack. | |
*/ | |
private static void packOverlay(Cache cache, WorldMapPlane plane) { | |
if (plane.getOverlay() == null) { | |
System.err.println("Overlay is null for world map plane " + plane.getName() + "!"); | |
return; | |
} | |
int count = 0; | |
ByteBuffer buffer = ByteBuffer.allocate(8195 * 5000); //Currently supports up to 5000 regions | |
for (ZoneBorders z : plane.getBoundaries()) { | |
for (int regionX = z.getSouthWestX() >> 6; regionX < (z.getNorthEastX() >> 6) + 1; regionX++) { | |
for (int regionY = z.getSouthWestY() >> 6; regionY < (z.getNorthEastY() >> 6) + 1; regionY++) { | |
int offX = ((regionX << 6) - plane.getBaseX()) >> 6; | |
int offY = ((regionY << 6) - plane.getBaseY()) >> 6; | |
buffer.put((byte) 0); //No support for chunk based packing yet! | |
buffer.put((byte) regionX); | |
buffer.put((byte) regionY); | |
for (int x = 0; x < 64; x++) { | |
for (int y = 0; y < 64; y++) { | |
if (offX >= 0 && offY >= 0 && offX < plane.getOverlay().length && offY < plane.getOverlay()[offX].length) { | |
byte[] data = plane.getOverlay()[offX][offY]; | |
int overlayId = data == null ? 0 : data[x + (63 - y << 6)] & 0xFF; | |
buffer.put((byte) overlayId); | |
if (overlayId != 0) { | |
count++; | |
buffer.put((byte) plane.getOverlayShapes()[offX][offY][x + (63 - y << 6)]); | |
} | |
} else { | |
buffer.put((byte) 0); | |
} | |
} | |
} | |
} | |
} | |
} | |
buffer.flip(); | |
byte[] bs = new byte[buffer.remaining()]; | |
buffer.get(bs); | |
Folder folder = null; | |
try { | |
folder = cache.getFilesSystem(INDEX).findFolderByName(plane.getArchive()); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
String fileName = "overlay"; | |
if (folder == null) { | |
folder = new Folder(plane.getArchive(), new File[] {new File(fileName, new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs))}); | |
} else { | |
File file = folder.findFileByName(fileName); | |
if (file != null) { | |
file.setData(new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs)); | |
} else { | |
file = new File(fileName, new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs)); | |
folder.addFile(file); | |
} | |
} | |
cache.getFilesSystem(INDEX).addFolder(folder); | |
System.out.println("Packed " + count + " overlays for plane " + plane.getName() + "!"); | |
} | |
/** | |
* Parses the overlay2 for the given world map plane. | |
* | |
* @param cache The cache store. | |
* @param plane The world map plane. | |
*/ | |
private static void parseOverlay2(Cache cache, WorldMapPlane plane) { | |
File file = cache.getFilesSystem(INDEX).findFolderByName(plane.getArchive()).findFileByName("overlay2"); | |
if (file == null) { | |
System.err.println("Overlay2 for world map plane " + plane.getName() + " (archive " + plane.getArchive() + ") not found!"); | |
return; | |
} | |
ByteBuffer buffer = ByteBuffer.wrap(file.getData().getBuffer()); | |
byte[][][] data = plane.getOverlay2(); | |
if (data == null) { | |
plane.setOverlay2(data = new byte[plane.getSizeX() >> 6][plane.getSizeY() >> 6][]); | |
} | |
byte[][][] shapes = plane.getOverlay2Shapes(); | |
if (shapes == null) { | |
plane.setOverlay2Shapes(shapes = new byte[plane.getSizeX() >> 6][plane.getSizeY() >> 6][]); | |
} | |
int count = 0; | |
while (buffer.hasRemaining()) { | |
boolean chunk = buffer.get() == 1; | |
int chunkX = 0; //Chunk x-coordinate | |
int chunkY = 0; //Chunk y-coordinate | |
if (chunk) { //Not used in 530 so far. | |
chunkX = buffer.get() & 0xFF; | |
chunkY = buffer.get() & 0xFF; | |
System.out.println("Parsing chunk instead of region!"); | |
} | |
int regionX = buffer.get() & 0xFF; | |
int regionY = buffer.get() & 0xFF; | |
int offsetX = ((regionX << 6) - plane.getBaseX()) >> 6; | |
int offsetY = ((regionY << 6) - plane.getBaseY()) >> 6; | |
if (offsetX >= 0 && offsetY >= 0 && offsetX < data.length && offsetY < data[offsetX].length) { | |
for (int i = 0; i < 64; ++i) { | |
for (int j = 0; j < 64; ++j) { | |
if (!chunk || i >= 8 * chunkX && 8 + 8 * chunkX > i && j >= chunkY * 8 && j < 8 + 8 * chunkY) { | |
int overlayId = buffer.get() & 0xFF; | |
if (overlayId != 0) { | |
if (data[offsetX][offsetY] == null) { | |
data[offsetX][offsetY] = new byte[4096]; | |
} | |
data[offsetX][offsetY][i + (63 - j << 6)] = (byte) overlayId; | |
if (shapes[offsetX][offsetY] == null) { | |
shapes[offsetX][offsetY] = new byte[4096]; | |
} | |
shapes[offsetX][offsetY][i + (63 - j << 6)] = buffer.get(); | |
count++; | |
} | |
} | |
} | |
} | |
} else { | |
for (int i = 0; i < (chunk ? 64 : 4096); ++i) { | |
int b = buffer.get(); | |
if (b != 0) { | |
buffer.position(buffer.position() + 1); | |
} | |
} | |
} | |
} | |
System.out.println("Parsed " + count + " overlay2 for plane " + plane.getName() + "!"); | |
} | |
/** | |
* Packs the overlay2 data. | |
* | |
* @param cache The store. | |
* @param plane The world map plane to pack. | |
*/ | |
private static void packOverlay2(Cache cache, WorldMapPlane plane) { | |
if (plane.getOverlay2() == null) { | |
System.err.println("Overlay is null for world map plane " + plane.getName() + "!"); | |
return; | |
} | |
int count = 0; | |
ByteBuffer buffer = ByteBuffer.allocate(8195 * 5000); //Currently supports up to 5000 regions | |
for (ZoneBorders z : plane.getBoundaries()) { | |
for (int regionX = z.getSouthWestX() >> 6; regionX < (z.getNorthEastX() >> 6) + 1; regionX++) { | |
for (int regionY = z.getSouthWestY() >> 6; regionY < (z.getNorthEastY() >> 6) + 1; regionY++) { | |
int offsetX = ((regionX << 6) - plane.getBaseX()) >> 6; | |
int offsetY = ((regionY << 6) - plane.getBaseY()) >> 6; | |
buffer.put((byte) 0); //No support for chunk based packing yet! | |
buffer.put((byte) regionX); | |
buffer.put((byte) regionY); | |
for (int x = 0; x < 64; x++) { | |
for (int y = 0; y < 64; y++) { | |
if (offsetX >= 0 && offsetY >= 0 && offsetX < plane.getOverlay().length && offsetY < plane.getOverlay()[offsetX].length) { | |
byte[] data = plane.getOverlay2()[offsetX][offsetY]; | |
int overlayId = data == null ? 0 : data[x + (63 - y << 6)] & 0xFF; | |
buffer.put((byte) overlayId); | |
if (overlayId != 0) { | |
count++; | |
buffer.put((byte) plane.getOverlay2Shapes()[offsetX][offsetY][x + (63 - y << 6)]); | |
} | |
} else { | |
buffer.put((byte) 0); | |
} | |
} | |
} | |
} | |
} | |
} | |
buffer.flip(); | |
byte[] bs = new byte[buffer.remaining()]; | |
buffer.get(bs); | |
Folder folder = null; | |
try { | |
folder = cache.getFilesSystem(INDEX).findFolderByName(plane.getArchive()); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
String fileName = "overlay2"; | |
if (folder == null) { | |
folder = new Folder(plane.getArchive(), new File[] {new File(fileName, new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs))}); | |
} else { | |
File file = folder.findFileByName(fileName); | |
if (file != null) { | |
file.setData(new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs)); | |
} else { | |
file = new File(fileName, new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs)); | |
folder.addFile(file); | |
} | |
} | |
cache.getFilesSystem(INDEX).addFolder(folder); | |
System.out.println("Packed " + count + " overlay2 for plane " + plane.getName() + " (" + bs.length + " bytes packed)!"); | |
} | |
/** | |
* Parses the object information for the given world map plane. | |
* | |
* @param cache The store. | |
* @param plane The plane. | |
*/ | |
private static void parseObjects(Cache cache, WorldMapPlane plane) { | |
File file = cache.getFilesSystem(INDEX).findFolderByName(plane.getArchive()).findFileByName("loc"); | |
if (file == null) { | |
System.err.println("Object locations for world map plane " + plane.getName() + " (archive " + plane.getArchive() + ") not found!"); | |
return; | |
} | |
byte[][][] walls = plane.getWalls(); | |
if (walls == null) { | |
plane.setWalls(walls = new byte[plane.getSizeX() >> 6][plane.getSizeY() >> 6][]); | |
} | |
int[][][] objects = plane.getObjectIcons(); | |
if (objects == null) { | |
plane.setObjectIcons(objects = new int[plane.getSizeX() >> 6][plane.getSizeY() >> 6][]); | |
} | |
int[][][] icons = plane.getMapIcons(); | |
if (icons == null) { | |
plane.setMapIcons(icons = new int[plane.getSizeX() >> 6][plane.getSizeY() >> 6][]); | |
} | |
ByteBuffer buffer = ByteBuffer.wrap(file.getData().getBuffer()); | |
int[] debug = new int[3]; | |
roar: | |
while (true) { | |
if (buffer.hasRemaining()) { | |
boolean chunk = buffer.get() == 1; | |
int chunkX = 0; //Chunk x-coordinate | |
int chunkY = 0; //Chunk y-coordinate | |
if (chunk) { //Not used in 530 so far. | |
chunkX = buffer.get() & 0xFF; | |
chunkY = buffer.get() & 0xFF; | |
System.out.println("Parsing chunk instead of region!"); | |
} | |
int regionX = buffer.get() & 0xFF; | |
int regionY = buffer.get() & 0xFF; | |
int offsetX = ((regionX << 6) - plane.getBaseX()) >> 6; | |
int offsetY = ((regionY << 6) - plane.getBaseY()) >> 6; | |
if (offsetX >= 0 && offsetY >= 0 && offsetX < plane.getSizeX() >> 6 && offsetY < plane.getSizeY() >> 6) { | |
int objX = 0; | |
while (true) { | |
if (objX >= 64) { | |
continue roar; | |
} | |
for (int objY = 0; objY < 64; objY++) { | |
if (!chunk || objX >= 8 * chunkX && 8 + 8 * chunkX > objX && objY >= chunkY * 8 && objY < 8 + 8 * chunkY) { | |
int flag = buffer.get(); | |
if (flag == 0) { | |
continue; | |
} | |
if ((flag & 1) == 1) { | |
if (walls[offsetX][offsetY] == null) { | |
walls[offsetX][offsetY] = new byte[4096]; | |
} | |
walls[offsetX][offsetY][objX + (63 - objY << 6)] = buffer.get(); | |
debug[0]++; | |
} | |
if ((flag & 2) == 2) { | |
if (objects[offsetX][offsetY] == null) { | |
objects[offsetX][offsetY] = new int[4096]; | |
} | |
objects[offsetX][offsetY][objX + (63 - objY << 6)] = ByteBufferUtils.getTriByte(buffer); | |
debug[1]++; | |
} | |
if ((flag & 4) == 4) { | |
if (icons[offsetX][offsetY] == null) { | |
icons[offsetX][offsetY] = new int[4096]; | |
} | |
//object id = value - 1 | |
icons[offsetX][offsetY][objX + (63 - objY << 6)] = ByteBufferUtils.getTriByte(buffer); | |
debug[2]++; | |
} | |
} | |
} | |
++objX; | |
} | |
} | |
int count = 0; | |
while (true) { | |
if (count >= (chunk ? 64 : 4096)) { | |
continue roar; | |
} | |
int flag = buffer.get(); | |
if (flag != 0) { | |
if ((flag & 1) == 1) { | |
buffer.position(buffer.position() + 1); | |
} | |
if ((flag & 2) == 2) { | |
buffer.position(buffer.position() + 3); | |
} | |
if ((flag & 4) == 4) { | |
buffer.position(buffer.position() + 3); | |
} | |
} | |
++count; | |
} | |
} | |
System.out.println("Parsed " + debug[0] + " walls, " + debug[1] + " object drawings and " + debug[2] + " map icons for plane " + plane.getName() + "!"); | |
return; | |
} | |
} | |
/** | |
* Packs the object information for the given world map plane. | |
* | |
* @param cache The store. | |
* @param plane The plane. | |
*/ | |
private static void packObjects(Cache cache, WorldMapPlane plane) { | |
if (plane.getObjectIcons() == null) { | |
System.err.println("Object icons is null for world map plane " + plane.getName() + "!"); | |
return; | |
} | |
int count = 0; | |
ByteBuffer buffer = ByteBuffer.allocate(8199 * 5000); //Currently supports up to 5000 regions | |
for (ZoneBorders z : plane.getBoundaries()) { | |
for (int regionX = z.getSouthWestX() >> 6; regionX < (z.getNorthEastX() >> 6) + 1; regionX++) { | |
for (int regionY = z.getSouthWestY() >> 6; regionY < (z.getNorthEastY() >> 6) + 1; regionY++) { | |
int offsetX = ((regionX << 6) - plane.getBaseX()) >> 6; | |
int offsetY = ((regionY << 6) - plane.getBaseY()) >> 6; | |
buffer.put((byte) 0); //No support for chunk based packing yet! | |
buffer.put((byte) regionX); | |
buffer.put((byte) regionY); | |
for (int x = 0; x < 64; x++) { | |
for (int y = 0; y < 64; y++) { | |
int wall = plane.getWalls()[offsetX][offsetY] == null ? 0 : plane.getWalls()[offsetX][offsetY][x + (63 - y << 6)]; | |
int object = plane.getObjectIcons()[offsetX][offsetY] == null ? 0 : plane.getObjectIcons()[offsetX][offsetY][x + (63 - y << 6)]; | |
int icon = plane.getMapIcons()[offsetX][offsetY] == null ? 0 : plane.getMapIcons()[offsetX][offsetY][x + (63 - y << 6)]; | |
int index = buffer.position(); | |
int flag = 0; | |
buffer.put((byte) flag); | |
if (wall != 0) { | |
flag |= 1; | |
buffer.put((byte) wall); | |
} | |
if (object > 0) { | |
flag |= 2; | |
ByteBufferUtils.putTriByte(object, buffer); | |
} | |
if (icon > 0) { | |
flag |= 4; | |
ByteBufferUtils.putTriByte(icon, buffer); | |
} | |
if (flag != 0) { | |
int pos = buffer.position(); | |
buffer.position(index); | |
buffer.put((byte) flag); | |
buffer.position(pos); | |
count++; | |
} | |
} | |
} | |
} | |
} | |
} | |
buffer.flip(); | |
byte[] bs = new byte[buffer.remaining()]; | |
buffer.get(bs); | |
Folder folder = null; | |
try { | |
folder = cache.getFilesSystem(INDEX).findFolderByName(plane.getArchive()); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
String fileName = "loc"; | |
if (folder == null) { | |
folder = new Folder(plane.getArchive(), new File[] {new File(fileName, new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs))}); | |
} else { | |
File file = folder.findFileByName(fileName); | |
if (file != null) { | |
file.setData(new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs)); | |
} else { | |
file = new File(fileName, new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs)); | |
folder.addFile(file); | |
} | |
} | |
cache.getFilesSystem(INDEX).addFolder(folder); | |
System.out.println("Packed " + count + " objects for plane " + plane.getName() + "!"); | |
} | |
/** | |
* Parses the name labels for a world map plane. | |
* | |
* @param cache The cache store. | |
* @param plane The world map plane. | |
*/ | |
private static void parseLabels(Cache cache, WorldMapPlane plane) { | |
Folder archiveId = cache.getFilesSystem(INDEX).findFolderByName(plane.getArchive() + "_labels"); | |
if (archiveId == null) { | |
System.out.println("Could not find labels for plane " + plane.getName() + "!"); | |
return; | |
} | |
int count = 0; | |
for (int i = 0; i < archiveId.filesCount(); i++) { | |
byte[] data = archiveId.findFileByID(i).getData().getBuffer(); | |
if (data == null || data.length < 2) { | |
System.err.println("Invalid label file for plane " + plane.getName() + "!"); | |
continue; | |
} | |
ByteBuffer buffer = ByteBuffer.wrap(data); | |
String name = ByteBufferUtils.getString(buffer); | |
byte flag = buffer.get(); | |
int x = buffer.getShort(); | |
int y = buffer.getShort(); | |
int hash = buffer.getInt(); //Always seems to be -1 | |
plane.getDetails().add(new RegionDetails(name, flag, x, y, hash)); | |
System.out.println("Parsing label " + name + ", " + x + ", " + y + ", " + flag); | |
count++; | |
} | |
System.out.println("Parsed " + count + " region details for plane " + plane.getName() + "!"); | |
} | |
/** | |
* Parses the name labels for a world map plane. | |
* | |
* @param cache The cache store. | |
* @param plane The world map plane. | |
*/ | |
private static void packLabels(Cache cache, WorldMapPlane plane) { | |
int count = 0; | |
for (RegionDetails r : plane.getDetails()) { | |
ByteBuffer buffer = ByteBuffer.allocate(256 + 9); | |
ByteBufferUtils.putString(r.getName(), buffer); | |
buffer.put((byte) r.getFlag()); | |
buffer.putShort((short) r.getX()); | |
buffer.putShort((short) r.getY()); | |
buffer.putInt(r.getData()); | |
buffer.flip(); | |
byte[] bs = new byte[buffer.remaining()]; | |
buffer.get(bs); | |
String groupname = plane.getArchive() + "_labels"; | |
Folder folder = null; | |
try { | |
folder = cache.getFilesSystem(INDEX).findFolderByName(groupname); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
int fileName = count++; | |
if (folder == null) { | |
folder = new Folder(groupname, new File[] {new File(fileName, new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs))}); | |
} else { | |
File file = folder.findFileByName(fileName); | |
if (file != null) { | |
file.setData(new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs)); | |
} else { | |
file = new File(fileName, new ps.eden.server.cache.editor.mgi.tools.rseditor.core.utilities.ByteBuffer(bs)); | |
folder.addFile(file); | |
} | |
} | |
cache.getFilesSystem(INDEX).addFolder(folder); | |
} | |
System.out.println("Packed " + count + " region details for plane " + plane.getName() + "!"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment