Implement Realtime MMO Communication

This commit is contained in:
Alan Moon 2024-11-26 15:31:21 -08:00
parent dcefeb5fc3
commit 62387149d3
5 changed files with 115 additions and 6 deletions

View File

@ -4,6 +4,7 @@ public class ApiServerConfig {
public string MMOAdress { get; set; } = "127.0.0.1"; public string MMOAdress { get; set; } = "127.0.0.1";
public int MMOPort { get; set; } = 9933; public int MMOPort { get; set; } = 9933;
public int MMOHttpApiPort { get; set; } = 9934;
public uint MMOSupportMinVersion { get; set; } = 0; public uint MMOSupportMinVersion { get; set; } = 0;
public DbProviders DbProvider { get; set; } = DbProviders.SQLite; public DbProviders DbProvider { get; set; } = DbProviders.SQLite;

View File

@ -22,6 +22,7 @@ public class ContentController : Controller {
private GameDataService gameDataService; private GameDataService gameDataService;
private DisplayNamesService displayNamesService; private DisplayNamesService displayNamesService;
private NeighborhoodService neighborhoodService; private NeighborhoodService neighborhoodService;
private MMOCommunicationService mMOCommunicationService;
private Random random = new Random(); private Random random = new Random();
private readonly IOptions<ApiServerConfig> config; private readonly IOptions<ApiServerConfig> config;
@ -36,6 +37,7 @@ public class ContentController : Controller {
GameDataService gameDataService, GameDataService gameDataService,
DisplayNamesService displayNamesService, DisplayNamesService displayNamesService,
NeighborhoodService neighborhoodService, NeighborhoodService neighborhoodService,
MMOCommunicationService mMOCommunicationService,
IOptions<ApiServerConfig> config IOptions<ApiServerConfig> config
) { ) {
this.ctx = ctx; this.ctx = ctx;
@ -48,6 +50,7 @@ public class ContentController : Controller {
this.gameDataService = gameDataService; this.gameDataService = gameDataService;
this.displayNamesService = displayNamesService; this.displayNamesService = displayNamesService;
this.neighborhoodService = neighborhoodService; this.neighborhoodService = neighborhoodService;
this.mMOCommunicationService = mMOCommunicationService;
this.config = config; this.config = config;
} }
@ -1608,13 +1611,14 @@ public class ContentController : Controller {
[Produces("application/xml")] [Produces("application/xml")]
[Route("ContentWebService.asmx/SetScene")] // used by World of Jumpstart [Route("ContentWebService.asmx/SetScene")] // used by World of Jumpstart
[VikingSession] [VikingSession]
public IActionResult SetScene(Viking viking, [FromForm] string sceneName, [FromForm] string contentXml) { public IActionResult SetScene(Viking viking, [FromForm] string sceneName, [FromForm] string contentXml, [FromForm] string apiToken) {
SceneData? existingScene = viking.SceneData.FirstOrDefault(e => e.SceneName == sceneName); SceneData? existingScene = viking.SceneData.FirstOrDefault(e => e.SceneName == sceneName);
if(existingScene is not null) if(existingScene is not null)
{ {
existingScene.XmlData = contentXml; existingScene.XmlData = contentXml;
ctx.SaveChanges(); ctx.SaveChanges();
mMOCommunicationService.SendPacketToRoom(apiToken, sceneName + '_' + viking.Uid.ToString(), "SNE", new string[] { "SNE", "-1", contentXml, "8" });
return Ok(true); return Ok(true);
} }
else else
@ -1634,13 +1638,14 @@ public class ContentController : Controller {
[Produces("application/xml")] [Produces("application/xml")]
[Route("ContentWebService.asmx/SetHouse")] // used by World Of Jumpstart [Route("ContentWebService.asmx/SetHouse")] // used by World Of Jumpstart
[VikingSession] [VikingSession]
public IActionResult SetHouse(Viking viking, [FromForm] string contentXml) { public IActionResult SetHouse(Viking viking, [FromForm] string contentXml, [FromForm] string apiToken) {
Util.SavedData.Set( Util.SavedData.Set(
viking, viking,
Util.SavedData.House(), Util.SavedData.House(),
contentXml contentXml
); );
ctx.SaveChanges(); ctx.SaveChanges();
mMOCommunicationService.SendPacketToRoom(apiToken, $"MyNeighborhood_{viking.Uid}", "SNE", new string[] { "SNE", "-1", viking.Uid.ToString(), "10" }); // hardcoding neighborhood here for now, client doesn't send a scene name here
return Ok(true); return Ok(true);
} }
@ -1648,8 +1653,8 @@ public class ContentController : Controller {
[Produces("application/xml")] [Produces("application/xml")]
[Route("ContentWebService.asmx/SetNeighbor")] // used by World Of Jumpstart [Route("ContentWebService.asmx/SetNeighbor")] // used by World Of Jumpstart
[VikingSession(UseLock=true)] [VikingSession(UseLock=true)]
public IActionResult SetNeighbor(Viking viking, string neighboruserid, int slot) { public IActionResult SetNeighbor(Viking viking, string neighboruserid, int slot, string apiToken) {
return Ok(neighborhoodService.SaveNeighbors(viking, neighboruserid, slot)); return Ok(neighborhoodService.SaveNeighbors(viking, neighboruserid, slot, apiToken));
} }
[HttpPost] [HttpPost]

View File

@ -39,6 +39,7 @@ builder.Services.AddScoped<AchievementService>();
builder.Services.AddScoped<GameDataService>(); builder.Services.AddScoped<GameDataService>();
builder.Services.AddScoped<ProfileService>(); builder.Services.AddScoped<ProfileService>();
builder.Services.AddScoped<NeighborhoodService>(); builder.Services.AddScoped<NeighborhoodService>();
builder.Services.AddScoped<MMOCommunicationService>();
bool assetServer = builder.Configuration.GetSection("AssetServer").GetValue<bool>("Enabled"); bool assetServer = builder.Configuration.GetSection("AssetServer").GetValue<bool>("Enabled");
string assetIP = builder.Configuration.GetSection("AssetServer").GetValue<string>("ListenIP"); string assetIP = builder.Configuration.GetSection("AssetServer").GetValue<string>("ListenIP");

View File

@ -0,0 +1,92 @@
using System;
using System.Data.Common;
using System.Text.Json;
using Microsoft.Extensions.Options;
using sodoff.Configuration;
using sodoff.Model;
namespace sodoff.Services;
public class MMOCommunicationService
{
public readonly DBContext dBContext;
public readonly HttpClient httpClient;
public readonly IOptions<ApiServerConfig> config;
public MMOCommunicationService(DBContext dBContext, IOptions<ApiServerConfig> options)
{
this.dBContext = dBContext;
config = options;
httpClient = new HttpClient();
}
public bool SendPacketToRoom(string apiToken, string roomName, string cmd, string[] args)
{
var serializedArgs = JsonSerializer.Serialize(args);
FormUrlEncodedContent form = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "apiToken", apiToken },
{ "roomName", roomName },
{ "cmd", cmd },
{ "serializedArgs", serializedArgs }
});
try
{
var result = httpClient.PostAsync($"http://{config.Value.MMOAdress}:{config.Value.MMOHttpApiPort}/mmo/update/SendPacketToRoom", form)?.Result;
if (result != null && result.StatusCode == System.Net.HttpStatusCode.OK) return true;
else return false;
} catch (AggregateException ex)
{
Console.WriteLine("MMO Communication Failiure. Please Investigate - " + ex.Message);
return false;
}
}
public bool SendPacketToPlayer(string apiToken, string userId, string cmd, string[] args)
{
var argsSerialized = JsonSerializer.Serialize(args);
FormUrlEncodedContent form = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "apiToken", apiToken },
{ "userId", userId },
{ "cmd", cmd },
{ "serializedArgs", argsSerialized }
});
try
{
var result = httpClient.PostAsync($"http://{config.Value.MMOAdress}:{config.Value.MMOHttpApiPort}/mmo/update/SendPacketToPlayer", form)?.Result;
if (result != null && result.StatusCode == System.Net.HttpStatusCode.OK) return true;
else return false;
}
catch (AggregateException ex)
{
Console.WriteLine("MMO Communication Failiure. Please Investigate - " + ex.Message);
return false;
}
}
public bool UpdateRoomVarsInRoom<T>(string apiToken, string roomName, Dictionary<string, T> vars)
{
var varsSerialized = JsonSerializer.Serialize(vars);
FormUrlEncodedContent form = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "apiToken", apiToken },
{ "roomName", roomName },
{ "serializedVars", varsSerialized }
});
try
{
var result = httpClient.PostAsync($"http://{config.Value.MMOAdress}:{config.Value.MMOHttpApiPort}/mmo/update/UpdateRoomVarsInRoom", form)?.Result;
if (result != null && result.StatusCode == System.Net.HttpStatusCode.OK) return true;
else return false;
}
catch (AggregateException ex)
{
Console.WriteLine("MMO Communication Failiure. Please Investigate - " + ex.Message);
return false;
}
}
}

