/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #ifndef INCLUDE_GRIDMATERMI_HEADER #define INCLUDE_GRIDMATERMI_HEADER #pragma once #include #include #include "../NetworkGridMateCommon.h" #include "GridMateNetSerialize.h" #include namespace GridMate { namespace RMI { typedef uint16 WhereType; enum { kInvocationBufferBaseSize = 128 }; /*! * Flushes any RMIs invoked by the game this frame, by dispatching via RPCs. */ void FlushQueue(); /*! * Empties pending RMI queue, does not dispatch. */ void EmptyQueue(); /*! * Used to limit client RMIs to be callable from the host */ struct ClientRMITraits : public GridMate::RpcDefaultTraits { }; /*! * Base helper template for wrapping CryEngine RMI invocations. * This object is managed by a smart ptr to ensure the memory it owns * is properly resource-managed while its queued in GridMate as an RPC. */ template class InvocationWrapperBase : public _i_multithread_reference_target_t { public: typedef _smart_ptr Ptr; WhereType m_where; ChannelId m_sentFromChannel; ChannelId m_targetChannelFilter; // contains channel to include or exclude, depending on WhereType typedef FlexibleBuffer ParamsBuffer; ParamsBuffer m_paramsBuffer; InvocationWrapperBase() : m_where(0) , m_sentFromChannel(kInvalidChannelId) , m_targetChannelFilter(kInvalidChannelId) { } InvocationWrapperBase(ChannelId sentFromChannel, ChannelId targetChannelFilter, WhereType where, const char* paramsBuffer, uint32 paramsBufferSize) : m_where(where) , m_sentFromChannel(sentFromChannel) , m_targetChannelFilter(targetChannelFilter) , m_paramsBuffer(paramsBuffer, paramsBufferSize) { } virtual ~InvocationWrapperBase() {} }; /*! * Marshaler base class handling base class' members. */ template class InvocationWrapperMarshalerBase { public: static bool RequiresFromChannel(WhereType where) { return !!(where & (eRMI_ToOtherRemoteClients | eRMI_NoLocalCalls)); } static bool RequiresTargetChannelFilter(WhereType where) { return !!(where & (eRMI_ToClientChannel | eRMI_ToOtherClients | eRMI_ToOtherRemoteClients)); } void Marshal(GridMate::WriteBuffer& wb, const typename DerivedType::Ptr& value) { wb.Write(value->m_where); if (RequiresFromChannel(value->m_where)) { wb.Write(value->m_sentFromChannel); } if (RequiresTargetChannelFilter(value->m_where)) { wb.Write(value->m_targetChannelFilter); } typename DerivedType::ParamsBuffer::Marshaler().Marshal(wb, value->m_paramsBuffer); } void Unmarshal(typename DerivedType::Ptr& value, GridMate::ReadBuffer& rb) { DerivedType* invocation = new DerivedType(); rb.Read(invocation->m_where); if (RequiresFromChannel(invocation->m_where)) { rb.Read(invocation->m_sentFromChannel); } if (RequiresTargetChannelFilter(invocation->m_where)) { rb.Read(invocation->m_targetChannelFilter); } typename DerivedType::ParamsBuffer::Marshaler().Unmarshal(invocation->m_paramsBuffer, rb); value = std::move(invocation); } }; /*! * Wrapper for legacy (GameObject / GameObjectExtension) RMIs. */ class LegacyInvocationWrapper : public InvocationWrapperBase < LegacyInvocationWrapper > { public: LegacyInvocationWrapper() {} LegacyInvocationWrapper(ChannelId sentFromChannel, uint32 repId, ChannelId targetChannelFilter, WhereType where, const char* paramsBuffer, uint32 paramsBufferSize) : InvocationWrapperBase(sentFromChannel, targetChannelFilter, where, paramsBuffer, paramsBufferSize) , m_repId(repId) { } uint32 m_repId; class Marshaler : public InvocationWrapperMarshalerBase < LegacyInvocationWrapper > { public: typedef InvocationWrapperMarshalerBase Super; void Marshal(GridMate::WriteBuffer& wb, const LegacyInvocationWrapper::Ptr& value) { Super::Marshal(wb, value); wb.Write(value->m_repId); } void Unmarshal(LegacyInvocationWrapper::Ptr& value, GridMate::ReadBuffer& rb) { Super::Unmarshal(value, rb); rb.Read(value->m_repId); } }; }; /*! * Wrapper for actor (GameCore / RPGSample) RMIs. */ class ActorInvocationWrapper : public InvocationWrapperBase < ActorInvocationWrapper > { public: ActorInvocationWrapper() {} ActorInvocationWrapper(ChannelId sentFromChannel, uint8 actorExtensionId, uint32 repId, ChannelId targetChannelFilter, WhereType where, const char* paramsBuffer, uint32 paramsBufferSize) : InvocationWrapperBase(sentFromChannel, targetChannelFilter, where, paramsBuffer, paramsBufferSize) , m_repId(repId) , m_actorExtensionId(actorExtensionId) { } uint32 m_repId; uint8 m_actorExtensionId; class Marshaler : public InvocationWrapperMarshalerBase < ActorInvocationWrapper > { public: typedef InvocationWrapperMarshalerBase Super; void Marshal(GridMate::WriteBuffer& wb, const ActorInvocationWrapper::Ptr& value) { // \todo: Investigate reduction of repId size, or combining to reduce per-RMI overhead. Super::Marshal(wb, value); wb.Write(value->m_repId); wb.Write(value->m_actorExtensionId); } void Unmarshal(ActorInvocationWrapper::Ptr& value, GridMate::ReadBuffer& rb) { Super::Unmarshal(value, rb); rb.Read(value->m_repId); rb.Read(value->m_actorExtensionId); } }; }; /*! * Wrapper for lua script entity RMIs. */ class ScriptInvocationWrapper : public _i_reference_target_t { public: typedef _smart_ptr Ptr; ScriptInvocationWrapper() {} ScriptInvocationWrapper(bool isServerRMI, ChannelId toChannelId, ChannelId avoidChannelId, const char* serializedData, size_t serializedDataSize) : m_toChannelId(toChannelId) , m_avoidChannelId(avoidChannelId) , m_isServerRMI(isServerRMI) , m_serializedData(serializedData, serializedDataSize) { } ~ScriptInvocationWrapper() {} ChannelId m_toChannelId; ChannelId m_avoidChannelId; bool m_isServerRMI; typedef FlexibleBuffer<128> DataBuffer; DataBuffer m_serializedData; class Marshaler { public: void Marshal(GridMate::WriteBuffer& wb, const ScriptInvocationWrapper::Ptr& value) { wb.Write(value->m_toChannelId); wb.Write(value->m_avoidChannelId); DataBuffer::Marshaler().Marshal(wb, value->m_serializedData); } void Unmarshal(ScriptInvocationWrapper::Ptr& value, GridMate::ReadBuffer& rb) { ScriptInvocationWrapper* invocation = new ScriptInvocationWrapper(); rb.Read(invocation->m_toChannelId); rb.Read(invocation->m_avoidChannelId); DataBuffer::Marshaler().Unmarshal(invocation->m_serializedData, rb); value = std::move(invocation); } }; }; //! Handles invocation for legacy game object RMIs. void InvokeLegacy(IGameObject* gameObject, IRMIRep& rep, void* params, ChannelId targetChannelFilter, WhereType whereMask); //! Handles invocation for actor (GameCore) RMIs. void InvokeActor(EntityId entityId, uint8 actorExtensionId, ChannelId targetChannelFilter, IActorRMIRep& rep); //! Handles invocation for lua script entity RMIs. void InvokeScript(ISerializable* serializable, bool isServerRMI, ChannelId toChannelId, ChannelId avoidChannelId); //! Handles deciphering and dispatching of legacy GameObject RMIs. bool HandleLegacy(EntityId entityId, LegacyInvocationWrapper::Ptr invocation, const GridMate::RpcContext& rc); //! Handles deciphering and dispatching of actor (GameCore) RMIs. bool HandleActor(EntityId entityId, ActorInvocationWrapper::Ptr invocation, const GridMate::RpcContext& rc); //! Handles deciphering and dispatching of lua script entity RMIs. bool HandleScript(ScriptInvocationWrapper::Ptr invocation, const GridMate::RpcContext& rc); //! Register/Unregister an actor RMI sink for dispatching upon receipt. void RegisterActorRMI(IActorRMIRep* rep); void UnregisterActorRMI(IActorRMIRep* rep); IActorRMIRep* FindActorRMIRep(uint32 repId); IRMIRep* FindLegacyRMIRep(EntityId entityId, uint32 repId, IGameObjectExtension** extension = nullptr); //! Convenience typedefs for RMI param serializers. typedef NetSerialize::EntityNetSerializerCollectState RMIParamsSerializerStoreParams; typedef NetSerialize::EntityNetSerializerDispatchState RMIParamsSerializerUnwindParams; } // namespace RMI } // namespace GridMate #endif // INCLUDE_GRIDMATERMI_HEADER