WIP client special permissions (kick, ban, end round)
This commit is contained in:
@@ -79,9 +79,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
public GUIComponent CreateBanFrame(GUIComponent parent)
|
||||
{
|
||||
//GUIFrame banFrame = new GUIFrame(new Rectangle(0,0,0,0), null, Alignment.Center, GUI.Style, parent);
|
||||
|
||||
//new GUITextBlock(new Rectangle(0, -10, 0, 30), "Banned IPs:", GUI.Style, Alignment.Left, Alignment.Left, banFrame, false, GUI.LargeFont);
|
||||
banFrame = new GUIListBox(new Rectangle(0, 0, 0, 0), GUI.Style, parent);
|
||||
|
||||
foreach (BannedPlayer bannedPlayer in bannedPlayers)
|
||||
@@ -91,18 +88,14 @@ namespace Barotrauma.Networking
|
||||
bannedPlayer.IP + " (" + bannedPlayer.Name + ")",
|
||||
GUI.Style,
|
||||
Alignment.Left, Alignment.Left, banFrame);
|
||||
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
|
||||
textBlock.Padding = new Vector4(10.0f, 10.0f, 0.0f, 0.0f);
|
||||
textBlock.UserData = banFrame;
|
||||
|
||||
var removeButton = new GUIButton(new Rectangle(0, 00, 100, 20), "Remove", Alignment.Right | Alignment.CenterY, GUI.Style, textBlock);
|
||||
var removeButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Remove", Alignment.Right | Alignment.CenterY, GUI.Style, textBlock);
|
||||
removeButton.UserData = bannedPlayer;
|
||||
removeButton.OnClicked = RemoveBan;
|
||||
}
|
||||
|
||||
//var closeButton = new GUIButton(new Rectangle(0,30,100,20), "Close", Alignment.BottomRight, GUI.Style, banFrame);
|
||||
//closeButton.OnClicked = CloseFrame;
|
||||
|
||||
|
||||
return banFrame;
|
||||
}
|
||||
|
||||
|
||||
169
Subsurface/Source/Networking/Client.cs
Normal file
169
Subsurface/Source/Networking/Client.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
using Barotrauma.Networking.ReliableMessages;
|
||||
using Lidgren.Network;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
[Flags]
|
||||
enum ClientPermissions
|
||||
{
|
||||
None = 0,
|
||||
[Description("End round")]
|
||||
EndRound = 1,
|
||||
[Description("Kick")]
|
||||
Kick = 2,
|
||||
[Description("Ban")]
|
||||
Ban = 4
|
||||
}
|
||||
|
||||
class Client
|
||||
{
|
||||
public string name;
|
||||
public byte ID;
|
||||
|
||||
public Character Character;
|
||||
public CharacterInfo characterInfo;
|
||||
public NetConnection Connection { get; set; }
|
||||
public string version;
|
||||
public bool inGame;
|
||||
|
||||
private List<Client> kickVoters;
|
||||
|
||||
public bool ReadyToStart;
|
||||
|
||||
private object[] votes;
|
||||
|
||||
public List<JobPrefab> jobPreferences;
|
||||
public JobPrefab assignedJob;
|
||||
|
||||
public FileStreamSender FileStreamSender;
|
||||
|
||||
public ReliableChannel ReliableChannel;
|
||||
|
||||
public float deleteDisconnectedTimer;
|
||||
|
||||
public ClientPermissions Permissions;
|
||||
|
||||
public int KickVoteCount
|
||||
{
|
||||
get { return kickVoters.Count; }
|
||||
}
|
||||
|
||||
public Client(NetPeer server, string name, byte ID)
|
||||
: this(name, ID)
|
||||
{
|
||||
ReliableChannel = new ReliableChannel(server);
|
||||
}
|
||||
|
||||
public Client(string name, byte ID)
|
||||
{
|
||||
this.name = name;
|
||||
this.ID = ID;
|
||||
|
||||
kickVoters = new List<Client>();
|
||||
|
||||
votes = new object[Enum.GetNames(typeof(VoteType)).Length];
|
||||
|
||||
jobPreferences = new List<JobPrefab>(JobPrefab.List.GetRange(0, 3));
|
||||
}
|
||||
|
||||
public static bool IsValidName(string name)
|
||||
{
|
||||
if (name.Contains("\n") || name.Contains("\r\n")) return false;
|
||||
|
||||
return (name.All(c =>
|
||||
c != ';' &&
|
||||
c != ',' &&
|
||||
c != '<' &&
|
||||
c != '/'));
|
||||
}
|
||||
|
||||
public static string SanitizeName(string name)
|
||||
{
|
||||
if (name.Length > 20)
|
||||
{
|
||||
name = name.Substring(0, 20);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public void SetPermissions(ClientPermissions permissions)
|
||||
{
|
||||
this.Permissions = permissions;
|
||||
}
|
||||
|
||||
public void GivePermission(ClientPermissions permission)
|
||||
{
|
||||
this.Permissions |= permission;
|
||||
}
|
||||
|
||||
public void RemovePermission(ClientPermissions permission)
|
||||
{
|
||||
this.Permissions &= ~permission;
|
||||
}
|
||||
|
||||
public bool HasPermission(ClientPermissions permission)
|
||||
{
|
||||
return Permissions.HasFlag(permission);
|
||||
}
|
||||
|
||||
public T GetVote<T>(VoteType voteType)
|
||||
{
|
||||
return (votes[(int)voteType] is T) ? (T)votes[(int)voteType] : default(T);
|
||||
}
|
||||
|
||||
public void SetVote(VoteType voteType, object value)
|
||||
{
|
||||
votes[(int)voteType] = value;
|
||||
}
|
||||
|
||||
public void ResetVotes()
|
||||
{
|
||||
for (int i = 0; i < votes.Length; i++)
|
||||
{
|
||||
votes[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddKickVote(Client voter)
|
||||
{
|
||||
if (!kickVoters.Contains(voter)) kickVoters.Add(voter);
|
||||
}
|
||||
|
||||
|
||||
public void RemoveKickVote(Client voter)
|
||||
{
|
||||
kickVoters.Remove(voter);
|
||||
}
|
||||
|
||||
public bool HasKickVoteFromID(int id)
|
||||
{
|
||||
return kickVoters.Any(k => k.ID == id);
|
||||
}
|
||||
|
||||
|
||||
public static void UpdateKickVotes(List<Client> connectedClients)
|
||||
{
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
client.kickVoters.RemoveAll(voter => !connectedClients.Contains(voter));
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelTransfer()
|
||||
{
|
||||
if (FileStreamSender == null) return;
|
||||
|
||||
FileStreamSender.CancelTransfer();
|
||||
FileStreamSender.Dispose();
|
||||
|
||||
FileStreamSender = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using FarseerPhysics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -21,7 +22,10 @@ namespace Barotrauma.Networking
|
||||
private FileStreamReceiver fileStreamReceiver;
|
||||
private Queue<Pair<string, FileTransferMessageType>> requestFileQueue;
|
||||
|
||||
private GUITickBox endRoundButton;
|
||||
private GUIButton endRoundButton;
|
||||
private GUITickBox endVoteTickBox;
|
||||
|
||||
private ClientPermissions permissions;
|
||||
|
||||
private bool connected;
|
||||
|
||||
@@ -51,8 +55,22 @@ namespace Barotrauma.Networking
|
||||
|
||||
public GameClient(string newName)
|
||||
{
|
||||
endRoundButton = new GUITickBox(new Rectangle(GameMain.GraphicsWidth - 170, 20, 20, 20), "End round", Alignment.TopLeft, inGameHUD);
|
||||
endRoundButton.OnSelected = ToggleEndRoundVote;
|
||||
endVoteTickBox = new GUITickBox(new Rectangle(GameMain.GraphicsWidth - 170, 20, 20, 20), "End round", Alignment.TopLeft, inGameHUD);
|
||||
endVoteTickBox.OnSelected = ToggleEndRoundVote;
|
||||
endVoteTickBox.Visible = false;
|
||||
|
||||
endRoundButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170, 20, 150, 20), "End round", Alignment.TopLeft, GUI.Style, inGameHUD);
|
||||
endRoundButton.OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (!permissions.HasFlag(ClientPermissions.EndRound)) return false;
|
||||
|
||||
var msg = client.CreateMessage();
|
||||
|
||||
msg.Write((byte)PacketTypes.EndGame);
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
|
||||
return true;
|
||||
};
|
||||
endRoundButton.Visible = false;
|
||||
|
||||
newName = newName.Replace(":", "");
|
||||
@@ -227,9 +245,12 @@ namespace Barotrauma.Networking
|
||||
if (packetType == (byte)PacketTypes.LoggedIn)
|
||||
{
|
||||
myID = inc.ReadByte();
|
||||
permissions = (ClientPermissions)inc.ReadInt32();
|
||||
gameStarted = inc.ReadBoolean();
|
||||
bool hasCharacter = inc.ReadBoolean();
|
||||
bool allowSpectating = inc.ReadBoolean();
|
||||
|
||||
endRoundButton.Visible = permissions.HasFlag(ClientPermissions.EndRound);
|
||||
|
||||
if (gameStarted && Screen.Selected != GameMain.GameScreen)
|
||||
{
|
||||
@@ -549,6 +570,46 @@ namespace Barotrauma.Networking
|
||||
|
||||
AddChatMessage(otherClient.name + " has joined the server", ChatMessageType.Server);
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.Permissions:
|
||||
ClientPermissions newPermissions = (ClientPermissions)inc.ReadInt32();
|
||||
|
||||
if (newPermissions != permissions)
|
||||
{
|
||||
if (GUIMessageBox.MessageBoxes.Count > 0)
|
||||
{
|
||||
var existingMsgBox = GUIMessageBox.MessageBoxes.Peek();
|
||||
if (existingMsgBox.UserData as string == "permissions")
|
||||
{
|
||||
GUIMessageBox.MessageBoxes.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
//new GUIMessageBox("The host has changed you permissions. New permissions")
|
||||
string msg = "";
|
||||
if (newPermissions == ClientPermissions.None)
|
||||
{
|
||||
msg = "The host has removed all your special permissions.";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "Your current permissions:\n";
|
||||
foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions)))
|
||||
{
|
||||
if (!newPermissions.HasFlag(permissions) || permission == ClientPermissions.None) continue;
|
||||
|
||||
System.Reflection.FieldInfo fi = typeof(ClientPermissions).GetField(permission.ToString());
|
||||
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
|
||||
msg += " - " + attributes[0].Description+"\n";
|
||||
}
|
||||
}
|
||||
|
||||
new GUIMessageBox("Permissions changed", msg).UserData = "permissions";
|
||||
}
|
||||
|
||||
endRoundButton.Visible = permissions.HasFlag(ClientPermissions.EndRound);
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.RequestFile:
|
||||
bool accepted = inc.ReadBoolean();
|
||||
@@ -572,11 +633,9 @@ namespace Barotrauma.Networking
|
||||
//todo: unexpected file
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
{
|
||||
fileStreamReceiver.ReadMessage(inc);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.PlayerLeft:
|
||||
@@ -653,7 +712,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (Character != null) Character.Remove();
|
||||
|
||||
endRoundButton.Selected = false;
|
||||
endVoteTickBox.Selected = false;
|
||||
|
||||
int seed = inc.ReadInt32();
|
||||
string levelSeed = inc.ReadString();
|
||||
@@ -746,7 +805,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
gameStarted = true;
|
||||
|
||||
endRoundButton.Visible = Voting.AllowEndVoting && myCharacter != null;
|
||||
endVoteTickBox.Visible = Voting.AllowEndVoting && myCharacter != null;
|
||||
|
||||
GameMain.GameScreen.Select();
|
||||
|
||||
@@ -804,6 +863,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
}
|
||||
|
||||
public bool HasPermission(ClientPermissions permission)
|
||||
{
|
||||
return permissions.HasFlag(permission);
|
||||
}
|
||||
|
||||
public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||
{
|
||||
base.Draw(spriteBatch);
|
||||
@@ -839,6 +903,10 @@ namespace Barotrauma.Networking
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true);
|
||||
spriteBatch.DrawString(GUI.Font, "Network statistics:", new Vector2(x + 10, y + 10), Color.White);
|
||||
|
||||
spriteBatch.DrawString(GUI.Font, "Ping: " + (int)(client.ServerConnection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 10, y + 25), Color.White);
|
||||
|
||||
y += 15;
|
||||
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + client.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White);
|
||||
spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + client.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White);
|
||||
|
||||
@@ -866,21 +934,35 @@ namespace Barotrauma.Networking
|
||||
Character character = obj as Character;
|
||||
if (character == null) return false;
|
||||
|
||||
if (character != myCharacter && Voting.AllowVoteKick)
|
||||
if (character != myCharacter)
|
||||
{
|
||||
var client = GameMain.NetworkMember.ConnectedClients.Find(c => c.Character == character);
|
||||
if (client != null)
|
||||
if (client == null) return false;
|
||||
|
||||
if (HasPermission(ClientPermissions.Ban))
|
||||
{
|
||||
var kickButton = new GUIButton(new Rectangle(0, 0, 120, 20), "Vote to Kick", Alignment.BottomLeft, GUI.Style, characterFrame);
|
||||
var banButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Ban", Alignment.BottomRight, GUI.Style, characterFrame);
|
||||
banButton.UserData = character.Name;
|
||||
banButton.OnClicked += GameMain.NetLobbyScreen.BanPlayer;
|
||||
}
|
||||
if (HasPermission(ClientPermissions.Kick))
|
||||
{
|
||||
var kickButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Kick", Alignment.BottomLeft, GUI.Style, characterFrame);
|
||||
kickButton.UserData = character.Name;
|
||||
kickButton.OnClicked += GameMain.NetLobbyScreen.KickPlayer;
|
||||
}
|
||||
else if (Voting.AllowVoteKick)
|
||||
{
|
||||
var kickVoteButton = new GUIButton(new Rectangle(0, 0, 120, 20), "Vote to Kick", Alignment.BottomLeft, GUI.Style, characterFrame);
|
||||
|
||||
if (GameMain.NetworkMember.ConnectedClients != null)
|
||||
{
|
||||
kickButton.Enabled = !client.HasKickVoteFromID(myID);
|
||||
kickVoteButton.Enabled = !client.HasKickVoteFromID(myID);
|
||||
}
|
||||
|
||||
kickButton.UserData = character;
|
||||
kickButton.OnClicked += VoteForKick;
|
||||
}
|
||||
kickVoteButton.UserData = character;
|
||||
kickVoteButton.OnClicked += VoteForKick;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -981,6 +1063,19 @@ namespace Barotrauma.Networking
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
public override void KickPlayer(string kickedName, bool ban)
|
||||
{
|
||||
if (!permissions.HasFlag(ClientPermissions.Kick) && !ban) return;
|
||||
if (!permissions.HasFlag(ClientPermissions.Ban) && ban) return;
|
||||
|
||||
NetOutgoingMessage msg = client.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.KickPlayer);
|
||||
msg.Write(ban);
|
||||
msg.Write(kickedName);
|
||||
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
public bool VoteForKick(GUIButton button, object userdata)
|
||||
{
|
||||
var votedClient = otherClients.Find(c => c.Character == userdata);
|
||||
@@ -1105,7 +1200,7 @@ namespace Barotrauma.Networking
|
||||
Character.Controlled = character;
|
||||
GameMain.LightManager.LosEnabled = true;
|
||||
|
||||
if (endRoundButton != null) endRoundButton.Visible = Voting.AllowEndVoting;
|
||||
if (endVoteTickBox != null) endVoteTickBox.Visible = Voting.AllowEndVoting;
|
||||
}
|
||||
|
||||
return character;
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Barotrauma.Networking
|
||||
//----------------------------------------
|
||||
|
||||
var endRoundButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170, 20, 150, 20), "End round", Alignment.TopLeft, GUI.Style, inGameHUD);
|
||||
endRoundButton.OnClicked = EndButtonHit;
|
||||
endRoundButton.OnClicked = (btn, userdata) => { EndGame(); return true; };
|
||||
|
||||
log = new ServerLog(name);
|
||||
showLogButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170, 20, 150, 20), "Server Log", Alignment.TopLeft, GUI.Style, inGameHUD);
|
||||
@@ -108,9 +108,9 @@ namespace Barotrauma.Networking
|
||||
banList = new BanList();
|
||||
|
||||
LoadSettings();
|
||||
LoadClientPermissions();
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
|
||||
CoroutineManager.StartCoroutine(StartServer(isPublic));
|
||||
}
|
||||
@@ -312,8 +312,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
Log("Ending round (submarine reached the end of the level)", Color.Cyan);
|
||||
}
|
||||
|
||||
EndButtonHit(null, null);
|
||||
|
||||
EndGame();
|
||||
UpdateNetLobby(null,null);
|
||||
return;
|
||||
}
|
||||
@@ -496,11 +496,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.Chatmessage:
|
||||
//SendChatMessage(ChatMessage.ReadNetworkMessage(inc));
|
||||
//!!!!!!!!!!!
|
||||
|
||||
ReadChatMessage(inc);
|
||||
|
||||
break;
|
||||
case (byte)PacketTypes.PlayerLeft:
|
||||
DisconnectClient(inc.SenderConnection);
|
||||
@@ -508,6 +504,38 @@ namespace Barotrauma.Networking
|
||||
case (byte)PacketTypes.StartGame:
|
||||
sender.ReadyToStart = true;
|
||||
break;
|
||||
case (byte)PacketTypes.EndGame:
|
||||
if (!sender.HasPermission(ClientPermissions.EndRound))
|
||||
{
|
||||
Log(sender.name+" attempted to end the round (insufficient permissions)", Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Round ended by " + sender.name, Color.Red);
|
||||
EndGame();
|
||||
}
|
||||
break;
|
||||
case (byte)PacketTypes.KickPlayer:
|
||||
bool ban = inc.ReadBoolean();
|
||||
string kickedName = inc.ReadString();
|
||||
|
||||
var kickedClient = connectedClients.Find(c => c.name.ToLowerInvariant() == kickedName.ToLowerInvariant());
|
||||
if (kickedClient == null || kickedClient == sender) return;
|
||||
|
||||
if (ban && !sender.HasPermission(ClientPermissions.Ban))
|
||||
{
|
||||
Log(sender.name + " attempted to ban " + kickedClient.name + " (insufficient permissions)", Color.Red);
|
||||
|
||||
}
|
||||
else if (!sender.HasPermission(ClientPermissions.Kick))
|
||||
{
|
||||
Log(sender.name + " attempted to kick " + kickedClient.name + " (insufficient permissions)", Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
KickClient(kickedClient, ban);
|
||||
}
|
||||
break;
|
||||
case (byte)PacketTypes.CharacterInfo:
|
||||
ReadCharacterData(inc);
|
||||
break;
|
||||
@@ -565,7 +593,7 @@ namespace Barotrauma.Networking
|
||||
((float)EndVoteCount / (float)EndVoteMax) >= EndVoteRequiredRatio)
|
||||
{
|
||||
Log("Ending round by votes (" + EndVoteCount + "/" + (EndVoteMax - EndVoteCount) + ")", Color.Cyan);
|
||||
EndButtonHit(null, null);
|
||||
EndGame();
|
||||
}
|
||||
break;
|
||||
case (byte)PacketTypes.RequestNetLobbyUpdate:
|
||||
@@ -578,7 +606,6 @@ namespace Barotrauma.Networking
|
||||
var startMessage = CreateStartMessage(roundStartSeed, Submarine.MainSub, GameMain.GameSession.gameMode.Preset);
|
||||
server.SendMessage(startMessage, inc.SenderConnection, NetDeliveryMethod.ReliableOrdered);
|
||||
|
||||
sender.Spectating = true;
|
||||
CoroutineManager.StartCoroutine(SyncSpectator(sender));
|
||||
}
|
||||
break;
|
||||
@@ -619,7 +646,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (recipients == null)
|
||||
{
|
||||
recipients = connectedClients.FindAll(c => c.Character != null || c.Spectating);
|
||||
recipients = connectedClients.FindAll(c => c.inGame);
|
||||
}
|
||||
|
||||
if (recipients.Count == 0) return;
|
||||
@@ -1002,9 +1029,9 @@ namespace Barotrauma.Networking
|
||||
return msg;
|
||||
}
|
||||
|
||||
private bool EndButtonHit(GUIButton button, object obj)
|
||||
public void EndGame()
|
||||
{
|
||||
if (!gameStarted) return false;
|
||||
if (!gameStarted) return;
|
||||
|
||||
string endMessage = "The round has ended." + '\n';
|
||||
|
||||
@@ -1018,12 +1045,7 @@ namespace Barotrauma.Networking
|
||||
if (autoRestart) AutoRestartTimer = AutoRestartInterval;
|
||||
|
||||
if (SaveServerLogs) log.Save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public IEnumerable<object> EndGame(string endMessage)
|
||||
{
|
||||
|
||||
Character.Controlled = null;
|
||||
myCharacter = null;
|
||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
@@ -1037,7 +1059,6 @@ namespace Barotrauma.Networking
|
||||
#endif
|
||||
|
||||
respawnManager = null;
|
||||
|
||||
gameStarted = false;
|
||||
|
||||
if (connectedClients.Count > 0)
|
||||
@@ -1053,12 +1074,16 @@ namespace Barotrauma.Networking
|
||||
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
client.Spectating = false;
|
||||
client.Character = null;
|
||||
client.inGame = false;
|
||||
}
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(EndCinematic());
|
||||
}
|
||||
|
||||
public IEnumerable<object> EndCinematic()
|
||||
{
|
||||
float endPreviewLength = 10.0f;
|
||||
|
||||
var cinematic = new TransitionCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, endPreviewLength);
|
||||
@@ -1077,7 +1102,6 @@ namespace Barotrauma.Networking
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
|
||||
}
|
||||
|
||||
public void SendRespawnManagerMsg(List<Character> spawnedCharacters = null, List<Item> spawnedItems = null, List<NetConnection> recipients = null)
|
||||
@@ -1163,7 +1187,7 @@ namespace Barotrauma.Networking
|
||||
//if (GameMain.GameSession!=null) GameMain.GameSession.CrewManager.CreateCrewFrame(crew);
|
||||
}
|
||||
|
||||
public void KickPlayer(string playerName, bool ban = false)
|
||||
public override void KickPlayer(string playerName, bool ban)
|
||||
{
|
||||
playerName = playerName.ToLowerInvariant();
|
||||
|
||||
@@ -1386,6 +1410,27 @@ namespace Barotrauma.Networking
|
||||
return true;
|
||||
}
|
||||
|
||||
public void UpdateClientPermissions(Client client)
|
||||
{
|
||||
var msg = server.CreateMessage();
|
||||
msg.Write((byte)PacketTypes.Permissions);
|
||||
msg.Write((int)client.Permissions);
|
||||
|
||||
server.SendMessage(msg, client.Connection, NetDeliveryMethod.ReliableUnordered);
|
||||
|
||||
clientPermissions.RemoveAll(cp => cp.IP == client.Connection.RemoteEndPoint.Address.ToString());
|
||||
|
||||
if (client.Permissions != ClientPermissions.None)
|
||||
{
|
||||
clientPermissions.Add(new SavedClientPermission(
|
||||
client.name,
|
||||
client.Connection.RemoteEndPoint.Address.ToString(),
|
||||
client.Permissions));
|
||||
}
|
||||
|
||||
SaveClientPermissions();
|
||||
}
|
||||
|
||||
public override bool SelectCrewCharacter(GUIComponent component, object obj)
|
||||
{
|
||||
base.SelectCrewCharacter(component, obj);
|
||||
@@ -1794,131 +1839,4 @@ namespace Barotrauma.Networking
|
||||
server.Shutdown("The server has been shut down");
|
||||
}
|
||||
}
|
||||
|
||||
class Client
|
||||
{
|
||||
public string name;
|
||||
public byte ID;
|
||||
|
||||
public Character Character;
|
||||
public CharacterInfo characterInfo;
|
||||
public NetConnection Connection { get; set; }
|
||||
public string version;
|
||||
public bool inGame;
|
||||
|
||||
private List<Client> kickVoters;
|
||||
|
||||
public bool ReadyToStart;
|
||||
|
||||
private object[] votes;
|
||||
|
||||
public List<JobPrefab> jobPreferences;
|
||||
public JobPrefab assignedJob;
|
||||
|
||||
public FileStreamSender FileStreamSender;
|
||||
|
||||
public bool Spectating;
|
||||
|
||||
public ReliableChannel ReliableChannel;
|
||||
|
||||
public float deleteDisconnectedTimer;
|
||||
|
||||
public int KickVoteCount
|
||||
{
|
||||
get { return kickVoters.Count; }
|
||||
}
|
||||
|
||||
|
||||
public Client(NetPeer server, string name, byte ID)
|
||||
: this(name, ID)
|
||||
{
|
||||
ReliableChannel = new ReliableChannel(server);
|
||||
}
|
||||
|
||||
public Client(string name, byte ID)
|
||||
{
|
||||
this.name = name;
|
||||
this.ID = ID;
|
||||
|
||||
kickVoters = new List<Client>();
|
||||
|
||||
votes = new object[Enum.GetNames(typeof(VoteType)).Length];
|
||||
|
||||
jobPreferences = new List<JobPrefab>(JobPrefab.List.GetRange(0,3));
|
||||
}
|
||||
|
||||
public static bool IsValidName(string name)
|
||||
{
|
||||
if (name.Contains("\n") || name.Contains("\r\n")) return false;
|
||||
|
||||
return (name.All(c =>
|
||||
c != ';' &&
|
||||
c != ',' &&
|
||||
c != '<' &&
|
||||
c != '/'));
|
||||
}
|
||||
|
||||
public static string SanitizeName(string name)
|
||||
{
|
||||
if (name.Length > 20)
|
||||
{
|
||||
name = name.Substring(0, 20);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public T GetVote<T>(VoteType voteType)
|
||||
{
|
||||
return (votes[(int)voteType] is T) ? (T)votes[(int)voteType] : default(T);
|
||||
}
|
||||
|
||||
public void SetVote(VoteType voteType, object value)
|
||||
{
|
||||
votes[(int)voteType] = value;
|
||||
}
|
||||
|
||||
public void ResetVotes()
|
||||
{
|
||||
for (int i = 0; i<votes.Length; i++)
|
||||
{
|
||||
votes[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddKickVote(Client voter)
|
||||
{
|
||||
if (!kickVoters.Contains(voter)) kickVoters.Add(voter);
|
||||
}
|
||||
|
||||
|
||||
public void RemoveKickVote(Client voter)
|
||||
{
|
||||
kickVoters.Remove(voter);
|
||||
}
|
||||
|
||||
public bool HasKickVoteFromID(int id)
|
||||
{
|
||||
return kickVoters.Any(k => k.ID == id);
|
||||
}
|
||||
|
||||
|
||||
public static void UpdateKickVotes(List<Client> connectedClients)
|
||||
{
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
client.kickVoters.RemoveAll(voter => !connectedClients.Contains(voter));
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelTransfer()
|
||||
{
|
||||
if (FileStreamSender == null) return;
|
||||
|
||||
FileStreamSender.CancelTransfer();
|
||||
FileStreamSender.Dispose();
|
||||
|
||||
FileStreamSender = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +177,12 @@ namespace Barotrauma.Networking
|
||||
newClient.Connection = inc.SenderConnection;
|
||||
newClient.version = version;
|
||||
|
||||
var savedPermissions = clientPermissions.Find(cp => cp.IP == newClient.Connection.RemoteEndPoint.Address.ToString());
|
||||
if (savedPermissions != null)
|
||||
{
|
||||
newClient.SetPermissions(savedPermissions.Permissions);
|
||||
}
|
||||
|
||||
connectedClients.Add(newClient);
|
||||
|
||||
UpdateCrewFrame();
|
||||
@@ -214,6 +220,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
outmsg.Write((byte)PacketTypes.LoggedIn);
|
||||
outmsg.Write(sender.ID);
|
||||
outmsg.Write((int)sender.Permissions);
|
||||
outmsg.Write(gameStarted);
|
||||
outmsg.Write(gameStarted && sender.Character != null && !sender.Character.IsDead);
|
||||
outmsg.Write(AllowSpectating);
|
||||
|
||||
@@ -21,7 +21,24 @@ namespace Barotrauma.Networking
|
||||
|
||||
partial class GameServer : NetworkMember, IPropertyObject
|
||||
{
|
||||
private class SavedClientPermission
|
||||
{
|
||||
public readonly string IP;
|
||||
public readonly string Name;
|
||||
|
||||
public ClientPermissions Permissions;
|
||||
|
||||
public SavedClientPermission(string name, string ip, ClientPermissions permissions)
|
||||
{
|
||||
this.Name = name;
|
||||
this.IP = ip;
|
||||
|
||||
this.Permissions = permissions;
|
||||
}
|
||||
}
|
||||
|
||||
public const string SettingsFile = "serversettings.xml";
|
||||
public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.txt";
|
||||
|
||||
public Dictionary<string, ObjectProperty> ObjectProperties
|
||||
{
|
||||
@@ -50,6 +67,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
private bool autoRestart;
|
||||
|
||||
private List<SavedClientPermission> clientPermissions = new List<SavedClientPermission>();
|
||||
|
||||
[HasDefaultValue(true, true)]
|
||||
public bool RandomizeSeed
|
||||
{
|
||||
@@ -504,6 +523,60 @@ namespace Barotrauma.Networking
|
||||
|
||||
|
||||
banList.CreateBanFrame(settingsTabs[2]);
|
||||
|
||||
}
|
||||
|
||||
public void LoadClientPermissions()
|
||||
{
|
||||
if (!File.Exists(ClientPermissionsFile)) return;
|
||||
|
||||
string[] lines;
|
||||
try
|
||||
{
|
||||
lines = File.ReadAllLines(ClientPermissionsFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to open client permission file " + ClientPermissionsFile, e);
|
||||
return;
|
||||
}
|
||||
|
||||
clientPermissions.Clear();
|
||||
foreach (string line in lines)
|
||||
{
|
||||
string[] separatedLine = line.Split('|');
|
||||
if (separatedLine.Length < 3) continue;
|
||||
|
||||
string name = String.Join("|", separatedLine.Take(separatedLine.Length - 2));
|
||||
string ip = separatedLine[separatedLine.Length - 2];
|
||||
|
||||
ClientPermissions permissions = ClientPermissions.None;
|
||||
if (Enum.TryParse<ClientPermissions>(separatedLine.Last(), out permissions))
|
||||
{
|
||||
clientPermissions.Add(new SavedClientPermission(name, ip, permissions));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveClientPermissions()
|
||||
{
|
||||
GameServer.Log("Saving client permissions", null);
|
||||
|
||||
List<string> lines = new List<string>();
|
||||
|
||||
foreach (SavedClientPermission clientPermission in clientPermissions)
|
||||
{
|
||||
lines.Add(clientPermission.Name + "|" + clientPermission.IP+"|"+clientPermission.Permissions.ToString());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllLines(ClientPermissionsFile, lines);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Saving client permissions to " + ClientPermissionsFile + " failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private bool SwitchSubSelection(GUITickBox tickBox)
|
||||
|
||||
@@ -17,6 +17,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
PlayerJoined, PlayerLeft,
|
||||
|
||||
KickPlayer,
|
||||
|
||||
Permissions,
|
||||
|
||||
RequestNetLobbyUpdate,
|
||||
|
||||
StartGame, EndGame, CanStartGame,
|
||||
@@ -330,6 +334,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
public virtual void SendChatMessage(string message, ChatMessageType? type = null) { }
|
||||
|
||||
public virtual void KickPlayer(string kickedName, bool ban) { }
|
||||
|
||||
public virtual void Update(float deltaTime)
|
||||
{
|
||||
if (gameStarted && Screen.Selected == GameMain.GameScreen)
|
||||
|
||||
Reference in New Issue
Block a user