View File

@ -10,6 +10,7 @@ namespace sodoff.Services
public class NeighborhoodService public class NeighborhoodService
{ {
private readonly DBContext ctx; private readonly DBContext ctx;
private readonly MMOCommunicationService mMOCommunicationService;
// default neighborhood slots (NPCs) // default neighborhood slots (NPCs)
Guid slot0 = new Guid("aaaaaaaa-0000-0000-0000-000000000000"); Guid slot0 = new Guid("aaaaaaaa-0000-0000-0000-000000000000");
@ -18,12 +19,14 @@ namespace sodoff.Services
Guid slot3 = new Guid("dddddddd-0000-0000-0000-000000000000"); Guid slot3 = new Guid("dddddddd-0000-0000-0000-000000000000");
Guid slot4 = new Guid("eeeeeeee-0000-0000-0000-000000000000"); Guid slot4 = new Guid("eeeeeeee-0000-0000-0000-000000000000");
public NeighborhoodService(DBContext ctx) { public NeighborhoodService(DBContext ctx, MMOCommunicationService mMOCommunicationService) {
this.ctx = ctx; this.ctx = ctx;
this.mMOCommunicationService = mMOCommunicationService;
} }
public bool SaveNeighbors(Viking viking, string neighborUid, int slot) { public bool SaveNeighbors(Viking viking, string neighborUid, int slot, string apiToken) {
Model.Neighborhood? neighborhood = viking.Neighborhood; Model.Neighborhood? neighborhood = viking.Neighborhood;
Dictionary<string, string> neighborRoomVars = new Dictionary<string, string>();
if (neighborhood == null) // if viking has no neighborhood yet, create a default one if (neighborhood == null) // if viking has no neighborhood yet, create a default one
viking.Neighborhood = new Model.Neighborhood { viking.Neighborhood = new Model.Neighborhood {
@ -39,21 +42,28 @@ namespace sodoff.Services
switch (slot) { switch (slot) {
case 0: case 0:
viking.Neighborhood.Slot0 = new Guid(neighborUid); viking.Neighborhood.Slot0 = new Guid(neighborUid);
neighborRoomVars.Add("S0", viking.Neighborhood.Slot0.ToString());
break; break;
case 1: case 1:
viking.Neighborhood.Slot1 = new Guid(neighborUid); viking.Neighborhood.Slot1 = new Guid(neighborUid);
neighborRoomVars.Add("S1", viking.Neighborhood.Slot1.ToString());
break; break;
case 2: case 2:
viking.Neighborhood.Slot2 = new Guid(neighborUid); viking.Neighborhood.Slot2 = new Guid(neighborUid);
neighborRoomVars.Add("S2", viking.Neighborhood.Slot2.ToString());
break; break;
case 3: case 3:
viking.Neighborhood.Slot3 = new Guid(neighborUid); viking.Neighborhood.Slot3 = new Guid(neighborUid);
neighborRoomVars.Add("S3", viking.Neighborhood.Slot3.ToString());
break; break;
case 4: case 4:
viking.Neighborhood.Slot4 = new Guid(neighborUid); viking.Neighborhood.Slot4 = new Guid(neighborUid);
neighborRoomVars.Add("S4", viking.Neighborhood.Slot4.ToString());
break; break;
} }
mMOCommunicationService.UpdateRoomVarsInRoom(apiToken, $"MyNeighborhood_{viking.Uid}", neighborRoomVars); // once again hardcoding neighborhood
ctx.SaveChanges(); ctx.SaveChanges();
return true; return true;
} }