using System;
using System.IO;
using MLAPI;
using MLAPI.Messaging;
using MLAPI.NetworkedVar;
using UnityEngine;
using MLAPI.Serialization.Pooled;
namespace BossRoom
{
///
/// Contains all NetworkedVars and RPCs of a character. This component is present on both client and server objects.
///
public class NetworkCharacterState : NetworkedBehaviour
{
///
/// The networked position of this Character. This reflects the authorative position on the server.
///
public NetworkedVarVector3 NetworkPosition { get;} = new NetworkedVarVector3();
///
/// The networked rotation of this Character. This reflects the authorative rotation on the server.
///
public NetworkedVarFloat NetworkRotationY { get; } = new NetworkedVarFloat();
public NetworkedVarFloat NetworkMovementSpeed { get; } = new NetworkedVarFloat();
public NetworkedVarInt HitPoints;
public NetworkedVarInt Mana;
///
/// Gets invoked when inputs are received from the client which own this networked character.
///
public event Action OnReceivedClientInput;
///
/// RPC to send inputs for this character from a client to a server.
///
/// The position which this character should move towards.
[ServerRPC]
public void SendCharacterInputServerRpc(Vector3 movementTarget)
{
OnReceivedClientInput?.Invoke(movementTarget);
}
// ACTION SYSTEM
///
/// This event is raised on the server when an action request arrives
///
public event Action DoActionEventServer;
///
/// This event is raised on the client when an action is being played back.
///
public event Action DoActionEventClient;
///
/// Client->Server RPC that sends a request to play an action.
///
/// Data about which action to play an dits associated details.
public void C2S_DoAction(ref ActionRequestData data)
{
using (PooledBitStream stream = PooledBitStream.Get())
{
SerializeAction(ref data, stream);
InvokeServerRpcPerformance(RecvDoActionServer, stream);
}
}
///
/// Server->Client RPC that broadcasts this action play to all clients.
///
/// The data associated with this Action, including what action type it is.
public void S2C_BroadcastAction(ref ActionRequestData data )
{
using (PooledBitStream stream = PooledBitStream.Get())
{
SerializeAction(ref data, stream);
InvokeClientRpcOnEveryonePerformance(RecvDoActionClient, stream);
}
}
private void SerializeAction( ref ActionRequestData data, PooledBitStream stream )
{
var Logic = ActionData.ActionDescriptions[data.ActionTypeEnum][0].Logic;
var Info = ActionData.LogicInfos[Logic];
using (PooledBitWriter writer = PooledBitWriter.Get(stream))
{
writer.WriteInt16((short)data.ActionTypeEnum);
writer.WriteBool(data.ShouldQueue);
if( Info.HasPosition )
{
writer.WriteVector3(data.Position);
}
if (Info.HasDirection)
{
writer.WriteVector3(data.Direction);
}
if (Info.HasTarget )
{
writer.WriteULongArray(data.TargetIds);
}
if( Info.HasAmount )
{
writer.WriteSingle(data.Amount);
}
}
}
[ClientRPC]
private void RecvDoActionClient(ulong clientId, Stream stream )
{
ActionRequestData data = RecvDoAction(clientId, stream);
DoActionEventClient?.Invoke(data);
}
[ServerRPC]
private void RecvDoActionServer(ulong clientId, Stream stream)
{
ActionRequestData data = RecvDoAction(clientId, stream);
DoActionEventServer?.Invoke(data);
}
private ActionRequestData RecvDoAction(ulong clientId, Stream stream )
{
ActionRequestData data = new ActionRequestData();
using (PooledBitReader reader = PooledBitReader.Get(stream))
{
data.ActionTypeEnum = (ActionType)reader.ReadInt16();
data.ShouldQueue = reader.ReadBool();
var Logic = ActionData.ActionDescriptions[data.ActionTypeEnum][0].Logic;
var Info = ActionData.LogicInfos[Logic];
if (Info.HasPosition)
{
data.Position = reader.ReadVector3();
}
if (Info.HasDirection)
{
data.Direction = reader.ReadVector3();
}
if (Info.HasTarget)
{
data.TargetIds = reader.ReadULongArray();
}
if (Info.HasAmount)
{
data.Amount = reader.ReadSingle();
}
}
return data;
}
}
}