public string Export(RealmTile[,] tiles) { int w = tiles.GetLength(0); int h = tiles.GetLength(1); byte[] dat = new byte[w * h * 2]; int i = 0; Dictionary <RealmTile, ushort> idxs = new Dictionary <RealmTile, ushort>(new TileComparer()); List <loc> dict = new List <loc>(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { RealmTile tile = tiles[x, y]; if (!idxs.TryGetValue(tile, out ushort idx)) { idxs.Add(tile, idx = (ushort)dict.Count); dict.Add(new loc { ground = RealmTileTypes.id[tile.TileId], objs = tile.TileObj == null ? null : new[] { new obj { id = tile.TileObj, name = tile.Name == null ? null : tile.Name } }, regions = tile.TileId == RealmTileTypes.Beach ? new[] { new obj { id = "Spawn" } } : null }); } dat[i + 1] = (byte)(idx & 0xff); dat[i] = (byte)(idx >> 8); i += 2; } } json_dat ret = new json_dat { data = ZlibStream.CompressBuffer(dat), width = w, height = h, dict = dict.ToArray() }; return(JsonConvert.SerializeObject(ret)); }
private void AddNoiseAndBiome(RealmTile[,] buff, Dictionary <MapPolygon, double> moist) { int w = buff.GetLength(0); int h = buff.GetLength(1); Noise elevationNoise = new Noise(rand.Next()); Noise moistureNoise = new Noise(rand.Next()); //var elevationNoise = PerlinNoise.GetPerlinNoise(rand.Next(), 256, 256, 2); //var moistureNoise = PerlinNoise.GetPerlinNoise(rand.Next(), 256, 256, 2); for (int y = 0; y < w; y++) { for (int x = 0; x < h; x++) { RealmTile tile = buff[x, y]; if (tile.PolygonId != -1) { MapPolygon poly = map.Polygons[tile.PolygonId]; tile.Elevation = Math.Min(1, (float)(poly.DistanceToCoast + poly.DistanceToCoast * elevationNoise.GetNoise(x * 128.0 / w, y * 128.0 / h, 0.3) * 0.01f) * 2); if (tile.Elevation > 1) { tile.Elevation = 1; } else if (tile.Elevation < 0) { tile.Elevation = 0; } tile.Elevation = (float)Math.Pow(tile.Elevation, 1.5); tile.Moisture = (float)(moist[poly] + moist[poly] * moistureNoise.GetNoise(x * 128.0 / w, y * 128.0 / h, 0.3) * 0.01f); if (tile.Moisture > 1) { tile.Moisture = 1; } else if (tile.Moisture < 0) { tile.Moisture = 0; } } tile.Biome = GetBiome(tile); ushort biomeGround = GetBiomeGround(tile.Biome); if (biomeGround != 0) { tile.TileId = biomeGround; } buff[x, y] = tile; } } }
public static byte[] Export(RealmTile[,] tiles) { List <RealmTile> dict = new List <RealmTile>(); int w = tiles.GetLength(0); int h = tiles.GetLength(1); byte[] dat = new byte[w * h * 3]; int idx = 0; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { RealmTile tile = tiles[x, y]; short i = (short)dict.IndexOf(tile); if (i == -1) { i = (short)dict.Count; dict.Add(tile); } dat[idx] = (byte)(i & 0xff); dat[idx + 1] = (byte)(i >> 8); dat[idx + 2] = (byte)(tile.Elevation * 255); idx += 3; } } MemoryStream ms = new MemoryStream(); using (BinaryWriter wtr = new BinaryWriter(ms)) { wtr.Write((short)dict.Count); foreach (var i in dict) { wtr.Write(i.TileId); wtr.Write(i.TileObj ?? ""); wtr.Write(i.Name ?? ""); wtr.Write((byte)i.Terrain); wtr.Write((byte)i.Region); } wtr.Write(w); wtr.Write(h); wtr.Write(dat); } byte[] buff = ZlibStream.CompressBuffer(ms.ToArray()); byte[] ret = new byte[buff.Length + 1]; Buffer.BlockCopy(buff, 0, ret, 1, buff.Length); ret[0] = 2; return(ret); }
private void ComputeSpawnTerrains(RealmTile[,] buff) { int w = buff.GetLength(0); int h = buff.GetLength(1); for (int y = 0; y < w; y++) { for (int x = 0; x < h; x++) { RealmTile tile = buff[x, y]; tile.Terrain = GetBiomeTerrain(tile); buff[x, y] = tile; } } }
private static RealmTile[,] CreateTerrain(int seed, PolygonMap map) { Rasterizer <RealmTile> rasterizer = new Rasterizer <RealmTile>(Size, Size); //Set all to ocean rasterizer.Clear(new RealmTile { PolygonId = -1, Elevation = 0, Moisture = 1, TileId = RealmTileTypes.DeepWater, TileObj = null }); //Render lands poly foreach (MapPolygon poly in map.Polygons.Where(_ => !_.IsWater)) { uint color = 0x00ffffff; color |= (uint)(poly.DistanceToCoast * 255) << 24; rasterizer.FillPolygon( poly.Nodes.SelectMany(_ => { return(new[] { (_.X + 1) / 2 * Size, (_.Y + 1) / 2 * Size }); }).Concat(new[] { (poly.Nodes[0].X + 1) / 2 * Size, (poly.Nodes[0].Y + 1) / 2 * Size }).ToArray(), new RealmTile { PolygonId = poly.Id, Elevation = (float)poly.DistanceToCoast, Moisture = -1, TileId = RealmTileTypes.Grass, TileObj = null }); } MapFeatures fea = new MapFeatures(map, seed); //Render roads IEnumerable <Coordinate[]> roads = fea.GenerateRoads(); foreach (Coordinate[] i in roads) { rasterizer.DrawClosedCurve(i.SelectMany(_ => new[] { (_.X + 1) / 2 * Size, (_.Y + 1) / 2 * Size }).ToArray(), 1, t => { t.TileId = RealmTileTypes.Road; return(t); }, 3); } //Render waters poly foreach (MapPolygon poly in map.Polygons.Where(_ => _.IsWater)) { RealmTile tile = new RealmTile { PolygonId = poly.Id, Elevation = (float)poly.DistanceToCoast, TileObj = null }; if (poly.IsCoast) { tile.TileId = RealmTileTypes.MovingWater; tile.Moisture = 0; } else { tile.TileId = RealmTileTypes.DeepWater; tile.Moisture = 1; } rasterizer.FillPolygon( poly.Nodes.SelectMany(_ => { return(new[] { (_.X + 1) / 2 * Size, (_.Y + 1) / 2 * Size }); }).Concat(new[] { (poly.Nodes[0].X + 1) / 2 * Size, (poly.Nodes[0].Y + 1) / 2 * Size }).ToArray(), tile); } //Render rivers IEnumerable <MapNode[]> rivers = fea.GenerateRivers(); Dictionary <Tuple <MapNode, MapNode>, int> edges = new Dictionary <Tuple <MapNode, MapNode>, int>(); foreach (MapNode[] i in rivers) { for (int j = 1; j < i.Length; j++) { Tuple <MapNode, MapNode> edge = new Tuple <MapNode, MapNode>(i[j - 1], i[j]); if (edges.TryGetValue(edge, out int count)) { count++; } else { count = 1; } edges[edge] = count; } } foreach (KeyValuePair <Tuple <MapNode, MapNode>, int> i in edges) { i.Key.Item1.IsWater = true; i.Key.Item1.RiverValue = i.Value + 1; i.Key.Item2.IsWater = true; i.Key.Item2.RiverValue = i.Value + 1; rasterizer.DrawLineBresenham( (i.Key.Item1.X + 1) / 2 * Size, (i.Key.Item1.Y + 1) / 2 * Size, (i.Key.Item2.X + 1) / 2 * Size, (i.Key.Item2.Y + 1) / 2 * Size, t => { t.TileId = RealmTileTypes.Water; t.Elevation = (float)(i.Key.Item1.DistanceToCoast + i.Key.Item2.DistanceToCoast) / 2; t.Moisture = 1; return(t); }, 3 * Math.Min(2, i.Value)); } return(rasterizer.Buffer); }
public static byte[] Convert(EmbeddedData data, string json) { var obj = JsonConvert.DeserializeObject <json_dat>(json); var dat = ZlibStream.UncompressBuffer(obj.data); Dictionary <short, RealmTile> tileDict = new Dictionary <short, RealmTile>(); for (int i = 0; i < obj.dict.Length; i++) { var o = obj.dict[i]; tileDict[(short)i] = new RealmTile() { TileId = o.ground == null ? (ushort)0xff : data.IdToTileType[o.ground], TileObj = o.objs == null ? null : o.objs[0].id, Name = o.objs == null ? "" : o.objs[0].name ?? "", Terrain = RealmTerrainType.None, Region = o.regions == null ? RealmTileRegion.None : (RealmTileRegion)Enum.Parse(typeof(RealmTileRegion), o.regions[0].id.Replace(' ', '_')) }; } var tiles = new RealmTile[obj.width, obj.height]; //creates a new case insensitive dictionary based on the XmlDatas Dictionary <string, ushort> icdatas = new Dictionary <string, ushort>( data.IdToObjectType, StringComparer.OrdinalIgnoreCase); using (NReader rdr = new NReader(new MemoryStream(dat))) for (int y = 0; y < obj.height; y++) { for (int x = 0; x < obj.width; x++) { tiles[x, y] = tileDict[rdr.ReadInt16()]; if (tiles[x, y].TileId.ToString().Length == 2) { File.AppendAllText("Tiles.txt", tiles[x, y].TileId.ToString() + " "); } else if (String.IsNullOrEmpty(tiles[x, y].TileId.ToString())) { File.AppendAllText("Tiles.txt", " "); } else { File.AppendAllText("Tiles.txt", tiles[x, y].TileId.ToString() + " "); } if (tiles[x, y].TileObj == null) { File.AppendAllText("Objects.txt", " "); } else { if (!icdatas.TryGetValue(tiles[x, y].TileObj, out ushort objType) || !data.ObjectDescs.ContainsKey(objType)) { } if (objType.ToString().Length == 3) { File.AppendAllText("Objects.txt", objType.ToString() + " "); } else { File.AppendAllText("Objects.txt", objType.ToString() + " "); } } } File.AppendAllText("Objects.txt", Environment.NewLine); File.AppendAllText("Tiles.txt", Environment.NewLine); } return(WorldMapExporter.Export(tiles)); }
private void Randomize(RealmTile[,] buff) { int w = buff.GetLength(0); int h = buff.GetLength(1); RealmTile[,] tmp = (RealmTile[, ])buff.Clone(); for (int y = 10; y < h - 10; y++) { for (int x = 10; x < w - 10; x++) { RealmTile tile = buff[x, y]; if (tile.TileId == RealmTileTypes.Water && tile.Elevation >= elevationThreshold[3]) { tile.TileId = RealmTileTypes.SnowRock; } else if (tile.TileId != RealmTileTypes.Water && tile.TileId != RealmTileTypes.Road && tile.TileId != RealmTileTypes.Beach && tile.TileId != RealmTileTypes.MovingWater && tile.TileId != RealmTileTypes.DeepWater) { ushort id = tmp[x + rand.Next(-3, 4), y + rand.Next(-3, 4)].TileId; while (id == RealmTileTypes.Water || id == RealmTileTypes.Road || id == RealmTileTypes.Beach || id == RealmTileTypes.MovingWater || id == RealmTileTypes.DeepWater) { id = tmp[x + rand.Next(-3, 4), y + rand.Next(-3, 4)].TileId; } tile.TileId = id; } string biome = tile.Biome; if (tile.TileId == RealmTileTypes.Beach) { biome = "beach"; } else if (tile.TileId == RealmTileTypes.MovingWater) { biome = "coast"; } string biomeObj = Decoration.GetDecor(biome, rand); if (biomeObj != null) { tile.TileObj = biomeObj; int?size = Decoration.GetSize(biomeObj, rand); if (size != null) { tile.Name = "size:" + size; } } float elevation = 0; int c = 0; for (int dy = -1; dy <= 1; dy++) { for (int dx = -1; dx <= 1; dx++) { if (x + dx < 0 || x + dx >= w || y + dy < 0 || y + dy >= h) { continue; } elevation += tmp[x + dx, y + dy].Elevation; c++; } } tile.Elevation = elevation / c; buff[x, y] = tile; } } }
private string GetBiome(RealmTile tile) { if (tile.PolygonId == -1) { return("unknown"); } if (tile.TileId == RealmTileTypes.Road) { return("road"); } if (tile.TileId == RealmTileTypes.Water) { return("river"); } MapPolygon poly = map.Polygons[tile.PolygonId]; if (tile.TileId == 0xb4) { return("towel"); } if (beaches.Contains(poly)) { return("beach"); } if (poly.IsWater) { if (poly.IsCoast) { return("coast"); } if (poly.IsOcean) { return("ocean"); } return("water"); } if (tile.Elevation >= elevationThreshold[3]) { if (tile.Moisture > moistureThreshold[4]) { return("snowy"); } return("mountain"); } if (tile.Elevation > elevationThreshold[2]) { if (tile.Moisture > moistureThreshold[4]) { return("dryland"); } if (tile.Moisture > moistureThreshold[2]) { return("taiga"); } return("desert"); } if (tile.Elevation > elevationThreshold[1]) { if (tile.Moisture > moistureThreshold[4]) { return("forest"); } if (tile.Moisture > moistureThreshold[2]) { return("shrub"); } return("desert"); } if (tile.Moisture > moistureThreshold[4]) { return("rainforest"); } if (tile.Moisture > moistureThreshold[3]) { return("forest"); } if (tile.Moisture > moistureThreshold[2]) { return("grassland"); } return("desert"); //return "unknown"; }
private RealmTerrainType GetBiomeTerrain(RealmTile tile) { if (tile.PolygonId == -1 || tile.TileId == RealmTileTypes.Road || tile.TileId == RealmTileTypes.Water) { return(RealmTerrainType.None); } MapPolygon poly = map.Polygons[tile.PolygonId]; if (!poly.IsWater && beaches.Contains(poly)) { return(RealmTerrainType.ShoreSand); } if (poly.IsWater) { return(RealmTerrainType.None); } if (tile.Elevation >= elevationThreshold[3]) { return(RealmTerrainType.Mountains); } if (tile.Elevation > elevationThreshold[2]) { if (tile.Moisture > moistureThreshold[4]) { return(RealmTerrainType.HighPlains); } if (tile.Moisture > moistureThreshold[2]) { return(RealmTerrainType.HighForest); } return(RealmTerrainType.HighSand); } if (tile.Elevation > elevationThreshold[1]) { if (tile.Moisture > moistureThreshold[4]) { return(RealmTerrainType.MidForest); } if (tile.Moisture > moistureThreshold[2]) { return(RealmTerrainType.MidPlains); } return(RealmTerrainType.MidSand); } if (poly.Neighbour.Any(_ => beaches.Contains(_))) { if (tile.Moisture > moistureThreshold[2]) { return(RealmTerrainType.ShorePlains); } } if (tile.Moisture > moistureThreshold[3]) { return(RealmTerrainType.LowForest); } if (tile.Moisture > moistureThreshold[2]) { return(RealmTerrainType.LowPlains); } return(RealmTerrainType.LowSand); //return TerrainType.None; }