Skip to content

Commit

Permalink
Update map warp file downloads to use new in-game handling of init pa…
Browse files Browse the repository at this point in the history
…ckets. Fixes crashes when warping to an undownloaded map.
  • Loading branch information
ethanmoffat committed May 28, 2022
1 parent deb186a commit e74e189
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 41 deletions.
15 changes: 15 additions & 0 deletions EOLib/Domain/Map/CurrentMapStateRepository.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AutomaticTypeMapper;
using Optional;
using System.Collections.Generic;

namespace EOLib.Domain.Map
Expand All @@ -25,6 +26,10 @@ public interface ICurrentMapStateRepository

WarpState MapWarpState { get; set; }

Option<short> MapWarpSession { get; set; }

Option<short> MapWarpID { get; set; }

HashSet<short> UnknownPlayerIDs { get; set; }

HashSet<byte> UnknownNPCIndexes { get; set; }
Expand Down Expand Up @@ -52,6 +57,10 @@ public interface ICurrentMapStateProvider

WarpState MapWarpState { get; }

Option<short> MapWarpSession { get; }

Option<short> MapWarpID { get; }

HashSet<short> UnknownPlayerIDs { get; }

HashSet<byte> UnknownNPCIndexes { get; }
Expand Down Expand Up @@ -80,6 +89,10 @@ public class CurrentMapStateRepository : ICurrentMapStateRepository, ICurrentMap

public WarpState MapWarpState { get; set; }

public Option<short> MapWarpSession { get; set; }

public Option<short> MapWarpID { get; set; }

public HashSet<short> UnknownPlayerIDs { get; set; }

public HashSet<byte> UnknownNPCIndexes { get; set; }
Expand Down Expand Up @@ -117,6 +130,8 @@ public void ResetState()
UnknownNPCIndexes = new HashSet<byte>();

MapWarpState = WarpState.None;
MapWarpSession = Option.None<short>();
MapWarpID = Option.None<short>();
}
}
}
36 changes: 18 additions & 18 deletions EOLib/Net/FileTransfer/FileRequestActions.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
using System;
using System.Threading.Tasks;
using AutomaticTypeMapper;
using EOLib.Domain.Login;
using EOLib.Domain.Map;
using EOLib.Domain.Protocol;
using EOLib.IO;
using EOLib.IO.Map;
using EOLib.IO.Pub;
using EOLib.IO.Repositories;
using EOLib.IO.Services;
using Optional;
using System;
using System.Threading.Tasks;

namespace EOLib.Net.FileTransfer
{
Expand All @@ -21,6 +22,7 @@ public class FileRequestActions : IFileRequestActions
private readonly ILoginFileChecksumProvider _loginFileChecksumProvider;
private readonly IPubFileRepository _pubFileRepository;
private readonly IMapFileRepository _mapFileRepository;
private readonly ICurrentMapStateRepository _currentMapStateRepository;
private readonly IPlayerInfoProvider _playerInfoProvider;

public FileRequestActions(INumberEncoderService numberEncoderService,
Expand All @@ -30,6 +32,7 @@ public FileRequestActions(INumberEncoderService numberEncoderService,
ILoginFileChecksumProvider loginFileChecksumProvider,
IPubFileRepository pubFileRepository,
IMapFileRepository mapFileRepository,
ICurrentMapStateRepository currentMapStateRepository,
IPlayerInfoProvider playerInfoProvider)
{
_numberEncoderService = numberEncoderService;
Expand All @@ -39,6 +42,7 @@ public FileRequestActions(INumberEncoderService numberEncoderService,
_loginFileChecksumProvider = loginFileChecksumProvider;
_pubFileRepository = pubFileRepository;
_mapFileRepository = mapFileRepository;
_currentMapStateRepository = currentMapStateRepository;
_playerInfoProvider = playerInfoProvider;
}

Expand All @@ -58,16 +62,22 @@ public bool NeedsMapForWarp(short mapID, byte[] mapRid, int fileSize)
return NeedMap(mapID, expectedChecksum, fileSize);
}

public async Task GetMapForWarp(short mapID, short sessionID)
public void RequestMapForWarp(short mapID, short sessionID)
{
var mapFile = await _fileRequestService.RequestMapFileForWarp(mapID, sessionID);
SaveAndCacheMapFile(mapID, mapFile);
_fileRequestService.RequestMapFileForWarp(mapID, sessionID);
_currentMapStateRepository.MapWarpSession = Option.Some(sessionID);
_currentMapStateRepository.MapWarpID = Option.Some(mapID);
}

public async Task GetMapFromServer(short mapID, short sessionID)
{
var mapFile = await _fileRequestService.RequestMapFile(mapID, sessionID);
SaveAndCacheMapFile(mapID, mapFile);
_mapFileSaveService.SaveFileToDefaultDirectory(mapFile, rewriteChecksum: false);

if (_mapFileRepository.MapFiles.ContainsKey(mapID))
_mapFileRepository.MapFiles[mapID] = mapFile;
else
_mapFileRepository.MapFiles.Add(mapID, mapFile);
}

public async Task GetItemFileFromServer(short sessionID)
Expand Down Expand Up @@ -133,16 +143,6 @@ private bool NeedPub(InitFileType fileType)
throw new ArgumentOutOfRangeException(nameof(fileType), fileType, null);
}
}

