194 lines
6.6 KiB
C#
194 lines
6.6 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using GameCult.Caching;
|
|
using GameCult.Caching.MessagePack;
|
|
|
|
namespace GameCult.Networking
|
|
{
|
|
/// <summary>
|
|
/// Options for creating a local CultNet host over CultCache and the canonical MessagePack store.
|
|
/// </summary>
|
|
public sealed class CultNetHostOptions
|
|
{
|
|
/// <summary>
|
|
/// Gets or sets the cache-open options used for the underlying CultCache.
|
|
/// </summary>
|
|
public CultCacheOpenOptions? CacheOptions { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the server security configuration. When omitted, development defaults are used.
|
|
/// </summary>
|
|
public ServerSecurityOptions? Security { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether the server should start immediately after creation.
|
|
/// </summary>
|
|
public bool StartServer { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the database sharding options used for the hosted CultCache.
|
|
/// </summary>
|
|
public CultNetDatabaseOptions? DatabaseOptions { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the database server bridge options used for shard routing and forwarding.
|
|
/// </summary>
|
|
public CultNetDatabaseServerOptions? DatabaseServerOptions { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets an optional callback used to customize the server before start.
|
|
/// </summary>
|
|
public Action<Server>? ConfigureServer { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convenience wrapper for a locally hosted CultNet server over a durable CultCache.
|
|
/// </summary>
|
|
public sealed class CultNetHost : IDisposable
|
|
{
|
|
internal CultNetHost(
|
|
CultCache cache,
|
|
SingleFileMessagePackBackingStore? store,
|
|
Server server,
|
|
CultNetDatabase database,
|
|
CultNetDatabaseServer databaseServer)
|
|
{
|
|
Cache = cache;
|
|
Store = store;
|
|
Server = server;
|
|
Database = database;
|
|
DatabaseServer = databaseServer;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the durable cache used by the host.
|
|
/// </summary>
|
|
public CultCache Cache { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the canonical single-file MessagePack store, when one is attached.
|
|
/// </summary>
|
|
public SingleFileMessagePackBackingStore? Store { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the underlying CultNet server.
|
|
/// </summary>
|
|
public Server Server { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the distributed database facade over the hosted cache.
|
|
/// </summary>
|
|
public CultNetDatabase Database { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the schema-v0 server bridge for distributed database messages.
|
|
/// </summary>
|
|
public CultNetDatabaseServer DatabaseServer { get; }
|
|
|
|
/// <summary>
|
|
/// Starts the server.
|
|
/// </summary>
|
|
public void Start()
|
|
{
|
|
Server.Start();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flushes the durable cache.
|
|
/// </summary>
|
|
public Task FlushAsync(bool soft = false)
|
|
{
|
|
return Cache.FlushAsync(soft);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops the server and disposes the host resources.
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
DatabaseServer.Dispose();
|
|
Server.Dispose();
|
|
Database.Dispose();
|
|
Cache.Dispose();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Friendly local entrypoints for CultNet host/client creation.
|
|
/// </summary>
|
|
public static class CultNetLocal
|
|
{
|
|
/// <summary>
|
|
/// Creates a local host with a durable CultCache and the canonical MessagePack backing store.
|
|
/// </summary>
|
|
public static async Task<CultNetHost> CreateHostAsync(string cachePath, CultNetHostOptions? options = null)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(cachePath))
|
|
{
|
|
throw new ArgumentException("Cache path must be non-empty.", nameof(cachePath));
|
|
}
|
|
|
|
options ??= new CultNetHostOptions();
|
|
var cache = await CultCacheMessagePack.OpenAsync(cachePath, options.CacheOptions).ConfigureAwait(false);
|
|
var store = cache.BackingStores.OfType<SingleFileMessagePackBackingStore>().FirstOrDefault();
|
|
var server = new Server(cache, options.Security ?? ServerSecurityOptions.Development());
|
|
var databaseOptions = options.DatabaseOptions ?? new CultNetDatabaseOptions();
|
|
var database = new CultNetDatabase(cache, databaseOptions);
|
|
var databaseServer = new CultNetDatabaseServer(server, database, options.DatabaseServerOptions);
|
|
options.ConfigureServer?.Invoke(server);
|
|
|
|
var host = new CultNetHost(cache, store, server, database, databaseServer);
|
|
if (options.StartServer)
|
|
{
|
|
host.Start();
|
|
}
|
|
|
|
return host;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates and starts a local host with development-friendly defaults.
|
|
/// </summary>
|
|
public static Task<CultNetHost> StartHostAsync(string cachePath, CultNetHostOptions? options = null)
|
|
{
|
|
options ??= new CultNetHostOptions();
|
|
options.StartServer = true;
|
|
return CreateHostAsync(cachePath, options);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a client configured for local CultNet use.
|
|
/// </summary>
|
|
public static Client CreateClient(ClientSecurityOptions? security = null, Action<Client>? configureClient = null)
|
|
{
|
|
var client = new Client(security ?? ClientSecurityOptions.Development());
|
|
configureClient?.Invoke(client);
|
|
return client;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates and connects a client to the specified host.
|
|
/// </summary>
|
|
public static Client ConnectClient(
|
|
string host = "localhost",
|
|
int port = 3075,
|
|
ClientSecurityOptions? security = null,
|
|
Action<Client>? configureClient = null)
|
|
{
|
|
var client = CreateClient(security, configureClient);
|
|
client.Connect(host, port);
|
|
return client;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates and connects a client to a local development host.
|
|
/// </summary>
|
|
public static Client ConnectLocal(
|
|
ClientSecurityOptions? security = null,
|
|
Action<Client>? configureClient = null)
|
|
{
|
|
return ConnectClient("localhost", 3075, security, configureClient);
|
|
}
|
|
}
|
|
}
|