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:
@@ -27,7 +27,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
base.Update(cam, deltaTime);
|
base.Update(cam, deltaTime);
|
||||||
|
|
||||||
if (!Enabled) return;
|
if (!Enabled || IsRemotePlayer) return;
|
||||||
|
|
||||||
float dist = Vector2.DistanceSquared(cam.WorldViewCenter, WorldPosition);
|
float dist = Vector2.DistanceSquared(cam.WorldViewCenter, WorldPosition);
|
||||||
if (dist > 8000.0f * 8000.0f)
|
if (dist > 8000.0f * 8000.0f)
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace Barotrauma
|
|||||||
public Hull PreviousHull = null;
|
public Hull PreviousHull = null;
|
||||||
public Hull CurrentHull = null;
|
public Hull CurrentHull = null;
|
||||||
|
|
||||||
public readonly bool IsRemotePlayer;
|
public bool IsRemotePlayer;
|
||||||
|
|
||||||
private CharacterInventory inventory;
|
private CharacterInventory inventory;
|
||||||
|
|
||||||
@@ -810,7 +810,7 @@ namespace Barotrauma
|
|||||||
ViewTarget = null;
|
ViewTarget = null;
|
||||||
if (!AllowInput) return;
|
if (!AllowInput) return;
|
||||||
|
|
||||||
if (!(this is AICharacter) || controlled == this)
|
if (!(this is AICharacter) || controlled == this || IsRemotePlayer)
|
||||||
{
|
{
|
||||||
Vector2 targetMovement = GetTargetMovement();
|
Vector2 targetMovement = GetTargetMovement();
|
||||||
|
|
||||||
@@ -1289,7 +1289,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (Character c in CharacterList)
|
foreach (Character c in CharacterList)
|
||||||
{
|
{
|
||||||
if (!(c is AICharacter)) continue;
|
if (!(c is AICharacter) && !c.IsRemotePlayer) continue;
|
||||||
|
|
||||||
if (GameMain.Server != null)
|
if (GameMain.Server != null)
|
||||||
{
|
{
|
||||||
@@ -1432,7 +1432,7 @@ namespace Barotrauma
|
|||||||
selectedConstruction = null;
|
selectedConstruction = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controlled != this && !(this is AICharacter))
|
if (controlled != this && (!(this is AICharacter) || IsRemotePlayer))
|
||||||
{
|
{
|
||||||
if (!LockHands)
|
if (!LockHands)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace Barotrauma
|
|||||||
private bool networkUpdateSent;
|
private bool networkUpdateSent;
|
||||||
|
|
||||||
public bool isSynced = false;
|
public bool isSynced = false;
|
||||||
|
|
||||||
public List<CharacterStateInfo> MemState
|
public List<CharacterStateInfo> MemState
|
||||||
{
|
{
|
||||||
get { return memState; }
|
get { return memState; }
|
||||||
@@ -93,6 +93,16 @@ namespace Barotrauma
|
|||||||
get { return memLocalState; }
|
get { return memLocalState; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ResetNetState()
|
||||||
|
{
|
||||||
|
memInput.Clear();
|
||||||
|
memState.Clear();
|
||||||
|
memLocalState.Clear();
|
||||||
|
|
||||||
|
LastNetworkUpdateID = 0;
|
||||||
|
LastProcessedID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateNetInput()
|
private void UpdateNetInput()
|
||||||
{
|
{
|
||||||
if (this != Character.Controlled)
|
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)
|
if (!AllowInput)
|
||||||
{
|
{
|
||||||
@@ -387,17 +397,24 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (extraData != null)
|
if (extraData != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch ((NetEntityEvent.Type)extraData[0])
|
switch ((NetEntityEvent.Type)extraData[0])
|
||||||
{
|
{
|
||||||
case NetEntityEvent.Type.InventoryState:
|
case NetEntityEvent.Type.InventoryState:
|
||||||
msg.Write(true);
|
msg.WriteRangedInteger(0, 2, 0);
|
||||||
inventory.ClientWrite(msg, extraData);
|
inventory.ClientWrite(msg, extraData);
|
||||||
break;
|
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:
|
case NetEntityEvent.Type.Status:
|
||||||
msg.Write(false);
|
msg.WriteRangedInteger(0, 2, 2);
|
||||||
WriteStatus(msg);
|
WriteStatus(msg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
msg.WritePadBits();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -573,15 +590,36 @@ namespace Barotrauma
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case ServerNetObject.ENTITY_EVENT:
|
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)
|
controlled = this;
|
||||||
{
|
IsRemotePlayer = false;
|
||||||
inventory.ClientRead(type, msg, sendingTime);
|
GameMain.Client.Character = this;
|
||||||
}
|
}
|
||||||
else
|
else if (controlled == this)
|
||||||
{
|
{
|
||||||
ReadStatus(msg);
|
controlled = null;
|
||||||
|
IsRemotePlayer = ownerID > 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ReadStatus(msg);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -404,17 +404,19 @@ namespace Barotrauma
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case "banip":
|
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]);
|
var client = GameMain.Server.ConnectedClients.Find(c => c.Connection.RemoteEndPoint.Address.ToString() == commands[1]);
|
||||||
if (client == null)
|
if (client == null)
|
||||||
{
|
{
|
||||||
GameMain.Server.BanList.BanPlayer("Unnamed", commands[1]);
|
GameMain.Server.BanList.BanPlayer("Unnamed", commands[1]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//GameMain.Server.KickClient(client, true);
|
GameMain.Server.KickClient(client, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "startclient":
|
case "startclient":
|
||||||
if (commands.Length == 1) return;
|
if (commands.Length == 1) return;
|
||||||
@@ -462,15 +464,43 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
case "controlcharacter":
|
case "controlcharacter":
|
||||||
case "control":
|
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;
|
break;
|
||||||
case "teleportcharacter":
|
case "teleportcharacter":
|
||||||
case "teleport":
|
case "teleport":
|
||||||
@@ -533,19 +563,29 @@ namespace Barotrauma
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case "revive":
|
case "revive":
|
||||||
Character reveivedCharacter = null;
|
Character revivedCharacter = null;
|
||||||
if (commands.Length == 1)
|
if (commands.Length == 1)
|
||||||
{
|
{
|
||||||
reveivedCharacter = Character.Controlled;
|
revivedCharacter = Character.Controlled;
|
||||||
}
|
}
|
||||||
else
|
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;
|
break;
|
||||||
case "freeze":
|
case "freeze":
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -1945,6 +1944,37 @@ namespace Barotrauma.Networking
|
|||||||
return true;
|
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)
|
private void UpdateCharacterInfo(NetIncomingMessage message, Client sender)
|
||||||
{
|
{
|
||||||
Gender gender = Gender.Male;
|
Gender gender = Gender.Male;
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
using Lidgren.Network;
|
using Lidgren.Network;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Barotrauma.Networking
|
namespace Barotrauma.Networking
|
||||||
{
|
{
|
||||||
@@ -16,7 +12,8 @@ namespace Barotrauma.Networking
|
|||||||
Status,
|
Status,
|
||||||
Repair,
|
Repair,
|
||||||
ApplyStatusEffect,
|
ApplyStatusEffect,
|
||||||
ChangeProperty
|
ChangeProperty,
|
||||||
|
Control
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly Entity Entity;
|
public readonly Entity Entity;
|
||||||
|
|||||||
Reference in New Issue
Block a user