private void SaveAndCacheMapFile(short mapID, IMapFile mapFile)
{
_mapFileSaveService.SaveFileToDefaultDirectory(mapFile, rewriteChecksum: false);

if (_mapFileRepository.MapFiles.ContainsKey(mapID))
_mapFileRepository.MapFiles[mapID] = mapFile;
else
_mapFileRepository.MapFiles.Add(mapID, mapFile);
}
}

public interface IFileRequestActions
Expand All @@ -151,7 +151,7 @@ public interface IFileRequestActions

bool NeedsMapForWarp(short mapID, byte[] mapRid, int fileSize);

Task GetMapForWarp(short mapID, short sessionID);
void RequestMapForWarp(short mapID, short sessionID);

Task GetMapFromServer(short mapID, short sessionID);

Expand Down
6 changes: 3 additions & 3 deletions EOLib/Net/FileTransfer/FileRequestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ public async Task<IMapFile> RequestMapFile(short mapID, short sessionID)
return await GetMapFile(request, mapID);
}

public async Task<IMapFile> RequestMapFileForWarp(short mapID, short sessionID)
public void RequestMapFileForWarp(short mapID, short sessionID)
{
var request = new PacketBuilder(PacketFamily.Warp, PacketAction.Take)
.AddShort(mapID)
.AddShort(sessionID)
.Build();

return await GetMapFile(request, mapID);
_packetSendService.SendPacket(request);
}

