#include "Monster.h" #include "ReplicaMember.h" #include "BitStream.h" #include "StringTable.h" #include "ReplicaManager.h" #include extern bool isServer; extern ReplicaManager replicaManager; extern Monster *monster; Monster::Monster() { // Setup my object position=1; health=2; replica = new ReplicaMember; // Only necessary if using the replication system by containing a member variable replica->SetParent(this); // Objects are only processed by the system after you tell the manager to replicate them. // Here I do it in the constructor, but in a real game you would probably do it after the object is done loading // This does NOT call serialize automatically - it only sends a call to create the remote object. if (isServer) replicaManager.Construct(replica, false, UNASSIGNED_PLAYER_ID, true); // Calling // replicaManager.SetScope(replica, true, UNASSIGNED_PLAYER_ID) // here would work for existing players, but not for future players. // So we call it in SendConstruction instead, which is called once for all players. if (isServer) { // For security, as a server disable all receives except REPLICA_RECEIVE_SERIALIZE // I could do this manually by putting if (isServer) return; at the top of all my receive functions too. replicaManager.DisableReplicaInterfaces(replica, REPLICA_RECEIVE_DESTRUCTION | REPLICA_RECEIVE_SCOPE_CHANGE); } else { // For convenience and for saving bandwidth, as a client disable all sends except REPLICA_SEND_SERIALIZE // I could do this manually by putting if (isServer==false) return; at the top of all my send functions too. replicaManager.DisableReplicaInterfaces(replica, REPLICA_SEND_CONSTRUCTION | REPLICA_SEND_DESTRUCTION | REPLICA_SEND_SCOPE_CHANGE); } } Monster::~Monster() { printf("Inside ~Monster\n"); // Remove the object before it is destroyed, or you will crash the next time the ReplicaManager updates replicaManager.Destruct(replica, UNASSIGNED_PLAYER_ID, true); replicaManager.DereferencePointer(replica); delete replica; monster=0; } ReplicaReturnResult Monster::SendConstruction( RakNetTime currentTime, PlayerID playerId, RakNet::BitStream *outBitStream, bool *includeTimestamp ) { // This string was pre-registered in main with stringTable->AddString so we can send it with the string table and save bandwidth stringTable->EncodeString("Monster", 255, outBitStream); // This means that this object starts in scope to this player. In a real game, you would only start in scope if an object // were immediately visible to that player. This only really applies to the server in a client/server game, since clients wouldn't hide their // own object updates from the server. // We could have left this line out by calling ReplicaManager::SetDefaultScope(true); in main() replicaManager.SetScope(replica, true, playerId, false); printf("Sending monster to %i:%i\n", playerId.binaryAddress, playerId.port); return REPLICA_PROCESSING_DONE; } void Monster::SendDestruction(RakNet::BitStream *outBitStream, PlayerID playerId) { } ReplicaReturnResult Monster::ReceiveDestruction(RakNet::BitStream *inBitStream, PlayerID playerId) { delete monster; return REPLICA_PROCESSING_DONE; } ReplicaReturnResult Monster::SendScopeChange(bool inScope, RakNet::BitStream *outBitStream, RakNetTime currentTime, PlayerID playerId) { if (inScope) printf("Sending scope change to true in Monster\n"); else printf("Sending scope change to false in Monster\n"); // Up to you to write this. If you write nothing, the system will treat that as if you wanted to cancel the scope change outBitStream->Write(inScope); return REPLICA_PROCESSING_DONE; } ReplicaReturnResult Monster::ReceiveScopeChange(RakNet::BitStream *inBitStream, PlayerID playerId) { bool inScope; inBitStream->Read(inScope); if (inScope) printf("Received message that scope is now true in Monster\n"); else printf("Received message that scope is now false in Monster\n"); return REPLICA_PROCESSING_DONE; } ReplicaReturnResult Monster::Serialize(bool *sendTimestamp, RakNet::BitStream *outBitStream, RakNetTime lastSendTime, PacketPriority *priority, PacketReliability *reliability, RakNetTime currentTime, PlayerID playerId) { if (lastSendTime==0) printf("First call to Monster::Serialize for %i:%i\n", playerId.binaryAddress, playerId.port); outBitStream->Write(position); outBitStream->Write(health); return REPLICA_PROCESSING_DONE; } ReplicaReturnResult Monster::Deserialize(RakNet::BitStream *inBitStream, RakNetTime timestamp, RakNetTime lastDeserializeTime, PlayerID playerId ) { if (lastDeserializeTime==0) printf("First call to Monster::Deserialize\n"); else printf("Got Monster::Deserialize\n"); inBitStream->Read(position); inBitStream->Read(health); return REPLICA_PROCESSING_DONE; } bool Monster::IsNetworkIDAuthority(void) const { return isServer; }