public static List <TiledMapLayer> BuildLayers(MapData2D map, TilesetData tileset, ref int nextLayerId) { var underlayId = nextLayerId++; var overlayId = nextLayerId++; return(new() { new() { Id = underlayId, Name = LayerName.Underlay, Width = map.Width, Height = map.Height, Data = new LayerData { Encoding = "csv", Content = BuildCsvData(map, tileset, false) } }, new() { Id = overlayId, Name = LayerName.Overlay, Width = map.Width, Height = map.Height, Data = new LayerData { Encoding = "csv", Content = BuildCsvData(map, tileset, true) } } }); }
void Write(BaseMapData existing, AssetInfo info, ISerializer s) { (byte[] bytes, string script) = existing switch { MapData2D map2d => Write2D(map2d, info), MapData3D map3d => Write3D(map3d, info), _ => (null, null) }; if (bytes != null) { s.Bytes(null, bytes, bytes.Length); } var disk = Resolve <IFileSystem>(); var scriptPattern = info.Get(AssetProperty.ScriptPattern, ""); if (script == null || string.IsNullOrEmpty(scriptPattern)) { return; } // TODO: Find a less hacky way of doing this var scriptPath = info.BuildFilename(scriptPattern, 0); var assetDir = GetAssetDir(info); if (!disk.DirectoryExists(assetDir)) { disk.CreateDirectory(assetDir); } disk.WriteAllText(Path.Combine(assetDir, scriptPath), script); }
public MapRenderable2D(MapData2D mapData, ITexture tileset, TilesetData tileData) : base(Handlers) { _mapData = mapData; _tileset = tileset; _tileData = tileData; _tileset.GetSubImageDetails(0, out var tileSize, out _, out _, out _); TileSize = tileSize; var underlay = new SpriteInstanceData[_mapData.Width * _mapData.Height]; var overlay = new SpriteInstanceData[_mapData.Width * _mapData.Height]; _underlay = new MultiSprite(new SpriteKey( _tileset, (int)DrawLayer.Underlay, underlay[0].Flags)) { Instances = underlay.ToArray() }; _overlay = new MultiSprite(new SpriteKey( _tileset, (int)DrawLayer.Overlay3, overlay[0].Flags)) { Instances = overlay.ToArray() }; }
static IEnumerable <ObjectGroup> BuildTriggers( MapData2D map, TilemapProperties properties, EventFormatter eventFormatter, ref int nextObjectGroupId, ref int nextObjectId) { var objectGroups = new List <ObjectGroup>(); var regions = TriggerZoneBuilder.BuildZones(map); var groupedByTriggerType = regions .Where(x => x.Item1.Chain != null) .GroupBy(x => x.Item1.Trigger) .OrderBy(x => x.Key); foreach (var triggerType in groupedByTriggerType) { objectGroups.Add(BuildTriggerObjectGroup( nextObjectGroupId++, $"T:{triggerType.Key}", triggerType, properties, eventFormatter, ref nextObjectId)); } return(objectGroups); }
public LogicalMap2D(IAssetManager assetManager, MapData2D mapData, IList <MapChange> tempChanges, IList <MapChange> permChanges) { _mapData = mapData ?? throw new ArgumentNullException(nameof(mapData)); _tempChanges = tempChanges ?? throw new ArgumentNullException(nameof(tempChanges)); _permChanges = permChanges ?? throw new ArgumentNullException(nameof(permChanges)); _tileData = assetManager.LoadTileData(_mapData.TilesetId); _blockList = assetManager.LoadBlockList((BlockListId)_mapData.TilesetId); // Note: Assuming a 1:1 correspondence between blocklist and tileset ids. UseSmallSprites = _tileData.UseSmallGraphics; // Clear out temp changes for other maps for (int i = 0; i < tempChanges.Count;) { if (_tempChanges[i].MapId != mapData.Id) { _tempChanges.RemoveAt(i); } else { i++; } } // Replay any changes for this map foreach (var change in permChanges.Where(x => x.MapId == mapData.Id)) { ApplyChange(change.X, change.Y, change.ChangeType, change.Value, change.Unk3); } foreach (var change in tempChanges) { ApplyChange(change.X, change.Y, change.ChangeType, change.Value, change.Unk3); } }
public MapRenderable2D(MapData2D mapData, ITexture tileset, TilesetData tileData) : base(Handlers) { _mapData = mapData; _tileset = tileset; _tileData = tileData; _tileset.GetSubImageDetails(0, out var tileSize, out _, out _, out _); TileSize = tileSize; }
public static (Map, string) FromAlbionMap2D( MapData2D map, TilesetData tileset, Tilemap2DProperties properties, string tilesetPath, Tileset npcTileset, EventFormatter eventFormatter) { if (map == null) { throw new ArgumentNullException(nameof(map)); } if (tileset == null) { throw new ArgumentNullException(nameof(tileset)); } if (properties == null) { throw new ArgumentNullException(nameof(properties)); } if (npcTileset == null) { throw new ArgumentNullException(nameof(npcTileset)); } ushort blankTileIndex = 0; int nextObjectId = 1; int nextLayerId = 3; // 1 & 2 are always underlay & overlay. npcTileset.GidOffset = tileset.Tiles.Count; var(script, functionsByEventId) = BuildScript(map, eventFormatter); var result = new Map { TiledVersion = "1.4.2", Version = "1.4", Width = map.Width, Height = map.Height, TileWidth = properties.TileWidth, TileHeight = properties.TileHeight, Infinite = 0, NextLayerId = 5, // max(layer or objectgroup id) + 1 Orientation = "orthogonal", RenderOrder = "right-down", BackgroundColor = "#000000", Properties = BuildMapProperties(map), Tilesets = new List <MapTileset> { new() { FirstGid = 0, Source = tilesetPath, }, new() { FirstGid = npcTileset.GidOffset, Source = npcTileset.Filename } },
public LogicalMap2D( IAssetManager assetManager, MapData2D mapData, MapChangeCollection tempChanges, MapChangeCollection permChanges) : base(mapData, tempChanges, permChanges) { if (assetManager == null) { throw new ArgumentNullException(nameof(assetManager)); } _mapData = mapData ?? throw new ArgumentNullException(nameof(mapData)); _tileData = assetManager.LoadTileData(_mapData.TilesetId); _blockList = assetManager.LoadBlockList(_mapData.TilesetId.ToBlockList()); UseSmallSprites = _tileData.UseSmallGraphics; }
public IMapData Serdes(IMapData existing, ISerializer s, AssetKey key, AssetInfo config) { var startPosition = s.Offset; s.UInt16("DummyRead", 0); // Initial flags + npc count, will be re-read by the 2D/3D specific map loader MapType mapType = s.EnumU8(nameof(mapType), existing?.MapType ?? MapType.Unknown); s.Seek(startPosition); return(mapType switch { MapType.TwoD => MapData2D.Serdes((MapData2D)existing, s, config), MapType.TwoDOutdoors => MapData2D.Serdes((MapData2D)existing, s, config), MapType.ThreeD => MapData3D.Serdes((MapData3D)existing, s, config), _ => throw new NotImplementedException($"Unrecognised map type {mapType} found.") });
public FlatMap(MapId mapId, MapData2D mapData) { On <PlayerEnteredTileEvent>(OnPlayerEnteredTile); On <NpcEnteredTileEvent>(OnNpcEnteredTile); On <ChangeIconEvent>(ChangeIcon); On <MapInitEvent>(e => FireEventChains(TriggerTypes.MapInit, true)); On <SlowClockEvent>(e => FireEventChains(TriggerTypes.EveryStep, false)); On <HourElapsedEvent>(e => FireEventChains(TriggerTypes.EveryHour, true)); On <DayElapsedEvent>(e => FireEventChains(TriggerTypes.EveryDay, true)); On <DisableEventChainEvent>(e => _logicalMap.DisableChain(e.ChainNumber)); On <PartyChangedEvent>(e => RebuildPartyMembers()); // On<UnloadMapEvent>(e => Unload()); MapId = mapId; _mapData = mapData ?? throw new ArgumentNullException(nameof(mapData)); }
public object Load(BinaryReader br, long streamLength, string name, AssetInfo config) { var startPosition = br.BaseStream.Position; br.ReadUInt16(); // Initial flags + npc count, will be re-read by the 2D/3D specific map loader int mapType = br.ReadByte(); br.BaseStream.Position = startPosition; switch (mapType) { case 1: return(MapData3D.Load(br, streamLength, name)); case 2: return(MapData2D.Load(br, streamLength, name)); default: throw new NotImplementedException($"Unrecognised map type {mapType} found."); } }
IMap BuildMap(MapId mapId) { var assets = Resolve <IAssetManager>(); var game = Resolve <IGameState>(); var mapData = assets.LoadMap(mapId); if (mapData == null) { return(null); } return(mapData switch { MapData2D map2d => new Entities.Map2D.FlatMap(mapId, map2d), MapData3D map3d => new Entities.Map3D.DungeonMap(mapId, map3d), _ => null });
public override void Subscribed() { if (_mapData == null) { var assets = Resolve <IAssetManager>(); _mapData = assets.LoadMap2D(MapId); var tileset = assets.LoadTexture((IconGraphicsId)_mapData.TilesetId); _tileData = assets.LoadTileData((IconDataId)_mapData.TilesetId); _renderable = new MapRenderable2D(_mapData, tileset, _tileData); _useSmallSprites = _tileData.UseSmallGraphics; Exchange.Attach(_renderable); Children.Add(_renderable); foreach (var npc in _mapData.Npcs) { IComponent sprite = _useSmallSprites ? new SmallNpc((SmallNpcId)npc.ObjectNumber, npc.Waypoints) as IComponent : new LargeNpc((LargeNpcId)npc.ObjectNumber, npc.Waypoints); Exchange.Attach(sprite); Children.Add(sprite); } IMovement partyMovement = new PartyMovement(_useSmallSprites, Vector2.Zero, PartyMovement.Direction.Right); // TODO: Initial position. Exchange.Register(partyMovement); Children.Add(partyMovement); var state = Resolve <IGameState>(); foreach (var player in state.Party.StatusBarOrder) { player.GetPosition = () => partyMovement.GetPositionHistory(player.Id).Item1; var playerSprite = _useSmallSprites ? (IComponent) new SmallPlayer(player.Id, (SmallPartyGraphicsId)player.Id, () => partyMovement.GetPositionHistory(player.Id)) // TODO: Use a function to translate logical to sprite id : new LargePlayer(player.Id, (LargePartyGraphicsId)player.Id, () => partyMovement.GetPositionHistory(player.Id)); // TODO: Use a function to translate logical to sprite id Exchange.Attach(playerSprite); Children.Add(playerSprite); } } Raise(new SetClearColourEvent(0, 0, 0)); }
static string BuildCsvData(MapData2D map, TilesetData tileset, bool useOverlay) { var sb = new StringBuilder(); for (int j = 0; j < map.Height; j++) { for (int i = 0; i < map.Width; i++) { int index = j * map.Width + i; var tileIndex = useOverlay ? map.Overlay[index] : map.Underlay[index]; var tile = tileset.Tiles[tileIndex]; sb.Append(tile.IsBlank ? BlankTileIndex : tileIndex); sb.Append(','); } sb.AppendLine(); } return(sb.ToString(0, sb.Length - (Environment.NewLine.Length + 1))); }
void Write(BaseMapData existing, AssetInfo info, ISerializer s) { (byte[] bytes, string script) = existing switch { MapData2D map2d => Write2D(map2d, info), MapData3D map3d => Write3D(map3d, info), _ => (null, null) }; if (bytes != null) { s.Bytes(null, bytes, bytes.Length); } else { Warn($"No bytes were generated when saving map {info.Id}"); } if (script == null) { Warn($"No script for map {info.Id}, aborting script output"); return; } var scriptPath = GetScriptFilename(info); if (string.IsNullOrEmpty(scriptPath)) { Warn($"No script path was set for map {info.Id}, aborting script output"); return; } var disk = Resolve <IFileSystem>(); var assetDir = GetAssetDir(info); if (!disk.DirectoryExists(assetDir)) { disk.CreateDirectory(assetDir); } disk.WriteAllText(Path.Combine(assetDir, scriptPath), script); }
public LogicalMap2D( IAssetManager assetManager, MapData2D mapData, MapChangeCollection tempChanges, MapChangeCollection permChanges) { if (assetManager == null) { throw new ArgumentNullException(nameof(assetManager)); } _mapData = mapData ?? throw new ArgumentNullException(nameof(mapData)); _tempChanges = tempChanges ?? throw new ArgumentNullException(nameof(tempChanges)); _permChanges = permChanges ?? throw new ArgumentNullException(nameof(permChanges)); _tileData = assetManager.LoadTileData(_mapData.TilesetId); _blockList = assetManager.LoadBlockList(_mapData.TilesetId.ToBlockList()); UseSmallSprites = _tileData.UseSmallGraphics; // Clear out temp changes for other maps for (int i = 0; i < tempChanges.Count;) { if (_tempChanges[i].MapId != mapData.Id) { _tempChanges.RemoveAt(i); } else { i++; } } // Replay any changes for this map foreach (var change in permChanges.Where(x => x.MapId == mapData.Id)) { ApplyChange(change.X, change.Y, change.ChangeType, change.Value); } foreach (var change in tempChanges) { ApplyChange(change.X, change.Y, change.ChangeType, change.Value); } }
IMap BuildMap(MapId mapId) { var assets = Resolve <IAssetManager>(); var game = Resolve <IGameState>(); var mapData = assets.LoadMap(mapId); if (mapData == null) { return(null); } mapData.AttachEventSets( x => game.GetSheet(x), x => assets.LoadEventSet(x)); return(mapData switch { MapData2D map2d => new Entities.Map2D.FlatMap(mapId, map2d), MapData3D map3d => new Entities.Map3D.DungeonMap(mapId, map3d), _ => null });
public FlatMapEditor(string name, MapData2D map) : base(map) { _name = name; _map = map ?? throw new ArgumentNullException(nameof(map)); }
public static (Map, string) FromAlbionMap2D( MapData2D map, TilesetData tileset, Tilemap2DProperties properties, string tilesetPath, Tileset npcTileset, EventFormatter eventFormatter) { if (map == null) { throw new ArgumentNullException(nameof(map)); } if (tileset == null) { throw new ArgumentNullException(nameof(tileset)); } if (properties == null) { throw new ArgumentNullException(nameof(properties)); } if (npcTileset == null) { throw new ArgumentNullException(nameof(npcTileset)); } int npcGidOffset = tileset.Tiles.Count; var(script, functionsByEventId) = BuildScript(map, eventFormatter); (int?tileId, int w, int h) GetNpcTileInfo(AssetId id) { var assetName = id.ToString(); var tile = npcTileset.Tiles.FirstOrDefault(x => x.Properties.Any(p => p.Name == NpcMapping.Prop.Visual && p.Value == assetName)); return( tile?.Id + npcGidOffset ?? 0, tile?.Image.Width ?? properties.TileWidth, tile?.Image.Height ?? properties.TileHeight); } int nextObjectId = 1; int nextLayerId = 1; var result = new Map { TiledVersion = "1.4.2", Version = "1.4", Width = map.Width, Height = map.Height, TileWidth = properties.TileWidth, TileHeight = properties.TileHeight, Infinite = 0, Orientation = "orthogonal", RenderOrder = "right-down", BackgroundColor = "#000000", Properties = MapMapping.BuildMapProperties(map), Tilesets = new List <MapTileset> { new() { FirstGid = 0, Source = tilesetPath, }, new() { FirstGid = npcGidOffset, Source = npcTileset.Filename } },
public static Map FromAlbionMap( MapData2D map, TilesetData tileset, TilemapProperties properties, string tilesetPath, Tileset npcTileset, EventFormatter eventFormatter) { if (map == null) { throw new ArgumentNullException(nameof(map)); } if (tileset == null) { throw new ArgumentNullException(nameof(tileset)); } if (properties == null) { throw new ArgumentNullException(nameof(properties)); } if (npcTileset == null) { throw new ArgumentNullException(nameof(npcTileset)); } ushort blankTileIndex = (ushort)(tileset.Tiles.Max(x => x.ImageNumber + x.FrameCount - 1) + 1); int nextObjectId = 1; int nextObjectGroupId = 3; // 1 & 2 are always underlay & overlay. npcTileset.GidOffset = tileset.Tiles.Count + 1; return(new Map { TiledVersion = "1.4.2", Version = "1.4", Width = map.Width, Height = map.Height, TileWidth = properties.TileWidth, TileHeight = properties.TileHeight, Infinite = 0, NextLayerId = 5, // max(layer or objectgroup id) + 1 NextObjectId = 1, Orientation = "orthogonal", RenderOrder = "right-down", BackgroundColor = "#000000", Tilesets = new List <MapTileset> { new MapTileset { FirstGid = 1, Source = tilesetPath, }, new MapTileset { FirstGid = npcTileset.GidOffset, Source = npcTileset.Filename } }, Layers = new List <MapLayer> { new MapLayer { Id = 1, Name = "Underlay", Width = map.Width, Height = map.Height, Data = new LayerData { Encoding = "csv", Content = BuildCsvData(map, tileset, false, blankTileIndex) } }, new MapLayer { Id = 2, Name = "Overlay", Width = map.Width, Height = map.Height, Data = new LayerData { Encoding = "csv", Content = BuildCsvData(map, tileset, true, blankTileIndex) } } }, ObjectGroups = new[] { BuildTriggers(map, properties, eventFormatter, ref nextObjectGroupId, ref nextObjectId), BuildNpcs(map, properties, eventFormatter, npcTileset, ref nextObjectGroupId, ref nextObjectId) }.SelectMany(x => x).ToList() }); }
public static BaseMapData ToAlbion(this Map map, AssetInfo info, string script) { if (map == null) { throw new ArgumentNullException(nameof(map)); } if (info == null) { throw new ArgumentNullException(nameof(info)); } // Check width/height <= 255 if (map.Width > 255) { throw new FormatException($"Map widths above 255 are not currently supported (was {map.Width})"); } if (map.Height > 255) { throw new FormatException($"Map heights above 255 are not currently supported (was {map.Height})"); } bool is3d = map.Orientation == "isometric"; var mapId = (MapId)info.AssetId; var eventLayout = AlbionCompiler.Compile(script, mapId.ToMapText()); List <TriggerInfo> triggers = new(); List <MapNpc> npcs = new(); List <MapEventZone> zones = new(); List <AutomapInfo> markers = new(); List <byte> markerTiles = new(); ObjectGroupMapping.LoadObjectGroups( info, map, is3d ? map.TileHeight : map.TileWidth, map.TileHeight, eventLayout, triggers, npcs, zones, markers, markerTiles); var paletteId = MapperUtil.PropId(map, MapMapping.Prop.Palette, true); BaseMapData albionMap; if (is3d) { var labId = MapperUtil.PropId(map, MapMapping.Prop.Labyrinth, true); var map3d = new MapData3D(info.AssetId, paletteId, labId, (byte)map.Width, (byte)map.Height, eventLayout.Events, eventLayout.Chains, npcs, zones); LayerMapping3D.ReadLayers(map3d, map.Layers); for (int i = 0; i < markerTiles.Count; i++) { map3d.AutomapGraphics[i] = markerTiles[i]; } map3d.Automap.Clear(); map3d.Automap.AddRange(markers); albionMap = map3d; } else { var tilesetId = MapperUtil.PropId(map, MapMapping.Prop.Tileset, true); albionMap = new MapData2D(info.AssetId, paletteId, tilesetId, (byte)map.Width, (byte)map.Height, eventLayout.Events, eventLayout.Chains, npcs, zones) { RawLayout = LayerMapping2D.ReadLayout(map) }; } MapMapping.ReadMapProperties(albionMap, map); return(albionMap); }