public async Task<IPubFile<TRecord>> RequestFile<TRecord>(InitFileType fileType, short sessionID)
Expand Down Expand Up @@ -112,7 +112,7 @@ public interface IFileRequestService
{
Task<IMapFile> RequestMapFile(short mapID, short sessionID);

Task<IMapFile> RequestMapFileForWarp(short mapID, short sessionID);
void RequestMapFileForWarp(short mapID, short sessionID);

Task<IPubFile<TRecord>> RequestFile<TRecord>(InitFileType fileType, short sessionID)
where TRecord : class, IPubRecord, new();
Expand Down
49 changes: 29 additions & 20 deletions EOLib/PacketHandlers/BeginPlayerWarpHandler.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.IO;
using System.Linq;
using AutomaticTypeMapper;
using AutomaticTypeMapper;
using EOLib.Domain.Login;
using EOLib.Domain.Map;
using EOLib.IO.Actions;
Expand All @@ -10,6 +7,9 @@
using EOLib.Net.Communication;
using EOLib.Net.FileTransfer;
using EOLib.Net.Handlers;
using System;
using System.IO;
using System.Linq;

namespace EOLib.PacketHandlers
{
Expand Down Expand Up @@ -47,34 +47,43 @@ public override bool HandlePacket(IPacket packet)
{
if (_mapStateRepository.MapWarpState != WarpState.None)
throw new InvalidOperationException("Attempted to warp while another warp was in progress");

_mapStateRepository.MapWarpState = WarpState.WarpStarted;

var warpType = packet.ReadChar();
var mapID = packet.ReadShort();
short sessionID;

switch (warpType)
{
case WARP_SAME_MAP:
sessionID = packet.ReadShort();
SendWarpAcceptToServer(mapID, sessionID);
{
var sessionID = packet.ReadShort();
SendWarpAcceptToServer(mapID, sessionID);
}
break;
case WARP_NEW_MAP:
var mapRid = packet.ReadBytes(4).ToArray();
var fileSize = packet.ReadThree();
sessionID = packet.ReadShort();

var mapIsDownloaded = true;
try
{
if (!_mapFileProvider.MapFiles.ContainsKey(mapID))
_mapFileLoadActions.LoadMapFileByID(mapID);
}
catch (IOException) { mapIsDownloaded = false; }
var mapRid = packet.ReadBytes(4).ToArray();
var fileSize = packet.ReadThree();
var sessionID = packet.ReadShort();

if (!mapIsDownloaded || _fileRequestActions.NeedsMapForWarp(mapID, mapRid, fileSize))
_fileRequestActions.GetMapForWarp(mapID, sessionID).Wait(5000);
var mapIsDownloaded = true;
try
{
if (!_mapFileProvider.MapFiles.ContainsKey(mapID))
_mapFileLoadActions.LoadMapFileByID(mapID);
}
catch (IOException) { mapIsDownloaded = false; }

SendWarpAcceptToServer(mapID, sessionID);
if (!mapIsDownloaded || _fileRequestActions.NeedsMapForWarp(mapID, mapRid, fileSize))
{
_fileRequestActions.RequestMapForWarp(mapID, sessionID);
}
else
{
SendWarpAcceptToServer(mapID, sessionID);
}
}
break;
default:
_mapStateRepository.MapWarpState = WarpState.None;
Expand Down
76 changes: 76 additions & 0 deletions EOLib/PacketHandlers/Init/MapWarpFileDownloadHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using AutomaticTypeMapper;
using EOLib.Domain.Character;
using EOLib.Domain.Map;
using EOLib.Domain.Notifiers;
using EOLib.Domain.Protocol;
using EOLib.IO.Map;
using EOLib.IO.Repositories;
using EOLib.IO.Services;
using EOLib.IO.Services.Serializers;
using EOLib.Net;
using EOLib.Net.Communication;
using System.Collections.Generic;
using System.Linq;

namespace EOLib.PacketHandlers.Init
{
[AutoMappedType]
public class MapWarpFileDownloadHandler : IInitPacketHandler
{
private readonly IMapFileRepository _mapFileRepository;
private readonly IMapDeserializer<IMapFile> _mapFileDeserializer;
private readonly IMapFileSaveService _mapFileSaveService;
private readonly ICurrentMapStateProvider _currentMapStateProvider;
private readonly IPacketSendService _packetSendService;

public InitReply Reply => InitReply.WarpMap;

public MapWarpFileDownloadHandler(IMapFileRepository mapFileRepository,
IMapDeserializer<IMapFile> mapFileDeserializer,
IMapFileSaveService mapFileSaveService,
ICurrentMapStateProvider currentMapStateProvider,
IPacketSendService packetSendService)
{
_mapFileRepository = mapFileRepository;
_mapFileDeserializer = mapFileDeserializer;
_mapFileSaveService = mapFileSaveService;
_currentMapStateProvider = currentMapStateProvider;
_packetSendService = packetSendService;
}

public bool HandlePacket(IPacket packet)
{
if (_currentMapStateProvider.MapWarpState != WarpState.WarpStarted)
return false;

if (!_currentMapStateProvider.MapWarpID.HasValue ||
!_currentMapStateProvider.MapWarpSession.HasValue)
return false;

_currentMapStateProvider.MapWarpID.MatchSome(
mapID =>
{
var fileData = packet.ReadBytes(packet.Length - packet.ReadPosition);
var mapFile = _mapFileDeserializer
.DeserializeFromByteArray(fileData.ToArray())
.WithMapID(mapID);

_mapFileRepository.MapFiles[mapID] = mapFile;
_mapFileSaveService.SaveFileToDefaultDirectory(mapFile, rewriteChecksum: false);

_currentMapStateProvider.MapWarpSession.MatchSome(sessionID => SendWarpAcceptToServer(mapID, sessionID));
});

return true;
}

private void SendWarpAcceptToServer(short mapID, short sessionID)
{
var response = new PacketBuilder(PacketFamily.Warp, PacketAction.Accept)
.AddShort(mapID)
.AddShort(sessionID)
.Build();
_packetSendService.SendPacket(response);
}
}
}

0 comments on commit e74e189

Please sign in to comment.