165 lines
5.0 KiB
C++
165 lines
5.0 KiB
C++
/*
|
|
ZNetworkEvent.hpp
|
|
Author: James Russell <jcrussell@762studios.com>
|
|
Created: 9/13/2015
|
|
|
|
Purpose:
|
|
|
|
Network Event abstract class. Intended to be subclassed into various subclasses that will be
|
|
serialized / deserialized and processed on both client and server.
|
|
|
|
Note that events that originate on the server will generally not have their HandleServer method
|
|
called, as the server already processed the occurrence that originated the event. Events
|
|
that originate on the client will generally be pushed to the server, have HandleServer
|
|
called on them, which will generally also cause an event to be pushed to each client, who
|
|
will then have HandleClient called when the event gets deserialized.
|
|
|
|
From the above usage pattern, we can see that clients generally push events to the server but
|
|
do not process the local occurrence (the HandleClient) until after the server has confirmed
|
|
the event happens by pushing the event back to all clients, the original sender included.
|
|
|
|
This usage pattern is not required for client authoritative events, which are processed locally
|
|
and then handed to the server to notify other attached clients.
|
|
|
|
License:
|
|
|
|
TODO
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#ifndef _ZNETWORKEVENT_HPP
|
|
#define _ZNETWORKEVENT_HPP
|
|
|
|
#include "ZSimulationDefs.hpp"
|
|
|
|
// forward decl
|
|
class ZSimulation;
|
|
|
|
/*
|
|
ZNetworkEvent class.
|
|
*/
|
|
class ZNetworkEvent {
|
|
DISABLE_COPY_AND_ASSIGN(ZNetworkEvent);
|
|
public:
|
|
|
|
nID Type; // the type of event this is
|
|
cID NetTarget; // the connection this is targeting
|
|
cID NetIgnore; // if NetTarget is set to all, this target will be ignored
|
|
bool InQueue; // flag set during a handle method to indicate this has been queued up for sending
|
|
|
|
// handler for events on client side
|
|
virtual void HandleClient(ZSimulation& server_sim) = 0;
|
|
|
|
// handler for events on server side
|
|
virtual void HandleServer(ZSimulation& client_sim) = 0;
|
|
|
|
// called by the network system to deserialize this event from binary form (after header is read)
|
|
virtual bool Deserialize(ZBinaryBufferReader& reader) = 0;
|
|
|
|
// called by the network system to serialize this event into binary form
|
|
virtual void Serialize(ZBinaryBufferWriter& writer) = 0;
|
|
|
|
// called to get the serialized size of this event (including uint8_t message type flag)
|
|
virtual size_t GetSerializedSize() = 0;
|
|
|
|
// called by subclass to serialize the header (Type, PlayerSource, and PlayerTarget)
|
|
void SerializeHeader(ZBinaryBufferWriter& writer) {
|
|
writer.WriteU32(Type);
|
|
}
|
|
|
|
// called by subclass to get serialized header size
|
|
size_t GetHeaderSize() {
|
|
return sizeof(nID);
|
|
}
|
|
|
|
protected:
|
|
// c'tor
|
|
ZNetworkEvent(nID type) : Type(type) { }
|
|
};
|
|
|
|
/*
|
|
Network Event base implementation, which attempts to automatically handle serialization and
|
|
deserialization via template POD structs.
|
|
|
|
Note the template on the game event (DS), which indicates a POD struct. This is the data
|
|
that is serialized and sent as part of the event. Wrap the struct definition in pragma
|
|
pack statements to ensure correct behavior across systems and reduce bandwidth.
|
|
*/
|
|
template <typename DS>
|
|
class ZNetworkEventBase : public ZNetworkEvent
|
|
{
|
|
DISABLE_COPY_AND_ASSIGN(ZNetworkEventBase);
|
|
public:
|
|
// the data struct for this event
|
|
DS EventData;
|
|
|
|
// called by the network system to deserialize this event from binary form (after header is read)
|
|
virtual bool Deserialize(ZBinaryBufferReader& reader) {
|
|
if (reader.CanRead(sizeof(DS))) {
|
|
reader.ReadU8Array((uint8_t*)&EventData, sizeof(DS));
|
|
return true;
|
|
} else return false;
|
|
}
|
|
|
|
// called by the network system to serialize this event into binary form
|
|
virtual void Serialize(ZBinaryBufferWriter& writer) {
|
|
SerializeHeader(writer);
|
|
writer.WriteU8Array((uint8_t*)&EventData, sizeof(DS));
|
|
}
|
|
|
|
// called to get the serialized size of this event
|
|
virtual size_t GetSerializedSize() {
|
|
return GetHeaderSize() + sizeof(DS);
|
|
}
|
|
|
|
protected:
|
|
// c'tor
|
|
ZNetworkEventBase(nID type) : ZNetworkEvent(type) { }
|
|
};
|
|
|
|
#pragma pack (push, 1)
|
|
|
|
/*
|
|
Data struct used for message events, which will simply create the
|
|
given message on the other side and pass it to the simulation.
|
|
*/
|
|
template <typename M>
|
|
struct ZMessageEventData {
|
|
mID Type;
|
|
eID Sender;
|
|
eID Target;
|
|
M MessageData;
|
|
|
|
cID Connection;
|
|
};
|
|
|
|
#pragma pack (pop)
|
|
|
|
/*
|
|
Message network event. This is used to duplicate a message on other
|
|
connected simulations. The template parameter type is the message
|
|
data definition struct. Be sure to use pragma pack to reduce network
|
|
overhead.
|
|
*/
|
|
template <typename MT>
|
|
class ZMessageEvent : public ZNetworkEventBase<ZMessageEventData<MT>> {
|
|
public:
|
|
// c'tor
|
|
ZMessageEvent(mID msg_type) : ZNetworkEventBase(0) { }
|
|
ZMessageEvent(mID msg_type, eID sender, eID target, MT payload, cID connection)
|
|
: ZNetworkEventBase(0), EventData({msg_type, sender, target, connection, payload}) { }
|
|
|
|
// subclass implementations
|
|
virtual void HandleClient(ZSimulation& server_sim) {
|
|
server_sim.SendLocalMessage(Data.Type, Data.Sender, Data.Target, Data.MessageData);
|
|
}
|
|
|
|
virtual void HandleServer(ZSimulation& client_sim) {
|
|
client_sim.SendLocalMessage(Data.Type, Data.Sender, Data.Target, Data.MessageData);
|
|
}
|
|
};
|
|
|
|
|
|
#endif |