Created
May 8, 2017 03:20
-
-
Save spacechase0/c2966360e12425cf1702b7ce366f54db to your computer and use it in GitHub Desktop.
Stardew Valley: Load a Tiled map file directly
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
// You will need "TiledNet" from NuGet. (Also found here: https://github.com/napen123/Tiled.Net) | |
using Tiled; | |
private class TileMapping | |
{ | |
public TileSheet tileSheet = null; | |
public int tileId = 0; | |
public TileMapping() { } | |
public TileMapping( TileSheet ts, int id ) | |
{ | |
tileSheet = ts; | |
tileId = id; | |
} | |
} | |
public static Map loadMap(string mapName) | |
{ | |
var tmap = new TiledMap(Path.Combine(Mod.instance.Helper.DirectoryPath, "locations/" + mapName + "/map.tmx")); | |
var xmap = new Map(mapName); | |
addTiledPropertiesToXTile(tmap.Properties, xmap.Properties); | |
var tileMapping = new Dictionary<int, TileMapping>(); | |
foreach ( var ttileSheet in tmap.Tilesets ) | |
{ | |
// xTile wants things like "Mines/mine", not "Mines/mine.png" | |
string image = ttileSheet.Image.Source; | |
if (image.EndsWith(".png")) | |
image = image.Substring(0, image.Length - 4); | |
var xtileSheet = new TileSheet(xmap, image, new Size(ttileSheet.Columns, ttileSheet.TileCount / ttileSheet.Columns), new Size(tmap.TileWidth, tmap.TileHeight)); | |
addTiledPropertiesToXTile(ttileSheet.Properties, xtileSheet.Properties); | |
xtileSheet.Id = ttileSheet.Name; | |
xtileSheet.Spacing = new Size( ttileSheet.Spacing, ttileSheet.Spacing); | |
xtileSheet.Margin = new Size(ttileSheet.Margin, ttileSheet.Margin); | |
for (int i = 0; i < ttileSheet.TileCount; ++i) | |
{ | |
tileMapping.Add(ttileSheet.FirstGlobalId + i, new TileMapping(xtileSheet, i)); | |
} | |
foreach (var ttile in ttileSheet.Tiles) | |
{ | |
addTiledPropertiesToXTile(ttile.Properties, xtileSheet.TileIndexProperties[ttile.Id - ttileSheet.FirstGlobalId]); | |
} | |
xmap.AddTileSheet(xtileSheet); | |
} | |
var tobjectGroups = new List<TiledObjectGroup>(); | |
foreach (var tlayer_ in tmap.Layers) | |
{ | |
if (tlayer_ is TiledTileLayer) | |
{ | |
var tlayer = tlayer_ as TiledTileLayer; | |
// Note that the tile size needs to be * 4. Otherwise, you will break collisions and many other things. | |
// Yes, even if you don't use the loaded map. Creating the layer is enough. | |
// For some reason vanilla has a tilesize of 16 for tilesheets, but 64 for the layers. | |
// I mean, I knew the game was scaled up, but that's kinda odd. | |
// Anyways, whenever you create a layer with a different tile size, it changes the tile size | |
// of EVERY OTHER LAYER IN EXISTANCE to match. And guess what, that breaks things. | |
// I spent hours figuring this out. I don't care about the underlying cause. I just want to mod. | |
var xlayer = new Layer(tlayer.Name, xmap, new Size(tmap.Width, tmap.Height), new Size(tmap.TileWidth * 4, tmap.TileHeight * 4)); | |
addTiledPropertiesToXTile(tlayer.Properties, xlayer.Properties); | |
if (tlayer.Data.Compression != TiledData.CompressionType.NoCompression) | |
throw new InvalidDataException("Compressed tile data is not supported."); | |
if (tlayer.Data.Encoding == TiledData.EncodingType.NoEncoding || tlayer.Data.Encoding == TiledData.EncodingType.Xml) | |
{ | |
for (int i = 0; i < tlayer.Data.Tiles.Count; ++i) | |
{ | |
var ttile = tlayer.Data.Tiles[i]; | |
int ix = i % tmap.Width; | |
int iy = i / tmap.Width; | |
var xtile = new StaticTile(xlayer, tileMapping[ttile.GlobalId].tileSheet, BlendMode.Alpha, tileMapping[ttile.GlobalId].tileId); | |
xlayer.Tiles[ix, iy] = xtile; | |
} | |
} | |
else if (tlayer.Data.Encoding == TiledData.EncodingType.Csv) | |
{ | |
string[] ttiles = string.Join("", tlayer.Data.Data).Split(','); | |
for (int i = 0; i < ttiles.Length; ++i) | |
{ | |
var ttile = int.Parse(ttiles[i]); | |
if (!tileMapping.ContainsKey(ttile)) | |
continue; | |
int ix = i % tmap.Width; | |
int iy = i / tmap.Width; | |
var xtile = new StaticTile(xlayer, tileMapping[ttile].tileSheet, BlendMode.Alpha, tileMapping[ttile].tileId); | |
xlayer.Tiles[ix, iy] = xtile; | |
} | |
} | |
else throw new InvalidDataException("Tile data encoding type " + tlayer.Data.Encoding + " not supported."); | |
xmap.AddLayer(xlayer); | |
} | |
else if (tlayer_ is TiledObjectGroup) | |
{ | |
tobjectGroups.Add(tlayer_ as TiledObjectGroup); | |
} | |
} | |
foreach ( var tobjectGroup in tobjectGroups ) | |
{ | |
var xlayer = xmap.GetLayer(tobjectGroup.Name); | |
if (xlayer == null) | |
continue; | |
foreach (var tobj in tobjectGroup.Objects) | |
{ | |
if (tobj.Name != "TileData" || tobj.Width != tmap.TileWidth || tobj.Height != tmap.TileWidth || tobj.Properties.Count == 0) | |
continue; | |
int x = (int)tobj.X / tmap.TileWidth; | |
int y = (int)tobj.Y / tmap.TileWidth; | |
if (xlayer.Tiles[new Location(x, y)] == null) | |
{ | |
Log.warn("Tile property for non-existant tile; skipping"); | |
continue; | |
} | |
addTiledPropertiesToXTile(tobj.Properties, xlayer.Tiles[new Location(x, y)].Properties); | |
} | |
} | |
return xmap; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment