/// <summary> /// Sets the Destroyable's current Health /// (if decreasing Health on the Server, use Server_TakeDamage instead for damage logic) /// </summary> /// <param name="health"></param> public virtual void SetHealth(int health) { if (health == Health) return; int OldHealth = Health; Health = health; if (Health < OldHealth) DoDamageFX(OldHealth - Health); else if(Health > OldHealth) DoHealingFX(Health - OldHealth); if (Health > MaxHealth) Health = MaxHealth; if (MyWorld.IsServer) { // THESE LINES WRITE TO THE RELIABLE MESSAGE BUFFER FOR ALL NETWORKCLIENTS WriteMessageType(MSGID_DESTROYABLE_SET_HEALTH, PACKET_RELIABLE); WriteInt(Health, PACKET_RELIABLE); } }
// Generates Server state update messages to send to a particular NetworkClient in the session public override void Server_MakeTickMessages(MNetworkActorPackets packet) { if (Occupied()) { // THESE LINES WRITE TO A SPECIFIC UNRELIABLE MESSAGE BUFFER PASSED TO US FROM A SPECIFIC NETWORKCLIENT WriteMessageType(packet.GetMessagePacket(PACKET_UNRELIABLE), MSGID_VEHICLE_SEAT_YAWPITCH); WriteChar(packet.GetMessagePacket(PACKET_UNRELIABLE), SeatIndex); WriteFloat(packet.GetMessagePacket(PACKET_UNRELIABLE), curRotX); WriteFloat(packet.GetMessagePacket(PACKET_UNRELIABLE), curRotY); } }
// Send initial spawn data to all connected NetworkClients public override void Server_MakeSpawnMessages() { WriteMessageType(MSGID_NETWORKACTOR_VELOCITY, PACKET_SPAWN); WriteVector(Velocity, PACKET_SPAWN); WriteMessageType(MSGID_NETWORKACTOR_LOCATION, PACKET_SPAWN); WriteVector(Location, PACKET_SPAWN); if (QuadDamage) WriteMessageType(MSGID_GRENADE_QUADDAMAGE_ON, PACKET_SPAWN); }
/// <summary> /// Server generates SPAWN messages for a specific MNetworkClient who has /// joined after this Actor has already been spawned (should include any unique state at the time of joining /// that the Client should know about, and physics data). /// When the Client receives these messages, they're processed in Client_HandleSpawnMessage() /// immediately after constructing the NetworkActor /// </summary> public override MNetworkActorPackets Server_MakeOnJoinSynchMessages(MNetworkClient client) { MNetworkActorPackets packet = client.GetOrCreateNetworkActorPackets(this); for (int i = 0; i < NumTeams; i++) { // Write Team Score WriteMessageType(packet.GetMessagePacket(PACKET_SPAWN), MSGID_GAMESTATE_TEAM_SCORE); WriteInt(packet.GetMessagePacket(PACKET_SPAWN), i); WriteInt(packet.GetMessagePacket(PACKET_SPAWN), TeamInfos[i].Score); } return packet; }
/// <summary> /// Client-side processes a state UPDATE message /// </summary> /// <param name="message"></param> /// <param name="packetBuffer"></param> public override void Client_HandleTickMessage(byte message, MReadPacketBuffer packetBuffer) { switch (message) { // read current health value case MSGID_DESTROYABLE_SET_HEALTH: SetHealth(ReadInt(packetBuffer)); break; case MSGID_NETWORKACTOR_LOCATION: //pass the location to the networkactor's prediction function, with interpolation Client_ReadLocation(packetBuffer, true, .14f); break; default: base.Client_HandleTickMessage(message, packetBuffer); break; } }
/// <summary> /// Client-side processes a state SPAWN message /// </summary> /// <param name="message"></param> /// <param name="packetBuffer"></param> public override void Client_HandleSpawnMessage(byte message, MReadPacketBuffer packetBuffer) { switch (message) { //read current health value case MSGID_DESTROYABLE_SET_HEALTH: SetHealth(ReadInt(packetBuffer)); break; case MSGID_NETWORKACTOR_LOCATION: //pass the location to the networkactor's prediction function, with no interpolation Client_ReadLocation(packetBuffer, false, 0); break; default: base.Client_HandleSpawnMessage(message, packetBuffer); break; } }
// if not the Server, send mouse state to the Server if (!MyWorld.IsServer) MInput.Client_SendMouseUpdate(this); // send single control press event to the Server if (GameInput.ControlJustPressed(GameInput.KEY_RELOAD)) GameInput.SendControlPress(this, GameInput.KEY_RELOAD, true); // send movement key states (held, unheld) to the Server GameInput.SendControlState(this, GameInput.KEY_WALK_FORWARD);
/// <summary> /// Handles the server-side effect of a change in key pressing state, /// such as Activating when the Activate network handle ID is received and the received "IsDown" is true. /// </summary> public override void Server_HandleNetworkKeyInput(bool isDown, int NetworkKeyHandle) { // reload weapon if (NetworkKeyHandle == GameInput.KEY_RELOAD.NetworkHandleID && isDown) { if (CurrentWeapon != null) CurrentWeapon.Reload(); return; } } /// <summary> /// Handles a network mouse update that the Server has received from a NetworkClient for which this player is the avatar. /// This function calculates the Player's current Rotation from the received Yaw/Pitch values. /// </summary> public override void Server_HandleNetworkMouseUpdate(float mouseYaw, float mousePitch) { // set the player's Rotation to correspond to the new yaw and pitch Rotation = MMatrix.LookTowards(MVector.MakeDirection(mouseYaw,mousePitch,0)); }
public override float Server_AdaptiveDegradation(MNetworkClient client) { float AdaptiveDegradationFactor = 1; if (client.IsServer) return AdaptiveDegradationFactor; MActor avatar = client.ActorAvatar; if(avatar != null) { if (IsPassenger(avatar)) AdaptiveDegradationFactor = 1.75f; else { float distance = (Location - avatar.Location).Length(); if (distance < 20) AdaptiveDegradationFactor = 1.0f; else if (distance < 50) AdaptiveDegradationFactor = .9f; else if (distance < 100) AdaptiveDegradationFactor = .72f; else if (distance < 160) AdaptiveDegradationFactor = .4f; else AdaptiveDegradationFactor = .2f; } } return AdaptiveDegradationFactor; }