using System;
using System.Collections.Generic;
using Sandbox.ModAPI;
using VRage;
using VRage.Utils;
using VRageMath;
namespace SENetworkAPI
{
public enum NetworkTypes
{
Dedicated,
Server,
Client
}
public abstract class NetworkAPI
{
public const int CompressionThreshold = 100000;
public static NetworkAPI Instance;
public static bool LogNetworkTraffic = false;
///
/// Gets the diffrence between now and a given timestamp in frames (60 fps)
///
///
///
private static readonly double frames = 1000d / 60d;
public readonly ushort ComId;
public readonly string Keyword;
public readonly string ModName;
internal Dictionary> ChatCommands = new Dictionary>();
internal Dictionary> NetworkCommands =
new Dictionary>();
///
/// Event driven client, server syncing API.
///
/// The communication channel this mod will listen on
/// The title use for displaying chat messages
/// The string identifying a chat command
public NetworkAPI(ushort comId, string modName, string keyword = null)
{
ComId = comId;
ModName = modName == null ? string.Empty : modName;
Keyword = keyword != null ? keyword.ToLower() : null;
if (UsingTextCommands)
{
MyAPIGateway.Utilities.MessageEntered -= HandleChatInput;
MyAPIGateway.Utilities.MessageEntered += HandleChatInput;
}
MyAPIGateway.Multiplayer.UnregisterMessageHandler(ComId, HandleIncomingPacket);
MyAPIGateway.Multiplayer.RegisterMessageHandler(ComId, HandleIncomingPacket);
MyLog.Default.Info(
$"[NetworkAPI] Initialized. Type: {GetType().Name} ComId: {ComId} Name: {ModName} Keyword: {Keyword}");
}
public static bool IsInitialized => Instance != null;
internal bool UsingTextCommands => Keyword != null;
///
/// Event triggers apon reciveing data over the network
/// steamId, command, data
///
public event Action OnCommandRecived;
///
/// Invokes chat command events
///
/// Chat message string
/// should be shown normally in global chat
private void HandleChatInput(string messageText, ref bool sendToOthers)
{
var args = messageText.ToLower().Split(' ');
if (args[0] != Keyword)
return;
sendToOthers = false;
var arguments = messageText.Substring(Keyword.Length).Trim(' ');
// Meh... this is kinda yucky
if (args.Length == 1 && ChatCommands.ContainsKey(string.Empty))
{
ChatCommands[string.Empty]?.Invoke(string.Empty);
}
else if (args.Length > 1 && ChatCommands.ContainsKey(args[1]))
{
ChatCommands[args[1]]?.Invoke(arguments.Substring(args[1].Length).Trim(' '));
}
else
{
if (!MyAPIGateway.Utilities.IsDedicated)
MyAPIGateway.Utilities.ShowMessage(ModName, "Command not recognized.");
}
}
///
/// Unpacks commands and handles arguments
///
/// Data chunck recived from the network
private void HandleIncomingPacket(byte[] msg)
{
try
{
var cmd = MyAPIGateway.Utilities.SerializeFromBinary(msg);
if (LogNetworkTraffic)
{
MyLog.Default.Info("[NetworkAPI] ----- TRANSMISSION RECIEVED -----");
MyLog.Default.Info(
$"[NetworkAPI] Type: {(cmd.IsProperty ? "Property" : $"Command ID: {cmd.CommandString}")}, {(cmd.IsCompressed ? "Compressed, " : "")}From: {cmd.SteamId} ");
}
if (cmd.IsCompressed)
{
cmd.Data = MyCompression.Decompress(cmd.Data);
cmd.IsCompressed = false;
}
if (cmd.IsProperty)
{
NetSync