Added a method for changing a client's controlled character. Clients now get back control if their character is revived via the debug console.

+ It's possible to give clients control of monsters, which should add some new gameplay possibilitie. ;)
This commit is contained in:
Joonas Rikkonen
2017-06-10 15:07:10 +03:00
parent 8886409d56
commit 9b0d7c1020
6 changed files with 151 additions and 46 deletions

View File

@@ -27,7 +27,7 @@ namespace Barotrauma
{
base.Update(cam, deltaTime);
if (!Enabled) return;
if (!Enabled || IsRemotePlayer) return;
float dist = Vector2.DistanceSquared(cam.WorldViewCenter, WorldPosition);
if (dist > 8000.0f * 8000.0f)

View File

@@ -64,7 +64,7 @@ namespace Barotrauma
public Hull PreviousHull = null;
public Hull CurrentHull = null;
public readonly bool IsRemotePlayer;
public bool IsRemotePlayer;
private CharacterInventory inventory;
@@ -810,7 +810,7 @@ namespace Barotrauma
ViewTarget = null;
if (!AllowInput) return;
if (!(this is AICharacter) || controlled == this)
if (!(this is AICharacter) || controlled == this || IsRemotePlayer)
{
Vector2 targetMovement = GetTargetMovement();
@@ -1289,7 +1289,7 @@ namespace Barotrauma
{
foreach (Character c in CharacterList)
{
if (!(c is AICharacter)) continue;
if (!(c is AICharacter) && !c.IsRemotePlayer) continue;
if (GameMain.Server != null)
{
@@ -1432,7 +1432,7 @@ namespace Barotrauma
selectedConstruction = null;
}
if (controlled != this && !(this is AICharacter))
if (controlled != this && (!(this is AICharacter) || IsRemotePlayer))
{
if (!LockHands)
{

View File

@@ -82,7 +82,7 @@ namespace Barotrauma
private bool networkUpdateSent;
public bool isSynced = false;
public List<CharacterStateInfo> MemState
{
get { return memState; }
@@ -93,6 +93,16 @@ namespace Barotrauma
get { return memLocalState; }
}
public void ResetNetState()
{
memInput.Clear();
memState.Clear();
memLocalState.Clear();
LastNetworkUpdateID = 0;
LastProcessedID = 0;
}
private void UpdateNetInput()
{
if (this != Character.Controlled)
@@ -112,7 +122,7 @@ namespace Barotrauma
}
}
}
else if (GameMain.Server != null && !(this is AICharacter))
else if (GameMain.Server != null && (!(this is AICharacter) || IsRemotePlayer))
{
if (!AllowInput)
{
@@ -387,17 +397,24 @@ namespace Barotrauma
if (extraData != null)
{
switch ((NetEntityEvent.Type)extraData[0])
{
case NetEntityEvent.Type.InventoryState:
msg.Write(true);
msg.WriteRangedInteger(0, 2, 0);
inventory.ClientWrite(msg, extraData);
break;
case NetEntityEvent.Type.Control:
msg.WriteRangedInteger(0, 2, 1);
Client owner = ((Client)extraData[1]);
msg.Write(owner == null ? (byte)0 : owner.ID);
break;
case NetEntityEvent.Type.Status:
msg.Write(false);
msg.WriteRangedInteger(0, 2, 2);
WriteStatus(msg);
break;
}
msg.WritePadBits();
}
else
{
@@ -573,15 +590,36 @@ namespace Barotrauma
break;
case ServerNetObject.ENTITY_EVENT:
bool isInventoryUpdate = msg.ReadBoolean();
int eventType = msg.ReadRangedInteger(0, 2);
switch (eventType)
{
case 0:
inventory.ClientRead(type, msg, sendingTime);
break;
case 1:
byte ownerID = msg.ReadByte();
ResetNetState();
if (ownerID == GameMain.Client.ID)
{
if (controlled != null)
{
LastNetworkUpdateID = controlled.LastNetworkUpdateID;
}
if (isInventoryUpdate)
{
inventory.ClientRead(type, msg, sendingTime);
}
else
{
ReadStatus(msg);
controlled = this;
IsRemotePlayer = false;
GameMain.Client.Character = this;
}
else if (controlled == this)
{
controlled = null;
IsRemotePlayer = ownerID > 0;
}
break;
case 2:
ReadStatus(msg);
break;
}
break;

View File

@@ -404,17 +404,19 @@ namespace Barotrauma
break;
case "banip":
if (GameMain.Server == null || commands.Length < 2) break;
{
if (GameMain.Server == null || commands.Length < 2) break;
var client = GameMain.Server.ConnectedClients.Find(c => c.Connection.RemoteEndPoint.Address.ToString() == commands[1]);
if (client == null)
{
GameMain.Server.BanList.BanPlayer("Unnamed", commands[1]);
}
else
{
//GameMain.Server.KickClient(client, true);
}
var client = GameMain.Server.ConnectedClients.Find(c => c.Connection.RemoteEndPoint.Address.ToString() == commands[1]);
if (client == null)
{
GameMain.Server.BanList.BanPlayer("Unnamed", commands[1]);
}
else
{
GameMain.Server.KickClient(client, true);
}
}
break;
case "startclient":
if (commands.Length == 1) return;
@@ -462,15 +464,43 @@ namespace Barotrauma
break;
case "controlcharacter":
case "control":
if (commands.Length < 2) break;
var character = FindMatchingCharacter(commands, true);
if (character != null)
{
Character.Controlled = character;
if (commands.Length < 2) break;
var character = FindMatchingCharacter(commands, true);
if (character != null)
{
Character.Controlled = character;
}
}
break;
case "setclientcharacter":
{
if (GameMain.Server == null) break;
int separatorIndex = Array.IndexOf(commands, ";");
if (separatorIndex == -1 || commands.Length < 4)
{
ThrowError("Invalid parameters. The command should be formatted as \"setclientcharacter [client] ; [character]\"");
break;
}
string[] commandsLeft = commands.Take(separatorIndex).ToArray();
string[] commandsRight = commands.Skip(separatorIndex).ToArray();
string clientName = String.Join(" ", commandsLeft.Skip(1));
var client = GameMain.Server.ConnectedClients.Find(c => c.name == clientName);
if (client == null)
{
ThrowError("Client \"" + clientName + "\" not found.");
}
var character = FindMatchingCharacter(commandsRight, false);
GameMain.Server.SetClientCharacter(client, character);
}
break;
case "teleportcharacter":
case "teleport":
@@ -533,19 +563,29 @@ namespace Barotrauma
break;
case "revive":
Character reveivedCharacter = null;
Character revivedCharacter = null;
if (commands.Length == 1)
{
reveivedCharacter = Character.Controlled;
revivedCharacter = Character.Controlled;
}
else
{
reveivedCharacter = FindMatchingCharacter(commands);
revivedCharacter = FindMatchingCharacter(commands);
}
if (reveivedCharacter != null)
if (revivedCharacter != null)
{
reveivedCharacter.Revive(false);
revivedCharacter.Revive(false);
if (GameMain.Server != null)
{
foreach (Client c in GameMain.Server.ConnectedClients)
{
if (c.Character != revivedCharacter) continue;
//clients stop controlling the character when it dies, force control back
GameMain.Server.SetClientCharacter(c, revivedCharacter);
break;
}
}
}
break;
case "freeze":

View File

@@ -1,5 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -1945,6 +1944,37 @@ namespace Barotrauma.Networking
return true;
}
public void SetClientCharacter(Client client, Character newCharacter)
{
if (client == null) return;
//the client's previous character is no longer a remote player
if (client.Character != null)
{
client.Character.IsRemotePlayer = false;
}
if (newCharacter == null)
{
if (client.Character != null) //removing control of the current character
{
newCharacter.IsRemotePlayer = false;
CreateEntityEvent(client.Character, new object[] { NetEntityEvent.Type.Control, null });
client.Character = null;
}
}
else if (client.Character != newCharacter) //taking control of a new character
{
newCharacter.ResetNetState();
newCharacter.LastNetworkUpdateID = client.Character.LastNetworkUpdateID;
newCharacter.IsRemotePlayer = true;
client.Character = newCharacter;
CreateEntityEvent(newCharacter, new object[] { NetEntityEvent.Type.Control, client });
}
}
private void UpdateCharacterInfo(NetIncomingMessage message, Client sender)
{
Gender gender = Gender.Male;

View File

@@ -1,9 +1,5 @@
using Lidgren.Network;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Barotrauma.Networking
{
@@ -16,7 +12,8 @@ namespace Barotrauma.Networking
Status,
Repair,
ApplyStatusEffect,
ChangeProperty
ChangeProperty,
Control
}
public readonly Entity Entity;