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; } } }