-
-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable replaying rooms after clear (#309)
- Set play_type = Multi on dungeon start - Correctly set is_host on dungeon start/record using StateManager api - Handle ClearQuestRequest in photon plugin - Restructure plugin to have helper methods in different file - Add Photon authentication handler Also: - Handle FailQuestRequest - Simplify plugin configuration - Set room state to closed in Photon on host leaving (should reduce ghost rooms) Closes #245
- Loading branch information
1 parent
61176d8
commit e37f333
Showing
42 changed files
with
1,180 additions
and
342 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace DragaliaAPI.Photon.Plugin.Constants | ||
{ | ||
public static class Event | ||
{ | ||
public static class Codes | ||
{ | ||
public const int GameEnd = 0x2; | ||
|
||
public const int Ready = 0x3; | ||
|
||
public const int CharacterData = 0x14; | ||
|
||
public const int StartQuest = 0x15; | ||
|
||
public const int RoomBroken = 0x17; | ||
|
||
public const int GameSucceed = 0x18; | ||
|
||
public const int WillLeave = 0x1e; | ||
|
||
public const int Party = 0x3e; | ||
|
||
public const int ClearQuestRequest = 0x3f; | ||
|
||
public const int ClearQuestResponse = 0x40; | ||
|
||
public const int FailQuestRequest = 0x43; | ||
|
||
public const int FailQuestResponse = 0x44; | ||
|
||
public const int SuccessiveGameTimer = 0x53; | ||
} | ||
|
||
public static class Constants | ||
{ | ||
public const int EventDataKey = 245; | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using DragaliaAPI.Photon.Plugin.Helpers; | ||
using DragaliaAPI.Photon.Plugin.Models; | ||
using MessagePack; | ||
using Newtonsoft.Json; | ||
using Photon.Hive.Plugin; | ||
|
||
namespace DragaliaAPI.Photon.Plugin | ||
{ | ||
/// <summary> | ||
/// Hardcoded plugin configuration. | ||
/// </summary> | ||
public partial class GluonPlugin | ||
{ | ||
private static readonly Uri GameCreateEndpoint = new Uri( | ||
"Event/GameCreate", | ||
UriKind.Relative | ||
); | ||
|
||
private static readonly Uri GameCloseEndpoint = new Uri( | ||
"Event/GameClose", | ||
UriKind.Relative | ||
); | ||
|
||
private static readonly Uri GameJoinEndpoint = new Uri("Event/GameJoin", UriKind.Relative); | ||
|
||
private static readonly Uri GameLeaveEndpoint = new Uri( | ||
"Event/GameLeave", | ||
UriKind.Relative | ||
); | ||
|
||
private static readonly Uri EntryConditionsEndpoint = new Uri( | ||
"Event/EntryConditions", | ||
UriKind.Relative | ||
); | ||
|
||
private static readonly Uri MatchingTypeEndpoint = new Uri( | ||
"Event/MatchingType", | ||
UriKind.Relative | ||
); | ||
|
||
private static readonly Uri RoomIdEndpoint = new Uri("Event/RoomId", UriKind.Relative); | ||
|
||
private static readonly Uri VisibleEndpoint = new Uri("Event/Visible", UriKind.Relative); | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using DragaliaAPI.Photon.Plugin.Helpers; | ||
using DragaliaAPI.Photon.Plugin.Models; | ||
using MessagePack; | ||
using Newtonsoft.Json; | ||
using Photon.Hive.Plugin; | ||
|
||
namespace DragaliaAPI.Photon.Plugin | ||
{ | ||
/// <summary> | ||
/// Support plugin methods. | ||
/// </summary> | ||
public partial class GluonPlugin | ||
{ | ||
/// <summary> | ||
/// Helper method to raise events. | ||
/// </summary> | ||
/// <param name="eventCode">The event code to raise.</param> | ||
/// <param name="eventData">The event data.</param> | ||
/// <param name="target">The actor to target -- if null, all actors will be targeted.</param> | ||
public void RaiseEvent(byte eventCode, object eventData, int? target = null) | ||
{ | ||
byte[] serializedEvent = MessagePackSerializer.Serialize( | ||
eventData, | ||
MessagePackSerializerOptions.Standard.WithCompression( | ||
MessagePackCompression.Lz4Block | ||
) | ||
); | ||
Dictionary<byte, object> props = new Dictionary<byte, object>() | ||
{ | ||
{ 245, serializedEvent }, | ||
{ 254, 0 } // Server actor number | ||
}; | ||
|
||
this.logger.DebugFormat( | ||
"Raising event 0x{0} with data {1}", | ||
eventCode.ToString("X"), | ||
JsonConvert.SerializeObject(eventData) | ||
); | ||
|
||
if (target is null) | ||
{ | ||
this.BroadcastEvent(eventCode, props); | ||
} | ||
else | ||
{ | ||
this.logger.DebugFormat("Event will target actor {0}", target); | ||
this.PluginHost.BroadcastEvent( | ||
new List<int>() { target.Value }, | ||
0, | ||
eventCode, | ||
props, | ||
CacheOperations.DoNotCache | ||
); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Helper method to POST a JSON request body to the Redis API. | ||
/// </summary> | ||
/// <param name="endpoint">The endpoint to send a request to.</param> | ||
/// <param name="forwardRequest">The request object.</param> | ||
/// <param name="info">The event info from the current event callback.</param> | ||
/// <param name="callAsync">Whether or not to suspend execution of the room while awaiting a response.</param> | ||
private void PostStateManagerRequest( | ||
Uri endpoint, | ||
object forwardRequest, | ||
ICallInfo info, | ||
bool callAsync = true | ||
) | ||
{ | ||
HttpRequestCallback callback = this.LogIfFailedCallback; | ||
|
||
MemoryStream stream = new MemoryStream(); | ||
string json = JsonConvert.SerializeObject( | ||
forwardRequest, | ||
new JsonSerializerSettings | ||
{ | ||
NullValueHandling = NullValueHandling.Ignore, | ||
TypeNameHandling = TypeNameHandling.None, | ||
} | ||
); | ||
byte[] data = Encoding.UTF8.GetBytes(json); | ||
stream.Write(data, 0, data.Length); | ||
|
||
string url = new Uri(this.config.StateManagerUrl, endpoint).AbsoluteUri; | ||
|
||
HttpRequest request = new HttpRequest | ||
{ | ||
Url = url, | ||
Method = "POST", | ||
Accept = "application/json", | ||
ContentType = "application/json", | ||
Callback = callback, | ||
CustomHeaders = new Dictionary<string, string>() | ||
{ | ||
{ "Authorization", $"Bearer {this.config.BearerToken}" } | ||
}, | ||
DataStream = stream, | ||
Async = callAsync | ||
}; | ||
|
||
this.PluginHost.LogDebug( | ||
string.Format("PostStateManagerRequest: {0} - {1}", url, json) | ||
); | ||
|
||
this.PluginHost.HttpRequest(request, info); | ||
} | ||
|
||
/// <summary> | ||
/// Helper method to POST a msgpack request to the main API server. | ||
/// </summary> | ||
/// <param name="endpoint">The endpoint to send a request to.</param> | ||
/// <param name="requestBody">The msgpack request body.</param> | ||
/// <param name="info">The event info from the current event callback.</param> | ||
/// <param name="callback">The callback to trigger on a response.</param> | ||
/// <param name="callAsync">Whether or not to suspend execution of the room while awaiting a response.</param> | ||
private void PostApiRequest( | ||
Uri endpoint, | ||
byte[] requestBody, | ||
IRaiseEventCallInfo info, | ||
HttpRequestCallback callback, | ||
bool callAsync = true | ||
) | ||
{ | ||
IActor actor = this.PluginHost.GameActors.First(x => x.ActorNr == info.ActorNr); | ||
|
||
Uri requestUri = new Uri(this.config.ApiServerUrl, endpoint); | ||
|
||
HttpRequest req = new HttpRequest() | ||
{ | ||
Url = requestUri.AbsoluteUri, | ||
ContentType = "application/octet-stream", | ||
Callback = callback, | ||
Async = callAsync, | ||
Accept = "application/octet-stream", | ||
DataStream = new MemoryStream(requestBody), | ||
UserState = new HttpRequestUserState() { RequestActorNr = info.ActorNr }, | ||
Method = "POST", | ||
CustomHeaders = new Dictionary<string, string>() | ||
{ | ||
{ "Auth-ViewerId", actor.GetViewerId().ToString() }, | ||
{ "Authorization", $"Bearer {this.config.BearerToken}" } | ||
} | ||
}; | ||
|
||
this.PluginHost.HttpRequest(req, info); | ||
} | ||
|
||
/// <summary> | ||
/// Logs an error if a HTTP response was not successful. | ||
/// </summary> | ||
/// <param name="httpResponse">The HTTP response.</param> | ||
/// <param name="userState">The user state.</param> | ||
private void LogIfFailedCallback(IHttpResponse httpResponse, object userState) | ||
{ | ||
if (httpResponse.Status != HttpRequestQueueResult.Success) | ||
{ | ||
this.ReportError( | ||
$"Request to {httpResponse.Request.Url} failed with Photon status {httpResponse.Status} and HTTP status {httpResponse.HttpCode} ({httpResponse.Reason})" | ||
); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Report an error. | ||
/// </summary> | ||
/// <param name="msg">The error message.</param> | ||
private void ReportError(string msg) | ||
{ | ||
this.PluginHost.LogError(msg); | ||
this.PluginHost.BroadcastErrorInfoEvent(msg); | ||
} | ||
|
||
private int GenerateRoomId() | ||
{ | ||
return this.rdm.Next(100_0000, 999_9999); | ||
} | ||
} | ||
} |
Oops, something went wrong.