Posted July 20, 2017 (edited) UPDATED FOR YOUR PLEASURE So I was rather disturbed by the black spots everywhere too. With some of the new pavement types it was like whole black holes for deeds in places lol. I went to decompile this mod and dig through, man let me first say Joneh is a genius coder, he will be missed around here. He had made a hand written array that contained 256 values one for each possible tile type since tile types are a byte (256 maximum values, 255 if you count from 0 and you should) but most of them were left to 0 or -1, which is why when those tiles were pulled they came out black. I did away with that, called the common.jar colors that wurm puts in for the mapdumps. This will help to futureproof it, if they change those colors or change tiles or whatever it will just call the new values from the new setup. The only thing that may break it is if they change the common.jar to make my target of the colors not stick. You will notice there are some dark spots in my tundra. Players told me that was ligonberries, I dunno, but at least its dark green and not black. Pay attention in my example images the deed north of the tundra (Carbonek) for an example of the giant black spots and how it changes in the new version. I was still using the older iteration of the mapviewer before this, and the setup with the newer version I just worked on is a bit different. So I will briefly touch on the setup after the images. Without further wait: Before After Original Before if you want a bigger view: http://i.imgur.com/PVe6tEg.png Original After if you want a bigger view: http://i.imgur.com/MdEFL77.png The mapviewer.jar and mapviewer.cfg need to go into the root folder of your server. Where your server.jar is. This new system has the class paths set up to get the common.jar and use it as a library, so its location is important. Unless you want to modify the MANIFEST For the mapviewer.cfg file: # WU MAP VIEWER CONFIG FILE # RELATIVE OR ABSOLUTE PATH TO DIRECTORY FOR MAP MAP_DIRECTORY = Creative # RELATIVE OR ABSOLUTE PATH TO DIRECTORY TO OUTPUT TO # THIS SHOULD BE A DIRECTORY ACCESSIBLE BY HTTP SERVER OUTPUT_DIRECTORY = mapviewer # SIZE OF SECTIONS TO SPLIT UP INTO # SMALLER SIZES ARE MORE EFFICIENT FOR CACHING BUT USE MORE BANDWIDTH SECTION_SIZE = 256 SHOW_DEEDS = true SHOW_DEED_BORDERS_IN_3D_MODE = false SHOW_DEED_BORDERS_IN_FLAT_MODE = true Pretty self explained. The older version I was using was not hard but a bit more difficult to configure. No I am not modding the custom version from a few posts back (September 2016 or so) this is just Jonneh's version updated for the modern era. Hope you guys enjoy. Cheers Now you can get it for yourself: https://www.dropbox.com/s/8w50njp1gl38ldv/mapviewer.zip?dl=0 I only had to edit one file in the jar, and the Manifest. So I only have 1 working source code. I thought you guys might like to have it, in the spoiler below. Spoiler package com.wyverngame.mapviewer; import com.wyverngame.mapviewer.Config; import com.wyverngame.mapviewer.zone.BridgePart; import com.wyverngame.mapviewer.zone.Deed; import com.wyverngame.mapviewer.zone.Tile; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.CopyOption; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.FileAttribute; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; public final class Renderer { private static final Logger LOGGER = Logger.getLogger(Renderer.class.getName()); private final Config config; @SuppressWarnings({ "unchecked", "rawtypes" }) private final Map<Tile, BridgePart> bridgeParts = new HashMap(); private int size = 4096; private int[][] typeData; private int[][] metaData; private int[][] heightData; public Renderer(Config config) { this.config = config; } @SuppressWarnings("unused") public int load(List<Deed> deeds, Map<Tile, BridgePart> bridgeParts) throws Throwable { this.bridgeParts.putAll(bridgeParts); Path temp = Paths.get("temp", new String[0]); if (Files.notExists(temp, new LinkOption[0])) { Files.createDirectory(temp, new FileAttribute[0]); } Path map = temp.resolve("top_layer.map"); Files.deleteIfExists(map); Files.copy(this.config.getMapDirectory().resolve("top_layer.map"), map, new CopyOption[0]); Throwable throwable = null; Object var6_7 = null; try { DataInputStream in = new DataInputStream( new BufferedInputStream(Files.newInputStream(map, new OpenOption[0]), 65536)); try { in.readLong(); in.readByte(); this.size = 1 << in.readByte(); in.skipBytes(1014); this.typeData = new int[this.size][this.size]; this.metaData = new int[this.size][this.size]; this.heightData = new int[this.size][this.size]; int y = 0; while (y < this.size) { int x = 0; while (x < this.size) { int tileType = in.read() & 255; int meta = in.read() & 255; short height = in.readShort(); this.typeData[x][y] = tileType; this.metaData[x][y] = meta; this.heightData[x][y] = height; ++x; } ++y; } for (Deed deed : deeds) { deed.setHeight(this.heightData[deed.getX()][deed.getY()]); } return this.size; } catch (Throwable var5_6) { throw var5_6; } finally { if (in != null) { in.close(); } } } catch (Throwable var6_8) { if (throwable == null) { throwable = var6_8; } else if (throwable != var6_8) { throwable.addSuppressed(var6_8); } throw throwable; } } public BufferedImage render(Renderer.Type type) { BufferedImage img = new BufferedImage(this.size, this.size, 1); int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData(); Arrays.fill(pixels, 3686001); for (int x = 0; x < this.size - 1; ++x) { if (x % 128 == 0) { LOGGER.log(Level.INFO, "Rendered " + (int) ((float) x / (float) this.size * 100.0F) + "%"); } for (int y = 0; y < this.size - 1; ++y) { int tiled = this.typeData[x][y]; com.wurmonline.mesh.Tiles.Tile tilef = com.wurmonline.mesh.Tiles.getTile(tiled); java.awt.Color color = tilef.getColor(); int r = color.getRed(); int g = color.getGreen(); int b = color.getBlue(); float tileHeight = (float) this.heightData[x][y] / 40.0F; float tileHeightN = (float) this.heightData[x + 1][y + 1] / 40.0F; float tileHeightB = (float) this.heightData[x][y + 1] / 40.0F; float delta = tileHeightN - tileHeight; float factor = (float) (1.0D + Math.tanh((double) (delta / 4.0F))); r = (int) (factor * (float) r); g = (int) (factor * (float) g); b = (int) (factor * (float) b); if (tileHeight < 0.0F) { r = r / 5 + 41; g = r / 5 + 51; b = r / 5 + 102; } if (r < 0) { r = 0; } if (r > 255) { r = 255; } if (g < 0) { g = 0; } if (g > 255) { g = 255; } if (b < 0) { b = 0; } if (b > 255) { b = 255; } int height; if (type.equals(Renderer.Type.NORMAL)) { int tile = y - (int) tileHeight; if (tileHeightB - 1.0F > tileHeight) { tile = y - (int) tileHeightB; } int part = Integer.MAX_VALUE; if (tileHeight >= 0.0F && tileHeightB < 0.0F) { part = y + 1; } for (height = tile; (float) height <= (float) tile + Math.abs(delta) + 9.0F; ++height) { if (height >= 0 && height < this.size) { if (height == part) { r = r / 5 + 41; g = r / 5 + 51; b = r / 5 + 102; } pixels[height * this.size + x] = r << 16 | g << 8 | b; } } } else { pixels[y * this.size + x] = r << 16 | g << 8 | b; } Tile arg20 = new Tile(x, y); BridgePart arg21 = (BridgePart) this.bridgeParts.get(arg20); if (arg21 != null) { if (type.equals(Renderer.Type.NORMAL)) { height = arg21.getHeightOffset(); if (arg21.getSlope() < 0) { height += arg21.getSlope(); } int h = y - height / 40; int ha = y - arg21.getHeightOffset() / 40; int hb = y - (arg21.getHeightOffset() + arg21.getSlope()) / 40; if (h >= 0 && h < this.size - 1) { if (ha != hb) { pixels[(h - 1) * this.size + x] = arg21.getColour(); } pixels[h * this.size + x] = arg21.getColour(); pixels[(h + 1) * this.size + x] = arg21.getShadowColour(); } } else { pixels[y * this.size + x] = arg21.getColour(); } } } } return img; } public void save(Path path, Renderer.Type type) throws Throwable { if (Files.notExists(path, new LinkOption[0])) { Files.createDirectory(path, new FileAttribute[0]); } BufferedImage img = this.render(type); BufferedImage[][] parts = split(img, this.config.getSectionSize()); int s = parts.length; for (int x = 0; x < s; ++x) { for (int y = 0; y < s; ++y) { overwriteIfChanged(parts[x][y], path.resolve(x + "." + y + ".png"), x, y); } } } @SuppressWarnings("unused") private static void overwriteIfChanged(BufferedImage img, Path path, int sx, int sy) throws Throwable { boolean changed = true; Throwable ex; Object arg5; if (Files.exists(path, new LinkOption[0])) { try { ex = null; arg5 = null; try { InputStream out = Files.newInputStream(path, new OpenOption[0]); try { BufferedImage ex1 = ImageIO.read(out); if (img.getWidth() == ex1.getWidth() && img.getHeight() == ex1.getHeight()) { changed = false; label467 : for (int x = 0; x < img.getWidth(); ++x) { for (int y = 0; y < img.getHeight(); ++y) { if (img.getRGB(x, y) != ex1.getRGB(x, y)) { changed = true; break label467; } } } } else { changed = true; } } finally { if (out != null) { out.close(); } } } catch (Throwable arg33) { if (ex == null) { ex = arg33; } else if (ex != arg33) { ex.addSuppressed(arg33); } throw ex; } } catch (Exception arg34) { changed = true; arg34.printStackTrace(); } } if (changed) { ex = null; arg5 = null; try { OutputStream arg35 = Files.newOutputStream(path, new OpenOption[0]); try { LOGGER.log(Level.INFO, "[Over]writing section " + sx + ", " + sy); ImageIO.write(img, "PNG", arg35); } finally { if (arg35 != null) { arg35.close(); } } } catch (Throwable arg31) { if (ex == null) { ex = arg31; } else if (ex != arg31) { ex.addSuppressed(arg31); } throw ex; } } } private static BufferedImage[][] split(BufferedImage render, int size) { int count = render.getWidth() / size; BufferedImage[][] sections = new BufferedImage[count][count]; for (int sx = 0; sx < count; ++sx) { for (int sy = 0; sy < count; ++sy) { int x = sx * size; int y = sy * size; LOGGER.log(Level.INFO, "Splitting section " + sx + ", " + sy); BufferedImage section = render.getSubimage(x, y, size, size); sections[sx][sy] = section; } } return sections; } public static enum Type { NORMAL, FLAT; } } Edited July 20, 2017 by Xyp added the source of the class I had to edit. Only source file I have. 5 Share this post Link to post Share on other sites
Posted July 21, 2017 (edited) Thanks man. Edited July 21, 2017 by MrLolan Share this post Link to post Share on other sites
Posted July 21, 2017 Thanks for the source and the update! Share this post Link to post Share on other sites
Posted July 21, 2017 (edited) Xyp, i dont know why but isnt working for me. Program making only map files and empty sections-3d folder Now I saw it: " The mapviewer.jar and mapviewer.cfg need to go into the root folder of your server. Where your server.jar is. This new system has the class paths set up to get the common.jar and use it as a library, so its location is important. Unless you want to modify the MANIFEST" Edited July 22, 2017 by MrLolan Share this post Link to post Share on other sites
Posted July 21, 2017 @XypWorking like a charm! Love you long time. If you ever have an urge to add guard towers, I wouldn't argue and might even love you longer time. LOL But seriously this no longer triggers OCD alert flare ups and cringing every time I look at my map. \o/ Share this post Link to post Share on other sites
Posted July 21, 2017 Yeah I was annoyed at the black holes too. It was either this or mod everything to pull towards the holes like gravity lol. I don't personally have interest in guard towers, so ill put it on my boredom list, but im quite busy lately. Its on a list though. Share this post Link to post Share on other sites
Posted July 22, 2017 No worries, like I say if you ever have an "urge" not critical by any means simply a 'would be nice' feature. Share this post Link to post Share on other sites
Posted September 26, 2017 Any idea if the newer version of Jonneh's map tool will be updated with Xyp's fix? Not so much for the towers, but for mobile/touch support that he had added. Share this post Link to post Share on other sites
Posted October 8, 2017 On 9/26/2017 at 3:47 PM, mwdennis said: Any idea if the newer version of Jonneh's map tool will be updated with Xyp's fix? Not so much for the towers, but for mobile/touch support that he had added. Xyp did his fix for the latest version Jonneh ever released. The one with the towers was done by someone else modifying the code it wasn't done by the original author. As the site that contained those modification is long gone the answer to your question is probably not. Share this post Link to post Share on other sites
Posted October 25, 2017 On 10/8/2017 at 4:05 AM, LifesaverM said: site that contained those modification is long gone Here you are 1 Share this post Link to post Share on other sites
Posted December 27, 2017 I've updated the generator and tweaked a few things... Can now pass name of config file as parameter to the jar, should make generating multiple maps in batch easier Added focus zone markers on the map (currently no build zones show with a transparent red color - other zone types can be tweaked in CSS) Added highways view Updated the colors for all new tile types I'm currently using this for my servers, you can see an example of all the features here - https://otherlands.bdew.net/map/walden/ Download: https://www.dropbox.com/s/gbamfmkyroz4cxy/mapgen.jar?dl=0 1 Share this post Link to post Share on other sites
Posted December 28, 2017 14 hours ago, bdew said: I've updated the generator and tweaked a few things... Can now pass name of config file as parameter to the jar, should make generating multiple maps in batch easier Added focus zone markers on the map (currently no build zones show with a transparent red color - other zone types can be tweaked in CSS) Added highways view Updated the colors for all new tile types I'm currently using this for my servers, you can see an example of all the features here - https://otherlands.bdew.net/map/walden/ Download: https://www.dropbox.com/s/gbamfmkyroz4cxy/mapgen.jar?dl=0 This map is awesome, but without async load-unload -- cant use it on 8k maps Share this post Link to post Share on other sites
Posted December 29, 2017 what do you mean async load-unload? what actual issues are you having? Share this post Link to post Share on other sites
Posted December 30, 2017 15 hours ago, bdew said: what do you mean async load-unload? what actual issues are you having? This map works like this: You open map and waiting for downloading all parts, then you can see procmon -- map use huge of memmory and GPU when using. For good usage I try to use huge map parts, like 4096. But a lot of people with low-end PC cant use this and we migrate to Share this post Link to post Share on other sites
Posted July 31, 2018 On 12/27/2017 at 7:02 AM, bdew said: Download: https://www.dropbox.com/s/gbamfmkyroz4cxy/mapgen.jar?dl=0 I'm just getting a blank map with the 3D, Flat, and Roads options on the side. I know that I've been able to use mapviewer on a previous LAN without having to set up a website for it, but I don't remember how it was done. I know this because I have never set up a website for myself, ever, in which to view maps. Share this post Link to post Share on other sites
Posted July 31, 2018 12 minutes ago, Batta said: I'm just getting a blank map with the 3D, Flat, and Roads options on the side. I know that I've been able to use mapviewer on a previous LAN without having to set up a website for it, but I don't remember how it was done. I know this because I have never set up a website for myself, ever, in which to view maps. It should work. Are you getting any errors when running the generator? And does your output folder look like this? Share this post Link to post Share on other sites
Posted July 31, 2018 11 minutes ago, bdew said: It should work. Are you getting any errors when running the generator? And does your output folder look like this? Everything except the sections folders. I do remember that I had them in the past, with previous mapviewer. Share this post Link to post Share on other sites
Posted July 31, 2018 1 minute ago, Batta said: Everything except the sections folders. I do remember that I had them in the past, with previous mapviewer. Those folders are where your actual map images are. Check the output from the generator for any errors. Share this post Link to post Share on other sites
Posted July 31, 2018 1 minute ago, bdew said: Those folders are where your actual map images are. Check the output from the generator for any errors. Okay, will do. Which file would I find the output in? Share this post Link to post Share on other sites
Posted July 31, 2018 (edited) @bdew Because your file was just a jar, I am also using the original mapviewer config file from the OP. Is that correct? And here's my mapviewer config: Spoiler # WU MAP VIEWER CONFIG FILE # RELATIVE OR ABSOLUTE PATH TO DIRECTORY FOR MAP MAP_DIRECTORY = C:\Program Files (x86)\Steam\steamapps\common\Wurm Unlimited Dedicated Server\Small World # RELATIVE OR ABSOLUTE PATH TO DIRECTORY TO OUTPUT TO # THIS SHOULD BE A DIRECTORY ACCESSIBLE BY HTTP SERVER OUTPUT_DIRECTORY = C:\Program Files (x86)\Steam\steamapps\common\Wurm Unlimited Dedicated Server\MapViewer # SIZE OF SECTIONS TO SPLIT UP INTO # SMALLER SIZES ARE MORE EFFICIENT FOR CACHING BUT USE MORE BANDWIDTH SECTION_SIZE = 256 SHOW_DEEDS = true SHOW_DEED_BORDERS_IN_3D_MODE = false SHOW_DEED_BORDERS_IN_FLAT_MODE = true Edited August 9, 2018 by Batta Share this post Link to post Share on other sites
Posted July 31, 2018 Try using the other slash ( / ) in the directory paths, or doubling them up ( \\ ) Share this post Link to post Share on other sites
Posted July 31, 2018 7 minutes ago, bdew said: Try using the other slash ( / ) in the directory paths, or doubling them up ( \\ ) Neither of those fixes worked. Anything else I can try? Share this post Link to post Share on other sites
Posted August 1, 2018 21 hours ago, bdew said: Check the output from the generator for any errors. Look at the output from the generator that it prints as it runs, if there is an error it will be there, if you can't figure it out post the full text here. Share this post Link to post Share on other sites
Posted August 1, 2018 2 hours ago, bdew said: Look at the output from the generator that it prints as it runs, if there is an error it will be there, if you can't figure it out post the full text here. I can't seem to find anything like this. When I run the mapgen.jar there is no screen that comes up, if that's what you mean? I also looked at all the files I could find and none of them seemed related. Would you please let me know what the output from the generator would look like, or what it would be called, so I can find it? Share this post Link to post Share on other sites
Posted August 2, 2018 20 hours ago, Batta said: I can't seem to find anything like this. When I run the mapgen.jar there is no screen that comes up, if that's what you mean? I also looked at all the files I could find and none of them seemed related. Would you please let me know what the output from the generator would look like, or what it would be called, so I can find it? run from the command line in the folder with the jar "java -jar mapgen.jar" - it should print stuff to the console window Share this post Link to post Share on other sites