maps/editor/scripts/WorldMaker

222 lines
8.0 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<script>
<name>WorldMaker</name>
<code><![CDATA[import java.io.IOException;
import javax.imageio.ImageIO;
import java.io.RandomAccessFile;
import java.io.FileOutputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
Path getSimpleFilename(Path mapFile) {
String mapFilename = mapFile.toString();
int i = mapFilename.lastIndexOf(File.separator);
if (i > 0) {
mapFilename = mapFilename.substring(i + 1);
}
return Paths.get(mapFilename, new String[0]);
}
Path getPngImageFilename(Path mapFile) {
return locationDir.resolve(PictureDirectory + getSimpleFilename(mapFile) + ".png");
}
boolean updateMap(Path mapFile, Path pictureFile) {
if (!Files.exists(mapFile, new LinkOption[0])) {
return false;
}
if (Files.exists(pictureFile, new LinkOption[0]) && Files.getLastModifiedTime(pictureFile, new LinkOption[0]).toMillis() >= Files.getLastModifiedTime(mapFile, new LinkOption[0]).toMillis()) {
return false;
}
print("converting " + mapFile + " to " + pictureFile + ".");
try {
map = mapManager.openMapFile(mapFile, false);
} catch (IOException ex) {
return false;
}
try {
try {
ImageIO.write(rendererFactory.newSimpleMapRenderer(map.getMapModel()).getFullImage(), "png", pictureFile.toFile());
} catch (IOException ex) {
print("cannot write " + pictureFile + ": " + ex.getMessage());
return false;
}
} finally {
mapManager.release(map);
}
return true;
}
boolean runCommand(String cmd) {
f = File.createTempFile("WMaker", ".sh");
FileWriter out = new FileWriter(f);
out.write(cmd);
out.close();
print("running " + cmd);
Process p = Runtime.getRuntime().exec("sh " + f.getAbsolutePath());
p.waitFor();
f.delete();
return p.exitValue() == 0;
}
void checkDaList() {
DestWidth = TileWidth.intValue() * NumX.intValue();
DestHeight = TileHeight.intValue() * NumY.intValue();
if (Location == null || Location.length() == 0) {
locationDir = globalSettings.getMapsDirectory();
} else {
locationDir = Paths.get(Location);
}
print("World map will be " + DestWidth + "x" + DestHeight + " in size");
if (!PictureDirectory.endsWith(File.separator)) {
PictureDirectory = PictureDirectory + File.separator;
}
Files.createDirectories(locationDir.resolve(PictureDirectory), new FileAttribute[0]);
final long bytesPerPixel = 3L;
HashSet mapList = new HashSet();
boolean firstRun = false;
byte[] header = ("P6\n" + DestWidth + " " + DestHeight + "\n255\n").getBytes("ISO-8859-1");
long headerSize = header.length;
Path destinationFilePpm = locationDir.resolve(PictureDirectory + WorldPicture + ".ppm");
Path destinationFilePng = locationDir.resolve(PictureDirectory + WorldPicture + ".png");
File tempFile = new File("/tmp/tmp.ppm");
if (Files.exists(destinationFilePpm, new LinkOption[0])) {
runCommand("cp '" + destinationFilePpm + "' '" + tempFile + "'");
} else {
print("generating empty picture");
FileOutputStream fos = new FileOutputStream(tempFile, false);
fos.write(header);
byte[] buf = new byte[(int) DestWidth.intValue() * bytesPerPixel];
for (int i = 0; i < DestHeight.intValue(); i++) {
fos.write(buf);
}
fos.close();
firstRun = true;
}
long toSkip = ("P6\n" + TileWidth + " " + TileHeight+"\n255\n").getBytes("ISO-8859-1").length;
RandomAccessFile raf = new RandomAccessFile(tempFile, "rw");
FileChannel fc = raf.getChannel();
byte[] buf = new byte[bytesPerPixel * TileWidth.intValue() * TileHeight.intValue()];
File tempImageFile = new File("/tmp/ppm.tmp");
for (int x = 0; x < NumX.intValue(); x++) {
for (int y = 0; y < NumY.intValue(); y++) {
currentX = StartX.intValue() + x;
currentY = StartY.intValue() + y;
currentMap = locationDir.resolve(MapFilename + "_" + currentX + "_" + currentY);
currentPicture = getPngImageFilename(currentMap);
didUpdate = updateMap(currentMap, currentPicture);
if ((didUpdate || firstRun) && Files.exists(currentPicture, new LinkOption[0])) {
runCommand("pngtopnm '" + currentPicture + "' | pnmscale -xysize " + TileWidth + " " + TileHeight + " > '" + tempImageFile + "'");
FileInputStream fis = new FileInputStream(tempImageFile);
fis.skip(toSkip);
fis.read(buf);
sx = x * TileWidth.intValue();
sy = y * TileHeight.intValue();
long index = ((long) sy * (long) DestWidth.intValue() + (long) sx) * bytesPerPixel + headerSize;
for (long row = 0; row < TileHeight.intValue(); row++) {
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, index + row * DestWidth.intValue() * bytesPerPixel, TileWidth.intValue() * bytesPerPixel);
mbb.put(buf, (int) (row * TileWidth.intValue() * bytesPerPixel), (int) (TileWidth.intValue() * bytesPerPixel));
}
}
}
}
raf.close();
runCommand("mv " + tempFile + " '" + destinationFilePpm + "'");
print("converting to png if possible.\n");
runCommand("pnmtopng '" + destinationFilePpm + "' > /tmp/tmp.png");
runCommand("mv /tmp/tmp.png '" + destinationFilePng + "'");
}
Path locationDir;
checkDaList();
print("Done!");]]></code>
<mode>
<autoboot>false</autoboot>
<bash>true</bash>
<filter>false</filter>
</mode>
<parameter>
<name>Location</name>
<description>Specify the map directory to use by this script. Leave empty for maps directory</description>
<type>java.lang.String</type>
<value />
</parameter>
<parameter>
<name>MapFilename</name>
<description>This map file name will be appended to the 'Location' parameter and '_mapx_mapy' will be added at the end</description>
<type>java.lang.String</type>
<value>world/world</value>
</parameter>
<parameter>
<name>TileWidth</name>
<description>The width in pixel of each generate map image</description>
<type>java.lang.Integer</type>
<value>50</value>
<minimum>0</minimum>
<maximum>2000</maximum>
</parameter>
<parameter>
<name>TileHeight</name>
<description>The height in pixel of each generated map image</description>
<type>java.lang.Integer</type>
<value>50</value>
<minimum>0</minimum>
<maximum>2000</maximum>
</parameter>
<parameter>
<name>NumX</name>
<description>The number of maps along X axis to analyze</description>
<type>java.lang.Integer</type>
<value>30</value>
<minimum>0</minimum>
<maximum>50000</maximum>
</parameter>
<parameter>
<name>NumY</name>
<description>The number of maps along Y axis to analyze</description>
<type>java.lang.Integer</type>
<value>30</value>
<minimum>0</minimum>
<maximum>50000</maximum>
</parameter>
<parameter>
<name>StartX</name>
<description>The first coordinate along X axis to analyze</description>
<type>java.lang.Integer</type>
<value>100</value>
<minimum>0</minimum>
<maximum>50000</maximum>
</parameter>
<parameter>
<name>StartY</name>
<description>The first coordinate along Y axis to analyze</description>
<type>java.lang.Integer</type>
<value>100</value>
<minimum>0</minimum>
<maximum>50000</maximum>
</parameter>
<parameter>
<name>PictureDirectory</name>
<description>The subdirectory where to put pictures</description>
<type>java.lang.String</type>
<value>images</value>
</parameter>
<parameter>
<name>WorldPicture</name>
<description>The picture which will store the world map</description>
<type>java.lang.String</type>
<value>worldmap</value>
</parameter>
</script>