Unstable v0.19.1.0
This commit is contained in:
@@ -6,7 +6,7 @@ using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class Camera : IDisposable
|
||||
class Camera : IDisposable
|
||||
{
|
||||
public static bool FollowSub = true;
|
||||
|
||||
|
||||
@@ -173,8 +173,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (character.Info != null && !character.ShouldLockHud() && character.SelectedCharacter == null && Screen.Selected != GameMain.SubEditorScreen)
|
||||
{
|
||||
bool mouseOnPortrait = HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) && GUI.MouseOn == null;
|
||||
if (mouseOnPortrait && PlayerInput.PrimaryMouseButtonClicked())
|
||||
bool mouseOnPortrait = MouseOnCharacterPortrait() && GUI.MouseOn == null;
|
||||
if (mouseOnPortrait && PlayerInput.PrimaryMouseButtonClicked() && Inventory.DraggingItems.None())
|
||||
{
|
||||
CharacterHealth.OpenHealthWindow = character.CharacterHealth;
|
||||
}
|
||||
@@ -491,7 +491,7 @@ namespace Barotrauma
|
||||
character.Info.DrawPortrait(spriteBatch, HUDLayoutSettings.PortraitArea.Location.ToVector2(), new Vector2(-12 * GUI.Scale, yOffset), targetWidth: HUDLayoutSettings.PortraitArea.Width, true, character.Info.IsDisguisedAsAnother);
|
||||
character.Info.DrawForeground(spriteBatch);
|
||||
}
|
||||
mouseOnPortrait = HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) && !character.ShouldLockHud();
|
||||
mouseOnPortrait = MouseOnCharacterPortrait() && !character.ShouldLockHud();
|
||||
if (mouseOnPortrait)
|
||||
{
|
||||
GUIStyle.UIGlow.Draw(spriteBatch, HUDLayoutSettings.BottomRightInfoArea, GUIStyle.Green * 0.5f);
|
||||
@@ -538,6 +538,13 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static bool MouseOnCharacterPortrait()
|
||||
{
|
||||
if (Character.Controlled == null) { return false; }
|
||||
if (CharacterHealth.OpenHealthWindow != null || Character.Controlled.SelectedCharacter != null) { return false; }
|
||||
return HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition);
|
||||
}
|
||||
|
||||
private static void DrawCharacterHoverTexts(SpriteBatch spriteBatch, Camera cam, Character character)
|
||||
{
|
||||
var allItems = character.Inventory?.AllItems;
|
||||
|
||||
@@ -175,6 +175,11 @@ namespace Barotrauma
|
||||
|
||||
AnimController.Frozen = false;
|
||||
Enabled = true;
|
||||
//if we start receiving position updates, it means the character's no longer disabled
|
||||
if (DisabledByEvent && !Removed)
|
||||
{
|
||||
DisabledByEvent = false;
|
||||
}
|
||||
|
||||
UInt16 networkUpdateID = 0;
|
||||
if (msg.ReadBoolean())
|
||||
@@ -534,6 +539,7 @@ namespace Barotrauma
|
||||
Vector2 position = new Vector2(inc.ReadSingle(), inc.ReadSingle());
|
||||
|
||||
bool enabled = inc.ReadBoolean();
|
||||
bool disabledByEvent = inc.ReadBoolean();
|
||||
|
||||
DebugConsole.Log("Received spawn data for " + speciesName);
|
||||
|
||||
@@ -569,7 +575,7 @@ namespace Barotrauma
|
||||
CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc);
|
||||
try
|
||||
{
|
||||
character = Create(speciesName, position, seed, characterInfo: info, id: id, isRemotePlayer: ownerId > 0 && GameMain.Client.ID != ownerId, hasAi: hasAi);
|
||||
character = Create(speciesName, position, seed, characterInfo: info, id: id, isRemotePlayer: ownerId > 0 && GameMain.Client.SessionId != ownerId, hasAi: hasAi);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -650,7 +656,7 @@ namespace Barotrauma
|
||||
GameMain.GameSession.CrewManager.AddCharacter(character);
|
||||
}
|
||||
|
||||
if (GameMain.Client.ID == ownerId)
|
||||
if (GameMain.Client.SessionId == ownerId)
|
||||
{
|
||||
GameMain.Client.HasSpawned = true;
|
||||
GameMain.Client.Character = character;
|
||||
@@ -667,7 +673,14 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
character.Enabled = Controlled == character || enabled;
|
||||
if (disabledByEvent)
|
||||
{
|
||||
character.DisabledByEvent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
character.Enabled = Controlled == character || enabled;
|
||||
}
|
||||
|
||||
return character;
|
||||
}
|
||||
|
||||
@@ -1461,7 +1461,7 @@ namespace Barotrauma
|
||||
|
||||
description.RectTransform.Resize(new Point(description.Rect.Width, (int)(description.TextSize.Y + 10)));
|
||||
|
||||
int vitalityDecrease = (int)affliction.GetVitalityDecrease(this);
|
||||
int vitalityDecrease = (int)GetVitalityDecreaseWithVitalityMultipliers(affliction);
|
||||
if (vitalityDecrease == 0)
|
||||
{
|
||||
vitality.Visible = false;
|
||||
@@ -1503,7 +1503,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Affliction affliction in afflictions)
|
||||
{
|
||||
float afflictionVitalityDecrease = affliction.GetVitalityDecrease(this);
|
||||
float afflictionVitalityDecrease = GetVitalityDecreaseWithVitalityMultipliers(affliction);
|
||||
Color afflictionEffectColor = Color.White;
|
||||
if (afflictionVitalityDecrease > 0.0f)
|
||||
{
|
||||
@@ -1586,7 +1586,7 @@ namespace Barotrauma
|
||||
affliction.Strength / affliction.Prefab.MaxStrength);
|
||||
|
||||
var vitalityText = labelContainer.GetChildByUserData("vitality") as GUITextBlock;
|
||||
int vitalityDecrease = (int)affliction.GetVitalityDecrease(this);
|
||||
int vitalityDecrease = (int)GetVitalityDecreaseWithVitalityMultipliers(affliction);
|
||||
if (vitalityDecrease == 0)
|
||||
{
|
||||
vitalityText.Visible = false;
|
||||
@@ -1604,7 +1604,7 @@ namespace Barotrauma
|
||||
{
|
||||
//items can be dropped outside the health window
|
||||
if (!ignoreMousePos &&
|
||||
!healthWindow.Rect.Contains(PlayerInput.MousePosition) )
|
||||
!healthWindow.Rect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1620,10 +1620,10 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex);
|
||||
|
||||
Limb targetLimb =
|
||||
Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex) ??
|
||||
Character.AnimController.MainLimb;
|
||||
item.ApplyTreatment(Character.Controlled, Character, targetLimb);
|
||||
|
||||
return true;
|
||||
}
|
||||
private void UpdateLimbIndicators(float deltaTime, Rectangle drawArea)
|
||||
@@ -1686,7 +1686,7 @@ namespace Barotrauma
|
||||
if (!affliction.ShouldShowIcon(Character)) { continue; }
|
||||
if (!affliction.Prefab.IsBuff)
|
||||
{
|
||||
negativeEffect += affliction.Strength;
|
||||
negativeEffect += affliction.Strength * GetVitalityMultiplier(affliction, limbHealth);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -226,7 +226,7 @@ namespace Barotrauma
|
||||
return client.HasPermission(ClientPermissions.Kick);
|
||||
case "ban":
|
||||
case "banip":
|
||||
case "banendpoint":
|
||||
case "banaddress":
|
||||
return client.HasPermission(ClientPermissions.Ban);
|
||||
case "unban":
|
||||
case "unbanip":
|
||||
@@ -429,24 +429,6 @@ namespace Barotrauma
|
||||
}
|
||||
}));
|
||||
|
||||
commands.Add(new Command("startlidgrenclient", "", (string[] args) =>
|
||||
{
|
||||
if (args.Length == 0) return;
|
||||
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
GameMain.Client = new GameClient("Name", args[0], 0);
|
||||
}
|
||||
}));
|
||||
|
||||
commands.Add(new Command("startsteamp2pclient", "", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
GameMain.Client = new GameClient("Name", null, 76561198977850505); //this is juan's alt account, feel free to abuse this one
|
||||
}
|
||||
}));
|
||||
|
||||
commands.Add(new Command("enablecheats", "enablecheats: Enables cheat commands and disables Steam achievements during this play session.", (string[] args) =>
|
||||
{
|
||||
CheatsEnabled = true;
|
||||
@@ -2849,7 +2831,7 @@ namespace Barotrauma
|
||||
);
|
||||
|
||||
AssignOnClientExecute(
|
||||
"banendpoint|banip",
|
||||
"banaddress|banip",
|
||||
(string[] args) =>
|
||||
{
|
||||
if (GameMain.Client == null || args.Length == 0) return;
|
||||
@@ -2871,7 +2853,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
GameMain.Client?.SendConsoleCommand(
|
||||
"banendpoint " +
|
||||
"banaddress " +
|
||||
args[0] + " " +
|
||||
(banDuration.HasValue ? banDuration.Value.TotalSeconds.ToString() : "0") + " " +
|
||||
reason);
|
||||
@@ -2884,13 +2866,16 @@ namespace Barotrauma
|
||||
{
|
||||
if (GameMain.Client == null || args.Length == 0) return;
|
||||
string clientName = string.Join(" ", args);
|
||||
GameMain.Client.UnbanPlayer(clientName, "");
|
||||
GameMain.Client.UnbanPlayer(clientName);
|
||||
}));
|
||||
|
||||
commands.Add(new Command("unbanip", "unbanip [ip]: Unban a specific IP.", (string[] args) =>
|
||||
commands.Add(new Command("unbanaddress", "unbanaddress [endpoint]: Unban a specific endpoint.", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Client == null || args.Length == 0) return;
|
||||
GameMain.Client.UnbanPlayer("", args[0]);
|
||||
if (Endpoint.Parse(args[0]).TryUnwrap(out var endpoint))
|
||||
{
|
||||
GameMain.Client.UnbanPlayer(endpoint);
|
||||
}
|
||||
}));
|
||||
|
||||
AssignOnClientExecute(
|
||||
|
||||
@@ -63,33 +63,43 @@ namespace Barotrauma
|
||||
|
||||
shouldFadeToBlack = fadeToBlack;
|
||||
|
||||
Sprite eventSprite = EventSet.GetEventSprite(spriteIdentifier);
|
||||
|
||||
if (lastMessageBox != null && !lastMessageBox.Closed && GUIMessageBox.MessageBoxes.Contains(lastMessageBox))
|
||||
{
|
||||
if (actionId != null && lastMessageBox.UserData is Pair<string, ushort> userData)
|
||||
if (eventSprite != null && lastMessageBox.BackgroundIcon == null)
|
||||
{
|
||||
if (userData.Second == actionId) { return; }
|
||||
lastMessageBox.UserData = new Pair<string, ushort>("ConversationAction", actionId.Value);
|
||||
//no background icon in the last message box: we need to create a new one
|
||||
lastMessageBox.Close();
|
||||
}
|
||||
|
||||
GUIListBox conversationList = lastMessageBox.FindChild("conversationlist", true) as GUIListBox;
|
||||
Debug.Assert(conversationList != null);
|
||||
|
||||
// gray out the last text block
|
||||
if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
|
||||
else
|
||||
{
|
||||
if (lastElement.FindChild("text", true) is GUITextBlock textLayout)
|
||||
if (actionId != null && lastMessageBox.UserData is Pair<string, ushort> userData)
|
||||
{
|
||||
textLayout.OverrideTextColor(Color.DarkGray * 0.8f);
|
||||
if (userData.Second == actionId) { return; }
|
||||
lastMessageBox.UserData = new Pair<string, ushort>("ConversationAction", actionId.Value);
|
||||
}
|
||||
|
||||
GUIListBox conversationList = lastMessageBox.FindChild("conversationlist", true) as GUIListBox;
|
||||
Debug.Assert(conversationList != null);
|
||||
|
||||
// gray out the last text block
|
||||
if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement)
|
||||
{
|
||||
if (lastElement.FindChild("text", true) is GUITextBlock textLayout)
|
||||
{
|
||||
textLayout.OverrideTextColor(Color.DarkGray * 0.8f);
|
||||
}
|
||||
}
|
||||
|
||||
List<GUIButton> extraButtons = CreateConversation(conversationList, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier));
|
||||
AssignActionsToButtons(extraButtons, lastMessageBox);
|
||||
RecalculateLastMessage(conversationList, true);
|
||||
|
||||
conversationList.ScrollToEnd(0.5f);
|
||||
lastMessageBox.SetBackgroundIcon(eventSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
List<GUIButton> extraButtons = CreateConversation(conversationList, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier));
|
||||
AssignActionsToButtons(extraButtons, lastMessageBox);
|
||||
RecalculateLastMessage(conversationList, true);
|
||||
|
||||
conversationList.ScrollToEnd(0.5f);
|
||||
lastMessageBox.SetBackgroundIcon(EventSet.GetEventSprite(spriteIdentifier));
|
||||
return;
|
||||
}
|
||||
|
||||
var (relative, min) = GetSizes(dialogType);
|
||||
@@ -100,7 +110,10 @@ namespace Barotrauma
|
||||
{
|
||||
UserData = "ConversationAction"
|
||||
};
|
||||
|
||||
messageBox.OnAddedToGUIUpdateList += (GUIComponent component) =>
|
||||
{
|
||||
if (!(Screen.Selected is GameScreen)) { messageBox.Close(); }
|
||||
};
|
||||
lastMessageBox = messageBox;
|
||||
|
||||
messageBox.InnerFrame.ClearChildren();
|
||||
|
||||
@@ -128,10 +128,11 @@ namespace Barotrauma
|
||||
|
||||
var sortGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), hireablesGroup.RectTransform), isHorizontal: true)
|
||||
{
|
||||
RelativeSpacing = 0.015f
|
||||
RelativeSpacing = 0.015f,
|
||||
Stretch = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sortGroup.RectTransform), text: TextManager.Get("campaignstore.sortby"));
|
||||
sortingDropDown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1.0f), sortGroup.RectTransform), elementCount: 5)
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sortGroup.RectTransform), text: TextManager.Get("campaignstore.sortby"));
|
||||
sortingDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1.0f), sortGroup.RectTransform), elementCount: 5)
|
||||
{
|
||||
OnSelected = (child, userData) =>
|
||||
{
|
||||
@@ -193,19 +194,20 @@ namespace Barotrauma
|
||||
{
|
||||
RelativeSpacing = 0.01f
|
||||
};
|
||||
validateHiresButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaigncrew.validate"))
|
||||
validateHiresButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), group.RectTransform), text: TextManager.Get("campaigncrew.validate"))
|
||||
{
|
||||
ClickSound = GUISoundType.ConfirmTransaction,
|
||||
ForceUpperCase = ForceUpperCase.Yes,
|
||||
OnClicked = (b, o) => ValidateHires(PendingHires, true)
|
||||
};
|
||||
clearAllButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall"))
|
||||
clearAllButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall"))
|
||||
{
|
||||
ClickSound = GUISoundType.Cart,
|
||||
ForceUpperCase = ForceUpperCase.Yes,
|
||||
Enabled = HasPermission,
|
||||
OnClicked = (b, o) => RemoveAllPendingHires()
|
||||
};
|
||||
GUITextBlock.AutoScaleAndNormalize(validateHiresButton.TextBlock, clearAllButton.TextBlock);
|
||||
|
||||
resolutionWhenCreated = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Barotrauma
|
||||
WaitingBackground = 6, // Cursor + Hourglass
|
||||
}
|
||||
|
||||
public static class GUI
|
||||
static class GUI
|
||||
{
|
||||
public static GUICanvas Canvas => GUICanvas.Instance;
|
||||
public static CursorState MouseCursor = CursorState.Default;
|
||||
@@ -981,7 +981,7 @@ namespace Barotrauma
|
||||
return editor.GetMouseCursorState();
|
||||
// Portrait area during gameplay
|
||||
case GameScreen _ when !(Character.Controlled?.ShouldLockHud() ?? true):
|
||||
if (HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) || CharacterHealth.IsMouseOnHealthBar())
|
||||
if (CharacterHUD.MouseOnCharacterPortrait() || CharacterHealth.IsMouseOnHealthBar())
|
||||
{
|
||||
return CursorState.Hand;
|
||||
}
|
||||
|
||||
@@ -806,6 +806,13 @@ namespace Barotrauma
|
||||
flashColor = (color == null) ? GUIStyle.Red : (Color)color;
|
||||
}
|
||||
|
||||
public void ImmediateFlash(Color? color = null)
|
||||
{
|
||||
flashTimer = MathHelper.Pi / 4.0f * 0.1f;
|
||||
flashDuration = 1.0f *0.1f;
|
||||
flashColor = (color == null) ? GUIStyle.Red : (Color)color;
|
||||
}
|
||||
|
||||
public void FadeOut(float duration, bool removeAfter, float wait = 0.0f)
|
||||
{
|
||||
CoroutineManager.StartCoroutine(LerpAlpha(0.0f, duration, removeAfter, wait));
|
||||
@@ -1156,7 +1163,7 @@ namespace Barotrauma
|
||||
try
|
||||
{
|
||||
#if USE_STEAM
|
||||
Steam.SteamManager.OverlayCustomURL(url);
|
||||
Steam.SteamManager.OverlayCustomUrl(url);
|
||||
#else
|
||||
ToolBox.OpenFileWithShell(url);
|
||||
#endif
|
||||
|
||||
@@ -7,68 +7,88 @@ namespace Barotrauma
|
||||
{
|
||||
private readonly RectTransform elementToMove;
|
||||
|
||||
private Point originalOffset;
|
||||
|
||||
private Vector2 dragStart;
|
||||
private bool dragStarted;
|
||||
|
||||
public Rectangle DragArea;
|
||||
|
||||
public Func<RectTransform, bool> ValidatePosition;
|
||||
|
||||
public GUIDragHandle(RectTransform rectT, RectTransform elementToMove, string style = "GUIDragIndicator")
|
||||
: base(style, rectT)
|
||||
{
|
||||
enabled = true;
|
||||
this.elementToMove = elementToMove;
|
||||
DragArea = new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
}
|
||||
|
||||
protected override void Update(float deltaTime)
|
||||
{
|
||||
if (!Visible) return;
|
||||
if (!Visible) { return; }
|
||||
base.Update(deltaTime);
|
||||
Enabled = true;
|
||||
if (dragStarted)
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
Point moveAmount = (PlayerInput.MousePosition - dragStart).ToPoint() - elementToMove.ScreenSpaceOffset;
|
||||
Rectangle rect = elementToMove.Rect;
|
||||
rect.Location += moveAmount;
|
||||
if (dragStarted)
|
||||
{
|
||||
Point moveAmount = (PlayerInput.MousePosition - dragStart).ToPoint() - elementToMove.ScreenSpaceOffset;
|
||||
Rectangle rect = elementToMove.Rect;
|
||||
rect.Location += moveAmount;
|
||||
|
||||
moveAmount.X += Math.Max(DragArea.X - rect.X, 0);
|
||||
moveAmount.X -= Math.Max(rect.Right - DragArea.Right, 0);
|
||||
moveAmount.Y += Math.Max(DragArea.Y - rect.Y, 0);
|
||||
moveAmount.Y -= Math.Max(rect.Bottom - DragArea.Bottom, 0);
|
||||
moveAmount.X += Math.Max(DragArea.X - rect.X, 0);
|
||||
moveAmount.X -= Math.Max(rect.Right - DragArea.Right, 0);
|
||||
moveAmount.Y += Math.Max(DragArea.Y - rect.Y, 0);
|
||||
moveAmount.Y -= Math.Max(rect.Bottom - DragArea.Bottom, 0);
|
||||
|
||||
if (moveAmount != Point.Zero)
|
||||
{
|
||||
elementToMove.ScreenSpaceOffset += moveAmount;
|
||||
}
|
||||
if (moveAmount != Point.Zero)
|
||||
{
|
||||
elementToMove.ScreenSpaceOffset += moveAmount;
|
||||
}
|
||||
|
||||
if (!PlayerInput.PrimaryMouseButtonHeld())
|
||||
{
|
||||
dragStarted = false;
|
||||
bool isPositionValid = ValidatePosition == null || ValidatePosition.Invoke(elementToMove);
|
||||
|
||||
if (!PlayerInput.PrimaryMouseButtonHeld())
|
||||
{
|
||||
if (!isPositionValid)
|
||||
{
|
||||
elementToMove.ScreenSpaceOffset = originalOffset;
|
||||
elementToMove.GUIComponent?.Flash();
|
||||
SoundPlayer.PlayUISound(GUISoundType.PickItemFail);
|
||||
}
|
||||
dragStarted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Rect.Contains(PlayerInput.MousePosition) && CanBeFocused && Enabled && GUI.IsMouseOn(this))
|
||||
{
|
||||
State = Selected ? ComponentState.HoverSelected : ComponentState.Hover;
|
||||
if (PlayerInput.PrimaryMouseButtonDown())
|
||||
else if (Rect.Contains(PlayerInput.MousePosition) && CanBeFocused && Enabled && GUI.IsMouseOn(this) && !(GUI.MouseOn is GUIButton))
|
||||
{
|
||||
dragStart = PlayerInput.MousePosition - elementToMove.ScreenSpaceOffset.ToVector2();
|
||||
dragStarted = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ExternalHighlight)
|
||||
{
|
||||
State = Selected ? ComponentState.Selected : ComponentState.None;
|
||||
State = Selected ? ComponentState.HoverSelected : ComponentState.Hover;
|
||||
if (PlayerInput.PrimaryMouseButtonDown())
|
||||
{
|
||||
originalOffset = elementToMove.ScreenSpaceOffset;
|
||||
dragStart = PlayerInput.MousePosition - elementToMove.ScreenSpaceOffset.ToVector2();
|
||||
dragStarted = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
State = ComponentState.Hover;
|
||||
if (!ExternalHighlight)
|
||||
{
|
||||
State = Selected ? ComponentState.Selected : ComponentState.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
State = ComponentState.Hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (GUIComponent child in Children)
|
||||
{
|
||||
//allow buttons to handle their states themselves
|
||||
if (child is GUIButton) { continue; }
|
||||
child.State = State;
|
||||
child.Enabled = enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,7 +448,7 @@ namespace Barotrauma
|
||||
{
|
||||
// Message box not of type GUIMessageBox is likely the round summary
|
||||
MessageBoxes[i].AddToGUIUpdateList();
|
||||
break;
|
||||
if (!(MessageBoxes[i].UserData is RoundSummary)) { break; }
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -471,7 +471,7 @@ namespace Barotrauma
|
||||
public void SetBackgroundIcon(Sprite icon)
|
||||
{
|
||||
if (icon == null) { return; }
|
||||
if (icon == BackgroundIcon.Sprite) { return; }
|
||||
if (icon == BackgroundIcon?.Sprite) { return; }
|
||||
GUIImage newIcon = new GUIImage(new RectTransform(icon.size.ToPoint(), RectTransform), icon)
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
|
||||
@@ -402,7 +402,8 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
if (MouseRect.Contains(PlayerInput.MousePosition) && (GUI.MouseOn == null || (!(GUI.MouseOn is GUIButton) && GUI.IsMouseOn(this))))
|
||||
bool isMouseOn = MouseRect.Contains(PlayerInput.MousePosition) && (GUI.MouseOn == null || (!(GUI.MouseOn is GUIButton) && GUI.IsMouseOn(this)));
|
||||
if (isMouseOn || isSelecting)
|
||||
{
|
||||
State = ComponentState.Hover;
|
||||
if (PlayerInput.PrimaryMouseButtonDown())
|
||||
@@ -438,10 +439,6 @@ namespace Barotrauma
|
||||
isSelecting = false;
|
||||
State = ComponentState.None;
|
||||
}
|
||||
if (!isSelecting)
|
||||
{
|
||||
isSelecting = PlayerInput.IsShiftDown();
|
||||
}
|
||||
|
||||
if (mouseHeldInside && !PlayerInput.PrimaryMouseButtonHeld())
|
||||
{
|
||||
|
||||
@@ -631,7 +631,7 @@ namespace Barotrauma
|
||||
|
||||
linkedGUIList = new List<LinkedGUI>();
|
||||
|
||||
List<Client> connectedClients = GameMain.Client.ConnectedClients;
|
||||
var connectedClients = GameMain.Client.ConnectedClients;
|
||||
|
||||
for (int i = 0; i < teamIDs.Count; i++)
|
||||
{
|
||||
|
||||
@@ -1313,6 +1313,8 @@ namespace Barotrauma
|
||||
Item[] entitiesOnSub = drawnSubmarine.GetItems(true).Where(i => drawnSubmarine.IsEntityFoundOnThisSub(i, true)).ToArray();
|
||||
foreach (UpgradeCategory category in UpgradeCategory.Categories)
|
||||
{
|
||||
//hide categories with no upgrades in them
|
||||
if (UpgradePrefab.Prefabs.None(p => p.UpgradeCategories.Contains(category))) { continue; }
|
||||
if (entitiesOnSub.Any(item => category.CanBeApplied(item, null)))
|
||||
{
|
||||
yield return category;
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Barotrauma
|
||||
{
|
||||
currentVoteType = type;
|
||||
CreateVotingGUI();
|
||||
if (starter.ID == GameMain.Client.ID) { SetGUIToVotedState(2); }
|
||||
if (starter.SessionId == GameMain.Client.SessionId) { SetGUIToVotedState(2); }
|
||||
VoteRunning = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,9 +109,7 @@ namespace Barotrauma
|
||||
|
||||
private readonly GameTime fixedTime;
|
||||
|
||||
public string ConnectName;
|
||||
public string ConnectEndpoint;
|
||||
public UInt64 ConnectLobby;
|
||||
public Option<ConnectCommand> ConnectCommand = Option<ConnectCommand>.None();
|
||||
|
||||
private static SpriteBatch spriteBatch;
|
||||
|
||||
@@ -232,20 +230,14 @@ namespace Barotrauma
|
||||
|
||||
ConsoleArguments = args;
|
||||
|
||||
ConnectName = null;
|
||||
ConnectEndpoint = null;
|
||||
ConnectLobby = 0;
|
||||
|
||||
try
|
||||
{
|
||||
ToolBox.ParseConnectCommand(ConsoleArguments, out ConnectName, out ConnectEndpoint, out ConnectLobby);
|
||||
ConnectCommand = ToolBox.ParseConnectCommand(ConsoleArguments);
|
||||
}
|
||||
catch (IndexOutOfRangeException e)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to parse console arguments ({string.Join(' ', ConsoleArguments)})", e);
|
||||
ConnectName = null;
|
||||
ConnectEndpoint = null;
|
||||
ConnectLobby = 0;
|
||||
ConnectCommand = Option<ConnectCommand>.None();
|
||||
}
|
||||
|
||||
GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window);
|
||||
@@ -595,7 +587,7 @@ namespace Barotrauma
|
||||
{
|
||||
try
|
||||
{
|
||||
ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand), out ConnectName, out ConnectEndpoint, out ConnectLobby);
|
||||
ConnectCommand = ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand));
|
||||
}
|
||||
catch (IndexOutOfRangeException e)
|
||||
{
|
||||
@@ -604,12 +596,8 @@ namespace Barotrauma
|
||||
#else
|
||||
DebugConsole.Log($"Failed to parse a Steam friend's connect invitation command ({connectCommand})\n" + e.StackTrace.CleanupStackTrace());
|
||||
#endif
|
||||
ConnectName = null;
|
||||
ConnectEndpoint = null;
|
||||
ConnectLobby = 0;
|
||||
ConnectCommand = Option<ConnectCommand>.None();
|
||||
}
|
||||
|
||||
DebugConsole.NewMessage(ConnectName + ", " + ConnectEndpoint, Color.Yellow);
|
||||
}
|
||||
|
||||
public void OnLobbyJoinRequested(Steamworks.Data.Lobby lobby, Steamworks.SteamId friendId)
|
||||
@@ -734,38 +722,29 @@ namespace Barotrauma
|
||||
}
|
||||
else if (HasLoaded)
|
||||
{
|
||||
if (ConnectLobby != 0)
|
||||
if (ConnectCommand is Some<ConnectCommand> { Value: var connectCommand })
|
||||
{
|
||||
if (Client != null)
|
||||
{
|
||||
Client.Disconnect();
|
||||
Client.Quit();
|
||||
Client = null;
|
||||
|
||||
GameMain.MainMenuScreen.Select();
|
||||
MainMenuScreen.Select();
|
||||
}
|
||||
Steam.SteamManager.JoinLobby(ConnectLobby, true);
|
||||
|
||||
ConnectLobby = 0;
|
||||
ConnectEndpoint = null;
|
||||
ConnectName = null;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(ConnectEndpoint))
|
||||
{
|
||||
if (Client != null)
|
||||
if (connectCommand.EndpointOrLobby.TryGet(out ulong lobbyId))
|
||||
{
|
||||
Client.Disconnect();
|
||||
Client = null;
|
||||
|
||||
GameMain.MainMenuScreen.Select();
|
||||
SteamManager.JoinLobby(lobbyId, joinServer: true);
|
||||
}
|
||||
UInt64 serverSteamId = SteamManager.SteamIDStringToUInt64(ConnectEndpoint);
|
||||
Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()),
|
||||
serverSteamId != 0 ? null : ConnectEndpoint,
|
||||
serverSteamId,
|
||||
string.IsNullOrWhiteSpace(ConnectName) ? ConnectEndpoint : ConnectName);
|
||||
ConnectLobby = 0;
|
||||
ConnectEndpoint = null;
|
||||
ConnectName = null;
|
||||
else if (connectCommand.EndpointOrLobby.TryGet(out ConnectCommand.NameAndEndpoint nameAndEndpoint)
|
||||
&& nameAndEndpoint is { ServerName: var serverName, Endpoint: var endpoint })
|
||||
{
|
||||
Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()),
|
||||
endpoint,
|
||||
string.IsNullOrWhiteSpace(serverName) ? endpoint.StringRepresentation : serverName,
|
||||
Option<int>.None());
|
||||
}
|
||||
|
||||
ConnectCommand = Option<ConnectCommand>.None();
|
||||
}
|
||||
|
||||
SoundPlayer.Update((float)Timing.Step);
|
||||
@@ -1082,7 +1061,7 @@ namespace Barotrauma
|
||||
|
||||
if (Client != null)
|
||||
{
|
||||
Client.Disconnect();
|
||||
Client.Quit();
|
||||
Client = null;
|
||||
}
|
||||
|
||||
@@ -1162,7 +1141,7 @@ namespace Barotrauma
|
||||
UserData = "https://steamcommunity.com/app/602960/discussions/1/",
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (!SteamManager.OverlayCustomURL(userdata as string))
|
||||
if (!SteamManager.OverlayCustomUrl(userdata as string))
|
||||
{
|
||||
ShowOpenUrlInWebBrowserPrompt(userdata as string);
|
||||
}
|
||||
@@ -1200,7 +1179,7 @@ namespace Barotrauma
|
||||
{
|
||||
exiting = true;
|
||||
DebugConsole.NewMessage("Exiting...");
|
||||
NetworkMember?.Disconnect();
|
||||
NetworkMember?.Quit();
|
||||
SteamManager.ShutDown();
|
||||
|
||||
try
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (soldItem.ItemPrefab != soldEntity.ItemPrefab) { return false; }
|
||||
if (matchId && (soldEntity.Item == null || soldItem.ID != soldEntity.Item.ID)) { return false; }
|
||||
if (soldItem.Origin == SoldItem.SellOrigin.Character && GameMain.Client != null && soldItem.SellerID != GameMain.Client.ID) { return false; }
|
||||
if (soldItem.Origin == SoldItem.SellOrigin.Character && GameMain.Client != null && soldItem.SellerID != GameMain.Client.SessionId) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,7 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null;
|
||||
byte sellerId = GameMain.Client?.ID ?? 0;
|
||||
byte sellerId = GameMain.Client?.SessionId ?? 0;
|
||||
// Check all the prices before starting the transaction to make sure the modifiers stay the same for the whole transaction
|
||||
var sellValues = GetSellValuesAtCurrentLocation(storeIdentifier, itemsToSell.Select(i => i.ItemPrefab));
|
||||
if (!(Location.GetStore(storeIdentifier) is { } store))
|
||||
|
||||
@@ -1390,7 +1390,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateCommandUI(HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) ? Character.Controlled : GUI.MouseOn?.UserData as Character);
|
||||
CreateCommandUI(CharacterHUD.MouseOnCharacterPortrait() ? Character.Controlled : GUI.MouseOn?.UserData as Character);
|
||||
}
|
||||
SoundPlayer.PlayUISound(GUISoundType.PopupMenu);
|
||||
clicklessSelectionActive = isOpeningClick = true;
|
||||
|
||||
@@ -132,9 +132,9 @@ namespace Barotrauma
|
||||
};
|
||||
}
|
||||
|
||||
PurchasedLostShuttles = element.GetAttributeBool("purchasedlostshuttles", false);
|
||||
PurchasedHullRepairs = element.GetAttributeBool("purchasedhullrepairs", false);
|
||||
PurchasedItemRepairs = element.GetAttributeBool("purchaseditemrepairs", false);
|
||||
PurchasedLostShuttlesInLatestSave = element.GetAttributeBool("purchasedlostshuttles", false);
|
||||
PurchasedHullRepairsInLatestSave = element.GetAttributeBool("purchasedhullrepairs", false);
|
||||
PurchasedItemRepairsInLatestSave = element.GetAttributeBool("purchaseditemrepairs", false);
|
||||
CheatsEnabled = element.GetAttributeBool("cheatsenabled", false);
|
||||
if (CheatsEnabled)
|
||||
{
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (var (id, _) in Clients)
|
||||
{
|
||||
Client? client = GameMain.Client.ConnectedClients.FirstOrDefault(c => c.ID == id);
|
||||
Client? client = GameMain.Client.ConnectedClients.FirstOrDefault(c => c.SessionId == id);
|
||||
GUIFrame container = new GUIFrame(new RectTransform(new Vector2(1f, 0.15f), listBox.Content.RectTransform), style: "ListBoxElement") { UserData = id };
|
||||
GUILayoutGroup frame = new GUILayoutGroup(new RectTransform(Vector2.One, container.RectTransform), isHorizontal: true) { Stretch = true };
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Barotrauma
|
||||
|
||||
if (client == null)
|
||||
{
|
||||
string list = GameMain.Client.ConnectedClients.Aggregate("Available clients:\n", (current, c) => current + $"{c.ID}: {c.Name}\n");
|
||||
string list = GameMain.Client.ConnectedClients.Aggregate("Available clients:\n", (current, c) => current + $"{c.SessionId}: {c.Name}\n");
|
||||
DebugConsole.ThrowError($"Client ID {id} was reported in ready check but was not found.\n" + list.TrimEnd('\n'));
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace Barotrauma
|
||||
{
|
||||
ReadyCheckState state = (ReadyCheckState) inc.ReadByte();
|
||||
CrewManager? crewManager = GameMain.GameSession?.CrewManager;
|
||||
List<Client> otherClients = GameMain.Client.ConnectedClients;
|
||||
var otherClients = GameMain.Client.ConnectedClients;
|
||||
if (crewManager == null || otherClients == null)
|
||||
{
|
||||
if (state == ReadyCheckState.Start)
|
||||
@@ -165,7 +165,7 @@ namespace Barotrauma
|
||||
if (hasAuthor)
|
||||
{
|
||||
authorId = inc.ReadByte();
|
||||
isOwn = authorId == GameMain.Client.ID;
|
||||
isOwn = authorId == GameMain.Client.SessionId;
|
||||
}
|
||||
|
||||
ushort clientCount = inc.ReadUInt16();
|
||||
|
||||
@@ -148,6 +148,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public GUIFrame GuiFrame { get; set; }
|
||||
|
||||
public bool LockGuiFramePosition;
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
public bool AllowUIOverlap
|
||||
{
|
||||
@@ -586,8 +588,58 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
|
||||
int iconHeight = GUIStyle.ItemFrameMargin.Y / 4;
|
||||
new GUIImage(new RectTransform(new Point(GuiFrame.Rect.Width, iconHeight), handle.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, iconHeight / 2) },
|
||||
var dragIcon = new GUIImage(new RectTransform(new Point(GuiFrame.Rect.Width, iconHeight), handle.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, iconHeight / 2) },
|
||||
style: "GUIDragIndicatorHorizontal");
|
||||
|
||||
handle.ValidatePosition = (RectTransform rectT) =>
|
||||
{
|
||||
var activeHuds = Character.Controlled?.SelectedItem?.ActiveHUDs ?? item.ActiveHUDs;
|
||||
foreach (ItemComponent ic in activeHuds)
|
||||
{
|
||||
if (ic == this || ic.GuiFrame == null || !ic.CanBeSelected) { continue; }
|
||||
if (ic.GuiFrame.Rect.Width > GameMain.GraphicsWidth * 0.9f && ic.GuiFrame.Rect.Height > GameMain.GraphicsHeight * 0.9f)
|
||||
{
|
||||
//a full-screen GUIFrame (or at least close to one) - this component is doing something weird,
|
||||
//an ItemContainer with no GUIFrame definition that positions itself in some other GUIFrame, some kind of an overlay?
|
||||
// -> allow intersecting
|
||||
continue;
|
||||
}
|
||||
if (dragIcon.Rect.Intersects(ic.GuiFrame.Rect))
|
||||
{
|
||||
GuiFrame.ImmediateFlash();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
int buttonHeight = (int)(GUIStyle.ItemFrameMargin.Y * 0.4f);
|
||||
new GUIButton(new RectTransform(new Point(buttonHeight), handle.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(buttonHeight / 10) },
|
||||
style: "GUIButtonRefresh")
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
GUIContextMenu.CreateContextMenu(
|
||||
new ContextMenuOption("item.resetuiposition", isEnabled: true, onSelected: () =>
|
||||
{
|
||||
if (Character.Controlled?.SelectedItem != null && item != Character.Controlled.SelectedItem)
|
||||
{
|
||||
Character.Controlled.SelectedItem.ForceHUDLayoutUpdate(ignoreLocking: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.ForceHUDLayoutUpdate(ignoreLocking: true);
|
||||
}
|
||||
}),
|
||||
new ContextMenuOption(TextManager.Get(LockGuiFramePosition ? "item.unlockuiposition" : "item.lockuiposition"), isEnabled: true, onSelected: () =>
|
||||
{
|
||||
LockGuiFramePosition = !LockGuiFramePosition;
|
||||
handle.Enabled = !LockGuiFramePosition;
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -648,6 +700,11 @@ namespace Barotrauma.Items.Components
|
||||
CreateGUI();
|
||||
}
|
||||
OnResolutionChanged();
|
||||
item.ForceHUDLayoutUpdate(ignoreLocking: true);
|
||||
if (GuiFrame != null && GuiFrame.GetChild<GUIDragHandle>() is GUIDragHandle dragHandle)
|
||||
{
|
||||
dragHandle.DragArea = HUDLayoutSettings.ItemHUDArea;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void AddTooltipInfo(ref LocalizedString name, ref LocalizedString description) { }
|
||||
|
||||
@@ -255,7 +255,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (DeconstructItem deconstructItem in it.Prefab.DeconstructItems)
|
||||
{
|
||||
RegisterItem(deconstructItem.ItemIdentifier);
|
||||
RegisterItem(deconstructItem.ItemIdentifier, deconstructItem.Amount);
|
||||
}
|
||||
|
||||
if (it.OwnInventory is { } inventory)
|
||||
@@ -266,15 +266,14 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterItem(Identifier identifier)
|
||||
void RegisterItem(Identifier identifier, int amount = 1)
|
||||
{
|
||||
if (itemCounts.ContainsKey(identifier))
|
||||
{
|
||||
itemCounts[identifier]++;
|
||||
itemCounts[identifier] += amount;
|
||||
return;
|
||||
}
|
||||
|
||||
itemCounts.Add(identifier, 1);
|
||||
itemCounts.Add(identifier, amount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Sounds;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -40,6 +40,9 @@ namespace Barotrauma.Items.Components
|
||||
private Color outputColor = Color.Goldenrod;
|
||||
private Color loadColor = Color.LightSteelBlue;
|
||||
|
||||
private RoundSound temperatureBoostSoundUp, temperatureBoostSoundDown;
|
||||
private GUIButton temperatureBoostUpButton, temperatureBoostDownButton;
|
||||
|
||||
public GUIScrollBar FissionRateScrollBar { get; private set; }
|
||||
|
||||
public GUIScrollBar TurbineOutputScrollBar { get; private set; }
|
||||
@@ -76,6 +79,20 @@ namespace Barotrauma.Items.Components
|
||||
tempRangeIndicator = new Sprite(element.GetChildElement("temprangeindicator")?.GetChildElement("sprite"));
|
||||
graphLine = new Sprite(element.GetChildElement("graphline")?.GetChildElement("sprite"));
|
||||
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
string textureDir = GetTextureDirectory(subElement);
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "temperatureboostsoundup":
|
||||
temperatureBoostSoundUp = RoundSound.Load(subElement, false);
|
||||
break;
|
||||
case "temperatureboostsounddown":
|
||||
temperatureBoostSoundDown = RoundSound.Load(subElement, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
paddedFrame = new GUILayoutGroup(new RectTransform(
|
||||
GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center)
|
||||
{ AbsoluteOffset = GUIStyle.ItemFrameOffset },
|
||||
@@ -354,7 +371,46 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(0.01f, 1.0f), bottomRightArea.RectTransform), style: "VerticalLine");
|
||||
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.1f, 1), bottomRightArea.RectTransform, Anchor.Center), DrawTempMeter, null);
|
||||
var temperatureArea = new GUILayoutGroup(new RectTransform(new Vector2(0.1f, 1), bottomRightArea.RectTransform, Anchor.Center), isHorizontal: false)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.01f
|
||||
};
|
||||
|
||||
temperatureBoostUpButton = new GUIButton(new RectTransform(Vector2.One, temperatureArea.RectTransform, scaleBasis: ScaleBasis.BothWidth), style: "GUIPlusButton")
|
||||
{
|
||||
ToolTip = TextManager.Get("reactor.temperatureboostup"),
|
||||
OnClicked = (_, __) =>
|
||||
{
|
||||
applyTemperatureBoost(TemperatureBoostAmount, temperatureBoostSoundUp);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, temperatureArea.RectTransform, Anchor.Center), DrawTempMeter, null);
|
||||
|
||||
temperatureBoostDownButton = new GUIButton(new RectTransform(Vector2.One, temperatureArea.RectTransform, scaleBasis: ScaleBasis.BothWidth), style: "GUIMinusButton")
|
||||
{
|
||||
ToolTip = TextManager.Get("reactor.temperatureboostdown"),
|
||||
OnClicked = (_, __) =>
|
||||
{
|
||||
applyTemperatureBoost(-TemperatureBoostAmount, temperatureBoostSoundDown);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void applyTemperatureBoost(float amount, RoundSound sound)
|
||||
{
|
||||
temperatureBoost = amount;
|
||||
if (sound != null)
|
||||
{
|
||||
SoundPlayer.PlaySound(
|
||||
sound.Sound,
|
||||
item.WorldPosition,
|
||||
sound.Volume,
|
||||
sound.Range,
|
||||
hullGuess: item.CurrentHull);
|
||||
}
|
||||
}
|
||||
|
||||
var graphArea = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 1.0f), bottomRightArea.RectTransform))
|
||||
{
|
||||
|
||||
@@ -354,7 +354,7 @@ namespace Barotrauma.Items.Components
|
||||
tinkerButtonText :
|
||||
tinkeringText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||
|
||||
System.Diagnostics.Debug.Assert(GuiFrame.GetChild(0) is GUILayoutGroup, "Repair UI hierarchy has changed, could not find skill texts");
|
||||
//System.Diagnostics.Debug.Assert(GuiFrame.GetChild(0) is GUILayoutGroup, "Repair UI hierarchy has changed, could not find skill texts");
|
||||
|
||||
extraButtonContainer.Visible = SabotageButton.Visible || TinkerButton.Visible;
|
||||
extraButtonContainer.IgnoreLayoutGroups = !extraButtonContainer.Visible;
|
||||
|
||||
@@ -317,6 +317,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
bool mouseOn =
|
||||
canDrag &&
|
||||
!(GUI.MouseOn is GUIDragHandle) &&
|
||||
((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) &&
|
||||
PlayerInput.MousePosition.X < Math.Max(start.X, end.X) &&
|
||||
MathUtils.LineToPointDistanceSquared(start, end, PlayerInput.MousePosition) < 36) ||
|
||||
|
||||
@@ -5,9 +5,7 @@ using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -94,14 +92,6 @@ namespace Barotrauma.Items.Components
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Use firing offset for muzzleflash? This field shouldn't be needed but I'm using it for prototyping")]
|
||||
public bool UseFiringOffsetForMuzzleFlash
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
|
||||
public Vector2 DrawSize
|
||||
{
|
||||
get
|
||||
@@ -188,7 +178,7 @@ namespace Barotrauma.Items.Components
|
||||
recoilTimer /= 1 + user.GetStatValue(StatTypes.TurretAttackSpeed);
|
||||
}
|
||||
PlaySound(ActionType.OnUse);
|
||||
Vector2 particlePos = GetRelativeFiringPosition(UseFiringOffsetForMuzzleFlash);
|
||||
Vector2 particlePos = GetRelativeFiringPosition();
|
||||
foreach (ParticleEmitter emitter in particleEmitters)
|
||||
{
|
||||
emitter.Emit(1.0f, particlePos, hullGuess: null, angle: -rotation, particleRotation: rotation);
|
||||
@@ -248,7 +238,6 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
moveSoundChannel.FadeOutAndDispose();
|
||||
moveSoundChannel = null;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (DamageModifier damageModifier in damageModifiers)
|
||||
{
|
||||
if (MathUtils.NearlyEqual(damageModifier.DamageMultiplier, 1f))
|
||||
if (MathUtils.NearlyEqual(damageModifier.DamageMultiplier * damageModifier.ProbabilityMultiplier, 1f))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1147,15 +1147,16 @@ namespace Barotrauma
|
||||
{
|
||||
Character.Controlled.ClearInputs();
|
||||
|
||||
bool mouseOnPortrait = CharacterHUD.MouseOnCharacterPortrait();
|
||||
if (!DetermineMouseOnInventory(ignoreDraggedItem: true) &&
|
||||
CharacterHealth.OpenHealthWindow != null)
|
||||
(CharacterHealth.OpenHealthWindow != null || mouseOnPortrait))
|
||||
{
|
||||
bool dropSuccessful = false;
|
||||
foreach (Item item in DraggingItems)
|
||||
{
|
||||
var inventory = item.ParentInventory;
|
||||
var indices = inventory?.FindIndices(item);
|
||||
dropSuccessful |= CharacterHealth.OpenHealthWindow.OnItemDropped(item, false);
|
||||
dropSuccessful |= (CharacterHealth.OpenHealthWindow ?? Character.Controlled.CharacterHealth).OnItemDropped(item, ignoreMousePos: mouseOnPortrait);
|
||||
if (dropSuccessful)
|
||||
{
|
||||
if (indices != null && inventory.visualSlots != null)
|
||||
@@ -1167,7 +1168,6 @@ namespace Barotrauma
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (dropSuccessful)
|
||||
{
|
||||
@@ -1444,7 +1444,10 @@ namespace Barotrauma
|
||||
float scale = Math.Min(Math.Min(iconSize / sprite.size.X, iconSize / sprite.size.Y), 1.5f);
|
||||
Vector2 itemPos = PlayerInput.MousePosition;
|
||||
|
||||
bool mouseOnHealthInterface = CharacterHealth.OpenHealthWindow != null && CharacterHealth.OpenHealthWindow.MouseOnElement && DraggingItems.Any(it => it.UseInHealthInterface);
|
||||
bool mouseOnHealthInterface =
|
||||
(CharacterHealth.OpenHealthWindow != null && CharacterHealth.OpenHealthWindow.MouseOnElement)||
|
||||
CharacterHUD.MouseOnCharacterPortrait();
|
||||
mouseOnHealthInterface = mouseOnHealthInterface && DraggingItems.Any(it => it.UseInHealthInterface);
|
||||
|
||||
if ((GUI.MouseOn == null || mouseOnHealthInterface) && selectedSlot == null)
|
||||
{
|
||||
@@ -1453,13 +1456,25 @@ namespace Barotrauma
|
||||
Character.Controlled.FocusedItem != null ?
|
||||
TextManager.GetWithVariable("PutItemIn", "[itemname]", Character.Controlled.FocusedItem.Name, FormatCapitals.Yes) :
|
||||
TextManager.Get(Screen.Selected is SubEditorScreen editor && editor.EntityMenu.Rect.Contains(PlayerInput.MousePosition) ? "Delete" : "DropItem");
|
||||
int textWidth = (int)Math.Max(GUIStyle.Font.MeasureString(DraggingItems.First().Name).X, GUIStyle.SmallFont.MeasureString(toolTip).X);
|
||||
|
||||
Vector2 nameSize = GUIStyle.Font.MeasureString(DraggingItems.First().Name);
|
||||
Vector2 toolTipSize = GUIStyle.SmallFont.MeasureString(toolTip);
|
||||
int textWidth = (int)Math.Max(nameSize.X, toolTipSize.X);
|
||||
int textSpacing = (int)(15 * GUI.Scale);
|
||||
Point shadowBorders = (new Point(40, 10)).Multiply(GUI.Scale);
|
||||
|
||||
Vector2 textPos = itemPos;
|
||||
int textDir = textPos.X + textWidth * 1.5f > GameMain.GraphicsWidth ? -1 : 1;
|
||||
int textOffset = textDir == 1 ? 0 : -1;
|
||||
textPos += new Vector2((iconSize / 2 + textSpacing) * textDir, 0);
|
||||
|
||||
Point shadowPadding = new Point(40, 20).Multiply(GUI.Scale);
|
||||
Point shadowSize = new Point(iconSize + textWidth + textSpacing, iconSize) + shadowPadding.Multiply(2);
|
||||
|
||||
shadowSprite.Draw(spriteBatch,
|
||||
new Rectangle(itemPos.ToPoint() - new Point(iconSize / 2) - shadowBorders, new Point(iconSize + textWidth + textSpacing, iconSize) + shadowBorders.Multiply(2)), Color.Black * 0.8f);
|
||||
GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y - iconSize / 2), DraggingItems.First().Name, Color.White);
|
||||
GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y), toolTip,
|
||||
new Rectangle(itemPos.ToPoint() - new Point((iconSize / 2 - shadowPadding.X) * textDir - shadowSize.X * textOffset, iconSize / 2 + shadowPadding.Y), shadowSize), Color.Black * 0.8f);
|
||||
|
||||
GUI.DrawString(spriteBatch, textPos + new Vector2(nameSize.X * textOffset, -iconSize / 2), DraggingItems.First().Name, Color.White);
|
||||
GUI.DrawString(spriteBatch, textPos + new Vector2(toolTipSize.X * textOffset, 0), toolTip,
|
||||
color: Character.Controlled.FocusedItem == null && !mouseOnHealthInterface ? GUIStyle.Red : Color.LightGreen,
|
||||
font: GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
@@ -569,6 +569,36 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
partial void Splash()
|
||||
{
|
||||
if (body == null || CurrentHull == null) { return; }
|
||||
//create a splash particle
|
||||
float massFactor = MathHelper.Clamp(body.Mass, 0.5f, 20.0f);
|
||||
for (int i = 0; i < MathHelper.Clamp(Math.Abs(body.LinearVelocity.Y), 1.0f, 10.0f); i++)
|
||||
{
|
||||
var splash = GameMain.ParticleManager.CreateParticle("watersplash",
|
||||
new Vector2(WorldPosition.X, CurrentHull.WorldSurface),
|
||||
new Vector2(0.0f, Math.Abs(-body.LinearVelocity.Y * massFactor)) + Rand.Vector(Math.Abs(body.LinearVelocity.Y * 10)),
|
||||
Rand.Range(0.0f, MathHelper.TwoPi), CurrentHull);
|
||||
if (splash != null)
|
||||
{
|
||||
splash.Size *= MathHelper.Clamp(Math.Abs(body.LinearVelocity.Y) * 0.1f * massFactor, 1.0f, 4.0f);
|
||||
}
|
||||
}
|
||||
GameMain.ParticleManager.CreateParticle("bubbles",
|
||||
new Vector2(WorldPosition.X, CurrentHull.WorldSurface),
|
||||
body.LinearVelocity * massFactor,
|
||||
0.0f, CurrentHull);
|
||||
|
||||
//create a wave
|
||||
if (body.LinearVelocity.Y < 0.0f)
|
||||
{
|
||||
int n = (int)((Position.X - CurrentHull.Rect.X) / Hull.WaveWidth);
|
||||
CurrentHull.WaveVel[n] += MathHelper.Clamp(body.LinearVelocity.Y * massFactor, -5.0f, 5.0f);
|
||||
}
|
||||
SoundPlayer.PlaySplashSound(WorldPosition, Math.Abs(body.LinearVelocity.Y) + Rand.Range(-10.0f, -5.0f));
|
||||
}
|
||||
|
||||
public void CheckNeedsSoundUpdate(ItemComponent ic)
|
||||
{
|
||||
if (ic.NeedsSoundUpdate())
|
||||
@@ -976,7 +1006,7 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Reposition currently active item interfaces to make sure they don't overlap with each other
|
||||
/// </summary>
|
||||
private void SetHUDLayout()
|
||||
private void SetHUDLayout(bool ignoreLocking = false)
|
||||
{
|
||||
//reset positions first
|
||||
List<GUIComponent> elementsToMove = new List<GUIComponent>();
|
||||
@@ -991,6 +1021,7 @@ namespace Barotrauma
|
||||
foreach (ItemComponent ic in activeHUDs)
|
||||
{
|
||||
if (ic.GuiFrame == null || ic.AllowUIOverlap || ic.GetLinkUIToComponent() != null) { continue; }
|
||||
if (!ignoreLocking && ic.LockGuiFramePosition) { continue; }
|
||||
//if the frame covers nearly all of the screen, don't trying to prevent overlaps because it'd fail anyway
|
||||
if (ic.GuiFrame.Rect.Width >= GameMain.GraphicsWidth * 0.9f && ic.GuiFrame.Rect.Height >= GameMain.GraphicsHeight * 0.9f) { continue; }
|
||||
ic.GuiFrame.RectTransform.ScreenSpaceOffset = Point.Zero;
|
||||
@@ -1015,11 +1046,7 @@ namespace Barotrauma
|
||||
disallowedAreas.Add(editor.ToggleEntityMenuButton.Rect);
|
||||
}
|
||||
|
||||
GUI.PreventElementOverlap(elementsToMove, disallowedAreas,
|
||||
new Rectangle(
|
||||
0, 20,
|
||||
GameMain.GraphicsWidth,
|
||||
HUDLayoutSettings.InventoryTopY > 0 ? HUDLayoutSettings.InventoryTopY - 40 : GameMain.GraphicsHeight - 80));
|
||||
GUI.PreventElementOverlap(elementsToMove, disallowedAreas, clampArea: HUDLayoutSettings.ItemHUDArea);
|
||||
|
||||
//System.Diagnostics.Debug.WriteLine("after: " + elementsToMove[0].Rect.ToString() + " " + elementsToMove[1].Rect.ToString());
|
||||
foreach (ItemComponent ic in activeHUDs)
|
||||
@@ -1239,6 +1266,24 @@ namespace Barotrauma
|
||||
return texts;
|
||||
}
|
||||
|
||||
public void ForceHUDLayoutUpdate(bool ignoreLocking = false)
|
||||
{
|
||||
foreach (ItemComponent ic in activeHUDs)
|
||||
{
|
||||
if (ic.GuiFrame == null || !ic.CanBeSelected) { continue; }
|
||||
ic.GuiFrame.RectTransform.ScreenSpaceOffset = Point.Zero;
|
||||
if (ic.UseAlternativeLayout)
|
||||
{
|
||||
ic.AlternativeLayout?.ApplyTo(ic.GuiFrame.RectTransform);
|
||||
}
|
||||
else
|
||||
{
|
||||
ic.DefaultLayout?.ApplyTo(ic.GuiFrame.RectTransform);
|
||||
}
|
||||
}
|
||||
SetHUDLayout(ignoreLocking);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList(int order = 0)
|
||||
{
|
||||
if (Screen.Selected is SubEditorScreen)
|
||||
|
||||
@@ -252,7 +252,7 @@ namespace Barotrauma
|
||||
|
||||
if (placePosition == Vector2.Zero)
|
||||
{
|
||||
if (PlayerInput.PrimaryMouseButtonHeld()) placePosition = position;
|
||||
if (PlayerInput.PrimaryMouseButtonHeld() && GUI.MouseOn == null) { placePosition = position; }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -270,11 +270,10 @@ namespace Barotrauma
|
||||
item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
|
||||
item.FindHull();
|
||||
|
||||
//selected = null;
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity> { item }, false));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
position = placePosition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,22 +281,12 @@ namespace Barotrauma
|
||||
{
|
||||
potentialContainer.IsHighlighted = true;
|
||||
}
|
||||
|
||||
|
||||
//if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null;
|
||||
|
||||
}
|
||||
|
||||
public override void DrawPlacing(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
|
||||
|
||||
if (PlayerInput.SecondaryMouseButtonClicked())
|
||||
{
|
||||
Selected = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ResizeHorizontal && !ResizeVertical)
|
||||
{
|
||||
Sprite.Draw(spriteBatch, new Vector2(position.X, -position.Y) + Sprite.size / 2.0f * Scale, SpriteColor, scale: Scale);
|
||||
|
||||
@@ -666,7 +666,7 @@ namespace Barotrauma
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, 256, 32), Color.White);
|
||||
}
|
||||
dPos.Y += 48;
|
||||
GUI.DrawString(spriteBatch, dPos, $"Difficulty: {location.LevelData.Difficulty.FormatZeroDecimal()}", Color.White, Color.Black * 0.8f, 4, font: GUIStyle.SmallFont);
|
||||
GUI.DrawString(spriteBatch, dPos, $"Difficulty: {location.LevelData.Difficulty.FormatSingleDecimal()}", Color.White, Color.Black * 0.8f, 4, font: GUIStyle.SmallFont);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -981,7 +981,7 @@ namespace Barotrauma
|
||||
Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
|
||||
if (viewArea.Contains(center) && connection.Biome != null)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, center, (connection.LevelData?.GenerationParams?.Identifier ?? connection.Biome.Identifier) + " (" + (int)connection.Difficulty + ")", Color.White);
|
||||
GUI.DrawString(spriteBatch, center, (connection.LevelData?.GenerationParams?.Identifier ?? connection.Biome.Identifier) + " (" + connection.Difficulty.FormatSingleDecimal() + ")", Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Barotrauma
|
||||
private static float keyDelay;
|
||||
|
||||
public static Vector2 StartMovingPos => startMovingPos;
|
||||
public static Vector2 SelectionPos => selectionPos;
|
||||
|
||||
public event Action<Rectangle> Resized;
|
||||
|
||||
@@ -128,7 +129,9 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
if (GUI.MouseOn != null || !PlayerInput.MouseInsideWindow)
|
||||
if (startMovingPos == Vector2.Zero
|
||||
&& selectionPos == Vector2.Zero
|
||||
&& (GUI.MouseOn != null || !PlayerInput.MouseInsideWindow))
|
||||
{
|
||||
if (highlightedListBox == null ||
|
||||
(GUI.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUI.MouseOn)))
|
||||
@@ -738,15 +741,6 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public static void DrawSelecting(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
if (Screen.Selected is SubEditorScreen subEditor)
|
||||
{
|
||||
if (subEditor.IsMouseOnEditorGUI()) { return; }
|
||||
}
|
||||
else if (GUI.MouseOn != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 position = PlayerInput.MousePosition;
|
||||
position = cam.ScreenToWorld(position);
|
||||
|
||||
@@ -819,7 +813,7 @@ namespace Barotrauma
|
||||
selectionPos = Vector2.Zero;
|
||||
}
|
||||
}
|
||||
if (selectionPos != null && selectionPos != Vector2.Zero)
|
||||
if (selectionPos != Vector2.Zero)
|
||||
{
|
||||
var (sizeX, sizeY) = selectionSize;
|
||||
var (posX, posY) = selectionPos;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Barotrauma
|
||||
{
|
||||
Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
|
||||
|
||||
if (PlayerInput.PrimaryMouseButtonHeld()) placePosition = position;
|
||||
if (PlayerInput.PrimaryMouseButtonHeld() && GUI.MouseOn == null) placePosition = position;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -39,7 +39,7 @@ namespace Barotrauma
|
||||
newRect.Location -= MathUtils.ToPoint(Submarine.MainSub.Position);
|
||||
}
|
||||
|
||||
if (PlayerInput.PrimaryMouseButtonReleased())
|
||||
if (PlayerInput.PrimaryMouseButtonReleased() && GUI.MouseOn == null)
|
||||
{
|
||||
CreateInstance(newRect);
|
||||
placePosition = Vector2.Zero;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Barotrauma
|
||||
|
||||
if (placePosition == Vector2.Zero)
|
||||
{
|
||||
if (PlayerInput.PrimaryMouseButtonHeld())
|
||||
if (PlayerInput.PrimaryMouseButtonClicked() && GUI.MouseOn == null)
|
||||
placePosition = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
|
||||
|
||||
newRect.X = (int)position.X;
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace Barotrauma.Media
|
||||
{
|
||||
public partial class Video : IDisposable
|
||||
partial class Video : IDisposable
|
||||
{
|
||||
private static class Internal
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ using Barotrauma.Sounds;
|
||||
|
||||
namespace Barotrauma.Media
|
||||
{
|
||||
public partial class Video : IDisposable
|
||||
partial class Video : IDisposable
|
||||
{
|
||||
private static Internal.EventCallback VideoFrameCallback;
|
||||
private static Internal.EventCallback VideoAudioCallback;
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
using Barotrauma.Steam;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
partial class BannedPlayer
|
||||
{
|
||||
public BannedPlayer(string name, UInt16 uniqueIdentifier, bool isRangeBan, string endPoint, ulong steamID, string reason, DateTime? expiration)
|
||||
public BannedPlayer(
|
||||
UInt32 uniqueIdentifier,
|
||||
string name,
|
||||
Either<Address, AccountId> addressOrAccountId,
|
||||
string reason,
|
||||
DateTime? expiration)
|
||||
{
|
||||
this.Name = name;
|
||||
this.EndPoint = endPoint;
|
||||
this.SteamID = steamID;
|
||||
ParseEndPointAsSteamId();
|
||||
this.IsRangeBan = isRangeBan;
|
||||
this.AddressOrAccountId = addressOrAccountId;
|
||||
this.UniqueIdentifier = uniqueIdentifier;
|
||||
this.Reason = reason;
|
||||
this.ExpirationTime = expiration;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class BanList
|
||||
partial class BanList
|
||||
{
|
||||
private GUIComponent banFrame;
|
||||
|
||||
@@ -31,8 +31,7 @@ namespace Barotrauma.Networking
|
||||
get { return banFrame; }
|
||||
}
|
||||
|
||||
public List<UInt16> localRemovedBans = new List<UInt16>();
|
||||
public List<UInt16> localRangeBans = new List<UInt16>();
|
||||
public List<UInt32> localRemovedBans = new List<UInt32>();
|
||||
|
||||
private void RecreateBanFrame()
|
||||
{
|
||||
@@ -71,28 +70,22 @@ namespace Barotrauma.Networking
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
string endPoint = bannedPlayer.EndPoint;
|
||||
if (localRangeBans.Contains(bannedPlayer.UniqueIdentifier)) endPoint = ToRange(endPoint);
|
||||
GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), topArea.RectTransform),
|
||||
bannedPlayer.Name + " (" + endPoint + ")");
|
||||
textBlock.RectTransform.MinSize = new Point(textBlock.Rect.Width, 0);
|
||||
var addressOrAccountId = bannedPlayer.AddressOrAccountId;
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new RectTransform(new Vector2(0.5f, 1.0f), topArea.RectTransform),
|
||||
bannedPlayer.Name + " (" + addressOrAccountId + ")") { CanBeFocused = true };
|
||||
textBlock.RectTransform.MinSize = new Point(
|
||||
(int)textBlock.Font.MeasureString(textBlock.Text.SanitizedValue).X, 0);
|
||||
|
||||
if (bannedPlayer.EndPoint.IndexOf(".x") <= -1)
|
||||
{
|
||||
var rangeBanButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.4f), topArea.RectTransform),
|
||||
TextManager.Get("BanRange"), style: "GUIButtonSmall")
|
||||
{
|
||||
UserData = bannedPlayer,
|
||||
OnClicked = RangeBan
|
||||
};
|
||||
}
|
||||
var removeButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.4f), topArea.RectTransform),
|
||||
TextManager.Get("BanListRemove"), style: "GUIButtonSmall")
|
||||
{
|
||||
UserData = bannedPlayer,
|
||||
OnClicked = RemoveBan
|
||||
};
|
||||
topArea.RectTransform.MinSize = new Point(0, (int)topArea.RectTransform.Children.Max(c => c.Rect.Height * 1.25f));
|
||||
topArea.RectTransform.MinSize = new Point(0, (int)(removeButton.Rect.Height * 1.25f));
|
||||
|
||||
topArea.ForceLayoutRecalculation();
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedPlayerFrame.RectTransform),
|
||||
bannedPlayer.ExpirationTime == null ?
|
||||
@@ -127,19 +120,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool RangeBan(GUIButton button, object obj)
|
||||
{
|
||||
BannedPlayer banned = obj as BannedPlayer;
|
||||
if (banned == null) { return false; }
|
||||
|
||||
localRangeBans.Add(banned.UniqueIdentifier);
|
||||
RecreateBanFrame();
|
||||
|
||||
GameMain.Client?.ServerSettings?.ClientAdminWrite(ServerSettings.NetFlags.Properties);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ClientAdminRead(IReadMessage incMsg)
|
||||
{
|
||||
@@ -159,8 +139,7 @@ namespace Barotrauma.Networking
|
||||
for (int i = 0; i < (int)bannedPlayerCount; i++)
|
||||
{
|
||||
string name = incMsg.ReadString();
|
||||
UInt16 uniqueIdentifier = incMsg.ReadUInt16();
|
||||
bool isRangeBan = incMsg.ReadBoolean();
|
||||
UInt32 uniqueIdentifier = incMsg.ReadUInt32();
|
||||
bool includesExpiration = incMsg.ReadBoolean();
|
||||
incMsg.ReadPadBits();
|
||||
|
||||
@@ -173,19 +152,30 @@ namespace Barotrauma.Networking
|
||||
|
||||
string reason = incMsg.ReadString();
|
||||
|
||||
string endPoint = "";
|
||||
UInt64 steamID = 0;
|
||||
Either<Address, AccountId> addressOrAccountId;
|
||||
if (isOwner)
|
||||
{
|
||||
endPoint = incMsg.ReadString();
|
||||
steamID = incMsg.ReadUInt64();
|
||||
bool isAddress = incMsg.ReadBoolean();
|
||||
incMsg.ReadPadBits();
|
||||
string str = incMsg.ReadString();
|
||||
if (isAddress && Address.Parse(str).TryUnwrap(out var address))
|
||||
{
|
||||
addressOrAccountId = address;
|
||||
}
|
||||
else if (AccountId.Parse(str).TryUnwrap(out var accountId))
|
||||
{
|
||||
addressOrAccountId = accountId;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
endPoint = "Endpoint concealed by host";
|
||||
steamID = 0;
|
||||
addressOrAccountId = new UnknownAddress();
|
||||
}
|
||||
bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, endPoint, steamID, reason, expiration));
|
||||
bannedPlayers.Add(new BannedPlayer(uniqueIdentifier, name, addressOrAccountId, reason, expiration));
|
||||
}
|
||||
|
||||
if (banFrame != null)
|
||||
@@ -198,20 +188,13 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void ClientAdminWrite(IWriteMessage outMsg)
|
||||
{
|
||||
outMsg.Write((UInt16)localRemovedBans.Count);
|
||||
foreach (UInt16 uniqueId in localRemovedBans)
|
||||
{
|
||||
outMsg.Write(uniqueId);
|
||||
}
|
||||
|
||||
outMsg.Write((UInt16)localRangeBans.Count);
|
||||
foreach (UInt16 uniqueId in localRangeBans)
|
||||
outMsg.WriteVariableUInt32((UInt32)localRemovedBans.Count);
|
||||
foreach (UInt32 uniqueId in localRemovedBans)
|
||||
{
|
||||
outMsg.Write(uniqueId);
|
||||
}
|
||||
|
||||
localRemovedBans.Clear();
|
||||
localRangeBans.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,9 @@ namespace Barotrauma.Networking
|
||||
bool hasSenderClient = msg.ReadBoolean();
|
||||
if (hasSenderClient)
|
||||
{
|
||||
UInt64 clientId = msg.ReadUInt64();
|
||||
senderClient = GameMain.Client.ConnectedClients.Find(c => c.SteamID == clientId || c.ID == clientId);
|
||||
string userId = msg.ReadString();
|
||||
senderClient = GameMain.Client.ConnectedClients.Find(c
|
||||
=> c.SessionOrAccountIdMatches(userId));
|
||||
if (senderClient != null) { senderName = senderClient.Name; }
|
||||
}
|
||||
bool hasSenderCharacter = msg.ReadBoolean();
|
||||
|
||||
@@ -72,8 +72,8 @@ namespace Barotrauma.Networking
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
VoipQueue = null; VoipSound = null;
|
||||
if (ID == GameMain.Client.ID) return;
|
||||
VoipQueue = new VoipQueue(ID, false, true);
|
||||
if (SessionId == GameMain.Client.SessionId) { return; }
|
||||
VoipQueue = new VoipQueue(SessionId, canSend: false, canReceive: true);
|
||||
GameMain.Client?.VoipClient?.RegisterQueue(VoipQueue);
|
||||
VoipSound = null;
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ namespace Barotrauma.Networking
|
||||
case (byte)FileTransferMessageType.Initiate:
|
||||
{
|
||||
byte transferId = inc.ReadByte();
|
||||
var existingTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.EndPointString) && t.ID == transferId);
|
||||
var existingTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.Endpoint) && t.ID == transferId);
|
||||
finishedTransfers.RemoveAll(t => t.transferId == transferId);
|
||||
byte fileType = inc.ReadByte();
|
||||
//ushort chunkLen = inc.ReadUInt16();
|
||||
@@ -329,7 +329,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
byte transferId = inc.ReadByte();
|
||||
|
||||
var activeTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.EndPointString) && t.ID == transferId);
|
||||
var activeTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.Endpoint) && t.ID == transferId);
|
||||
if (activeTransfer == null)
|
||||
{
|
||||
//it's possible for the server to send some extra data
|
||||
@@ -406,7 +406,7 @@ namespace Barotrauma.Networking
|
||||
case (byte)FileTransferMessageType.Cancel:
|
||||
{
|
||||
byte transferId = inc.ReadByte();
|
||||
var matchingTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.EndPointString) && t.ID == transferId);
|
||||
var matchingTransfer = activeTransfers.Find(t => t.Connection.EndpointMatches(t.Connection.Endpoint) && t.ID == transferId);
|
||||
if (matchingTransfer != null)
|
||||
{
|
||||
new GUIMessageBox("File transfer cancelled", "The server has cancelled the transfer of the file \"" + matchingTransfer.FileName + "\".");
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.IO;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Steam;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using Barotrauma.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -23,14 +21,9 @@ namespace Barotrauma.Networking
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
private string name;
|
||||
|
||||
private UInt16 nameId = 0;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
}
|
||||
public string Name { get; private set; }
|
||||
|
||||
public string PendingName = string.Empty;
|
||||
|
||||
@@ -38,7 +31,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
value = value.Replace(":", "").Replace(";", "");
|
||||
if (string.IsNullOrEmpty(value)) { return; }
|
||||
name = value;
|
||||
Name = value;
|
||||
nameId++;
|
||||
}
|
||||
|
||||
@@ -89,13 +82,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
public bool RoundStarting => roundInitStatus == RoundInitStatus.Starting || roundInitStatus == RoundInitStatus.WaitingForStartGameFinalize;
|
||||
|
||||
private byte myID;
|
||||
|
||||
private readonly List<Client> otherClients;
|
||||
|
||||
public readonly List<SubmarineInfo> ServerSubmarines = new List<SubmarineInfo>();
|
||||
|
||||
private string serverIP, serverName;
|
||||
public string ServerName { get; private set; }
|
||||
|
||||
private bool allowReconnect;
|
||||
private bool requiresPw;
|
||||
@@ -129,10 +120,7 @@ namespace Barotrauma.Networking
|
||||
public LocalizedString TraitorFirstObjective;
|
||||
public TraitorMissionPrefab TraitorMission = null;
|
||||
|
||||
public byte ID
|
||||
{
|
||||
get { return myID; }
|
||||
}
|
||||
public byte SessionId { get; private set; }
|
||||
|
||||
public VoipClient VoipClient
|
||||
{
|
||||
@@ -140,7 +128,7 @@ namespace Barotrauma.Networking
|
||||
private set;
|
||||
}
|
||||
|
||||
public override List<Client> ConnectedClients
|
||||
public override IReadOnlyList<Client> ConnectedClients
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -175,14 +163,10 @@ namespace Barotrauma.Networking
|
||||
set;
|
||||
}
|
||||
|
||||
private readonly object serverEndpoint;
|
||||
private readonly int ownerKey;
|
||||
private readonly bool steamP2POwner;
|
||||
private readonly Endpoint serverEndpoint;
|
||||
private readonly Option<int> ownerKey;
|
||||
|
||||
public bool IsServerOwner
|
||||
{
|
||||
get { return ownerKey > 0 || steamP2POwner; }
|
||||
}
|
||||
public bool IsServerOwner => ownerKey.IsSome();
|
||||
|
||||
internal readonly struct PermissionChangedEvent
|
||||
{
|
||||
@@ -198,11 +182,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
public readonly NamedEvent<PermissionChangedEvent> OnPermissionChanged = new NamedEvent<PermissionChangedEvent>();
|
||||
|
||||
public GameClient(string newName, string ip, UInt64 steamId, string serverName = null, int ownerKey = 0, bool steamP2POwner = false)
|
||||
public GameClient(string newName, Endpoint endpoint, string serverName, Option<int> ownerKey)
|
||||
{
|
||||
//TODO: gui stuff should probably not be here?
|
||||
this.ownerKey = ownerKey;
|
||||
this.steamP2POwner = steamP2POwner;
|
||||
|
||||
roundInitStatus = RoundInitStatus.NotStarted;
|
||||
|
||||
@@ -280,7 +263,7 @@ namespace Barotrauma.Networking
|
||||
fileReceiver.OnFinished += OnFileReceived;
|
||||
fileReceiver.OnTransferFailed += OnTransferFailed;
|
||||
|
||||
characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, name, null)
|
||||
characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, Name, originalName: null)
|
||||
{
|
||||
Job = null
|
||||
};
|
||||
@@ -290,15 +273,8 @@ namespace Barotrauma.Networking
|
||||
serverSettings = new ServerSettings(this, "Server", 0, 0, 0, false, false);
|
||||
Voting = new Voting();
|
||||
|
||||
if (steamId == 0)
|
||||
{
|
||||
serverEndpoint = ip;
|
||||
}
|
||||
else
|
||||
{
|
||||
serverEndpoint = steamId;
|
||||
}
|
||||
ConnectToServer(serverEndpoint, serverName);
|
||||
serverEndpoint = endpoint;
|
||||
InitiateServerJoin(serverName);
|
||||
|
||||
//ServerLog = new ServerLog("");
|
||||
|
||||
@@ -306,7 +282,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.ResetNetLobbyScreen();
|
||||
}
|
||||
|
||||
private void ConnectToServer(object endpoint, string hostName)
|
||||
private void InitiateServerJoin(string hostName)
|
||||
{
|
||||
LastClientListUpdateID = 0;
|
||||
|
||||
@@ -315,7 +291,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.NetLobbyScreen.RemovePlayer(c);
|
||||
c.Dispose();
|
||||
}
|
||||
ConnectedClients.Clear();
|
||||
otherClients.Clear();
|
||||
|
||||
chatBox.InputBox.Enabled = false;
|
||||
if (GameMain.NetLobbyScreen?.ChatInput != null)
|
||||
@@ -323,102 +299,48 @@ namespace Barotrauma.Networking
|
||||
GameMain.NetLobbyScreen.ChatInput.Enabled = false;
|
||||
}
|
||||
|
||||
serverName = hostName;
|
||||
ServerName = hostName;
|
||||
|
||||
myCharacter = Character.Controlled;
|
||||
ChatMessage.LastID = 0;
|
||||
|
||||
clientPeer?.Close();
|
||||
clientPeer = null;
|
||||
object translatedEndpoint = null;
|
||||
if (endpoint is string hostIP)
|
||||
{
|
||||
int port;
|
||||
string[] address = hostIP.Split(':');
|
||||
if (address.Length == 1)
|
||||
{
|
||||
serverIP = hostIP;
|
||||
port = NetConfig.DefaultPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
serverIP = string.Join(":", address.Take(address.Length - 1));
|
||||
if (!int.TryParse(address[address.Length - 1], out port))
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid port: " + address[address.Length - 1] + "!");
|
||||
port = NetConfig.DefaultPort;
|
||||
}
|
||||
}
|
||||
|
||||
clientPeer = new LidgrenClientPeer(Name);
|
||||
|
||||
System.Net.IPEndPoint IPEndPoint = null;
|
||||
try
|
||||
{
|
||||
IPEndPoint = new System.Net.IPEndPoint(Lidgren.Network.NetUtility.Resolve(serverIP), port);
|
||||
}
|
||||
catch
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("CouldNotConnectToServer"),
|
||||
TextManager.GetWithVariables("InvalidIPAddress", ("[serverip]", serverIP), ("[port]", port.ToString())));
|
||||
return;
|
||||
}
|
||||
|
||||
translatedEndpoint = IPEndPoint;
|
||||
}
|
||||
else if (endpoint is UInt64)
|
||||
{
|
||||
if (steamP2POwner)
|
||||
{
|
||||
clientPeer = new SteamP2POwnerPeer(Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
clientPeer = new SteamP2PClientPeer(Name);
|
||||
}
|
||||
|
||||
translatedEndpoint = endpoint;
|
||||
}
|
||||
clientPeer.OnDisconnect = OnDisconnect;
|
||||
clientPeer.OnDisconnectMessageReceived = HandleDisconnectMessage;
|
||||
clientPeer.OnInitializationComplete = OnConnectionInitializationComplete;
|
||||
clientPeer.OnRequestPassword = (int salt, int retries) =>
|
||||
{
|
||||
if (pwRetries != retries)
|
||||
{
|
||||
wrongPassword = retries > 0;
|
||||
requiresPw = true;
|
||||
}
|
||||
pwRetries = retries;
|
||||
};
|
||||
clientPeer.OnMessageReceived = ReadDataMessage;
|
||||
|
||||
// Connect client, to endpoint previously requested from user
|
||||
try
|
||||
{
|
||||
clientPeer.Start(translatedEndpoint, ownerKey);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't connect to " + endpoint.ToString() + ". Error message: " + e.Message);
|
||||
Disconnect();
|
||||
chatBox.InputBox.Enabled = true;
|
||||
if (GameMain.NetLobbyScreen?.ChatInput != null)
|
||||
{
|
||||
GameMain.NetLobbyScreen.ChatInput.Enabled = true;
|
||||
}
|
||||
GameMain.ServerListScreen.Select();
|
||||
return;
|
||||
}
|
||||
clientPeer = CreateNetPeer();
|
||||
clientPeer.Start();
|
||||
|
||||
updateInterval = new TimeSpan(0, 0, 0, 0, 150);
|
||||
|
||||
CoroutineManager.StartCoroutine(WaitForStartingInfo(), "WaitForStartingInfo");
|
||||
}
|
||||
|
||||
private ClientPeer CreateNetPeer()
|
||||
{
|
||||
Networking.ClientPeer.Callbacks callbacks = new ClientPeer.Callbacks(
|
||||
ReadDataMessage,
|
||||
OnClientPeerDisconnect,
|
||||
HandleDisconnectMessage,
|
||||
(int salt, int retries) =>
|
||||
{
|
||||
if (pwRetries != retries)
|
||||
{
|
||||
wrongPassword = retries > 0;
|
||||
requiresPw = true;
|
||||
}
|
||||
pwRetries = retries;
|
||||
},
|
||||
OnConnectionInitializationComplete);
|
||||
return serverEndpoint switch
|
||||
{
|
||||
LidgrenEndpoint lidgrenEndpoint => new LidgrenClientPeer(lidgrenEndpoint, callbacks, ownerKey),
|
||||
SteamP2PEndpoint _ when ownerKey is Some<int> { Value: var key } => new SteamP2POwnerPeer(callbacks, key),
|
||||
SteamP2PEndpoint steamP2PServerEndpoint when ownerKey.IsNone() => new SteamP2PClientPeer(steamP2PServerEndpoint, callbacks),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
private bool ReturnToPreviousMenu(GUIButton button, object obj)
|
||||
{
|
||||
Disconnect();
|
||||
Quit();
|
||||
|
||||
Submarine.Unload();
|
||||
GameMain.Client = null;
|
||||
@@ -442,7 +364,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
ChildServerRelay.ShutDown();
|
||||
connectCancelled = true;
|
||||
Disconnect();
|
||||
Quit();
|
||||
}
|
||||
|
||||
private bool wrongPassword;
|
||||
@@ -467,14 +389,13 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (reconnectBox == null && waitInServerQueueBox == null)
|
||||
{
|
||||
string serverDisplayName = serverName;
|
||||
if (string.IsNullOrEmpty(serverDisplayName)) { serverDisplayName = serverIP; }
|
||||
string serverDisplayName = ServerName;
|
||||
if (string.IsNullOrEmpty(serverDisplayName) && clientPeer?.ServerConnection is SteamP2PConnection steamConnection)
|
||||
{
|
||||
serverDisplayName = steamConnection.SteamID.ToString();
|
||||
if (SteamManager.IsInitialized)
|
||||
if (SteamManager.IsInitialized && steamConnection.AccountInfo.AccountId.TryUnwrap(out var accountId) && accountId is SteamId steamId)
|
||||
{
|
||||
string steamUserName = Steamworks.SteamFriends.GetFriendPersonaName(steamConnection.SteamID);
|
||||
serverDisplayName = steamId.ToString();
|
||||
string steamUserName = Steamworks.SteamFriends.GetFriendPersonaName(steamId.Value);
|
||||
if (!string.IsNullOrEmpty(steamUserName) && steamUserName != "[unknown]")
|
||||
{
|
||||
serverDisplayName = steamUserName;
|
||||
@@ -604,7 +525,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (VoipCapture.Instance.LastEnqueueAudio > DateTime.Now - new TimeSpan(0, 0, 0, 0, milliseconds: 100))
|
||||
{
|
||||
var myClient = ConnectedClients.Find(c => c.ID == ID);
|
||||
var myClient = ConnectedClients.Find(c => c.SessionId == SessionId);
|
||||
if (Screen.Selected == GameMain.NetLobbyScreen)
|
||||
{
|
||||
GameMain.NetLobbyScreen.SetPlayerSpeaking(myClient);
|
||||
@@ -645,7 +566,7 @@ namespace Barotrauma.Networking
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.Update:CheckServerMessagesException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
DebugConsole.ThrowError("Error while reading a message from server.", e);
|
||||
new GUIMessageBox(TextManager.Get("Error"), TextManager.GetWithVariables("MessageReadError", ("[message]", e.Message), ("[targetsite]", e.TargetSite.ToString())));
|
||||
Disconnect();
|
||||
Quit();
|
||||
GameMain.ServerListScreen.Select();
|
||||
return;
|
||||
}
|
||||
@@ -688,7 +609,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (ChildServerRelay.Process?.HasExited ?? true)
|
||||
{
|
||||
Disconnect();
|
||||
Quit();
|
||||
if (!GUIMessageBox.MessageBoxes.Any(mb => (mb as GUIMessageBox)?.Text?.Text == ChildServerRelay.CrashMessage))
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage);
|
||||
@@ -769,7 +690,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
byte clientId = inc.ReadByte();
|
||||
UInt16 clientPing = inc.ReadUInt16();
|
||||
Client client = ConnectedClients.Find(c => c.ID == clientId);
|
||||
Client client = ConnectedClients.Find(c => c.SessionId == clientId);
|
||||
if (client != null)
|
||||
{
|
||||
client.Ping = clientPing;
|
||||
@@ -1079,16 +1000,15 @@ namespace Barotrauma.Networking
|
||||
roundInitStatus = RoundInitStatus.Started;
|
||||
}
|
||||
|
||||
|
||||
private void OnDisconnect(bool disableReconnect)
|
||||
/// <summary>
|
||||
/// Fires when the ClientPeer gets disconnected from the server. Does not necessarily mean the client is shutting down, we may still be able to reconnect.
|
||||
/// </summary>
|
||||
private void OnClientPeerDisconnect(bool disableReconnect)
|
||||
{
|
||||
CoroutineManager.StopCoroutines("WaitForStartingInfo");
|
||||
reconnectBox?.Close();
|
||||
reconnectBox = null;
|
||||
|
||||
GameMain.ModDownloadScreen.Reset();
|
||||
ContentPackageManager.EnabledPackages.Restore();
|
||||
|
||||
GUI.ClearCursorWait();
|
||||
|
||||
if (disableReconnect) { allowReconnect = false; }
|
||||
@@ -1125,7 +1045,6 @@ namespace Barotrauma.Networking
|
||||
if (disconnectReason != DisconnectReason.Banned &&
|
||||
disconnectReason != DisconnectReason.ServerShutdown &&
|
||||
disconnectReason != DisconnectReason.TooManyFailedLogins &&
|
||||
disconnectReason != DisconnectReason.NotOnWhitelist &&
|
||||
disconnectReason != DisconnectReason.MissingContentPackage &&
|
||||
disconnectReason != DisconnectReason.InvalidVersion)
|
||||
{
|
||||
@@ -1197,14 +1116,16 @@ namespace Barotrauma.Networking
|
||||
reconnectBox?.Close();
|
||||
reconnectBox = new GUIMessageBox(
|
||||
TextManager.Get("ConnectionLost"), msg,
|
||||
new LocalizedString[] { TextManager.Get("Cancel") });
|
||||
reconnectBox.Buttons[0].OnClicked += (btn, userdata) => { CancelConnect(); return true; };
|
||||
new LocalizedString[] { TextManager.Get("Cancel") })
|
||||
{
|
||||
DisplayInLoadingScreens = true
|
||||
};
|
||||
reconnectBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
||||
connected = false;
|
||||
|
||||
var prevContentPackages = clientPeer.ServerContentPackages;
|
||||
//decrement lobby update ID to make sure we update the lobby when we reconnect
|
||||
GameMain.NetLobbyScreen.LastUpdateID--;
|
||||
ConnectToServer(serverEndpoint, serverName);
|
||||
InitiateServerJoin(ServerName);
|
||||
if (clientPeer != null)
|
||||
{
|
||||
//restore the previous list of content packages so we can reconnect immediately without having to recheck that the packages match
|
||||
@@ -1243,12 +1164,18 @@ namespace Barotrauma.Networking
|
||||
if (msg == Lidgren.Network.NetConnection.NoResponseMessage)
|
||||
{
|
||||
//display a generic "could not connect" popup if the message is Lidgren's "failed to establish connection"
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionFailed"), TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer"));
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionFailed"), TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer"))
|
||||
{
|
||||
DisplayInLoadingScreens = true
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
||||
}
|
||||
else
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer"), msg);
|
||||
var msgBox = new GUIMessageBox(TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer"), msg)
|
||||
{
|
||||
DisplayInLoadingScreens = true
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
||||
}
|
||||
|
||||
@@ -1266,8 +1193,8 @@ namespace Barotrauma.Networking
|
||||
if (SteamManager.IsInitialized)
|
||||
{
|
||||
Steamworks.SteamFriends.ClearRichPresence();
|
||||
Steamworks.SteamFriends.SetRichPresence("status", "Playing on " + serverName);
|
||||
Steamworks.SteamFriends.SetRichPresence("connect", "-connect \"" + serverName.Replace("\"", "\\\"") + "\" " + serverEndpoint);
|
||||
Steamworks.SteamFriends.SetRichPresence("status", "Playing on " + ServerName);
|
||||
Steamworks.SteamFriends.SetRichPresence("connect", "-connect \"" + ServerName.Replace("\"", "\\\"") + "\" " + serverEndpoint);
|
||||
}
|
||||
|
||||
canStart = true;
|
||||
@@ -1275,7 +1202,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
VoipClient = new VoipClient(this, clientPeer);
|
||||
|
||||
if (Screen.Selected != GameMain.GameScreen)
|
||||
if (Screen.Selected != GameMain.GameScreen && !(Screen.Selected is RoundSummaryScreen))
|
||||
{
|
||||
GameMain.ModDownloadScreen.Select();
|
||||
}
|
||||
@@ -1312,7 +1239,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!CoroutineManager.IsCoroutineRunning("WaitForStartingInfo"))
|
||||
{
|
||||
ConnectToServer(serverEndpoint, serverName);
|
||||
InitiateServerJoin(ServerName);
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
@@ -1383,15 +1310,15 @@ namespace Barotrauma.Networking
|
||||
private void ReadPermissions(IReadMessage inc)
|
||||
{
|
||||
List<string> permittedConsoleCommands = new List<string>();
|
||||
byte clientID = inc.ReadByte();
|
||||
byte clientId = inc.ReadByte();
|
||||
|
||||
ClientPermissions permissions = ClientPermissions.None;
|
||||
List<DebugConsole.Command> permittedCommands = new List<DebugConsole.Command>();
|
||||
Client.ReadPermissions(inc, out permissions, out permittedCommands);
|
||||
|
||||
Client targetClient = ConnectedClients.Find(c => c.ID == clientID);
|
||||
Client targetClient = ConnectedClients.Find(c => c.SessionId == clientId);
|
||||
targetClient?.SetPermissions(permissions, permittedCommands);
|
||||
if (clientID == myID)
|
||||
if (clientId == SessionId)
|
||||
{
|
||||
SetMyPermissions(permissions, permittedCommands.Select(command => command.names[0]));
|
||||
}
|
||||
@@ -1923,7 +1850,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
private void ReadInitialUpdate(IReadMessage inc)
|
||||
{
|
||||
myID = inc.ReadByte();
|
||||
SessionId = inc.ReadByte();
|
||||
|
||||
UInt16 subListCount = inc.ReadUInt16();
|
||||
ServerSubmarines.Clear();
|
||||
@@ -1983,22 +1910,22 @@ namespace Barotrauma.Networking
|
||||
foreach (TempClient tc in tempClients)
|
||||
{
|
||||
//see if the client already exists
|
||||
var existingClient = ConnectedClients.Find(c => c.ID == tc.ID && c.Name == tc.Name);
|
||||
var existingClient = ConnectedClients.Find(c => c.SessionId == tc.SessionId && c.Name == tc.Name);
|
||||
if (existingClient == null) //if not, create it
|
||||
{
|
||||
existingClient = new Client(tc.Name, tc.ID)
|
||||
existingClient = new Client(tc.Name, tc.SessionId)
|
||||
{
|
||||
SteamID = tc.SteamID,
|
||||
AccountInfo = tc.AccountInfo,
|
||||
Muted = tc.Muted,
|
||||
InGame = tc.InGame,
|
||||
AllowKicking = tc.AllowKicking,
|
||||
IsOwner = tc.IsOwner
|
||||
};
|
||||
ConnectedClients.Add(existingClient);
|
||||
otherClients.Add(existingClient);
|
||||
refreshCampaignUI = true;
|
||||
GameMain.NetLobbyScreen.AddPlayer(existingClient);
|
||||
}
|
||||
existingClient.NameID = tc.NameID;
|
||||
existingClient.NameId = tc.NameId;
|
||||
existingClient.PreferredJob = tc.PreferredJob;
|
||||
existingClient.PreferredTeam = tc.PreferredTeam;
|
||||
existingClient.Character = null;
|
||||
@@ -2009,22 +1936,22 @@ namespace Barotrauma.Networking
|
||||
existingClient.AllowKicking = tc.AllowKicking;
|
||||
existingClient.IsDownloading = tc.IsDownloading;
|
||||
GameMain.NetLobbyScreen.SetPlayerNameAndJobPreference(existingClient);
|
||||
if (Screen.Selected != GameMain.NetLobbyScreen && tc.CharacterID > 0)
|
||||
if (Screen.Selected != GameMain.NetLobbyScreen && tc.CharacterId > 0)
|
||||
{
|
||||
existingClient.CharacterID = tc.CharacterID;
|
||||
existingClient.CharacterID = tc.CharacterId;
|
||||
}
|
||||
if (existingClient.ID == myID)
|
||||
if (existingClient.SessionId == SessionId)
|
||||
{
|
||||
existingClient.SetPermissions(permissions, permittedConsoleCommands);
|
||||
if (!NetIdUtils.IdMoreRecent(nameId, tc.NameID))
|
||||
if (!NetIdUtils.IdMoreRecent(nameId, tc.NameId))
|
||||
{
|
||||
name = tc.Name;
|
||||
nameId = tc.NameID;
|
||||
Name = tc.Name;
|
||||
nameId = tc.NameId;
|
||||
}
|
||||
if (GameMain.NetLobbyScreen.CharacterNameBox != null &&
|
||||
!GameMain.NetLobbyScreen.CharacterNameBox.Selected)
|
||||
{
|
||||
GameMain.NetLobbyScreen.CharacterNameBox.Text = name;
|
||||
GameMain.NetLobbyScreen.CharacterNameBox.Text = Name;
|
||||
}
|
||||
}
|
||||
currentClients.Add(existingClient);
|
||||
@@ -2035,14 +1962,14 @@ namespace Barotrauma.Networking
|
||||
if (!currentClients.Contains(ConnectedClients[i]))
|
||||
{
|
||||
GameMain.NetLobbyScreen.RemovePlayer(ConnectedClients[i]);
|
||||
ConnectedClients[i].Dispose();
|
||||
ConnectedClients.RemoveAt(i);
|
||||
otherClients[i].Dispose();
|
||||
otherClients.RemoveAt(i);
|
||||
refreshCampaignUI = true;
|
||||
}
|
||||
}
|
||||
foreach (Client client in ConnectedClients)
|
||||
{
|
||||
int index = previouslyConnectedClients.FindIndex(c => c.ID == client.ID);
|
||||
int index = previouslyConnectedClients.FindIndex(c => c.SessionId == client.SessionId);
|
||||
if (index < 0)
|
||||
{
|
||||
if (previouslyConnectedClients.Count > 100)
|
||||
@@ -2405,7 +2332,7 @@ namespace Barotrauma.Networking
|
||||
outmsg.Write(ChatMessage.LastID);
|
||||
outmsg.Write(LastClientListUpdateID);
|
||||
outmsg.Write(nameId);
|
||||
outmsg.Write(name);
|
||||
outmsg.Write(Name);
|
||||
var jobPreferences = GameMain.NetLobbyScreen.JobPreferences;
|
||||
if (jobPreferences.Count > 0)
|
||||
{
|
||||
@@ -2519,7 +2446,7 @@ namespace Barotrauma.Networking
|
||||
if (clientPeer?.ServerConnection == null) { return; }
|
||||
|
||||
ChatMessage chatMessage = ChatMessage.Create(
|
||||
gameStarted && myCharacter != null ? myCharacter.Name : name,
|
||||
gameStarted && myCharacter != null ? myCharacter.Name : Name,
|
||||
message,
|
||||
type,
|
||||
gameStarted && myCharacter != null ? myCharacter : null);
|
||||
@@ -2761,7 +2688,7 @@ namespace Barotrauma.Networking
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Disconnect()
|
||||
public override void Quit()
|
||||
{
|
||||
allowReconnect = false;
|
||||
|
||||
@@ -2770,6 +2697,9 @@ namespace Barotrauma.Networking
|
||||
SteamManager.LeaveLobby();
|
||||
}
|
||||
|
||||
GameMain.ModDownloadScreen.Reset();
|
||||
ContentPackageManager.EnabledPackages.Restore();
|
||||
|
||||
CampaignMode.StartRoundCancellationToken?.Cancel();
|
||||
|
||||
clientPeer?.Close();
|
||||
@@ -2864,7 +2794,7 @@ namespace Barotrauma.Networking
|
||||
public void VoteForKick(Client votedClient)
|
||||
{
|
||||
if (votedClient == null) { return; }
|
||||
votedClient.AddKickVote(ConnectedClients.FirstOrDefault(c => c.ID == myID));
|
||||
votedClient.AddKickVote(ConnectedClients.FirstOrDefault(c => c.SessionId == SessionId));
|
||||
Vote(VoteType.Kick, votedClient);
|
||||
}
|
||||
|
||||
@@ -2918,26 +2848,35 @@ namespace Barotrauma.Networking
|
||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public override void BanPlayer(string kickedName, string reason, bool range = false, TimeSpan? duration = null)
|
||||
public override void BanPlayer(string kickedName, string reason, TimeSpan? duration = null)
|
||||
{
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.Write((byte)ClientPacketHeader.SERVER_COMMAND);
|
||||
msg.Write((UInt16)ClientPermissions.Ban);
|
||||
msg.Write(kickedName);
|
||||
msg.Write(reason);
|
||||
msg.Write(range);
|
||||
msg.Write(duration.HasValue ? duration.Value.TotalSeconds : 0.0); //0 = permaban
|
||||
|
||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public override void UnbanPlayer(string playerName, string playerIP)
|
||||
public override void UnbanPlayer(string playerName)
|
||||
{
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.Write((byte)ClientPacketHeader.SERVER_COMMAND);
|
||||
msg.Write((UInt16)ClientPermissions.Unban);
|
||||
msg.Write(string.IsNullOrEmpty(playerName) ? "" : playerName);
|
||||
msg.Write(string.IsNullOrEmpty(playerIP) ? "" : playerIP);
|
||||
msg.Write(true); msg.WritePadBits();
|
||||
msg.Write(playerName);
|
||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public override void UnbanPlayer(Endpoint endpoint)
|
||||
{
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.Write((byte)ClientPacketHeader.SERVER_COMMAND);
|
||||
msg.Write((UInt16)ClientPermissions.Unban);
|
||||
msg.Write(false); msg.WritePadBits();
|
||||
msg.Write(endpoint.StringRepresentation);
|
||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
@@ -3470,7 +3409,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public virtual bool SelectCrewClient(Client client, GUIComponent frame)
|
||||
{
|
||||
if (client == null || client.ID == ID) { return false; }
|
||||
if (client == null || client.SessionId == SessionId) { return false; }
|
||||
CreateSelectionRelatedButtons(client, frame);
|
||||
return true;
|
||||
}
|
||||
@@ -3543,12 +3482,12 @@ namespace Barotrauma.Networking
|
||||
};
|
||||
if (GameMain.NetworkMember.ConnectedClients != null)
|
||||
{
|
||||
kickVoteButton.Enabled = !client.HasKickVoteFromID(myID);
|
||||
kickVoteButton.Enabled = !client.HasKickVoteFromSessionId(SessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateKickReasonPrompt(string clientName, bool ban, bool rangeBan = false)
|
||||
public void CreateKickReasonPrompt(string clientName, bool ban)
|
||||
{
|
||||
var banReasonPrompt = new GUIMessageBox(
|
||||
TextManager.Get(ban ? "BanReasonPrompt" : "KickReasonPrompt"),
|
||||
@@ -3609,11 +3548,11 @@ namespace Barotrauma.Networking
|
||||
if (!permaBanTickBox.Selected)
|
||||
{
|
||||
TimeSpan banDuration = new TimeSpan(durationInputDays.IntValue, durationInputHours.IntValue, 0, 0);
|
||||
BanPlayer(clientName, banReasonBox.Text, ban, banDuration);
|
||||
BanPlayer(clientName, banReasonBox.Text, banDuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
BanPlayer(clientName, banReasonBox.Text, range: rangeBan);
|
||||
BanPlayer(clientName, banReasonBox.Text);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3626,7 +3565,7 @@ namespace Barotrauma.Networking
|
||||
banReasonPrompt.Buttons[1].OnClicked += banReasonPrompt.Close;
|
||||
}
|
||||
|
||||
public void ReportError(ClientNetError error, UInt16 expectedID = 0, UInt16 eventID = 0, UInt16 entityID = 0)
|
||||
public void ReportError(ClientNetError error, UInt16 expectedId = 0, UInt16 eventId = 0, UInt16 entityId = 0)
|
||||
{
|
||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||
outMsg.Write((byte)ClientPacketHeader.ERROR);
|
||||
@@ -3634,12 +3573,12 @@ namespace Barotrauma.Networking
|
||||
switch (error)
|
||||
{
|
||||
case ClientNetError.MISSING_EVENT:
|
||||
outMsg.Write(expectedID);
|
||||
outMsg.Write(eventID);
|
||||
outMsg.Write(expectedId);
|
||||
outMsg.Write(eventId);
|
||||
break;
|
||||
case ClientNetError.MISSING_ENTITY:
|
||||
outMsg.Write(eventID);
|
||||
outMsg.Write(entityID);
|
||||
outMsg.Write(eventId);
|
||||
outMsg.Write(entityId);
|
||||
outMsg.Write((byte)Submarine.Loaded.Count);
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
{
|
||||
@@ -3651,7 +3590,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (!eventErrorWritten)
|
||||
{
|
||||
WriteEventErrorData(error, expectedID, eventID, entityID);
|
||||
WriteEventErrorData(error, expectedId, eventId, entityId);
|
||||
eventErrorWritten = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.NewMessage(
|
||||
"Received msg " + thisEventID + ", entity " + entityID + " not found",
|
||||
GUIStyle.Red);
|
||||
GameMain.Client.ReportError(ClientNetError.MISSING_ENTITY, eventID: thisEventID, entityID: entityID);
|
||||
GameMain.Client.ReportError(ClientNetError.MISSING_ENTITY, eventId: thisEventID, entityId: entityID);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Barotrauma.Extensions;
|
||||
#nullable enable
|
||||
using Barotrauma.Steam;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -18,7 +16,7 @@ namespace Barotrauma.Networking
|
||||
public readonly UInt64 WorkshopId;
|
||||
public readonly DateTime InstallTime;
|
||||
|
||||
public RegularPackage RegularPackage
|
||||
public RegularPackage? RegularPackage
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -26,7 +24,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public CorePackage CorePackage
|
||||
public CorePackage? CorePackage
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -34,8 +32,8 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public ContentPackage ContentPackage
|
||||
=> (ContentPackage)RegularPackage ?? CorePackage;
|
||||
public ContentPackage? ContentPackage
|
||||
=> (ContentPackage?)RegularPackage ?? CorePackage;
|
||||
|
||||
|
||||
public string GetPackageStr()
|
||||
@@ -58,21 +56,44 @@ namespace Barotrauma.Networking
|
||||
public delegate void DisconnectMessageCallback(string message);
|
||||
public delegate void PasswordCallback(int salt, int retries);
|
||||
public delegate void InitializationCompleteCallback();
|
||||
|
||||
[Obsolete("TODO: delete in nr3-layer-1-2-cleanup")]
|
||||
public readonly struct Callbacks
|
||||
{
|
||||
public readonly MessageCallback OnMessageReceived;
|
||||
public readonly DisconnectCallback OnDisconnect;
|
||||
public readonly DisconnectMessageCallback OnDisconnectMessageReceived;
|
||||
public readonly PasswordCallback OnRequestPassword;
|
||||
public readonly InitializationCompleteCallback OnInitializationComplete;
|
||||
|
||||
public Callbacks(MessageCallback onMessageReceived, DisconnectCallback onDisconnect, DisconnectMessageCallback onDisconnectMessageReceived, PasswordCallback onRequestPassword, InitializationCompleteCallback onInitializationComplete)
|
||||
{
|
||||
OnMessageReceived = onMessageReceived;
|
||||
OnDisconnect = onDisconnect;
|
||||
OnDisconnectMessageReceived = onDisconnectMessageReceived;
|
||||
OnRequestPassword = onRequestPassword;
|
||||
OnInitializationComplete = onInitializationComplete;
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly Callbacks callbacks;
|
||||
|
||||
public readonly Endpoint ServerEndpoint;
|
||||
public NetworkConnection? ServerConnection { get; protected set; }
|
||||
|
||||
protected readonly bool isOwner;
|
||||
protected readonly Option<int> ownerKey;
|
||||
|
||||
public ClientPeer(Endpoint serverEndpoint, Callbacks callbacks, Option<int> ownerKey)
|
||||
{
|
||||
ServerEndpoint = serverEndpoint;
|
||||
this.callbacks = callbacks;
|
||||
this.ownerKey = ownerKey;
|
||||
isOwner = ownerKey.IsSome();
|
||||
}
|
||||
|
||||
public MessageCallback OnMessageReceived;
|
||||
public DisconnectCallback OnDisconnect;
|
||||
public DisconnectMessageCallback OnDisconnectMessageReceived;
|
||||
public PasswordCallback OnRequestPassword;
|
||||
public InitializationCompleteCallback OnInitializationComplete;
|
||||
|
||||
public string Name;
|
||||
|
||||
public string Version { get; protected set; }
|
||||
|
||||
public NetworkConnection ServerConnection { get; protected set; }
|
||||
|
||||
public abstract void Start(object endPoint, int ownerKey);
|
||||
public abstract void Close(string msg = null, bool disableReconnect = false);
|
||||
public abstract void Start();
|
||||
public abstract void Close(string? msg = null, bool disableReconnect = false);
|
||||
public abstract void Update(float deltaTime);
|
||||
public abstract void Send(IWriteMessage msg, DeliveryMethod deliveryMethod, bool compressPastThreshold = true);
|
||||
public abstract void SendPassword(string password);
|
||||
@@ -80,10 +101,9 @@ namespace Barotrauma.Networking
|
||||
protected abstract void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg);
|
||||
|
||||
protected ConnectionInitialization initializationStep;
|
||||
protected bool contentPackageOrderReceived;
|
||||
protected int ownerKey = 0;
|
||||
public bool ContentPackageOrderReceived { get; protected set; }
|
||||
protected int passwordSalt;
|
||||
protected Steamworks.AuthTicket steamAuthTicket;
|
||||
protected Steamworks.AuthTicket? steamAuthTicket;
|
||||
protected void ReadConnectionInitializationStep(IReadMessage inc)
|
||||
{
|
||||
ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();
|
||||
@@ -97,9 +117,9 @@ namespace Barotrauma.Networking
|
||||
outMsg = new WriteOnlyMessage();
|
||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||
outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
|
||||
outMsg.Write(Name);
|
||||
outMsg.Write(ownerKey);
|
||||
outMsg.Write(SteamManager.GetSteamID());
|
||||
outMsg.Write(GameMain.Client.Name);
|
||||
outMsg.Write(ownerKey.Fallback(0));
|
||||
outMsg.Write(SteamManager.GetSteamId().Select(steamId => steamId.Value).Fallback(0));
|
||||
if (steamAuthTicket == null)
|
||||
{
|
||||
outMsg.Write((UInt16)0);
|
||||
@@ -122,8 +142,6 @@ namespace Barotrauma.Networking
|
||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||
outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder);
|
||||
|
||||
string serverName = inc.ReadString();
|
||||
|
||||
UInt32 packageCount = inc.ReadVariableUInt32();
|
||||
List<ServerContentPackage> serverPackages = new List<ServerContentPackage>();
|
||||
for (int i = 0; i < packageCount; i++)
|
||||
@@ -139,9 +157,16 @@ namespace Barotrauma.Networking
|
||||
serverPackages.Add(pkg);
|
||||
}
|
||||
|
||||
if (!contentPackageOrderReceived)
|
||||
if (!ContentPackageOrderReceived)
|
||||
{
|
||||
ServerContentPackages = serverPackages.ToImmutableArray();
|
||||
if (serverPackages.Count == 0)
|
||||
{
|
||||
string errorMsg = "Error in ContentPackageOrder message: list of content packages enabled on the server was empty.";
|
||||
GameAnalyticsManager.AddErrorEventOnce("ClientPeer.ReadConnectionInitializationStep:NoContentPackages", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
}
|
||||
ContentPackageOrderReceived = true;
|
||||
SendMsgInternal(DeliveryMethod.Reliable, outMsg);
|
||||
}
|
||||
break;
|
||||
@@ -158,7 +183,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
retries = inc.ReadInt32();
|
||||
}
|
||||
OnRequestPassword?.Invoke(passwordSalt, retries);
|
||||
callbacks.OnRequestPassword.Invoke(passwordSalt, retries);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Barotrauma.Steam;
|
||||
using Lidgren.Network;
|
||||
using Barotrauma.Steam;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -16,39 +14,42 @@ namespace Barotrauma.Networking
|
||||
|
||||
List<NetIncomingMessage> incomingLidgrenMessages;
|
||||
|
||||
public LidgrenClientPeer(string name)
|
||||
private LidgrenEndpoint lidgrenEndpoint
|
||||
=> ServerConnection is LidgrenConnection { Endpoint: LidgrenEndpoint result }
|
||||
? result
|
||||
: throw new InvalidOperationException();
|
||||
|
||||
public LidgrenClientPeer(LidgrenEndpoint endpoint, Callbacks callbacks, Option<int> ownerKey) : base(endpoint, callbacks, ownerKey)
|
||||
{
|
||||
ServerConnection = null;
|
||||
|
||||
Name = name;
|
||||
|
||||
netClient = null;
|
||||
isActive = false;
|
||||
}
|
||||
|
||||
public override void Start(object endPoint, int ownerKey)
|
||||
public override void Start()
|
||||
{
|
||||
if (isActive) { return; }
|
||||
|
||||
this.ownerKey = ownerKey;
|
||||
|
||||
contentPackageOrderReceived = false;
|
||||
ContentPackageOrderReceived = false;
|
||||
|
||||
netPeerConfiguration = new NetPeerConfiguration("barotrauma")
|
||||
{
|
||||
UseDualModeSockets = GameSettings.CurrentConfig.UseDualModeSockets
|
||||
};
|
||||
|
||||
netPeerConfiguration.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt
|
||||
| NetIncomingMessageType.ErrorMessage | NetIncomingMessageType.Error);
|
||||
netPeerConfiguration.DisableMessageType(
|
||||
NetIncomingMessageType.DebugMessage
|
||||
| NetIncomingMessageType.WarningMessage
|
||||
| NetIncomingMessageType.Receipt
|
||||
| NetIncomingMessageType.ErrorMessage
|
||||
| NetIncomingMessageType.Error);
|
||||
|
||||
netClient = new NetClient(netPeerConfiguration);
|
||||
|
||||
if (SteamManager.IsInitialized)
|
||||
{
|
||||
steamAuthTicket = SteamManager.GetAuthSessionTicket();
|
||||
//TODO: wait for GetAuthSessionTicketResponse_t
|
||||
|
||||
if (steamAuthTicket == null)
|
||||
{
|
||||
throw new Exception("GetAuthSessionTicket returned null");
|
||||
@@ -59,7 +60,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
initializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
||||
|
||||
if (!(endPoint is IPEndPoint ipEndPoint))
|
||||
if (!(ServerEndpoint is LidgrenEndpoint lidgrenEndpoint))
|
||||
{
|
||||
throw new InvalidCastException("endPoint is not IPEndPoint");
|
||||
}
|
||||
@@ -69,7 +70,10 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
netClient.Start();
|
||||
ServerConnection = new LidgrenConnection("Server", netClient.Connect(ipEndPoint), 0)
|
||||
|
||||
var netConnection = netClient.Connect(lidgrenEndpoint.NetEndpoint);
|
||||
|
||||
ServerConnection = new LidgrenConnection(netConnection)
|
||||
{
|
||||
Status = NetworkConnectionStatus.Connected
|
||||
};
|
||||
@@ -81,7 +85,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
|
||||
if (ownerKey != 0 && (ChildServerRelay.Process?.HasExited ?? true))
|
||||
if (isOwner && !(ChildServerRelay.Process is { HasExited: false }))
|
||||
{
|
||||
Close();
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage);
|
||||
@@ -97,7 +101,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
foreach (NetIncomingMessage inc in incomingLidgrenMessages)
|
||||
{
|
||||
if (inc.SenderConnection != (ServerConnection as LidgrenConnection).NetConnection) { continue; }
|
||||
if (!inc.SenderConnection.RemoteEndPoint.Equals(lidgrenEndpoint.NetEndpoint)) { continue; }
|
||||
|
||||
switch (inc.MessageType)
|
||||
{
|
||||
@@ -125,12 +129,12 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (initializationStep != ConnectionInitialization.Success)
|
||||
{
|
||||
OnInitializationComplete?.Invoke();
|
||||
callbacks.OnInitializationComplete.Invoke();
|
||||
initializationStep = ConnectionInitialization.Success;
|
||||
}
|
||||
UInt16 length = inc.ReadUInt16();
|
||||
IReadMessage msg = new ReadOnlyMessage(inc.Data, packetHeader.IsCompressed(), inc.PositionInBytes, length, ServerConnection);
|
||||
OnMessageReceived?.Invoke(msg);
|
||||
callbacks.OnMessageReceived.Invoke(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +148,7 @@ namespace Barotrauma.Networking
|
||||
case NetConnectionStatus.Disconnected:
|
||||
string disconnectMsg = inc.ReadString();
|
||||
Close(disconnectMsg);
|
||||
OnDisconnectMessageReceived?.Invoke(disconnectMsg);
|
||||
callbacks.OnDisconnectMessageReceived.Invoke(disconnectMsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -176,7 +180,7 @@ namespace Barotrauma.Networking
|
||||
netClient.Shutdown(msg ?? TextManager.Get("Disconnecting").Value);
|
||||
netClient = null;
|
||||
steamAuthTicket?.Cancel(); steamAuthTicket = null;
|
||||
OnDisconnect?.Invoke(disableReconnect);
|
||||
callbacks.OnDisconnect.Invoke(disableReconnect);
|
||||
}
|
||||
|
||||
public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod, bool compressPastThreshold = true)
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
using System;
|
||||
using Barotrauma.Steam;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using Barotrauma.Steam;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
class SteamP2PClientPeer : ClientPeer
|
||||
{
|
||||
private bool isActive;
|
||||
private UInt64 hostSteamId;
|
||||
private readonly SteamId hostSteamId;
|
||||
private double timeout;
|
||||
private double heartbeatTimer;
|
||||
private double connectionStatusTimer;
|
||||
@@ -21,18 +20,23 @@ namespace Barotrauma.Networking
|
||||
private List<IReadMessage> incomingInitializationMessages;
|
||||
private List<IReadMessage> incomingDataMessages;
|
||||
|
||||
public SteamP2PClientPeer(string name)
|
||||
public SteamP2PClientPeer(SteamP2PEndpoint endpoint, Callbacks callbacks) : base(endpoint, callbacks, Option<int>.None())
|
||||
{
|
||||
ServerConnection = null;
|
||||
|
||||
Name = name;
|
||||
|
||||
isActive = false;
|
||||
|
||||
if (!(ServerEndpoint is SteamP2PEndpoint steamIdEndpoint))
|
||||
{
|
||||
throw new InvalidCastException("endPoint is not SteamId");
|
||||
}
|
||||
|
||||
hostSteamId = steamIdEndpoint.SteamId;
|
||||
}
|
||||
|
||||
public override void Start(object endPoint, int ownerKey)
|
||||
public override void Start()
|
||||
{
|
||||
contentPackageOrderReceived = false;
|
||||
ContentPackageOrderReceived = false;
|
||||
|
||||
steamAuthTicket = SteamManager.GetAuthSessionTicket();
|
||||
//TODO: wait for GetAuthSessionTicketResponse_t
|
||||
@@ -42,21 +46,14 @@ namespace Barotrauma.Networking
|
||||
throw new Exception("GetAuthSessionTicket returned null");
|
||||
}
|
||||
|
||||
if (!(endPoint is UInt64 steamIdEndpoint))
|
||||
{
|
||||
throw new InvalidCastException("endPoint is not UInt64");
|
||||
}
|
||||
|
||||
hostSteamId = steamIdEndpoint;
|
||||
|
||||
Steamworks.SteamNetworking.ResetActions();
|
||||
Steamworks.SteamNetworking.OnP2PSessionRequest = OnIncomingConnection;
|
||||
Steamworks.SteamNetworking.OnP2PConnectionFailed = OnConnectionFailed;
|
||||
|
||||
Steamworks.SteamNetworking.AllowP2PPacketRelay(true);
|
||||
|
||||
ServerConnection = new SteamP2PConnection("Server", hostSteamId);
|
||||
ServerConnection.SetOwnerSteamIDIfUnknown(hostSteamId);
|
||||
ServerConnection = new SteamP2PConnection(hostSteamId);
|
||||
ServerConnection.SetAccountInfo(new AccountInfo(hostSteamId));
|
||||
|
||||
incomingInitializationMessages = new List<IReadMessage>();
|
||||
incomingDataMessages = new List<IReadMessage>();
|
||||
@@ -66,7 +63,7 @@ namespace Barotrauma.Networking
|
||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||
outMsg.Write((byte)ConnectionInitialization.ConnectionStarted);
|
||||
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
||||
sentBytes += outMsg.LengthBytes;
|
||||
|
||||
initializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
||||
@@ -81,7 +78,7 @@ namespace Barotrauma.Networking
|
||||
private void OnIncomingConnection(Steamworks.SteamId steamId)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
if (steamId == hostSteamId)
|
||||
if (steamId == hostSteamId.Value)
|
||||
{
|
||||
Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId);
|
||||
}
|
||||
@@ -90,23 +87,23 @@ namespace Barotrauma.Networking
|
||||
initializationStep != ConnectionInitialization.Success)
|
||||
{
|
||||
DebugConsole.ThrowError($"Connection from incorrect SteamID was rejected: "+
|
||||
$"expected {SteamManager.SteamIDUInt64ToString(hostSteamId)}," +
|
||||
$"got {SteamManager.SteamIDUInt64ToString(steamId)}");
|
||||
$"expected {hostSteamId}," +
|
||||
$"got {new SteamId(steamId)}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnConnectionFailed(Steamworks.SteamId steamId, Steamworks.P2PSessionError error)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
if (steamId != hostSteamId) { return; }
|
||||
if (steamId != hostSteamId.Value) { return; }
|
||||
Close($"SteamP2P connection failed: {error}");
|
||||
OnDisconnectMessageReceived?.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P connection failed: {error}");
|
||||
callbacks.OnDisconnectMessageReceived.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P connection failed: {error}");
|
||||
}
|
||||
|
||||
private void OnP2PData(ulong steamId, byte[] data, int dataLength)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
if (steamId != hostSteamId) { return; }
|
||||
if (steamId != hostSteamId.Value) { return; }
|
||||
|
||||
timeout = Screen.Selected == GameMain.GameScreen ?
|
||||
NetworkConnection.TimeoutThresholdInGame :
|
||||
@@ -138,7 +135,7 @@ namespace Barotrauma.Networking
|
||||
IReadMessage inc = new ReadOnlyMessage(data, false, 1, dataLength - 1, ServerConnection);
|
||||
string msg = inc.ReadString();
|
||||
Close(msg);
|
||||
OnDisconnectMessageReceived?.Invoke(msg);
|
||||
callbacks.OnDisconnectMessageReceived.Invoke(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -166,18 +163,18 @@ namespace Barotrauma.Networking
|
||||
connectionStatusTimer -= deltaTime;
|
||||
if (connectionStatusTimer <= 0.0)
|
||||
{
|
||||
var state = Steamworks.SteamNetworking.GetP2PSessionState(hostSteamId);
|
||||
var state = Steamworks.SteamNetworking.GetP2PSessionState(hostSteamId.Value);
|
||||
if (state == null)
|
||||
{
|
||||
Close("SteamP2P connection could not be established");
|
||||
OnDisconnectMessageReceived?.Invoke(DisconnectReason.SteamP2PError.ToString());
|
||||
callbacks.OnDisconnectMessageReceived.Invoke(DisconnectReason.SteamP2PError.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state?.P2PSessionError != Steamworks.P2PSessionError.None)
|
||||
{
|
||||
Close($"SteamP2P error code: {state?.P2PSessionError}");
|
||||
OnDisconnectMessageReceived?.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P error code: {state?.P2PSessionError}");
|
||||
callbacks.OnDisconnectMessageReceived.Invoke($"{DisconnectReason.SteamP2PError}/SteamP2P error code: {state?.P2PSessionError}");
|
||||
}
|
||||
}
|
||||
connectionStatusTimer = 1.0f;
|
||||
@@ -204,7 +201,7 @@ namespace Barotrauma.Networking
|
||||
outMsg.Write((byte)DeliveryMethod.Unreliable);
|
||||
outMsg.Write((byte)PacketHeader.IsHeartbeatMessage);
|
||||
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Unreliable);
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Unreliable);
|
||||
sentBytes += outMsg.LengthBytes;
|
||||
|
||||
heartbeatTimer = 5.0;
|
||||
@@ -213,7 +210,7 @@ namespace Barotrauma.Networking
|
||||
if (timeout < 0.0)
|
||||
{
|
||||
Close("Timed out");
|
||||
OnDisconnectMessageReceived?.Invoke(DisconnectReason.SteamP2PTimeOut.ToString());
|
||||
callbacks.OnDisconnectMessageReceived.Invoke(DisconnectReason.SteamP2PTimeOut.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -221,7 +218,22 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (incomingDataMessages.Count > 0)
|
||||
{
|
||||
OnInitializationComplete?.Invoke();
|
||||
var incomingMessage = incomingDataMessages.First();
|
||||
byte incomingHeader = incomingMessage.LengthBytes > 0 ? incomingMessage.PeekByte() : (byte)0;
|
||||
if (ContentPackageOrderReceived)
|
||||
{
|
||||
#warning: TODO: do not allow completing initialization until content package order has been received?
|
||||
string errorMsg = $"Error during connection initialization: completed initialization before receiving content package order. Incoming header: {incomingHeader}";
|
||||
GameAnalyticsManager.AddErrorEventOnce("SteamP2PClientPeer.OnInitializationComplete:ContentPackageOrderNotReceived", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
}
|
||||
if (ServerContentPackages.Length == 0)
|
||||
{
|
||||
string errorMsg = $"Error during connection initialization: list of content packages enabled on the server was empty when completing initialization. Incoming header: {incomingHeader}";
|
||||
GameAnalyticsManager.AddErrorEventOnce("SteamP2PClientPeer.OnInitializationComplete:NoContentPackages", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
}
|
||||
callbacks.OnInitializationComplete.Invoke();
|
||||
initializationStep = ConnectionInitialization.Success;
|
||||
}
|
||||
else
|
||||
@@ -237,7 +249,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
foreach (IReadMessage inc in incomingDataMessages)
|
||||
{
|
||||
OnMessageReceived?.Invoke(inc);
|
||||
callbacks.OnMessageReceived.Invoke(inc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +315,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
private void Send(byte[] buf, int length, Steamworks.P2PSend sendType)
|
||||
{
|
||||
bool successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, buf, length + 4, 0, sendType);
|
||||
bool successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, buf, length + 4, 0, sendType);
|
||||
sentBytes += length + 4;
|
||||
if (!successSend)
|
||||
{
|
||||
@@ -311,7 +323,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
DebugConsole.Log("WARNING: message couldn't be sent unreliably, forcing reliable send (" + length.ToString() + " bytes)");
|
||||
sendType = Steamworks.P2PSend.Reliable;
|
||||
successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, buf, length + 4, 0, sendType);
|
||||
successSend = Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, buf, length + 4, 0, sendType);
|
||||
sentBytes += length + 4;
|
||||
}
|
||||
if (!successSend)
|
||||
@@ -335,7 +347,7 @@ namespace Barotrauma.Networking
|
||||
outMsg.Write(saltedPw, 0, saltedPw.Length);
|
||||
|
||||
heartbeatTimer = 5.0;
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
||||
sentBytes += outMsg.LengthBytes;
|
||||
}
|
||||
|
||||
@@ -354,7 +366,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
try
|
||||
{
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
||||
sentBytes += outMsg.LengthBytes;
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -365,12 +377,11 @@ namespace Barotrauma.Networking
|
||||
Thread.Sleep(100);
|
||||
|
||||
Steamworks.SteamNetworking.ResetActions();
|
||||
Steamworks.SteamNetworking.CloseP2PSessionWithUser(hostSteamId);
|
||||
Steamworks.SteamNetworking.CloseP2PSessionWithUser(hostSteamId.Value);
|
||||
|
||||
steamAuthTicket?.Cancel(); steamAuthTicket = null;
|
||||
hostSteamId = 0;
|
||||
|
||||
OnDisconnect?.Invoke(disableReconnect);
|
||||
callbacks.OnDisconnect.Invoke(disableReconnect);
|
||||
}
|
||||
|
||||
protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg)
|
||||
@@ -394,7 +405,7 @@ namespace Barotrauma.Networking
|
||||
msgToSend.Write(msg.Buffer, 0, msg.LengthBytes);
|
||||
|
||||
heartbeatTimer = 5.0;
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, msgToSend.Buffer, msgToSend.LengthBytes, 0, sendType);
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId.Value, msgToSend.Buffer, msgToSend.LengthBytes, 0, sendType);
|
||||
sentBytes += msg.LengthBytes;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Barotrauma.Steam;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Steam;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
@@ -10,20 +10,20 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
private bool isActive;
|
||||
|
||||
private readonly UInt64 selfSteamID;
|
||||
private UInt64 ownerKey64 => unchecked((UInt64)ownerKey);
|
||||
private readonly SteamId selfSteamID;
|
||||
private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Fallback(0));
|
||||
|
||||
private UInt64 ReadSteamId(IReadMessage inc)
|
||||
=> inc.ReadUInt64() ^ ownerKey64;
|
||||
private void WriteSteamId(IWriteMessage msg, UInt64 val)
|
||||
=> msg.Write(val ^ ownerKey64);
|
||||
private SteamId ReadSteamId(IReadMessage inc)
|
||||
=> new SteamId(inc.ReadUInt64() ^ ownerKey64);
|
||||
private void WriteSteamId(IWriteMessage msg, SteamId val)
|
||||
=> msg.Write(val.Value ^ ownerKey64);
|
||||
|
||||
private long sentBytes, receivedBytes;
|
||||
|
||||
class RemotePeer
|
||||
{
|
||||
public UInt64 SteamID;
|
||||
public UInt64 OwnerSteamID;
|
||||
public SteamId SteamId;
|
||||
public Option<SteamId> OwnerSteamId;
|
||||
public double? DisconnectTime;
|
||||
public bool Authenticating;
|
||||
public bool Authenticated;
|
||||
@@ -33,12 +33,12 @@ namespace Barotrauma.Networking
|
||||
public DeliveryMethod DeliveryMethod;
|
||||
public IWriteMessage Message;
|
||||
}
|
||||
public List<UnauthedMessage> UnauthedMessages;
|
||||
public readonly List<UnauthedMessage> UnauthedMessages;
|
||||
|
||||
public RemotePeer(UInt64 steamId)
|
||||
public RemotePeer(SteamId steamId)
|
||||
{
|
||||
SteamID = steamId;
|
||||
OwnerSteamID = 0;
|
||||
SteamId = steamId;
|
||||
OwnerSteamId = Option<SteamId>.None();
|
||||
DisconnectTime = null;
|
||||
Authenticating = false;
|
||||
Authenticated = false;
|
||||
@@ -49,27 +49,27 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
List<RemotePeer> remotePeers;
|
||||
|
||||
public SteamP2POwnerPeer(string name)
|
||||
public SteamP2POwnerPeer(Callbacks callbacks, int ownerKey) : base(new PipeEndpoint(), callbacks, Option<int>.Some(ownerKey))
|
||||
{
|
||||
ServerConnection = null;
|
||||
|
||||
Name = name;
|
||||
|
||||
isActive = false;
|
||||
|
||||
selfSteamID = Steam.SteamManager.GetSteamID();
|
||||
selfSteamID = SteamManager.GetSteamId().TryUnwrap(out var steamId)
|
||||
? steamId
|
||||
: throw new InvalidOperationException("Steamworks not initialized");
|
||||
}
|
||||
|
||||
public override void Start(object endPoint, int ownerKey)
|
||||
public override void Start()
|
||||
{
|
||||
if (isActive) { return; }
|
||||
|
||||
this.ownerKey = ownerKey;
|
||||
|
||||
initializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
||||
|
||||
ServerConnection = new PipeConnection(selfSteamID);
|
||||
ServerConnection.Status = NetworkConnectionStatus.Connected;
|
||||
ServerConnection = new PipeConnection(selfSteamID)
|
||||
{
|
||||
Status = NetworkConnectionStatus.Connected
|
||||
};
|
||||
|
||||
remotePeers = new List<RemotePeer>();
|
||||
|
||||
@@ -82,10 +82,10 @@ namespace Barotrauma.Networking
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
private void OnAuthChange(Steamworks.SteamId steamID, Steamworks.SteamId ownerID, Steamworks.AuthResponse status)
|
||||
private void OnAuthChange(Steamworks.SteamId steamId, Steamworks.SteamId ownerId, Steamworks.AuthResponse status)
|
||||
{
|
||||
RemotePeer remotePeer = remotePeers.Find(p => p.SteamID == steamID);
|
||||
DebugConsole.Log(steamID + " validation: " + status + ", " + (remotePeer != null));
|
||||
RemotePeer remotePeer = remotePeers.Find(p => p.SteamId.Value == steamId);
|
||||
DebugConsole.Log(steamId + " validation: " + status + ", " + (remotePeer != null));
|
||||
|
||||
if (remotePeer == null) { return; }
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (status == Steamworks.AuthResponse.OK)
|
||||
{
|
||||
remotePeer.OwnerSteamID = ownerID;
|
||||
remotePeer.OwnerSteamId = Option<SteamId>.Some(new SteamId(ownerId));
|
||||
remotePeer.Authenticated = true;
|
||||
remotePeer.Authenticating = false;
|
||||
foreach (var msg in remotePeer.UnauthedMessages)
|
||||
@@ -111,7 +111,7 @@ namespace Barotrauma.Networking
|
||||
//known now
|
||||
int prevBitPosition = msg.Message.BitPosition;
|
||||
msg.Message.BitPosition = sizeof(ulong) * 8;
|
||||
WriteSteamId(msg.Message, ownerID);
|
||||
WriteSteamId(msg.Message, new SteamId(ownerId));
|
||||
msg.Message.BitPosition = prevBitPosition;
|
||||
byte[] msgToSend = (byte[])msg.Message.Buffer.Clone();
|
||||
Array.Resize(ref msgToSend, msg.Message.LengthBytes);
|
||||
@@ -130,34 +130,33 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
|
||||
if (!remotePeers.Any(p => p.SteamID == steamId))
|
||||
if (remotePeers.None(p => p.SteamId.Value == steamId))
|
||||
{
|
||||
remotePeers.Add(new RemotePeer(steamId));
|
||||
remotePeers.Add(new RemotePeer(new SteamId(steamId)));
|
||||
}
|
||||
|
||||
Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId); //accept all connections, the server will figure things out later
|
||||
}
|
||||
|
||||
private void OnP2PData(ulong steamId, byte[] data, int dataLength, int channel)
|
||||
private void OnP2PData(ulong steamId, byte[] data, int dataLength, int _)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
|
||||
RemotePeer remotePeer = remotePeers.Find(p => p.SteamID == steamId);
|
||||
if (remotePeer == null || remotePeer.DisconnectTime != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
RemotePeer remotePeer = remotePeers.Find(p => p.SteamId.Value == steamId);
|
||||
if (remotePeer == null) { return; }
|
||||
if (remotePeer.DisconnectTime != null) { return; }
|
||||
|
||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||
WriteSteamId(outMsg, steamId);
|
||||
WriteSteamId(outMsg, remotePeer.OwnerSteamID);
|
||||
var steamUserId = new SteamId(steamId);
|
||||
WriteSteamId(outMsg, steamUserId);
|
||||
WriteSteamId(outMsg, remotePeer.OwnerSteamId.Fallback(steamUserId));
|
||||
outMsg.Write(data, 1, dataLength - 1);
|
||||
|
||||
DeliveryMethod deliveryMethod = (DeliveryMethod)data[0];
|
||||
|
||||
PacketHeader packetHeader = (PacketHeader)data[1];
|
||||
|
||||
if (!remotePeer.Authenticated & !remotePeer.Authenticating && packetHeader.IsConnectionInitializationStep())
|
||||
if (!remotePeer.Authenticated && !remotePeer.Authenticating && packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
remotePeer.DisconnectTime = null;
|
||||
|
||||
@@ -240,7 +239,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
|
||||
UInt64 recipientSteamId = ReadSteamId(inc);
|
||||
SteamId recipientSteamId = ReadSteamId(inc);
|
||||
DeliveryMethod deliveryMethod = (DeliveryMethod)inc.ReadByte();
|
||||
|
||||
int p2pDataStart = inc.BytePosition;
|
||||
@@ -255,7 +254,7 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
RemotePeer peer = remotePeers.Find(p => p.SteamID == recipientSteamId);
|
||||
RemotePeer peer = remotePeers.Find(p => p.SteamId == recipientSteamId);
|
||||
|
||||
if (peer == null) { return; }
|
||||
|
||||
@@ -314,7 +313,7 @@ namespace Barotrauma.Networking
|
||||
sendType = Steamworks.P2PSend.Reliable;
|
||||
}
|
||||
|
||||
bool successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId, p2pData, p2pData.Length, 0, sendType);
|
||||
bool successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId.Value, p2pData, p2pData.Length, 0, sendType);
|
||||
sentBytes += p2pData.Length;
|
||||
|
||||
if (!successSend)
|
||||
@@ -323,7 +322,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
DebugConsole.Log("WARNING: message couldn't be sent unreliably, forcing reliable send (" + p2pData.Length.ToString() + " bytes)");
|
||||
sendType = Steamworks.P2PSend.Reliable;
|
||||
successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId, p2pData, p2pData.Length, 0, sendType);
|
||||
successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId.Value, p2pData, p2pData.Length, 0, sendType);
|
||||
sentBytes += p2pData.Length;
|
||||
}
|
||||
if (!successSend)
|
||||
@@ -354,7 +353,7 @@ namespace Barotrauma.Networking
|
||||
WriteSteamId(outMsg, selfSteamID);
|
||||
WriteSteamId(outMsg, selfSteamID);
|
||||
outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep));
|
||||
outMsg.Write(Name);
|
||||
outMsg.Write(GameMain.Client.Name);
|
||||
|
||||
byte[] msgToSend = (byte[])outMsg.Buffer.Clone();
|
||||
Array.Resize(ref msgToSend, outMsg.LengthBytes);
|
||||
@@ -365,12 +364,12 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (initializationStep != ConnectionInitialization.Success)
|
||||
{
|
||||
OnInitializationComplete?.Invoke();
|
||||
callbacks.OnInitializationComplete.Invoke();
|
||||
initializationStep = ConnectionInitialization.Success;
|
||||
}
|
||||
UInt16 length = inc.ReadUInt16();
|
||||
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, packetHeader.IsCompressed(), inc.BytePosition, length, ServerConnection);
|
||||
OnMessageReceived?.Invoke(msg);
|
||||
callbacks.OnMessageReceived.Invoke(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -390,7 +389,7 @@ namespace Barotrauma.Networking
|
||||
outMsg.Write((byte)(PacketHeader.IsServerMessage | PacketHeader.IsDisconnectMessage));
|
||||
outMsg.Write(msg);
|
||||
|
||||
Steamworks.SteamNetworking.SendP2PPacket(peer.SteamID, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
||||
Steamworks.SteamNetworking.SendP2PPacket(peer.SteamId.Value, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
||||
sentBytes += outMsg.LengthBytes;
|
||||
}
|
||||
else
|
||||
@@ -401,7 +400,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
private void ClosePeerSession(RemotePeer peer)
|
||||
{
|
||||
Steamworks.SteamNetworking.CloseP2PSessionWithUser(peer.SteamID);
|
||||
Steamworks.SteamNetworking.CloseP2PSessionWithUser(peer.SteamId.Value);
|
||||
remotePeers.Remove(peer);
|
||||
}
|
||||
|
||||
@@ -430,7 +429,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
ChildServerRelay.ClosePipes();
|
||||
|
||||
OnDisconnect?.Invoke(disableReconnect);
|
||||
callbacks.OnDisconnect.Invoke(disableReconnect);
|
||||
|
||||
SteamManager.LeaveLobby();
|
||||
Steamworks.SteamNetworking.ResetActions();
|
||||
|
||||
@@ -3,7 +3,6 @@ using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -11,13 +10,14 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
class ServerInfo
|
||||
{
|
||||
public string IP;
|
||||
public string Port;
|
||||
public string QueryPort;
|
||||
|
||||
public Steamworks.Data.NetPingLocation? PingLocation;
|
||||
public Endpoint Endpoint;
|
||||
|
||||
#region TODO: genericize
|
||||
public int QueryPort;
|
||||
public UInt64 LobbyID;
|
||||
public UInt64 OwnerID;
|
||||
public Steamworks.Data.NetPingLocation? PingLocation;
|
||||
#endregion
|
||||
|
||||
public bool OwnerVerified;
|
||||
|
||||
private string serverName;
|
||||
@@ -42,7 +42,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
//null value means that the value isn't known (the server may be using
|
||||
//an old version of the game that didn't report these values or the FetchRules query to Steam may not have finished yet)
|
||||
public bool? UsingWhiteList;
|
||||
// TODO: death to Nullable<T>!!!!
|
||||
public SelectionMode? ModeSelectionMode;
|
||||
public SelectionMode? SubSelectionMode;
|
||||
public bool? AllowSpectating;
|
||||
@@ -140,7 +140,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), frame.RectTransform),
|
||||
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"),
|
||||
Endpoint.ServerTypeString,
|
||||
textAlignment: Alignment.TopLeft)
|
||||
{
|
||||
CanBeFocused = false
|
||||
@@ -248,20 +248,6 @@ namespace Barotrauma.Networking
|
||||
else
|
||||
voipEnabledTickBox.Selected = VoipEnabled.Value;*/
|
||||
|
||||
var usingWhiteList = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerListUsingWhitelist"))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
if (!UsingWhiteList.HasValue)
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), usingWhiteList.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center);
|
||||
else
|
||||
usingWhiteList.Selected = UsingWhiteList.Value;
|
||||
|
||||
content.RectTransform.SizeChanged += () =>
|
||||
{
|
||||
GUITextBlock.AutoScaleAndNormalize(allowSpectating.TextBlock, allowRespawn.TextBlock, usingWhiteList.TextBlock);
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
|
||||
TextManager.Get("ServerListContentPackages"), textAlignment: Alignment.Center, font: GUIStyle.SubHeadingFont);
|
||||
|
||||
@@ -350,34 +336,27 @@ namespace Barotrauma.Networking
|
||||
|
||||
public static ServerInfo FromXElement(XElement element)
|
||||
{
|
||||
ServerInfo info = new ServerInfo()
|
||||
string endpointStr
|
||||
= element.GetAttributeString("Endpoint", null)
|
||||
?? element.GetAttributeString("OwnerID", null)
|
||||
?? $"{element.GetAttributeString("IP", "")}:{element.GetAttributeInt("Port", 0)}";
|
||||
|
||||
if (!(Endpoint.Parse(endpointStr).TryUnwrap(out var endpoint))) { return null; }
|
||||
|
||||
ServerInfo info = new ServerInfo
|
||||
{
|
||||
ServerName = element.GetAttributeString("ServerName", ""),
|
||||
ServerMessage = element.GetAttributeString("ServerMessage", ""),
|
||||
IP = element.GetAttributeString("IP", ""),
|
||||
Port = element.GetAttributeString("Port", ""),
|
||||
QueryPort = element.GetAttributeString("QueryPort", ""),
|
||||
OwnerID = element.GetAttributeSteamID("OwnerID",0)
|
||||
Endpoint = endpoint,
|
||||
QueryPort = element.GetAttributeInt("QueryPort", 0),
|
||||
GameMode = element.GetAttributeIdentifier("GameMode", Identifier.Empty),
|
||||
GameVersion = element.GetAttributeString("GameVersion", ""),
|
||||
MaxPlayers = Math.Min(element.GetAttributeInt("MaxPlayers", 0), NetConfig.MaxPlayers),
|
||||
HasPassword = element.GetAttributeBool("HasPassword", false),
|
||||
RespondedToSteamQuery = null
|
||||
};
|
||||
|
||||
info.RespondedToSteamQuery = null;
|
||||
|
||||
info.GameMode = element.GetAttributeIdentifier("GameMode", Identifier.Empty);
|
||||
info.GameVersion = element.GetAttributeString("GameVersion", "");
|
||||
|
||||
int maxPlayersElement = element.GetAttributeInt("MaxPlayers", 0);
|
||||
|
||||
if (maxPlayersElement > NetConfig.MaxPlayers)
|
||||
{
|
||||
/*DebugConsole.IsOpen = true;
|
||||
DebugConsole.NewMessage($"Setting the maximum amount of players to {maxPlayersElement} failed due to exceeding the limit of {NetConfig.MaxPlayers} players per server. Using the maximum of {NetConfig.MaxPlayers} instead.", Color.Red);*/
|
||||
maxPlayersElement = NetConfig.MaxPlayers;
|
||||
}
|
||||
|
||||
info.MaxPlayers = maxPlayersElement;
|
||||
|
||||
if (Enum.TryParse(element.GetAttributeString("PlayStyle", ""), out PlayStyle playStyleTemp)) { info.PlayStyle = playStyleTemp; }
|
||||
if (bool.TryParse(element.GetAttributeString("UsingWhiteList", ""), out bool whitelistTemp)) { info.UsingWhiteList = whitelistTemp; }
|
||||
if (Enum.TryParse(element.GetAttributeString("TraitorsEnabled", ""), out YesNoMaybe traitorsTemp)) { info.TraitorsEnabled = traitorsTemp; }
|
||||
if (Enum.TryParse(element.GetAttributeString("SubSelectionMode", ""), out SelectionMode subSelectionTemp)) { info.SubSelectionMode = subSelectionTemp; }
|
||||
if (Enum.TryParse(element.GetAttributeString("ModeSelectionMode", ""), out SelectionMode modeSelectionTemp)) { info.ModeSelectionMode = modeSelectionTemp; }
|
||||
@@ -385,8 +364,6 @@ namespace Barotrauma.Networking
|
||||
if (bool.TryParse(element.GetAttributeString("KarmaEnabled", ""), out bool karmaTemp)) { info.KarmaEnabled = karmaTemp; }
|
||||
if (bool.TryParse(element.GetAttributeString("FriendlyFireEnabled", ""), out bool friendlyFireTemp)) { info.FriendlyFireEnabled = friendlyFireTemp; }
|
||||
|
||||
info.HasPassword = element.GetAttributeBool("HasPassword", false);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -394,9 +371,9 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!SteamManager.IsInitialized) { return; }
|
||||
|
||||
if (int.TryParse(QueryPort, out int parsedPort) && IPAddress.TryParse(IP, out IPAddress parsedIP))
|
||||
if (QueryPort != 0 && Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var ipAddress } })
|
||||
{
|
||||
if (MatchmakingPingResponse?.QueryActive ?? false)
|
||||
if (MatchmakingPingResponse is { QueryActive: true })
|
||||
{
|
||||
MatchmakingPingResponse.Cancel();
|
||||
}
|
||||
@@ -433,14 +410,11 @@ namespace Barotrauma.Networking
|
||||
RespondedToSteamQuery = false;
|
||||
});
|
||||
|
||||
MatchmakingPingResponse.HQueryPing(parsedIP, parsedPort);
|
||||
MatchmakingPingResponse.HQueryPing(ipAddress, QueryPort);
|
||||
}
|
||||
else if (OwnerID != 0)
|
||||
else if (Endpoint is SteamP2PEndpoint { SteamId: var ownerId })
|
||||
{
|
||||
if (SteamFriend == null)
|
||||
{
|
||||
SteamFriend = new Steamworks.Friend(OwnerID);
|
||||
}
|
||||
SteamFriend ??= new Steamworks.Friend(ownerId.Value);
|
||||
if (LobbyID == 0)
|
||||
{
|
||||
TaskPool.Add("RequestSteamP2POwnerInfo", SteamFriend?.RequestInfoAsync(),
|
||||
@@ -474,20 +448,15 @@ namespace Barotrauma.Networking
|
||||
bool.TryParse(lobby.GetData("haspassword"), out bool hasPassword);
|
||||
int.TryParse(lobby.GetData("playercount"), out int currPlayers);
|
||||
int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers);
|
||||
UInt64 ownerId = SteamManager.SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
||||
|
||||
if (OwnerID != ownerId) { return; }
|
||||
|
||||
if (!SteamId.Parse(lobby.GetData("lobbyowner")).TryUnwrap(out var ownerId)) { return; }
|
||||
if (!(Endpoint is SteamP2PEndpoint { SteamId: var id }) || id != ownerId) { return; }
|
||||
|
||||
ServerName = lobby.GetData("name");
|
||||
IP = "";
|
||||
Port = "";
|
||||
QueryPort = "";
|
||||
PlayerCount = currPlayers;
|
||||
MaxPlayers = maxPlayers;
|
||||
HasPassword = hasPassword;
|
||||
RespondedToSteamQuery = true;
|
||||
LobbyID = lobby.Id;
|
||||
OwnerID = ownerId;
|
||||
PingChecked = false;
|
||||
OwnerVerified = true;
|
||||
|
||||
@@ -496,7 +465,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public XElement ToXElement()
|
||||
{
|
||||
if (OwnerID == 0 && string.IsNullOrEmpty(Port))
|
||||
if (Endpoint is null)
|
||||
{
|
||||
return null; //can't save this one since it's not set up correctly
|
||||
}
|
||||
@@ -505,22 +474,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
element.SetAttributeValue("ServerName", ServerName);
|
||||
element.SetAttributeValue("ServerMessage", ServerMessage);
|
||||
if (OwnerID == 0)
|
||||
{
|
||||
element.SetAttributeValue("IP", IP);
|
||||
element.SetAttributeValue("Port", Port);
|
||||
element.SetAttributeValue("QueryPort", QueryPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
element.SetAttributeValue("OwnerID", SteamManager.SteamIDUInt64ToString(OwnerID));
|
||||
}
|
||||
element.SetAttributeValue("Endpoint", Endpoint.ToString());
|
||||
|
||||
element.SetAttributeValue("GameMode", GameMode);
|
||||
element.SetAttributeValue("GameVersion", GameVersion ?? "");
|
||||
element.SetAttributeValue("MaxPlayers", MaxPlayers);
|
||||
if (PlayStyle.HasValue) { element.SetAttributeValue("PlayStyle", PlayStyle.Value.ToString()); }
|
||||
if (UsingWhiteList.HasValue) { element.SetAttributeValue("UsingWhiteList", UsingWhiteList.Value.ToString()); }
|
||||
if (TraitorsEnabled.HasValue) { element.SetAttributeValue("TraitorsEnabled", TraitorsEnabled.Value.ToString()); }
|
||||
if (SubSelectionMode.HasValue) { element.SetAttributeValue("SubSelectionMode", SubSelectionMode.Value.ToString()); }
|
||||
if (ModeSelectionMode.HasValue) { element.SetAttributeValue("ModeSelectionMode", ModeSelectionMode.Value.ToString()); }
|
||||
@@ -540,14 +499,19 @@ namespace Barotrauma.Networking
|
||||
public bool Equals(ServerInfo other)
|
||||
{
|
||||
return
|
||||
other.OwnerID == OwnerID &&
|
||||
(other.LobbyID == LobbyID || other.LobbyID == 0 || LobbyID == 0) &&
|
||||
((OwnerID == 0) ? (other.IP == IP && other.Port == Port) : true);
|
||||
other.Endpoint == Endpoint &&
|
||||
(other.LobbyID == LobbyID || other.LobbyID == 0 || LobbyID == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class is trash, so punish its use by making it horribly inefficient in hashsets
|
||||
/// Doing anything else here would make it cause even more bugs
|
||||
/// </summary>
|
||||
public override int GetHashCode() => 0;
|
||||
|
||||
public bool MatchesByEndpoint(ServerInfo other)
|
||||
{
|
||||
return OwnerID == other.OwnerID && (OwnerID != 0 ? true : (IP == other.IP && Port == other.Port));
|
||||
return other.Endpoint == Endpoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -196,11 +196,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
foreach (var data in richString.RichTextData.Value)
|
||||
{
|
||||
if (!UInt64.TryParse(data.Metadata, out ulong id)) { return; }
|
||||
Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id)
|
||||
?? GameMain.Client.ConnectedClients.Find(c => c.ID == id)
|
||||
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id)
|
||||
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id);
|
||||
Client client = data.ExtractClient();
|
||||
if (client != null && client.Karma < 40.0f)
|
||||
{
|
||||
textContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), listBox.Content.RectTransform),
|
||||
@@ -258,11 +254,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
foreach (GUIComponent child in listBox.Content.Children)
|
||||
{
|
||||
var textBlock = child as GUITextBlock;
|
||||
if (textBlock == null) continue;
|
||||
|
||||
if (!(child is GUITextBlock textBlock)) { continue; }
|
||||
child.Visible = true;
|
||||
|
||||
if (msgTypeHidden[(int)((LogMessage)child.UserData).Type])
|
||||
{
|
||||
child.Visible = false;
|
||||
@@ -287,10 +280,10 @@ namespace Barotrauma.Networking
|
||||
listBox.Content.RectTransform.ReverseChildren();
|
||||
}
|
||||
|
||||
public bool ClearFilter(GUIComponent button, object obj)
|
||||
public bool ClearFilter(GUIComponent button, object _)
|
||||
{
|
||||
var searchBox = button.UserData as GUITextBox;
|
||||
if (searchBox != null) searchBox.Text = "";
|
||||
if (searchBox != null) { searchBox.Text = ""; }
|
||||
|
||||
msgFilter = "";
|
||||
FilterMessages();
|
||||
|
||||
@@ -121,7 +121,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
ReadMonsterEnabled(incMsg);
|
||||
BanList.ClientAdminRead(incMsg);
|
||||
Whitelist.ClientAdminRead(incMsg);
|
||||
}
|
||||
|
||||
public void ClientRead(IReadMessage incMsg)
|
||||
@@ -225,7 +224,6 @@ namespace Barotrauma.Networking
|
||||
outMsg.Write(changedMonsterSettings); outMsg.WritePadBits();
|
||||
if (changedMonsterSettings) WriteMonsterEnabled(outMsg, tempMonsterEnabled);
|
||||
BanList.ClientAdminWrite(outMsg);
|
||||
Whitelist.ClientAdminWrite(outMsg);
|
||||
}
|
||||
|
||||
if (dataToSend.HasFlag(NetFlags.HiddenSubs))
|
||||
@@ -273,8 +271,7 @@ namespace Barotrauma.Networking
|
||||
General,
|
||||
Rounds,
|
||||
Antigriefing,
|
||||
Banlist,
|
||||
Whitelist
|
||||
Banlist
|
||||
}
|
||||
|
||||
private NetPropertyData GetPropertyData(string name)
|
||||
@@ -949,13 +946,6 @@ namespace Barotrauma.Networking
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
BanList.CreateBanFrame(settingsTabs[(int)SettingsTab.Banlist]);
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// whitelist
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
Whitelist.CreateWhiteListFrame(settingsTabs[(int)SettingsTab.Whitelist]);
|
||||
Whitelist.localEnabled = Whitelist.Enabled;
|
||||
}
|
||||
|
||||
private void CreateLabeledSlider(GUIComponent parent, string labelTag, out GUIScrollBar slider, out GUITextBlock label)
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameMain.Client?.ID ?? 0;
|
||||
return GameMain.Client?.SessionId ?? 0;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
@@ -82,7 +82,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private VoipCapture(string deviceName) : base(GameMain.Client?.ID ?? 0, true, false)
|
||||
private VoipCapture(string deviceName) : base(GameMain.Client?.SessionId ?? 0, true, false)
|
||||
{
|
||||
Disconnected = false;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -54,7 +55,7 @@ namespace Barotrauma
|
||||
voteCountMax[voteType] = value;
|
||||
}
|
||||
|
||||
public void UpdateVoteTexts(List<Client> clients, VoteType voteType)
|
||||
public void UpdateVoteTexts(IEnumerable<Client> clients, VoteType voteType)
|
||||
{
|
||||
switch (voteType)
|
||||
{
|
||||
@@ -92,7 +93,7 @@ namespace Barotrauma
|
||||
|
||||
private void SetVoteText(GUIListBox listBox, object userData, int votes)
|
||||
{
|
||||
if (userData == null) return;
|
||||
if (userData == null) { return; }
|
||||
foreach (GUIComponent comp in listBox.Content.Children)
|
||||
{
|
||||
if (comp.UserData != userData) { continue; }
|
||||
@@ -136,7 +137,7 @@ namespace Barotrauma
|
||||
case VoteType.Kick:
|
||||
if (!(data is Client votedClient)) { return; }
|
||||
|
||||
msg.Write(votedClient.ID);
|
||||
msg.Write(votedClient.SessionId);
|
||||
break;
|
||||
case VoteType.StartRound:
|
||||
if (!(data is bool)) { return; }
|
||||
@@ -233,21 +234,22 @@ namespace Barotrauma
|
||||
DebugConsole.ThrowError("Failed to cast vote type \"" + voteTypeByte + "\"", e);
|
||||
}
|
||||
|
||||
byte yesClientCount = inc.ReadByte();
|
||||
for (int i = 0; i < yesClientCount; i++)
|
||||
int readVote(int value)
|
||||
{
|
||||
byte clientID = inc.ReadByte();
|
||||
var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID);
|
||||
matchingClient?.SetVote(voteType, 2);
|
||||
}
|
||||
byte clientCount = inc.ReadByte();
|
||||
for (int i = 0; i < clientCount; i++)
|
||||
{
|
||||
byte clientId = inc.ReadByte();
|
||||
var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == clientId);
|
||||
matchingClient?.SetVote(voteType, value);
|
||||
}
|
||||
|
||||
byte noClientCount = inc.ReadByte();
|
||||
for (int i = 0; i < noClientCount; i++)
|
||||
{
|
||||
byte clientID = inc.ReadByte();
|
||||
var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID);
|
||||
matchingClient?.SetVote(voteType, 1);
|
||||
return clientCount;
|
||||
}
|
||||
|
||||
int yesClientCount = readVote(value: 2);
|
||||
int noClientCount = readVote(value: 1);
|
||||
|
||||
byte maxClientCount = inc.ReadByte();
|
||||
|
||||
SetVoteCountYes(voteType, yesClientCount);
|
||||
@@ -258,10 +260,10 @@ namespace Barotrauma
|
||||
{
|
||||
case VoteState.Started:
|
||||
byte starterID = inc.ReadByte();
|
||||
Client starterClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == starterID);
|
||||
Client starterClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == starterID);
|
||||
float timeOut = inc.ReadByte();
|
||||
|
||||
Client myClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == GameMain.Client.ID);
|
||||
Client myClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == GameMain.Client.SessionId);
|
||||
if (myClient == null || !myClient.InGame) { return; }
|
||||
|
||||
switch (voteType)
|
||||
@@ -284,8 +286,8 @@ namespace Barotrauma
|
||||
byte toClientId = inc.ReadByte();
|
||||
int transferAmount = inc.ReadInt32();
|
||||
|
||||
Client fromClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == fromClientId);
|
||||
Client toClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == toClientId);
|
||||
Client fromClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == fromClientId);
|
||||
Client toClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == toClientId);
|
||||
GameMain.Client.ShowMoneyTransferVoteInterface(starterClient, fromClient, transferAmount, toClient, timeOut);
|
||||
break;
|
||||
}
|
||||
@@ -343,8 +345,8 @@ namespace Barotrauma
|
||||
byte readyClientCount = inc.ReadByte();
|
||||
for (int i = 0; i < readyClientCount; i++)
|
||||
{
|
||||
byte clientID = inc.ReadByte();
|
||||
var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID);
|
||||
byte clientId = inc.ReadByte();
|
||||
var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.SessionId == clientId);
|
||||
matchingClient?.SetVote(VoteType.StartRound, true);
|
||||
}
|
||||
UpdateVoteTexts(GameMain.NetworkMember.ConnectedClients, VoteType.StartRound);
|
||||
|
||||
@@ -810,7 +810,7 @@ namespace Barotrauma
|
||||
GUI.DrawString(spriteBatch, pos, interestingPos.PositionType.ToString(), Color.White, font: GUIStyle.LargeFont);
|
||||
}
|
||||
|
||||
// TODO: Improve this temporary level editor debug solution (or remove it)
|
||||
// TODO: Improve this temporary level editor debug solution
|
||||
foreach (var pathPoint in Level.Loaded.PathPoints)
|
||||
{
|
||||
Vector2 pathPointPos = new Vector2(pathPoint.Position.X, -pathPoint.Position.Y);
|
||||
@@ -833,6 +833,17 @@ namespace Barotrauma
|
||||
GUI.DrawString(spriteBatch, pathPointPos, "Path Point\n" + pathPoint.Id, color, font: GUIStyle.LargeFont);
|
||||
}
|
||||
|
||||
foreach (var location in Level.Loaded.AbyssResources)
|
||||
{
|
||||
if (location.Resources == null) { continue; }
|
||||
foreach (var resource in location.Resources)
|
||||
{
|
||||
Vector2 resourcePos = new Vector2(resource.Position.X, -resource.Position.Y);
|
||||
spriteBatch.DrawCircle(resourcePos, 100, 6, Color.DarkGreen * 0.5f, thickness: (int)(2 / Cam.Zoom));
|
||||
GUI.DrawString(spriteBatch, resourcePos, resource.Name, Color.DarkGreen, font: GUIStyle.LargeFont);
|
||||
}
|
||||
}
|
||||
|
||||
/*for (int i = 0; i < Level.Loaded.distanceField.Count; i++)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
|
||||
@@ -390,7 +390,7 @@ namespace Barotrauma
|
||||
SelectTab(tb, userdata);
|
||||
|
||||
GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()),
|
||||
IPAddress.Loopback.ToString(), 0, "localhost", 0, false);
|
||||
new LidgrenEndpoint(IPAddress.Loopback, NetConfig.DefaultPort), "localhost", Option<int>.None());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -489,7 +489,7 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.Disconnect();
|
||||
GameMain.Client.Quit();
|
||||
GameMain.Client = null;
|
||||
}
|
||||
|
||||
@@ -834,9 +834,9 @@ namespace Barotrauma
|
||||
arguments += " -nopassword";
|
||||
}
|
||||
|
||||
if (Steam.SteamManager.GetSteamID() != 0)
|
||||
if (SteamManager.GetSteamId().TryUnwrap(out var steamId1))
|
||||
{
|
||||
arguments += " -steamid " + Steam.SteamManager.GetSteamID();
|
||||
arguments += " -steamid " + steamId1.Value;
|
||||
}
|
||||
int ownerKey = Math.Max(CryptoRandom.Instance.Next(), 1);
|
||||
arguments += " -ownerkey " + ownerKey;
|
||||
@@ -865,8 +865,12 @@ namespace Barotrauma
|
||||
Thread.Sleep(1000); //wait until the server is ready before connecting
|
||||
|
||||
GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(
|
||||
SteamManager.GetUsername().FallbackNullOrEmpty(name)),
|
||||
System.Net.IPAddress.Loopback.ToString(), Steam.SteamManager.GetSteamID(), name, ownerKey, true);
|
||||
SteamManager.GetUsername().FallbackNullOrEmpty(name)),
|
||||
SteamManager.GetSteamId().TryUnwrap(out var steamId)
|
||||
? new SteamP2PEndpoint(steamId)
|
||||
: (Endpoint)new LidgrenEndpoint(IPAddress.Loopback, NetConfig.DefaultPort),
|
||||
name,
|
||||
Option<int>.Some(ownerKey));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -68,12 +68,28 @@ namespace Barotrauma
|
||||
{
|
||||
OnClicked = (guiButton, o) =>
|
||||
{
|
||||
GameMain.Client?.Disconnect();
|
||||
GameMain.Client?.Quit();
|
||||
GameMain.MainMenuScreen.Select();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (!GameMain.Client.IsServerOwner)
|
||||
{
|
||||
if (GameMain.Client.ClientPeer.ServerContentPackages.Length == 0)
|
||||
{
|
||||
string errorMsg = $"Error in ModDownloadScreen: the list of mods the server has enabled was empty. Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}";
|
||||
GameAnalyticsManager.AddErrorEventOnce("ModDownloadScreen.Select:NoContentPackages", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
throw new InvalidOperationException(errorMsg);
|
||||
}
|
||||
if (GameMain.Client.ClientPeer.ServerContentPackages.None(p => p.CorePackage != null))
|
||||
{
|
||||
string errorMsg = $"Error in ModDownloadScreen: no core packages in the list of mods the server has enabled. Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}";
|
||||
GameAnalyticsManager.AddErrorEventOnce("ModDownloadScreen.Select:NoCorePackage", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
throw new InvalidOperationException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
var missingPackages = GameMain.Client.ClientPeer.ServerContentPackages
|
||||
.Where(sp => sp.ContentPackage is null).ToArray();
|
||||
if (!missingPackages.Any())
|
||||
@@ -84,11 +100,14 @@ namespace Barotrauma
|
||||
ContentPackageManager.EnabledPackages.SetCore(
|
||||
GameMain.Client.ClientPeer.ServerContentPackages
|
||||
.Select(p => p.CorePackage)
|
||||
.First(p => p != null));
|
||||
ContentPackageManager.EnabledPackages.SetRegular(
|
||||
.OfType<CorePackage>().First());
|
||||
List<RegularPackage> regularPackages =
|
||||
GameMain.Client.ClientPeer.ServerContentPackages
|
||||
.Select(p => p.RegularPackage)
|
||||
.Where(p => p != null).ToArray());
|
||||
.OfType<RegularPackage>().ToList();
|
||||
//keep enabled client-side-only mods enabled
|
||||
regularPackages.AddRange(ContentPackageManager.EnabledPackages.Regular.Where(p => !p.HasMultiplayerSyncedContent));
|
||||
ContentPackageManager.EnabledPackages.SetRegular(regularPackages);
|
||||
}
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
return;
|
||||
@@ -153,7 +172,7 @@ namespace Barotrauma
|
||||
buttonContainerSpacing(0.2f);
|
||||
button(TextManager.Get("No"), () =>
|
||||
{
|
||||
GameMain.Client?.Disconnect();
|
||||
GameMain.Client?.Quit();
|
||||
GameMain.MainMenuScreen.Select();
|
||||
});
|
||||
buttonContainerSpacing(0.1f);
|
||||
@@ -173,10 +192,10 @@ namespace Barotrauma
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
BulkDownloader.SubscribeToServerMods(missingIds,
|
||||
rejoinEndpoint: GameMain.Client.ClientPeer.ServerConnection.EndPointString,
|
||||
rejoinLobby: SteamManager.CurrentLobbyID,
|
||||
rejoinServerName: GameMain.NetLobbyScreen.ServerName.Text);
|
||||
GameMain.Client.Disconnect();
|
||||
new ConnectCommand(
|
||||
serverName: GameMain.Client.ServerName,
|
||||
endpoint: GameMain.Client.ClientPeer.ServerEndpoint));
|
||||
GameMain.Client.Quit();
|
||||
}
|
||||
GameMain.MainMenuScreen.Select();
|
||||
}, width: 0.7f);
|
||||
@@ -275,19 +294,22 @@ namespace Barotrauma
|
||||
?? serverPackages.FirstOrDefault(p => p.CorePackage != null)
|
||||
?.CorePackage
|
||||
?? throw new Exception($"Failed to find core package to enable");
|
||||
RegularPackage[] regularPackages
|
||||
List<RegularPackage> regularPackages
|
||||
= serverPackages.Where(p => p.CorePackage is null)
|
||||
.Select(p =>
|
||||
p.RegularPackage
|
||||
?? downloadedPackages.FirstOrDefault(d => d is RegularPackage && d.Hash.Equals(p.Hash))
|
||||
?? throw new Exception($"Could not find regular package \"{p.Name}\""))
|
||||
.Cast<RegularPackage>()
|
||||
.ToArray();
|
||||
.ToList();
|
||||
foreach (var regularPackage in regularPackages)
|
||||
{
|
||||
DebugConsole.NewMessage($"Enabling \"{regularPackage.Name}\" ({regularPackage.Dir})", Color.Lime);
|
||||
}
|
||||
|
||||
//keep enabled client-side-only mods enabled
|
||||
regularPackages.AddRange(ContentPackageManager.EnabledPackages.Regular.Where(p => !p.HasMultiplayerSyncedContent));
|
||||
|
||||
ContentPackageManager.EnabledPackages.BackUp();
|
||||
ContentPackageManager.EnabledPackages.SetCore(corePackage);
|
||||
ContentPackageManager.EnabledPackages.SetRegular(regularPackages);
|
||||
|
||||
@@ -1529,14 +1529,13 @@ namespace Barotrauma
|
||||
while (i < MultiplayerPreferences.Instance.JobPreferences.Count)
|
||||
{
|
||||
var jobPreference = MultiplayerPreferences.Instance.JobPreferences[i];
|
||||
if (!JobPrefab.Prefabs.ContainsKey(jobPreference.JobIdentifier))
|
||||
if (!JobPrefab.Prefabs.TryGet(jobPreference.JobIdentifier, out JobPrefab prefab) || prefab.HiddenJob)
|
||||
{
|
||||
MultiplayerPreferences.Instance.JobPreferences.RemoveAt(i);
|
||||
continue;
|
||||
}
|
||||
// The old job variant system used one-based indexing
|
||||
// so let's make sure no one get to pick a variant which doesn't exist
|
||||
var prefab = JobPrefab.Prefabs[jobPreference.JobIdentifier];
|
||||
var variant = Math.Min(jobPreference.Variant, prefab.Variants - 1);
|
||||
jobPrefab = new JobVariant(prefab, variant);
|
||||
break;
|
||||
@@ -2160,15 +2159,8 @@ namespace Barotrauma
|
||||
if (child != null) { PlayerList.RemoveChild(child); }
|
||||
}
|
||||
|
||||
private Client ExtractClientFromClickableArea(GUITextBlock.ClickableArea area)
|
||||
{
|
||||
if (!UInt64.TryParse(area.Data.Metadata, out UInt64 id)) { return null; }
|
||||
Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id)
|
||||
?? GameMain.Client.ConnectedClients.Find(c => c.ID == id)
|
||||
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id)
|
||||
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id);
|
||||
return client;
|
||||
}
|
||||
public static Client ExtractClientFromClickableArea(GUITextBlock.ClickableArea area)
|
||||
=> area.Data.ExtractClient();
|
||||
|
||||
public void SelectPlayer(GUITextBlock component, GUITextBlock.ClickableArea area)
|
||||
{
|
||||
@@ -2188,29 +2180,35 @@ namespace Barotrauma
|
||||
public static void CreateModerationContextMenu(Client client)
|
||||
{
|
||||
if (GUIContextMenu.CurrentContextMenu != null) { return; }
|
||||
if (GameMain.IsSingleplayer || client == null || ((!GameMain.Client?.PreviouslyConnectedClients?.Contains(client)) ?? true)) { return; }
|
||||
bool hasSteam = client.SteamID > 0 && SteamManager.IsInitialized,
|
||||
canKick = GameMain.Client.HasPermission(ClientPermissions.Kick),
|
||||
canBan = GameMain.Client.HasPermission(ClientPermissions.Ban) && client.AllowKicking,
|
||||
canPromo = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions);
|
||||
if (GameMain.IsSingleplayer || client == null) { return; }
|
||||
if (!(GameMain.Client is { PreviouslyConnectedClients: var previouslyConnectedClients })
|
||||
|| !previouslyConnectedClients.Contains(client)) { return; }
|
||||
|
||||
bool hasAccountId = client.AccountId.IsSome();
|
||||
bool canKick = GameMain.Client.HasPermission(ClientPermissions.Kick);
|
||||
bool canBan = GameMain.Client.HasPermission(ClientPermissions.Ban) && client.AllowKicking;
|
||||
bool canManagePermissions = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions);
|
||||
|
||||
// Disable options if we are targeting ourselves
|
||||
if (client.ID == GameMain.Client?.ID)
|
||||
if (client.SessionId == GameMain.Client.SessionId)
|
||||
{
|
||||
canKick = canBan = canPromo = false;
|
||||
canKick = canBan = canManagePermissions = false;
|
||||
}
|
||||
|
||||
List<ContextMenuOption> options = new List<ContextMenuOption>
|
||||
List<ContextMenuOption> options = new List<ContextMenuOption>();
|
||||
|
||||
if (client.AccountId.TryUnwrap(out var accountId) && accountId is SteamId steamId)
|
||||
{
|
||||
new ContextMenuOption("ViewSteamProfile", isEnabled: hasSteam, onSelected: delegate
|
||||
{
|
||||
Steamworks.SteamFriends.OpenWebOverlay($"https://steamcommunity.com/profiles/{client.SteamID}");
|
||||
}),
|
||||
new ContextMenuOption("ModerationMenu.ManagePlayer", isEnabled: true, onSelected: delegate
|
||||
options.Add(new ContextMenuOption("ViewSteamProfile", isEnabled: hasAccountId, onSelected: () =>
|
||||
{
|
||||
SteamManager.OverlayProfile(steamId);
|
||||
}));
|
||||
}
|
||||
|
||||
options.Add(new ContextMenuOption("ModerationMenu.ManagePlayer", isEnabled: true, onSelected: () =>
|
||||
{
|
||||
GameMain.NetLobbyScreen?.SelectPlayer(client);
|
||||
})
|
||||
};
|
||||
}));
|
||||
|
||||
// Creates sub context menu options for all the ranks
|
||||
List<ContextMenuOption> rankOptions = new List<ContextMenuOption>();
|
||||
@@ -2236,18 +2234,18 @@ namespace Barotrauma
|
||||
}) { Tooltip = rank.Description });
|
||||
}
|
||||
|
||||
options.Add(new ContextMenuOption("Rank", isEnabled: canPromo, options: rankOptions.ToArray()));
|
||||
options.Add(new ContextMenuOption("Rank", isEnabled: canManagePermissions, options: rankOptions.ToArray()));
|
||||
|
||||
Color clientColor = client.Character?.Info?.Job.Prefab.UIColor ?? Color.White;
|
||||
|
||||
if (GameMain.Client.ConnectedClients.Contains(client))
|
||||
{
|
||||
options.Add(new ContextMenuOption(client.MutedLocally ? "Unmute" : "Mute", isEnabled: client.ID != GameMain.Client?.ID, onSelected: delegate
|
||||
options.Add(new ContextMenuOption(client.MutedLocally ? "Unmute" : "Mute", isEnabled: client.SessionId != GameMain.Client.SessionId, onSelected: delegate
|
||||
{
|
||||
client.MutedLocally = !client.MutedLocally;
|
||||
}));
|
||||
|
||||
bool kickEnabled = client.ID != GameMain.Client?.ID && client.AllowKicking;
|
||||
bool kickEnabled = client.SessionId != GameMain.Client.SessionId && client.AllowKicking;
|
||||
|
||||
// if the user can kick create a kick option else create the votekick option
|
||||
ContextMenuOption kickOption;
|
||||
@@ -2281,7 +2279,7 @@ namespace Barotrauma
|
||||
|
||||
public bool SelectPlayer(Client selectedClient)
|
||||
{
|
||||
bool myClient = selectedClient.ID == GameMain.Client.ID;
|
||||
bool myClient = selectedClient.SessionId == GameMain.Client.SessionId;
|
||||
bool hasManagePermissions = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions);
|
||||
|
||||
PlayerFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null)
|
||||
@@ -2510,14 +2508,6 @@ namespace Barotrauma
|
||||
};
|
||||
banButton.OnClicked = (bt, userdata) => { BanPlayer(selectedClient); return true; };
|
||||
banButton.OnClicked += ClosePlayerFrame;
|
||||
|
||||
var rangebanButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
|
||||
TextManager.Get("BanRange"))
|
||||
{
|
||||
UserData = selectedClient
|
||||
};
|
||||
rangebanButton.OnClicked = (bt, userdata) => { BanPlayerRange(selectedClient); return true; };
|
||||
rangebanButton.OnClicked += ClosePlayerFrame;
|
||||
}
|
||||
|
||||
if (GameMain.Client != null && GameMain.Client.ConnectedClients.Contains(selectedClient))
|
||||
@@ -2528,7 +2518,7 @@ namespace Barotrauma
|
||||
var kickVoteButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaLower.RectTransform),
|
||||
TextManager.Get("VoteToKick"))
|
||||
{
|
||||
Enabled = !selectedClient.HasKickVoteFromID(GameMain.Client.ID),
|
||||
Enabled = !selectedClient.HasKickVoteFromSessionId(GameMain.Client.SessionId),
|
||||
OnClicked = (btn, userdata) => { GameMain.Client.VoteForKick(selectedClient); btn.Enabled = false; return true; },
|
||||
UserData = selectedClient
|
||||
};
|
||||
@@ -2560,7 +2550,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedClient.SteamID != 0 && Steam.SteamManager.IsInitialized)
|
||||
if (selectedClient.AccountId.TryUnwrap(out var accountId) && accountId is SteamId steamId && Steam.SteamManager.IsInitialized)
|
||||
{
|
||||
var viewSteamProfileButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), headerContainer.RectTransform, Anchor.TopCenter) { MaxSize = new Point(int.MaxValue, (int)(40 * GUI.Scale)) },
|
||||
TextManager.Get("ViewSteamProfile"))
|
||||
@@ -2570,7 +2560,7 @@ namespace Barotrauma
|
||||
viewSteamProfileButton.TextBlock.AutoScaleHorizontal = true;
|
||||
viewSteamProfileButton.OnClicked = (bt, userdata) =>
|
||||
{
|
||||
SteamManager.OverlayCustomURL("https://steamcommunity.com/profiles/" + selectedClient.SteamID.ToString());
|
||||
SteamManager.OverlayProfile(steamId);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
@@ -2628,13 +2618,7 @@ namespace Barotrauma
|
||||
public void BanPlayer(Client client)
|
||||
{
|
||||
if (GameMain.NetworkMember == null || client == null) { return; }
|
||||
GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true, rangeBan: false);
|
||||
}
|
||||
|
||||
public void BanPlayerRange(Client client)
|
||||
{
|
||||
if (GameMain.NetworkMember == null || client == null) { return; }
|
||||
GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true, rangeBan: true);
|
||||
GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
@@ -2679,7 +2663,7 @@ namespace Barotrauma
|
||||
if (child.FindChild(c => c.UserData is Pair<string, float> pair && pair.First == "soundicon") is GUIImage soundIcon)
|
||||
{
|
||||
double voipAmplitude = 0.0f;
|
||||
if (client.ID != GameMain.Client.ID)
|
||||
if (client.SessionId != GameMain.Client.SessionId)
|
||||
{
|
||||
voipAmplitude = client.VoipSound?.CurrentAmplitude ?? 0.0f;
|
||||
}
|
||||
|
||||
@@ -53,21 +53,19 @@ namespace Barotrauma
|
||||
|
||||
private class FriendInfo
|
||||
{
|
||||
public UInt64 SteamID;
|
||||
public UInt64 SteamId;
|
||||
public string Name;
|
||||
public Sprite Sprite;
|
||||
public LocalizedString StatusText;
|
||||
public bool PlayingThisGame;
|
||||
public bool PlayingAnotherGame;
|
||||
public string ConnectName;
|
||||
public string ConnectEndpoint;
|
||||
public UInt64 ConnectLobby;
|
||||
public Option<ConnectCommand> ConnectCommand = Option<ConnectCommand>.None();
|
||||
|
||||
public bool InServer
|
||||
{
|
||||
get
|
||||
{
|
||||
return PlayingThisGame && !StatusText.IsNullOrWhiteSpace() && (!string.IsNullOrWhiteSpace(ConnectEndpoint) || ConnectLobby != 0);
|
||||
return PlayingThisGame && !StatusText.IsNullOrWhiteSpace() && ConnectCommand.IsSome();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,7 +79,7 @@ namespace Barotrauma
|
||||
private List<ServerInfo> favoriteServers;
|
||||
private List<ServerInfo> recentServers;
|
||||
|
||||
private readonly Dictionary<string, int> activePings = new Dictionary<string, int>();
|
||||
private readonly Dictionary<IPAddress, int> activePings = new Dictionary<IPAddress, int>();
|
||||
|
||||
private enum ServerListTab
|
||||
{
|
||||
@@ -153,7 +151,6 @@ namespace Barotrauma
|
||||
private GUITickBox filterIncompatible;
|
||||
private GUITickBox filterFull;
|
||||
private GUITickBox filterEmpty;
|
||||
private GUITickBox filterWhitelisted;
|
||||
private Dictionary<Identifier, GUIDropDown> ternaryFilters;
|
||||
private Dictionary<Identifier, GUITickBox> filterTickBoxes;
|
||||
private Dictionary<Identifier, GUITickBox> playStyleTickBoxes;
|
||||
@@ -405,7 +402,6 @@ namespace Barotrauma
|
||||
filterIncompatible = addTickBox("FilterIncompatibleServers".ToIdentifier());
|
||||
filterFull = addTickBox("FilterFullServers".ToIdentifier());
|
||||
filterEmpty = addTickBox("FilterEmptyServers".ToIdentifier());
|
||||
filterWhitelisted = addTickBox("FilterWhitelistedServers".ToIdentifier());
|
||||
filterOffensive = addTickBox("FilterOffensiveServers".ToIdentifier());
|
||||
|
||||
// Filter Tags
|
||||
@@ -608,14 +604,14 @@ namespace Barotrauma
|
||||
{
|
||||
if (selectedServer != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(selectedServer.IP) && !string.IsNullOrWhiteSpace(selectedServer.Port) && int.TryParse(selectedServer.Port, out _))
|
||||
{
|
||||
JoinServer(selectedServer.IP + ":" + selectedServer.Port, selectedServer.ServerName);
|
||||
}
|
||||
else if (selectedServer.LobbyID != 0)
|
||||
if (selectedServer.LobbyID != 0)
|
||||
{
|
||||
Steam.SteamManager.JoinLobby(selectedServer.LobbyID, true);
|
||||
}
|
||||
else if (selectedServer.Endpoint != null)
|
||||
{
|
||||
JoinServer(selectedServer.Endpoint, selectedServer.ServerName);
|
||||
}
|
||||
else
|
||||
{
|
||||
new GUIMessageBox("", TextManager.Get("ServerOffline"));
|
||||
@@ -753,20 +749,11 @@ namespace Barotrauma
|
||||
doc.SaveSafe(file);
|
||||
}
|
||||
|
||||
public ServerInfo UpdateServerInfoWithServerSettings(NetworkConnection endpoint, ServerSettings serverSettings)
|
||||
public ServerInfo UpdateServerInfoWithServerSettings(NetworkConnection connection, ServerSettings serverSettings)
|
||||
{
|
||||
UInt64 steamId = 0;
|
||||
string ip = ""; string port = "";
|
||||
if (endpoint is SteamP2PConnection steamP2PConnection) { steamId = steamP2PConnection.SteamID; }
|
||||
else if (endpoint is LidgrenConnection lidgrenConnection)
|
||||
{
|
||||
ip = lidgrenConnection.IPString;
|
||||
port = lidgrenConnection.Port.ToString();
|
||||
}
|
||||
|
||||
bool isInfoNew = false;
|
||||
ServerInfo info = serverList.Content.FindChild(d => (d.UserData is ServerInfo serverInfo) &&
|
||||
(steamId != 0 ? steamId == serverInfo.OwnerID : (ip == serverInfo.IP && port == serverInfo.Port)))?.UserData as ServerInfo;
|
||||
serverInfo.Endpoint == connection.Endpoint)?.UserData as ServerInfo;
|
||||
if (info == null)
|
||||
{
|
||||
isInfoNew = true;
|
||||
@@ -775,17 +762,14 @@ namespace Barotrauma
|
||||
|
||||
info.ServerName = serverSettings.ServerName;
|
||||
info.ServerMessage = serverSettings.ServerMessageText;
|
||||
info.OwnerID = steamId;
|
||||
info.Endpoint = connection.Endpoint;
|
||||
info.LobbyID = SteamManager.CurrentLobbyID;
|
||||
info.IP = ip;
|
||||
info.Port = port;
|
||||
info.GameMode = GameMain.NetLobbyScreen.SelectedMode?.Identifier ?? Identifier.Empty;
|
||||
info.GameStarted = Screen.Selected != GameMain.NetLobbyScreen;
|
||||
info.GameVersion = GameMain.Version.ToString();
|
||||
info.MaxPlayers = serverSettings.MaxPlayers;
|
||||
info.PlayStyle = serverSettings.PlayStyle;
|
||||
info.RespondedToSteamQuery = true;
|
||||
info.UsingWhiteList = serverSettings.Whitelist.Enabled;
|
||||
info.TraitorsEnabled = serverSettings.TraitorsEnabled;
|
||||
info.SubSelectionMode = serverSettings.SubSelectionMode;
|
||||
info.ModeSelectionMode = serverSettings.ModeSelectionMode;
|
||||
@@ -807,10 +791,9 @@ namespace Barotrauma
|
||||
|
||||
public void AddToRecentServers(ServerInfo info)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(info.IP))
|
||||
if (info.Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var ip } } && IPAddress.IsLoopback(ip))
|
||||
{
|
||||
//don't add localhost to recent servers
|
||||
if (IPAddress.TryParse(info.IP, out IPAddress ip) && IPAddress.IsLoopback(ip)) { return; }
|
||||
return;
|
||||
}
|
||||
|
||||
info.Recent = true;
|
||||
@@ -870,8 +853,7 @@ namespace Barotrauma
|
||||
|
||||
private void SortList(string sortBy, bool toggle)
|
||||
{
|
||||
GUIButton button = labelHolder.GetChildByUserData(sortBy) as GUIButton;
|
||||
if (button == null) { return; }
|
||||
if (!(labelHolder.GetChildByUserData(sortBy) is GUIButton button)) { return; }
|
||||
|
||||
sortedBy = sortBy;
|
||||
|
||||
@@ -985,7 +967,7 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.Disconnect();
|
||||
GameMain.Client.Quit();
|
||||
GameMain.Client = null;
|
||||
}
|
||||
|
||||
@@ -1060,14 +1042,13 @@ namespace Barotrauma
|
||||
(!filterIncompatible.Selected || !incompatible) &&
|
||||
(!filterFull.Selected || serverInfo.PlayerCount < serverInfo.MaxPlayers) &&
|
||||
(!filterEmpty.Selected || serverInfo.PlayerCount > 0) &&
|
||||
(!filterWhitelisted.Selected || serverInfo.UsingWhiteList == true) &&
|
||||
(!filterOffensive.Selected || !ForbiddenWordFilter.IsForbidden(serverInfo.ServerName)) &&
|
||||
karmaFilterPassed &&
|
||||
friendlyFireFilterPassed &&
|
||||
traitorsFilterPassed &&
|
||||
voipFilterPassed &&
|
||||
moddedFilterPassed &&
|
||||
((selectedTab == ServerListTab.All && (serverInfo.LobbyID != 0 || !string.IsNullOrWhiteSpace(serverInfo.Port))) ||
|
||||
((selectedTab == ServerListTab.All && (serverInfo.LobbyID != 0 || serverInfo.Endpoint != null)) ||
|
||||
(selectedTab == ServerListTab.Recent && serverInfo.Recent) ||
|
||||
(selectedTab == ServerListTab.Favorites && serverInfo.Favorite));
|
||||
}
|
||||
@@ -1105,7 +1086,7 @@ namespace Barotrauma
|
||||
serverList.UpdateScrollBarSize();
|
||||
}
|
||||
|
||||
private Queue<ServerInfo> pendingQueries = new Queue<ServerInfo>();
|
||||
private readonly Queue<ServerInfo> pendingQueries = new Queue<ServerInfo>();
|
||||
int activeQueries = 0;
|
||||
private void QueueInfoQuery(ServerInfo info)
|
||||
{
|
||||
@@ -1152,46 +1133,22 @@ namespace Barotrauma
|
||||
okButton.Enabled = false;
|
||||
okButton.OnClicked = (btn, userdata) =>
|
||||
{
|
||||
JoinServer(endpointBox.Text, "");
|
||||
if (!(Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint))) { return false; }
|
||||
JoinServer(endpoint, "");
|
||||
msgBox.Close();
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
var favoriteButton = msgBox.Buttons[1];
|
||||
favoriteButton.Enabled = false;
|
||||
favoriteButton.OnClicked = (button, userdata) =>
|
||||
{
|
||||
UInt64 steamId = SteamManager.SteamIDStringToUInt64(endpointBox.Text);
|
||||
string ip = ""; int port = 0;
|
||||
if (steamId == 0)
|
||||
{
|
||||
string hostIP = endpointBox.Text;
|
||||
if (!(Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint))) { return false; }
|
||||
|
||||
string[] address = hostIP.Split(':');
|
||||
if (address.Length == 1)
|
||||
{
|
||||
ip = hostIP;
|
||||
port = NetConfig.DefaultPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
ip = string.Join(":", address.Take(address.Length - 1));
|
||||
if (!int.TryParse(address[address.Length - 1], out port))
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid port: " + address[address.Length - 1] + "!");
|
||||
port = NetConfig.DefaultPort;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: add a better way to get the query port, right now we're just assuming that it'll always be the default
|
||||
ServerInfo serverInfo = new ServerInfo()
|
||||
{
|
||||
ServerName = "Server",
|
||||
OwnerID = steamId,
|
||||
IP = ip,
|
||||
Port = port.ToString(),
|
||||
QueryPort = NetConfig.DefaultQueryPort.ToString(),
|
||||
Endpoint = endpoint,
|
||||
GameVersion = GameMain.Version.ToString(),
|
||||
PlayStyle = null
|
||||
};
|
||||
@@ -1231,37 +1188,25 @@ namespace Barotrauma
|
||||
|
||||
private bool JoinFriend(GUIButton button, object userdata)
|
||||
{
|
||||
FriendInfo info = userdata as FriendInfo;
|
||||
if (!(userdata is FriendInfo { InServer: true } info)) { return false; }
|
||||
|
||||
if (info.InServer)
|
||||
{
|
||||
if (info.ConnectLobby != 0)
|
||||
{
|
||||
GameMain.Instance.ConnectLobby = info.ConnectLobby;
|
||||
GameMain.Instance.ConnectEndpoint = null;
|
||||
GameMain.Instance.ConnectName = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Instance.ConnectLobby = 0;
|
||||
GameMain.Instance.ConnectEndpoint = info.ConnectEndpoint;
|
||||
GameMain.Instance.ConnectName = info.ConnectName;
|
||||
}
|
||||
}
|
||||
GameMain.Instance.ConnectCommand = info.ConnectCommand;
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool OpenFriendPopup(GUIButton button, object userdata)
|
||||
{
|
||||
FriendInfo info = userdata as FriendInfo;
|
||||
if (!(userdata is FriendInfo { InServer: true } info)) { return false; }
|
||||
|
||||
if (info.InServer)
|
||||
if (info.InServer
|
||||
&& info.ConnectCommand is Some<ConnectCommand> { Value: { EndpointOrLobby: var endpointOrLobby } }
|
||||
&& endpointOrLobby.TryGet(out ConnectCommand.NameAndEndpoint nameAndEndpoint))
|
||||
{
|
||||
int framePadding = 5;
|
||||
const int framePadding = 5;
|
||||
|
||||
friendPopup = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas));
|
||||
|
||||
var serverNameText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), friendPopup.RectTransform, Anchor.CenterLeft), info.ConnectName ?? "[Unnamed]");
|
||||
var serverNameText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), friendPopup.RectTransform, Anchor.CenterLeft), nameAndEndpoint.ServerName ?? "[Unnamed]");
|
||||
serverNameText.RectTransform.AbsoluteOffset = new Point(framePadding, 0);
|
||||
|
||||
var joinButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), friendPopup.RectTransform, Anchor.CenterRight), TextManager.Get("ServerListJoin"))
|
||||
@@ -1349,7 +1294,7 @@ namespace Barotrauma
|
||||
for (int i = friendsList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var friend = friendsList[i];
|
||||
if (!friends.Any(g => g.Id == friend.SteamID && g.IsOnline))
|
||||
if (!friends.Any(g => g.Id == friend.SteamId && g.IsOnline))
|
||||
{
|
||||
friend.Sprite?.Remove();
|
||||
friendsList.RemoveAt(i);
|
||||
@@ -1360,12 +1305,12 @@ namespace Barotrauma
|
||||
{
|
||||
if (!friend.IsOnline) { continue; }
|
||||
|
||||
FriendInfo info = friendsList.Find(f => f.SteamID == friend.Id);
|
||||
FriendInfo info = friendsList.Find(f => f.SteamId == friend.Id);
|
||||
if (info == null)
|
||||
{
|
||||
info = new FriendInfo()
|
||||
{
|
||||
SteamID = friend.Id
|
||||
SteamId = friend.Id
|
||||
};
|
||||
friendsList.Insert(0, info);
|
||||
}
|
||||
@@ -1425,9 +1370,7 @@ namespace Barotrauma
|
||||
|
||||
info.Name = friend.Name;
|
||||
|
||||
info.ConnectName = null;
|
||||
info.ConnectEndpoint = null;
|
||||
info.ConnectLobby = 0;
|
||||
info.ConnectCommand = Option<ConnectCommand>.None();
|
||||
|
||||
info.PlayingThisGame = friend.IsPlayingThisGame;
|
||||
info.PlayingAnotherGame = friend.GameInfo.HasValue;
|
||||
@@ -1439,7 +1382,7 @@ namespace Barotrauma
|
||||
|
||||
try
|
||||
{
|
||||
ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand), out info.ConnectName, out info.ConnectEndpoint, out info.ConnectLobby);
|
||||
info.ConnectCommand = ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand));
|
||||
}
|
||||
catch (IndexOutOfRangeException e)
|
||||
{
|
||||
@@ -1448,9 +1391,7 @@ namespace Barotrauma
|
||||
#else
|
||||
DebugConsole.Log($"Failed to parse a Steam friend's connect command ({connectCommand})\n" + e.StackTrace.CleanupStackTrace());
|
||||
#endif
|
||||
info.ConnectName = null;
|
||||
info.ConnectEndpoint = null;
|
||||
info.ConnectLobby = 0;
|
||||
info.ConnectCommand = Option<ConnectCommand>.None();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1650,86 +1591,16 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private void UpdateServerList(string masterServerData)
|
||||
{
|
||||
serverList.ClearChildren();
|
||||
|
||||
if (masterServerData.Substring(0, 5).Equals("error", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
DebugConsole.ThrowError("Error while connecting to master server (" + masterServerData + ")!");
|
||||
return;
|
||||
}
|
||||
|
||||
string[] lines = masterServerData.Split('\n');
|
||||
List<ServerInfo> serverInfos = new List<ServerInfo>();
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string[] arguments = lines[i].Split('|');
|
||||
if (arguments.Length < 3) continue;
|
||||
|
||||
string ip = arguments[0];
|
||||
string port = arguments[1];
|
||||
string serverName = arguments[2];
|
||||
bool gameStarted = arguments.Length > 3 && arguments[3] == "1";
|
||||
string currPlayersStr = arguments.Length > 4 ? arguments[4] : "";
|
||||
string maxPlayersStr = arguments.Length > 5 ? arguments[5] : "";
|
||||
bool hasPassWord = arguments.Length > 6 && arguments[6] == "1";
|
||||
string gameVersion = arguments.Length > 7 ? arguments[7] : "";
|
||||
string contentPackageNames = arguments.Length > 8 ? arguments[8] : "";
|
||||
string contentPackageHashes = arguments.Length > 9 ? arguments[9] : "";
|
||||
|
||||
int.TryParse(currPlayersStr, out int playerCount);
|
||||
int.TryParse(maxPlayersStr, out int maxPlayers);
|
||||
|
||||
var serverInfo = new ServerInfo()
|
||||
{
|
||||
IP = ip,
|
||||
Port = port,
|
||||
ServerName = serverName,
|
||||
GameStarted = gameStarted,
|
||||
PlayerCount = playerCount,
|
||||
MaxPlayers = maxPlayers,
|
||||
HasPassword = hasPassWord,
|
||||
GameVersion = gameVersion,
|
||||
OwnerVerified = true
|
||||
};
|
||||
foreach (string contentPackageName in contentPackageNames.Split(','))
|
||||
{
|
||||
if (string.IsNullOrEmpty(contentPackageName)) continue;
|
||||
serverInfo.ContentPackageNames.Add(contentPackageName);
|
||||
}
|
||||
foreach (string contentPackageHash in contentPackageHashes.Split(','))
|
||||
{
|
||||
if (string.IsNullOrEmpty(contentPackageHash)) continue;
|
||||
serverInfo.ContentPackageHashes.Add(contentPackageHash);
|
||||
}
|
||||
|
||||
serverInfos.Add(serverInfo);
|
||||
}
|
||||
|
||||
serverList.Content.ClearChildren();
|
||||
if (serverInfos.Count() == 0)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), serverList.Content.RectTransform),
|
||||
TextManager.Get("NoServers"), textAlignment: Alignment.Center)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
return;
|
||||
}
|
||||
foreach (ServerInfo serverInfo in serverInfos)
|
||||
{
|
||||
AddToServerList(serverInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private GUIComponent FindFrameMatchingServerInfo(ServerInfo serverInfo)
|
||||
=> serverList.Content.FindChild(d =>
|
||||
d.UserData is ServerInfo info
|
||||
&& (info.LobbyID == 0 || info.LobbyID == serverInfo.LobbyID)
|
||||
&& info.OwnerVerified
|
||||
&& serverInfo.Endpoint == info.Endpoint);
|
||||
|
||||
private void AddToServerList(ServerInfo serverInfo)
|
||||
{
|
||||
var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) &&
|
||||
(info.LobbyID == serverInfo.LobbyID ||
|
||||
(info.LobbyID == 0 && info.OwnerID == serverInfo.OwnerID &&
|
||||
serverInfo.OwnerVerified)) &&
|
||||
(serverInfo.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port)));
|
||||
var serverFrame = FindFrameMatchingServerInfo(serverInfo);
|
||||
|
||||
if (serverFrame == null)
|
||||
{
|
||||
@@ -1763,8 +1634,10 @@ namespace Barotrauma
|
||||
|
||||
if (serverInfo.OwnerVerified)
|
||||
{
|
||||
var childrenToRemove = serverList.Content.FindChildren(c => (c.UserData is ServerInfo info) && info != serverInfo &&
|
||||
(serverInfo.OwnerID != 0 ? info.OwnerID == serverInfo.OwnerID : info.IP == serverInfo.IP)).ToList();
|
||||
var childrenToRemove = serverList.Content.FindChildren(c =>
|
||||
c.UserData is ServerInfo info
|
||||
&& !ReferenceEquals(info, serverInfo)
|
||||
&& serverInfo.Endpoint == info.Endpoint).ToList();
|
||||
foreach (var child in childrenToRemove)
|
||||
{
|
||||
serverList.Content.RemoveChild(child);
|
||||
@@ -1779,11 +1652,7 @@ namespace Barotrauma
|
||||
|
||||
private void UpdateServerInfo(ServerInfo serverInfo)
|
||||
{
|
||||
var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) &&
|
||||
(info.LobbyID == serverInfo.LobbyID ||
|
||||
(info.LobbyID == 0 && info.OwnerID == serverInfo.OwnerID &&
|
||||
serverInfo.OwnerVerified)) &&
|
||||
(serverInfo.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port)));
|
||||
var serverFrame = FindFrameMatchingServerInfo(serverInfo);
|
||||
if (serverFrame == null) return;
|
||||
|
||||
var serverContent = serverFrame.Children.First() as GUILayoutGroup;
|
||||
@@ -1806,11 +1675,10 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[2] * 1.1f, 1.0f), serverContent.RectTransform),
|
||||
#if !DEBUG
|
||||
serverInfo.ServerName,
|
||||
#else
|
||||
((serverInfo.OwnerID != 0 || serverInfo.LobbyID != 0) ? "[STEAMP2P] " : "[LIDGREN] ") + serverInfo.ServerName,
|
||||
#if DEBUG
|
||||
(serverInfo.Endpoint is SteamP2PEndpoint ? "[STEAMP2P] " : "[LIDGREN] ") +
|
||||
#endif
|
||||
serverInfo.ServerName,
|
||||
style: "GUIServerListTextBox");
|
||||
serverName.UserData = serverName.Text;
|
||||
serverName.RectTransform.SizeChanged += () =>
|
||||
@@ -1850,7 +1718,7 @@ namespace Barotrauma
|
||||
serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?";
|
||||
serverPingText.TextColor = GetPingTextColor(serverInfo.Ping);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(serverInfo.IP))
|
||||
else if (serverInfo.Endpoint is LidgrenEndpoint lidgrenEndpoint)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1866,7 +1734,7 @@ namespace Barotrauma
|
||||
CoroutineManager.StartCoroutine(EstimateLobbyPing(serverInfo, serverPingText), "EstimateLobbyPing");
|
||||
}
|
||||
|
||||
if (serverInfo.LobbyID == 0 && (string.IsNullOrWhiteSpace(serverInfo.IP) || string.IsNullOrWhiteSpace(serverInfo.Port)))
|
||||
if (serverInfo.LobbyID == 0)
|
||||
{
|
||||
LocalizedString toolTip = TextManager.Get("ServerOffline");
|
||||
serverContent.Children.ForEach(c => c.ToolTip = toolTip);
|
||||
@@ -1930,7 +1798,7 @@ namespace Barotrauma
|
||||
LocalizedString toolTip = "";
|
||||
for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++)
|
||||
{
|
||||
if (!ContentPackageManager.EnabledPackages.All.Any(contentPackage => contentPackage.Hash.StringRepresentation == serverInfo.ContentPackageHashes[i]))
|
||||
if (ContentPackageManager.EnabledPackages.All.None(contentPackage => contentPackage.Hash.StringRepresentation == serverInfo.ContentPackageHashes[i]))
|
||||
{
|
||||
if (toolTip != "") { toolTip += "\n"; }
|
||||
toolTip += TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", serverInfo.ContentPackageNames[i]);
|
||||
@@ -1995,7 +1863,7 @@ namespace Barotrauma
|
||||
masterServerResponded = true;
|
||||
}
|
||||
|
||||
private bool JoinServer(string endpoint, string serverName)
|
||||
private bool JoinServer(Endpoint endpoint, string serverName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ClientNameBox.Text))
|
||||
{
|
||||
@@ -2013,17 +1881,13 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerable<CoroutineStatus> ConnectToServer(string endpoint, string serverName)
|
||||
private IEnumerable<CoroutineStatus> ConnectToServer(Endpoint endpoint, string serverName)
|
||||
{
|
||||
string serverIP = null;
|
||||
UInt64 serverSteamID = SteamManager.SteamIDStringToUInt64(endpoint);
|
||||
if (serverSteamID == 0) { serverIP = endpoint; }
|
||||
|
||||
#if !DEBUG
|
||||
try
|
||||
{
|
||||
#endif
|
||||
GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()), serverIP, serverSteamID, serverName);
|
||||
GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()), endpoint, serverName, Option<int>.None());
|
||||
#if !DEBUG
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -2035,31 +1899,32 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText)
|
||||
private void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText)
|
||||
{
|
||||
if (CoroutineManager.IsCoroutineRunning("ConnectToServer")) { return; }
|
||||
|
||||
if (!(serverInfo.Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var address } })) { return; }
|
||||
|
||||
lock (activePings)
|
||||
{
|
||||
if (activePings.ContainsKey(serverInfo.IP)) { return; }
|
||||
activePings.Add(serverInfo.IP, activePings.Any() ? activePings.Values.Max()+1 : 0);
|
||||
if (activePings.ContainsKey(address)) { return; }
|
||||
activePings.Add(address, activePings.Any() ? activePings.Values.Max()+1 : 0);
|
||||
}
|
||||
|
||||
serverInfo.PingChecked = false;
|
||||
serverInfo.Ping = -1;
|
||||
|
||||
TaskPool.Add($"PingServerAsync ({serverInfo?.IP ?? "NULL"})", PingServerAsync(serverInfo.IP, 1000),
|
||||
TaskPool.Add($"PingServerAsync ({address})", PingServerAsync(address, 1000),
|
||||
new Tuple<ServerInfo, GUITextBlock>(serverInfo, serverPingText),
|
||||
(rtt, obj) =>
|
||||
{
|
||||
var info = obj.Item1;
|
||||
var text = obj.Item2;
|
||||
rtt.TryGetResult(out info.Ping); info.PingChecked = true;
|
||||
var (info, text) = obj;
|
||||
if (!rtt.TryGetResult(out info.Ping)) { info.Ping = -1; }
|
||||
info.PingChecked = true;
|
||||
text.TextColor = GetPingTextColor(info.Ping);
|
||||
text.Text = info.Ping > -1 ? info.Ping.ToString() : "?";
|
||||
lock (activePings)
|
||||
{
|
||||
activePings.Remove(info.IP);
|
||||
activePings.Remove(address);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -2070,7 +1935,7 @@ namespace Barotrauma
|
||||
return ToolBox.GradientLerp(ping / 200.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red);
|
||||
}
|
||||
|
||||
public async Task<int> PingServerAsync(string ip, int timeOut)
|
||||
public async Task<int> PingServerAsync(IPAddress ipAddress, int timeOut)
|
||||
{
|
||||
await Task.Yield();
|
||||
bool shouldGo = false;
|
||||
@@ -2078,29 +1943,22 @@ namespace Barotrauma
|
||||
{
|
||||
lock (activePings)
|
||||
{
|
||||
shouldGo = activePings.Count(kvp => kvp.Value < activePings[ip]) < 25;
|
||||
shouldGo = activePings.Count(kvp => kvp.Value < activePings[ipAddress]) < 25;
|
||||
}
|
||||
await Task.Delay(25);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ip))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
long rtt = -1;
|
||||
IPAddress address = null;
|
||||
IPAddress.TryParse(ip, out address);
|
||||
if (address != null)
|
||||
if (ipAddress != null)
|
||||
{
|
||||
//don't attempt to ping if the address is IPv6 and it's not supported
|
||||
if (address.AddressFamily != AddressFamily.InterNetworkV6 || Socket.OSSupportsIPv6)
|
||||
if (ipAddress.AddressFamily != AddressFamily.InterNetworkV6 || Socket.OSSupportsIPv6)
|
||||
{
|
||||
Ping ping = new Ping();
|
||||
byte[] buffer = new byte[32];
|
||||
try
|
||||
{
|
||||
PingReply pingReply = ping.Send(address, timeOut, buffer, new PingOptions(128, true));
|
||||
PingReply pingReply = ping.Send(ipAddress, timeOut, buffer, new PingOptions(128, true));
|
||||
|
||||
if (pingReply != null)
|
||||
{
|
||||
@@ -2117,9 +1975,9 @@ namespace Barotrauma
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ip, GameAnalyticsManager.ErrorSeverity.Warning, "Failed to ping a server - " + (ex?.InnerException?.Message ?? ex.Message));
|
||||
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ipAddress, GameAnalyticsManager.ErrorSeverity.Warning, "Failed to ping a server - " + (ex?.InnerException?.Message ?? ex.Message));
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage("Failed to ping a server (" + ip + ") - " + (ex?.InnerException?.Message ?? ex.Message), Color.Red);
|
||||
DebugConsole.NewMessage("Failed to ping a server (" + ipAddress + ") - " + (ex?.InnerException?.Message ?? ex.Message), Color.Red);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace Barotrauma
|
||||
private GUIDropDown linkedSubBox;
|
||||
|
||||
private static GUIComponent autoSaveLabel;
|
||||
private static int maxAutoSaves => GameSettings.CurrentConfig.MaxAutoSaves;
|
||||
private static int MaxAutoSaves => GameSettings.CurrentConfig.MaxAutoSaves;
|
||||
|
||||
public static readonly object ItemAddMutex = new object(), ItemRemoveMutex = new object();
|
||||
|
||||
@@ -228,6 +228,8 @@ namespace Barotrauma
|
||||
|
||||
private static bool isAutoSaving;
|
||||
|
||||
private KeyOrMouse toggleEntityListBind;
|
||||
|
||||
public override Camera Cam => cam;
|
||||
|
||||
public static XDocument AutoSaveInfo;
|
||||
@@ -926,7 +928,6 @@ namespace Barotrauma
|
||||
toggleEntityMenuButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.08f), EntityMenu.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) { MinSize = new Point(0, 15) },
|
||||
style: "UIToggleButtonVertical")
|
||||
{
|
||||
ToolTip = RichString.Rich($"{TextManager.Get("EntityMenuToggleTooltip")}\n‖color:125,125,125‖{GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].Name}‖color:end‖"),
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
entityMenuOpen = !entityMenuOpen;
|
||||
@@ -1645,7 +1646,7 @@ namespace Barotrauma
|
||||
if (AutoSaveInfo?.Root == null || MainSub?.Info == null) { return; }
|
||||
|
||||
int saveCount = AutoSaveInfo.Root.Elements().Count();
|
||||
while (AutoSaveInfo.Root.Elements().Count() > maxAutoSaves)
|
||||
while (AutoSaveInfo.Root.Elements().Count() > MaxAutoSaves)
|
||||
{
|
||||
XElement min = AutoSaveInfo.Root.Elements().OrderBy(element => element.GetAttributeUInt64("time", 0)).FirstOrDefault();
|
||||
#warning TODO: revise
|
||||
@@ -5192,6 +5193,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (toggleEntityListBind != GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory])
|
||||
{
|
||||
toggleEntityMenuButton.ToolTip = RichString.Rich($"{TextManager.Get("EntityMenuToggleTooltip")}\n‖color:125,125,125‖{GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].Name}‖color:end‖");
|
||||
toggleEntityListBind = GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory];
|
||||
}
|
||||
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].IsHit() && mode == Mode.Default)
|
||||
{
|
||||
toggleEntityMenuButton.OnClicked?.Invoke(toggleEntityMenuButton, toggleEntityMenuButton.UserData);
|
||||
@@ -5528,8 +5534,10 @@ namespace Barotrauma
|
||||
MouseDragStart = Vector2.Zero;
|
||||
}
|
||||
|
||||
if (!saveAssemblyFrame.Rect.Contains(PlayerInput.MousePosition) && !snapToGridFrame.Rect.Contains(PlayerInput.MousePosition) &&
|
||||
dummyCharacter?.SelectedItem == null && !WiringMode && GUI.MouseOn == null)
|
||||
if (!saveAssemblyFrame.Rect.Contains(PlayerInput.MousePosition)
|
||||
&& !snapToGridFrame.Rect.Contains(PlayerInput.MousePosition)
|
||||
&& dummyCharacter?.SelectedItem == null && !WiringMode
|
||||
&& (GUI.MouseOn == null || MapEntity.SelectedAny || MapEntity.SelectionPos != Vector2.Zero))
|
||||
{
|
||||
if (layerList is { Visible: true } && GUI.KeyboardDispatcher.Subscriber == layerList)
|
||||
{
|
||||
@@ -5556,7 +5564,7 @@ namespace Barotrauma
|
||||
{
|
||||
bool shouldCloseHud = dummyCharacter?.SelectedItem != null && HUD.CloseHUD(dummyCharacter.SelectedItem.Rect) && DraggedItemPrefab == null;
|
||||
|
||||
if (MapEntityPrefab.Selected != null && GUI.MouseOn == null)
|
||||
if (MapEntityPrefab.Selected != null)
|
||||
{
|
||||
MapEntityPrefab.Selected.UpdatePlacing(cam);
|
||||
}
|
||||
@@ -5708,7 +5716,7 @@ namespace Barotrauma
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, transformMatrix: cam.Transform);
|
||||
Submarine.DrawFront(spriteBatch, editing: true, e => !IsSubcategoryHidden(e.Prefab?.Subcategory));
|
||||
if (!WiringMode && !IsMouseOnEditorGUI())
|
||||
if (!WiringMode)
|
||||
{
|
||||
MapEntityPrefab.Selected?.DrawPlacing(spriteBatch, cam);
|
||||
MapEntity.DrawSelecting(spriteBatch, cam);
|
||||
|
||||
@@ -382,10 +382,9 @@ namespace Barotrauma
|
||||
LocalizedString toolTip = TextManager.Get($"sp.{propertyTag}.description");
|
||||
if (toolTip.IsNullOrEmpty())
|
||||
{
|
||||
toolTip = TextManager.Get($"{propertyTag}.description", $"sp.{fallbackTag}.description");
|
||||
toolTip = TextManager.Get($"{propertyTag}.description", $"sp.{fallbackTag}.description");
|
||||
}
|
||||
|
||||
if (toolTip == null)
|
||||
if (toolTip.IsNullOrEmpty())
|
||||
{
|
||||
toolTip = property.GetAttribute<Serialize>().Description;
|
||||
}
|
||||
@@ -700,9 +699,12 @@ namespace Barotrauma
|
||||
List<MapEntity> prevSelected = MapEntity.SelectedList.ToList();
|
||||
//reselect the entities that were selected during editing
|
||||
//otherwise multi-editing won't work when we deselect the entities with unapplied changes in the textbox
|
||||
foreach (var entity in editedEntities)
|
||||
{
|
||||
MapEntity.SelectedList.Add(entity);
|
||||
if (editedEntities.Count > 1)
|
||||
{
|
||||
foreach (var entity in editedEntities)
|
||||
{
|
||||
MapEntity.SelectedList.Add(entity);
|
||||
}
|
||||
}
|
||||
if (SetPropertyValue(property, entity, textBox.Text))
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Sounds
|
||||
{
|
||||
public class OggSound : Sound
|
||||
class OggSound : Sound
|
||||
{
|
||||
private VorbisReader reader;
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (!muffleFilters.TryGetValue(sampleRate, out BiQuad filter))
|
||||
{
|
||||
filter = new LowpassFilter(sampleRate, 800);
|
||||
filter = new LowpassFilter(sampleRate, 1600);
|
||||
muffleFilters.Add(sampleRate, filter);
|
||||
}
|
||||
filter.Process(buffer);
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Sounds
|
||||
{
|
||||
public abstract class Sound : IDisposable
|
||||
abstract class Sound : IDisposable
|
||||
{
|
||||
protected bool disposed;
|
||||
public bool Disposed
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Text;
|
||||
|
||||
namespace Barotrauma.Sounds
|
||||
{
|
||||
public class SoundBuffers : IDisposable
|
||||
class SoundBuffers : IDisposable
|
||||
{
|
||||
private static readonly HashSet<uint> bufferPool = new HashSet<uint>();
|
||||
#if OSX
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Diagnostics;
|
||||
|
||||
namespace Barotrauma.Sounds
|
||||
{
|
||||
public class SoundSourcePool : IDisposable
|
||||
class SoundSourcePool : IDisposable
|
||||
{
|
||||
public uint[] ALSources
|
||||
{
|
||||
@@ -80,7 +80,7 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
|
||||
public class SoundChannel : IDisposable
|
||||
class SoundChannel : IDisposable
|
||||
{
|
||||
private const int STREAM_BUFFER_SIZE = 8820;
|
||||
private short[] streamShortBuffer;
|
||||
|
||||
@@ -9,7 +9,7 @@ using Barotrauma.IO;
|
||||
|
||||
namespace Barotrauma.Sounds
|
||||
{
|
||||
public class SoundManager : IDisposable
|
||||
class SoundManager : IDisposable
|
||||
{
|
||||
public const int SOURCE_COUNT = 32;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ using Barotrauma.Media;
|
||||
|
||||
namespace Barotrauma.Sounds
|
||||
{
|
||||
public class VideoSound : Sound
|
||||
class VideoSound : Sound
|
||||
{
|
||||
private readonly object mutex;
|
||||
private Queue<short[]> sampleQueue;
|
||||
|
||||
@@ -8,7 +8,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma.Sounds
|
||||
{
|
||||
public class VoipSound : Sound
|
||||
class VoipSound : Sound
|
||||
{
|
||||
public override SoundManager.SourcePoolIndex SourcePoolIndex
|
||||
{
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Particles;
|
||||
using Barotrauma.Sounds;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Items.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Barotrauma.Steam
|
||||
});
|
||||
}
|
||||
|
||||
internal static void SubscribeToServerMods(IEnumerable<UInt64> missingIds, string rejoinEndpoint, ulong rejoinLobby, string rejoinServerName)
|
||||
internal static void SubscribeToServerMods(IEnumerable<UInt64> missingIds, ConnectCommand rejoinCommand)
|
||||
{
|
||||
CloseAllMessageBoxes();
|
||||
GUIMessageBox msgBox = new GUIMessageBox(headerText: "", text: TextManager.Get("PreparingWorkshopDownloads"),
|
||||
@@ -59,9 +59,7 @@ namespace Barotrauma.Steam
|
||||
InitiateDownloads(items, onComplete: () =>
|
||||
{
|
||||
ContentPackageManager.UpdateContentPackageList();
|
||||
GameMain.Instance.ConnectEndpoint = rejoinEndpoint;
|
||||
GameMain.Instance.ConnectLobby = rejoinLobby;
|
||||
GameMain.Instance.ConnectName = rejoinServerName;
|
||||
GameMain.Instance.ConnectCommand = Option<ConnectCommand>.Some(rejoinCommand);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -92,7 +92,9 @@ namespace Barotrauma.Steam
|
||||
//currentLobby?.SetData("hostipaddress", lobbyIP);
|
||||
string pingLocation = Steamworks.SteamNetworkingUtils.LocalPingLocation?.ToString();
|
||||
currentLobby?.SetData("pinglocation", pingLocation ?? "");
|
||||
currentLobby?.SetData("lobbyowner", SteamIDUInt64ToString(GetSteamID()));
|
||||
currentLobby?.SetData("lobbyowner", GetSteamId().TryUnwrap(out var steamId)
|
||||
? steamId.StringRepresentation
|
||||
: throw new InvalidOperationException("Steamworks not initialized"));
|
||||
currentLobby?.SetData("haspassword", serverSettings.HasPassword.ToString());
|
||||
|
||||
currentLobby?.SetData("message", serverSettings.ServerMessageText);
|
||||
@@ -101,7 +103,6 @@ namespace Barotrauma.Steam
|
||||
currentLobby?.SetData("contentpackage", string.Join(",", contentPackages.Select(cp => cp.Name)));
|
||||
currentLobby?.SetData("contentpackagehash", string.Join(",", contentPackages.Select(cp => cp.Hash.StringRepresentation)));
|
||||
currentLobby?.SetData("contentpackageid", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopId)));
|
||||
currentLobby?.SetData("usingwhitelist", (serverSettings.Whitelist != null && serverSettings.Whitelist.Enabled).ToString());
|
||||
currentLobby?.SetData("modeselectionmode", serverSettings.ModeSelectionMode.ToString());
|
||||
currentLobby?.SetData("subselectionmode", serverSettings.SubSelectionMode.ToString());
|
||||
currentLobby?.SetData("voicechatenabled", serverSettings.VoiceChatEnabled.ToString());
|
||||
@@ -144,9 +145,10 @@ namespace Barotrauma.Steam
|
||||
lobbyID = (currentLobby?.Id).Value;
|
||||
if (joinServer)
|
||||
{
|
||||
GameMain.Instance.ConnectLobby = 0;
|
||||
GameMain.Instance.ConnectName = currentLobby?.GetData("servername");
|
||||
GameMain.Instance.ConnectEndpoint = SteamIDUInt64ToString((currentLobby?.Owner.Id).Value);
|
||||
GameMain.Instance.ConnectCommand = Option<ConnectCommand>.Some(
|
||||
new ConnectCommand(
|
||||
currentLobby?.GetData("servername") ?? "Server",
|
||||
new SteamP2PEndpoint(new SteamId(currentLobby?.Owner.Id ?? 0))));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -189,14 +191,16 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
if (string.IsNullOrEmpty(lobby.GetData("name"))) { continue; }
|
||||
|
||||
ServerInfo serverInfo = new ServerInfo();
|
||||
serverInfo.ServerName = lobby.GetData("name");
|
||||
serverInfo.OwnerID = SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
||||
serverInfo.LobbyID = lobby.Id;
|
||||
ServerInfo serverInfo = new ServerInfo
|
||||
{
|
||||
ServerName = lobby.GetData("name"),
|
||||
Endpoint = new SteamP2PEndpoint(SteamId.Parse(lobby.GetData("lobbyowner")).Fallback(default(SteamId))),
|
||||
LobbyID = lobby.Id,
|
||||
RespondedToSteamQuery = true
|
||||
};
|
||||
bool.TryParse(lobby.GetData("haspassword"), out serverInfo.HasPassword);
|
||||
serverInfo.PlayerCount = int.TryParse(lobby.GetData("playercount"), out int playerCount) ? playerCount : 0;
|
||||
serverInfo.MaxPlayers = int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers) ? maxPlayers : 1;
|
||||
serverInfo.RespondedToSteamQuery = true;
|
||||
|
||||
AssignLobbyDataToServerInfo(lobby, serverInfo);
|
||||
|
||||
@@ -215,8 +219,7 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
ServerName = info.Name,
|
||||
HasPassword = info.Passworded,
|
||||
IP = info.Address.ToString(),
|
||||
Port = info.ConnectionPort.ToString(),
|
||||
Endpoint = new LidgrenEndpoint(info.Address, info.ConnectionPort),
|
||||
PlayerCount = info.Players,
|
||||
MaxPlayers = info.MaxPlayers,
|
||||
RespondedToSteamQuery = responsive
|
||||
@@ -316,7 +319,6 @@ namespace Barotrauma.Steam
|
||||
serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls));
|
||||
}
|
||||
|
||||
serverInfo.UsingWhiteList = getLobbyBool("usingwhitelist");
|
||||
if (Enum.TryParse(lobby.GetData("modeselectionmode"), out SelectionMode selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; }
|
||||
if (Enum.TryParse(lobby.GetData("subselectionmode"), out selectionMode)) { serverInfo.SubSelectionMode = selectionMode; }
|
||||
|
||||
@@ -365,7 +367,7 @@ namespace Barotrauma.Steam
|
||||
|
||||
if (rules.ContainsKey("playercount"))
|
||||
{
|
||||
if (int.TryParse(rules["playercount"], out int playerCount)) serverInfo.PlayerCount = playerCount;
|
||||
if (int.TryParse(rules["playercount"], out int playerCount)) { serverInfo.PlayerCount = playerCount; }
|
||||
}
|
||||
|
||||
serverInfo.ContentPackageNames.Clear();
|
||||
@@ -383,7 +385,6 @@ namespace Barotrauma.Steam
|
||||
serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls));
|
||||
}
|
||||
|
||||
if (rules.ContainsKey("usingwhitelist")) { serverInfo.UsingWhiteList = rules["usingwhitelist"] == "True"; }
|
||||
if (rules.ContainsKey("modeselectionmode"))
|
||||
{
|
||||
if (Enum.TryParse(rules["modeselectionmode"], out SelectionMode selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; }
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Barotrauma.Steam
|
||||
if (IsInitialized)
|
||||
{
|
||||
DebugConsole.NewMessage(
|
||||
$"Logged in as {GetUsername()} (SteamID {SteamIDUInt64ToString(GetSteamID())})");
|
||||
$"Logged in as {GetUsername()} (SteamID {(GetSteamId().TryUnwrap(out var steamId) ? steamId.ToString() : "[NULL]")})");
|
||||
|
||||
popularTags.Clear();
|
||||
int i = 0;
|
||||
@@ -129,7 +129,7 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
|
||||
|
||||
public static bool OverlayCustomURL(string url)
|
||||
public static bool OverlayCustomUrl(string url)
|
||||
{
|
||||
if (!IsInitialized || !Steamworks.SteamClient.IsValid)
|
||||
{
|
||||
@@ -139,5 +139,10 @@ namespace Barotrauma.Steam
|
||||
Steamworks.SteamFriends.OpenWebOverlay(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void OverlayProfile(SteamId steamId)
|
||||
{
|
||||
OverlayCustomUrl($"https://steamcommunity.com/profiles/{steamId.Value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
SteamManager.OverlayCustomURL(workshopItem.Url);
|
||||
SteamManager.OverlayCustomUrl(workshopItem.Url);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -234,7 +234,7 @@ namespace Barotrauma.Steam
|
||||
|
||||
int indexOfUserDataInPublishedItemsArray(object userData)
|
||||
=> publishedItems.IndexOf(t
|
||||
=> t.WorkshopItem.Id == ((Steamworks.Ugc.Item)(userData as ItemOrPackage)).Id);
|
||||
=> t.WorkshopItem.Id == ((Steamworks.Ugc.Item)(userData as ItemOrPackage)!).Id);
|
||||
|
||||
//Take the existing GUI items that are in the list and sort to match the order of publishedItems
|
||||
var publishedGuiComponents = selfModsList.Content.Children.OrderBy(c => indexOfUserDataInPublishedItemsArray(c.UserData)).ToArray();
|
||||
@@ -582,7 +582,7 @@ namespace Barotrauma.Steam
|
||||
SelectedTextColor = GUIStyle.TextColorNormal,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
SteamManager.OverlayCustomURL(
|
||||
SteamManager.OverlayCustomUrl(
|
||||
$"https://steamcommunity.com/profiles/{author.Id}/myworkshopfiles/?appid={SteamManager.AppID}");
|
||||
return false;
|
||||
}
|
||||
@@ -639,9 +639,10 @@ namespace Barotrauma.Steam
|
||||
new RectTransform(Vector2.Zero, reinstallButton.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
reinstallButton.Visible = workshopItem.IsSubscribed || workshopItem.Owner.Id == SteamManager.GetSteamID();
|
||||
reinstallButton.Enabled = !workshopItem.IsDownloading && !workshopItem.IsDownloadPending &&
|
||||
!SteamManager.Workshop.IsInstalling(workshopItem);
|
||||
reinstallButton.Visible = workshopItem.IsSubscribed
|
||||
|| workshopItem.Owner.Id == SteamManager.GetSteamId().Select(steamId => steamId.Value).Fallback(0);
|
||||
reinstallButton.Enabled = !workshopItem.IsDownloading && !workshopItem.IsDownloadPending
|
||||
&& !SteamManager.Workshop.IsInstalling(workshopItem);
|
||||
|
||||
reinstallSprite.Color = reinstallButton.Enabled
|
||||
? reinstallSprite.Style.Color
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
SteamManager.OverlayCustomURL($"https://steamcommunity.com/app/{SteamManager.AppID}/workshop/");
|
||||
SteamManager.OverlayCustomUrl($"https://steamcommunity.com/app/{SteamManager.AppID}/workshop/");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -546,7 +546,7 @@ namespace Barotrauma.Steam
|
||||
|
||||
if (result.Value.NeedsWorkshopAgreement)
|
||||
{
|
||||
SteamManager.OverlayCustomURL(resultItem.Url);
|
||||
SteamManager.OverlayCustomUrl(resultItem.Url);
|
||||
}
|
||||
new GUIMessageBox(string.Empty, TextManager.GetWithVariable("workshopitempublished", "[itemname]", localPackage.Name));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#nullable enable
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
readonly struct ConnectCommand
|
||||
{
|
||||
public readonly struct NameAndEndpoint
|
||||
{
|
||||
public readonly string ServerName;
|
||||
public readonly Endpoint Endpoint;
|
||||
|
||||
public NameAndEndpoint(string serverName, Endpoint endpoint)
|
||||
{
|
||||
ServerName = serverName;
|
||||
Endpoint = endpoint;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly Either<NameAndEndpoint, ulong> EndpointOrLobby;
|
||||
|
||||
public ConnectCommand(string serverName, Endpoint endpoint)
|
||||
{
|
||||
EndpointOrLobby = new NameAndEndpoint(serverName, endpoint);
|
||||
}
|
||||
|
||||
public ConnectCommand(ulong lobbyId)
|
||||
{
|
||||
EndpointOrLobby = lobbyId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
static class RichTextDataExtensions
|
||||
{
|
||||
public static Client ExtractClient(this RichTextData data)
|
||||
{
|
||||
bool isInt = UInt64.TryParse(data.Metadata, out ulong uintId);
|
||||
Option<AccountId> accountId = AccountId.Parse(data.Metadata);
|
||||
Client client = GameMain.Client.ConnectedClients.Find(c => accountId.IsSome() && accountId == c.AccountId)
|
||||
?? GameMain.Client.ConnectedClients.Find(c => isInt && c.SessionId == uintId)
|
||||
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => accountId.IsSome() && accountId == c.AccountId)
|
||||
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => isInt && c.SessionId == uintId);
|
||||
return client;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class SpriteRecorder : ISpriteBatch, IDisposable
|
||||
class SpriteRecorder : ISpriteBatch, IDisposable
|
||||
{
|
||||
private struct Command
|
||||
{
|
||||
|
||||
@@ -4,11 +4,12 @@ using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Barotrauma.Networking;
|
||||
using Color = Microsoft.Xna.Framework.Color;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public static partial class ToolBox
|
||||
static partial class ToolBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if point is inside of a polygon
|
||||
@@ -450,21 +451,26 @@ namespace Barotrauma
|
||||
public static string WrapText(string text, float lineLength, ScalableFont font, float textScale = 1.0f)
|
||||
=> font.WrapText(text, lineLength / textScale);
|
||||
|
||||
public static void ParseConnectCommand(string[] args, out string name, out string endpoint, out UInt64 lobbyId)
|
||||
public static Option<ConnectCommand> ParseConnectCommand(string[] args)
|
||||
{
|
||||
name = null; endpoint = null; lobbyId = 0;
|
||||
if (args == null || args.Length < 2) { return; }
|
||||
if (args == null || args.Length < 2) { return Option<ConnectCommand>.None(); }
|
||||
|
||||
if (args[0].Equals("-connect", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (args.Length < 3) { return; }
|
||||
name = args[1];
|
||||
endpoint = args[2];
|
||||
if (args.Length < 3) { return Option<ConnectCommand>.None(); }
|
||||
if (!(Endpoint.Parse(args[2]).TryUnwrap(out var endpoint))) { return Option<ConnectCommand>.None(); }
|
||||
return Option<ConnectCommand>.Some(
|
||||
new ConnectCommand(
|
||||
serverName: args[1],
|
||||
endpoint: endpoint));
|
||||
}
|
||||
else if (args[0].Equals("+connect_lobby", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
UInt64.TryParse(args[1], out lobbyId);
|
||||
return UInt64.TryParse(args[1], out var lobbyId)
|
||||
? Option<ConnectCommand>.Some(new ConnectCommand(lobbyId))
|
||||
: Option<ConnectCommand>.None();
|
||||
}
|
||||
return Option<ConnectCommand>.None();
|
||||
}
|
||||
|
||||
public static bool VersionNewerIgnoreRevision(Version a, Version b)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.19.0.0</Version>
|
||||
<Version>0.19.1.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.19.0.0</Version>
|
||||
<Version>0.19.1.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.19.0.0</Version>
|
||||
<Version>0.19.1.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.19.0.0</Version>
|
||||
<Version>0.19.1.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.19.0.0</Version>
|
||||
<Version>0.19.1.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Barotrauma
|
||||
{
|
||||
partial class Character
|
||||
{
|
||||
public string OwnerClientEndPoint;
|
||||
public Endpoint OwnerClientEndpoint;
|
||||
public string OwnerClientName;
|
||||
public bool ClientDisconnected;
|
||||
public float KillDisconnectedTimer;
|
||||
@@ -423,7 +423,7 @@ namespace Barotrauma
|
||||
case ControlEventData controlEventData:
|
||||
Client owner = controlEventData.Owner;
|
||||
msg.Write(owner == c && owner.Character == this);
|
||||
msg.Write(owner != null && owner.Character == this && GameMain.Server.ConnectedClients.Contains(owner) ? owner.ID : (byte)0);
|
||||
msg.Write(owner != null && owner.Character == this && GameMain.Server.ConnectedClients.Contains(owner) ? owner.SessionId : (byte)0);
|
||||
break;
|
||||
case CharacterStatusEventData statusEventData:
|
||||
WriteStatus(msg, statusEventData.ForceAfflictionData);
|
||||
@@ -632,6 +632,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
msg.Write(Enabled);
|
||||
msg.Write(DisabledByEvent);
|
||||
|
||||
//character with no characterinfo (e.g. some monster)
|
||||
if (Info == null)
|
||||
@@ -644,7 +645,7 @@ namespace Barotrauma
|
||||
if (ownerClient != null)
|
||||
{
|
||||
msg.Write(true);
|
||||
msg.Write(ownerClient.ID);
|
||||
msg.Write(ownerClient.SessionId);
|
||||
}
|
||||
else if (GameMain.Server.Character == this)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Barotrauma.Steam;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -299,10 +300,16 @@ namespace Barotrauma
|
||||
Client client = GameMain.Server.ConnectedClients.Find(c => Homoglyphs.Compare(c.Name, arg));
|
||||
if (int.TryParse(arg, out int id))
|
||||
{
|
||||
client ??= GameMain.Server.ConnectedClients.Find(c => c.ID == id);
|
||||
client ??= GameMain.Server.ConnectedClients.Find(c => c.SessionId == id);
|
||||
}
|
||||
if (Endpoint.Parse(arg).TryUnwrap(out var endpoint))
|
||||
{
|
||||
client ??= GameMain.Server.ConnectedClients.Find(c => c.EndpointMatches(endpoint));
|
||||
}
|
||||
if (AccountId.Parse(arg).TryUnwrap(out var argAccountId))
|
||||
{
|
||||
client ??= GameMain.Server.ConnectedClients.Find(c => c.AccountId.ValueEquals(argAccountId));
|
||||
}
|
||||
client ??= GameMain.Server.ConnectedClients.Find(c => c.EndpointMatches(arg));
|
||||
client ??= GameMain.Server.ConnectedClients.Find(c => c.SteamID == Steam.SteamManager.SteamIDStringToUInt64(arg));
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -872,7 +879,7 @@ namespace Barotrauma
|
||||
NewMessage("***************", Color.Cyan);
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
NewMessage("- " + c.ID.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Karma, Color.Cyan);
|
||||
NewMessage("- " + c.SessionId.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Karma, Color.Cyan);
|
||||
}
|
||||
NewMessage("***************", Color.Cyan);
|
||||
});
|
||||
@@ -881,7 +888,7 @@ namespace Barotrauma
|
||||
GameMain.Server.SendConsoleMessage("***************", client);
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
GameMain.Server.SendConsoleMessage("- " + c.ID.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Karma, client);
|
||||
GameMain.Server.SendConsoleMessage("- " + c.SessionId.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Karma, client);
|
||||
}
|
||||
GameMain.Server.SendConsoleMessage("***************", client);
|
||||
});
|
||||
@@ -904,10 +911,12 @@ namespace Barotrauma
|
||||
client);
|
||||
});
|
||||
|
||||
AssignOnExecute("banendpoint", (string[] args) =>
|
||||
AssignOnExecute("banaddress", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null || args.Length == 0) return;
|
||||
|
||||
if (!(Endpoint.Parse(args[0]).TryUnwrap(out var endpoint))) { return; }
|
||||
|
||||
ShowQuestionPrompt("Reason for banning the endpoint \"" + args[0] + "\"? (c to cancel)", (reason) =>
|
||||
{
|
||||
if (reason == "c" || reason == "C") { return; }
|
||||
@@ -925,16 +934,16 @@ namespace Barotrauma
|
||||
banDuration = parsedBanDuration;
|
||||
}
|
||||
|
||||
var clients = GameMain.Server.ConnectedClients.FindAll(c => c.EndpointMatches(args[0]));
|
||||
var clients = GameMain.Server.ConnectedClients.Where(c => c.EndpointMatches(endpoint)).ToList();
|
||||
if (clients.Count == 0)
|
||||
{
|
||||
GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", args[0], reason, banDuration);
|
||||
GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", endpoint, reason, banDuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Client cl in clients)
|
||||
{
|
||||
GameMain.Server.BanClient(cl, reason, false, banDuration);
|
||||
GameMain.Server.BanClient(cl, reason, banDuration);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1036,7 +1045,8 @@ namespace Barotrauma
|
||||
NewMessage("***************", Color.Cyan);
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
NewMessage("- " + c.ID.ToString() + ": " + c.Name + (c.Character != null ? " playing " + c.Character.LogName : "") + ", " + c.Connection.EndPointString + $", ping {c.Ping} ms", Color.Cyan);
|
||||
NewMessage(
|
||||
$"- {c.SessionId}: {c.Name}{(c.Character != null ? " playing " + c.Character.LogName : "")}, {c.Connection.Endpoint.StringRepresentation}, {c.Connection.AccountInfo.AccountId}, ping {c.Ping} ms", Color.Cyan);
|
||||
}
|
||||
NewMessage("***************", Color.Cyan);
|
||||
}));
|
||||
@@ -1045,7 +1055,7 @@ namespace Barotrauma
|
||||
GameMain.Server.SendConsoleMessage("***************", client, Color.Cyan);
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
GameMain.Server.SendConsoleMessage("- " + c.ID.ToString() + ": " + c.Name + ", " + c.Connection.EndPointString + $", ping {c.Ping} ms", client, Color.Cyan);
|
||||
GameMain.Server.SendConsoleMessage("- " + c.SessionId.ToString() + ": " + c.Name + ", " + c.Connection.Endpoint.StringRepresentation + $", ping {c.Ping} ms", client, Color.Cyan);
|
||||
}
|
||||
GameMain.Server.SendConsoleMessage("***************", client, Color.Cyan);
|
||||
});
|
||||
@@ -1496,11 +1506,12 @@ namespace Barotrauma
|
||||
);
|
||||
|
||||
AssignOnClientRequestExecute(
|
||||
"banendpoint|banip",
|
||||
"banaddress|banip",
|
||||
(Client client, Vector2 cursorPos, string[] args) =>
|
||||
{
|
||||
if (args.Length < 1) return;
|
||||
var clients = GameMain.Server.ConnectedClients.FindAll(c => c.EndpointMatches(args[0]));
|
||||
if (args.Length < 1) { return; }
|
||||
if (!(Endpoint.Parse(args[0]).TryUnwrap(out var endpoint))) { return; }
|
||||
var clients = GameMain.Server.ConnectedClients.Where(c => c.EndpointMatches(endpoint)).ToList();
|
||||
TimeSpan? duration = null;
|
||||
if (args.Length > 1)
|
||||
{
|
||||
@@ -1519,13 +1530,13 @@ namespace Barotrauma
|
||||
|
||||
if (clients.Count == 0)
|
||||
{
|
||||
GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", args[0], reason, duration);
|
||||
GameMain.Server.ServerSettings.BanList.BanPlayer("Unnamed", endpoint, reason, duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Client cl in clients)
|
||||
{
|
||||
GameMain.Server.BanClient(cl, reason, false, duration);
|
||||
GameMain.Server.BanClient(cl, reason, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1535,7 +1546,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (GameMain.Server == null || args.Length == 0) return;
|
||||
string clientName = string.Join(" ", args);
|
||||
GameMain.Server.UnbanPlayer(clientName, "");
|
||||
GameMain.Server.UnbanPlayer(clientName);
|
||||
},
|
||||
() =>
|
||||
{
|
||||
@@ -1546,17 +1557,20 @@ namespace Barotrauma
|
||||
};
|
||||
}));
|
||||
|
||||
commands.Add(new Command("unbanip", "unbanip [ip]: Unban a specific IP.", (string[] args) =>
|
||||
commands.Add(new Command("unbanaddress", "unbanaddress [endpoint]: Unban a specific endpoint.", (string[] args) =>
|
||||
{
|
||||
if (GameMain.Server == null || args.Length == 0) return;
|
||||
GameMain.Server.UnbanPlayer("", args[0]);
|
||||
if (Endpoint.Parse(args[0]).TryUnwrap(out var endpoint))
|
||||
{
|
||||
GameMain.Server.UnbanPlayer(endpoint);
|
||||
}
|
||||
},
|
||||
() =>
|
||||
{
|
||||
if (GameMain.Server == null) return null;
|
||||
return new string[][]
|
||||
{
|
||||
GameMain.Server.ServerSettings.BanList.BannedEndPoints.ToArray()
|
||||
GameMain.Server.ServerSettings.BanList.BannedAddresses.Select(ep => ep.ToString()).ToArray()
|
||||
};
|
||||
}));
|
||||
|
||||
|
||||
@@ -151,9 +151,9 @@ namespace Barotrauma
|
||||
string password = "";
|
||||
bool enableUpnp = false;
|
||||
|
||||
int maxPlayers = 10;
|
||||
int? ownerKey = null;
|
||||
UInt64 steamId = 0;
|
||||
int maxPlayers = 10;
|
||||
Option<int> ownerKey = Option<int>.None();
|
||||
Option<SteamId> steamId = Option<SteamId>.None();
|
||||
|
||||
XDocument doc = XMLExtensions.TryLoadXml(ServerSettings.SettingsFile);
|
||||
if (doc?.Root == null)
|
||||
@@ -169,7 +169,7 @@ namespace Barotrauma
|
||||
password = doc.Root.GetAttributeString("password", "");
|
||||
enableUpnp = doc.Root.GetAttributeBool("enableupnp", false);
|
||||
maxPlayers = doc.Root.GetAttributeInt("maxplayers", 10);
|
||||
ownerKey = null;
|
||||
ownerKey = Option<int>.None();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
@@ -218,12 +218,12 @@ namespace Barotrauma
|
||||
case "-ownerkey":
|
||||
if (int.TryParse(CommandLineArgs[i + 1], out int key))
|
||||
{
|
||||
ownerKey = key;
|
||||
ownerKey = Option<int>.Some(key);
|
||||
}
|
||||
i++;
|
||||
break;
|
||||
case "-steamid":
|
||||
UInt64.TryParse(CommandLineArgs[i + 1], out steamId);
|
||||
steamId = SteamId.Parse(CommandLineArgs[i + 1]);
|
||||
i++;
|
||||
break;
|
||||
case "-pipes":
|
||||
@@ -274,7 +274,7 @@ namespace Barotrauma
|
||||
|
||||
public void CloseServer()
|
||||
{
|
||||
Server?.Disconnect();
|
||||
Server?.Quit();
|
||||
ShouldRun = false;
|
||||
Server = null;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace Barotrauma
|
||||
public CharacterCampaignData(Client client)
|
||||
{
|
||||
Name = client.Name;
|
||||
ClientEndPoint = client.Connection.EndPointString;
|
||||
SteamID = client.SteamID;
|
||||
ClientAddress = client.Connection.Endpoint.Address;
|
||||
AccountId = client.AccountId;
|
||||
CharacterInfo = client.CharacterInfo;
|
||||
|
||||
healthData = new XElement("health");
|
||||
@@ -55,13 +55,13 @@ namespace Barotrauma
|
||||
public CharacterCampaignData(XElement element)
|
||||
{
|
||||
Name = element.GetAttributeString("name", "Unnamed");
|
||||
ClientEndPoint = element.GetAttributeString("endpoint", null) ?? element.GetAttributeString("ip", "");
|
||||
string steamID = element.GetAttributeString("steamid", "");
|
||||
if (!string.IsNullOrEmpty(steamID))
|
||||
{
|
||||
ulong.TryParse(steamID, out ulong parsedID);
|
||||
SteamID = parsedID;
|
||||
}
|
||||
string clientEndPointStr = element.GetAttributeString("address", null)
|
||||
?? element.GetAttributeString("endpoint", null)
|
||||
?? element.GetAttributeString("ip", "");
|
||||
ClientAddress = Address.Parse(clientEndPointStr).Fallback(new UnknownAddress());
|
||||
string accountIdStr = element.GetAttributeString("accountid", null)
|
||||
?? element.GetAttributeString("steamid", "");
|
||||
AccountId = Networking.AccountId.Parse(accountIdStr);
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
@@ -89,19 +89,20 @@ namespace Barotrauma
|
||||
|
||||
public bool MatchesClient(Client client)
|
||||
{
|
||||
if (SteamID > 0)
|
||||
if (AccountId.TryUnwrap(out var accountId)
|
||||
&& client.AccountId.TryUnwrap(out var clientId))
|
||||
{
|
||||
return SteamID == client.SteamID;
|
||||
return accountId == clientId;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ClientEndPoint == client.Connection.EndPointString;
|
||||
return ClientAddress == client.Connection.Endpoint.Address;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDuplicate(CharacterCampaignData other)
|
||||
{
|
||||
return other.SteamID == SteamID && other.ClientEndPoint == ClientEndPoint;
|
||||
return AccountId == other.AccountId && other.ClientAddress == ClientAddress;
|
||||
}
|
||||
|
||||
public void SpawnInventoryItems(Character character, Inventory inventory)
|
||||
@@ -136,8 +137,8 @@ namespace Barotrauma
|
||||
{
|
||||
XElement element = new XElement("CharacterCampaignData",
|
||||
new XAttribute("name", Name),
|
||||
new XAttribute("endpoint", ClientEndPoint),
|
||||
new XAttribute("steamid", SteamID));
|
||||
new XAttribute("address", ClientAddress),
|
||||
new XAttribute("accountid", AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : ""));
|
||||
|
||||
CharacterInfo?.Save(element);
|
||||
if (itemData != null) { element.Add(itemData); }
|
||||
|
||||
@@ -6,6 +6,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Steam;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -45,21 +46,26 @@ namespace Barotrauma
|
||||
|
||||
class SavedExperiencePoints
|
||||
{
|
||||
public readonly ulong SteamID;
|
||||
public readonly string EndPoint;
|
||||
public readonly Option<AccountId> AccountId;
|
||||
public readonly Address Address;
|
||||
public readonly int ExperiencePoints;
|
||||
|
||||
public SavedExperiencePoints(Client client)
|
||||
{
|
||||
SteamID = client.SteamID;
|
||||
EndPoint = client.Connection.EndPointString;
|
||||
AccountId = client.AccountId;
|
||||
Address = client.Connection.Endpoint.Address;
|
||||
ExperiencePoints = client.Character?.Info?.ExperiencePoints ?? 0;
|
||||
}
|
||||
|
||||
public SavedExperiencePoints(XElement element)
|
||||
{
|
||||
SteamID = element.GetAttributeUInt64("steamid", 0);
|
||||
EndPoint = element.GetAttributeString("endpoint", string.Empty);
|
||||
AccountId = Networking.AccountId.Parse(
|
||||
element.GetAttributeString("accountid", null)
|
||||
?? element.GetAttributeString("steamid", ""));
|
||||
Address = Address.Parse(
|
||||
element.GetAttributeString("address", null)
|
||||
?? element.GetAttributeString("endpoint", ""))
|
||||
.Fallback(new UnknownAddress());
|
||||
ExperiencePoints = element.GetAttributeInt("points", 0);
|
||||
}
|
||||
}
|
||||
@@ -202,11 +208,11 @@ namespace Barotrauma
|
||||
}
|
||||
public int GetSavedExperiencePoints(Client client)
|
||||
{
|
||||
return savedExperiencePoints.Find(s => s.SteamID != 0 && client.SteamID == s.SteamID || client.EndpointMatches(s.EndPoint))?.ExperiencePoints ?? 0;
|
||||
return savedExperiencePoints.Find(s => client.AccountId == s.AccountId || client.Connection.Endpoint.Address == s.Address)?.ExperiencePoints ?? 0;
|
||||
}
|
||||
public void ClearSavedExperiencePoints(Client client)
|
||||
{
|
||||
savedExperiencePoints.RemoveAll(s => s.SteamID != 0 && client.SteamID == s.SteamID || client.EndpointMatches(s.EndPoint));
|
||||
savedExperiencePoints.RemoveAll(s => client.AccountId == s.AccountId || client.Connection.Endpoint.Address == s.Address);
|
||||
}
|
||||
|
||||
public void SavePlayers()
|
||||
@@ -805,6 +811,10 @@ namespace Barotrauma
|
||||
|
||||
Wallet personalWallet = GetWallet(sender);
|
||||
personalWallet?.ForceUpdate();
|
||||
if (AllowedToManageWallets(sender))
|
||||
{
|
||||
Bank.ForceUpdate();
|
||||
}
|
||||
|
||||
if (purchasedHullRepairs != PurchasedHullRepairs)
|
||||
{
|
||||
@@ -886,7 +896,9 @@ namespace Barotrauma
|
||||
foreach (var item in store.Value.ToList())
|
||||
{
|
||||
if (map?.CurrentLocation?.Stores == null || !map.CurrentLocation.Stores.ContainsKey(store.Key)) { continue; }
|
||||
item.Quantity = Math.Min(map.CurrentLocation.Stores[store.Key].Stock.Find(s => s.ItemPrefab == item.ItemPrefab)?.Quantity ?? 0, item.Quantity);
|
||||
int availableQuantity = map.CurrentLocation.Stores[store.Key].Stock.Find(s => s.ItemPrefab == item.ItemPrefab)?.Quantity ?? 0;
|
||||
int alreadyPurchasedQuantity = CargoManager.GetBuyCrateItem(store.Key, item.ItemPrefab)?.Quantity ?? 0;
|
||||
item.Quantity = Math.Min(availableQuantity - alreadyPurchasedQuantity, item.Quantity);
|
||||
if (item.Quantity <= 0) { continue; }
|
||||
CargoManager.ModifyItemQuantityInBuyCrate(store.Key, item.ItemPrefab, item.Quantity, sender);
|
||||
}
|
||||
@@ -1364,8 +1376,8 @@ namespace Barotrauma
|
||||
foreach (var savedExperiencePoint in savedExperiencePoints)
|
||||
{
|
||||
savedExperiencePointsElement.Add(new XElement("Point",
|
||||
new XAttribute("steamid", savedExperiencePoint.SteamID),
|
||||
new XAttribute("endpoint", savedExperiencePoint?.EndPoint ?? string.Empty),
|
||||
new XAttribute("accountid", savedExperiencePoint.AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : ""),
|
||||
new XAttribute("address", savedExperiencePoint.Address.StringRepresentation),
|
||||
new XAttribute("points", savedExperiencePoint.ExperiencePoints)));
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Barotrauma
|
||||
if (sender != null)
|
||||
{
|
||||
msg.Write(true);
|
||||
msg.Write(sender.ID);
|
||||
msg.Write(sender.SessionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -99,10 +99,10 @@ namespace Barotrauma
|
||||
case ReadyCheckState.Update when readyCheck != null:
|
||||
|
||||
ReadyStatus status = (ReadyStatus) inc.ReadByte();
|
||||
if (!readyCheck.Clients.ContainsKey(client.ID)) { return; }
|
||||
if (!readyCheck.Clients.ContainsKey(client.SessionId)) { return; }
|
||||
|
||||
readyCheck.Clients[client.ID] = status;
|
||||
readyCheck.UpdateReadyCheck(client.ID, status);
|
||||
readyCheck.Clients[client.SessionId] = status;
|
||||
readyCheck.UpdateReadyCheck(client.SessionId, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -111,8 +111,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (GameMain.GameSession?.CrewManager == null || GameMain.GameSession.CrewManager.ActiveReadyCheck != null) { return; }
|
||||
|
||||
List<Client> connectedClients = GameMain.Server.ConnectedClients;
|
||||
ReadyCheck newReadyCheck = new ReadyCheck(connectedClients.Where(c => !c.Spectating).Select(c => c.ID).ToList(), 30);
|
||||
var connectedClients = GameMain.Server.ConnectedClients;
|
||||
ReadyCheck newReadyCheck = new ReadyCheck(connectedClients.Where(c => !c.Spectating).Select(c => c.SessionId).ToList(), 30);
|
||||
GameMain.GameSession.CrewManager.ActiveReadyCheck = newReadyCheck;
|
||||
newReadyCheck.InitializeReadyCheck(author, sender);
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ namespace Barotrauma.Items.Components
|
||||
msg.Write(timeUntilReady);
|
||||
uint recipeHash = fabricatedItem?.RecipeHash ?? 0;
|
||||
msg.Write(recipeHash);
|
||||
UInt16 userID = fabricatedItem is null || user is null ? (UInt16)0 : user.ID;
|
||||
msg.Write(userID);
|
||||
UInt16 userId = fabricatedItem is null || user is null ? (UInt16)0 : user.ID;
|
||||
msg.Write(userId);
|
||||
|
||||
var reachedLimits = fabricationLimits.Where(kvp => kvp.Value <= 0);
|
||||
msg.Write((ushort)reachedLimits.Count());
|
||||
|
||||
@@ -9,56 +9,16 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
partial class BannedPlayer
|
||||
{
|
||||
private static UInt16 LastIdentifier = 0;
|
||||
private static UInt32 LastIdentifier = 0;
|
||||
|
||||
public BannedPlayer(string name, string endPoint, string reason, DateTime? expirationTime)
|
||||
public BannedPlayer(
|
||||
string name, Either<Address, AccountId> addressOrAccountId, string reason, DateTime? expirationTime)
|
||||
{
|
||||
this.Name = name;
|
||||
this.EndPoint = endPoint;
|
||||
ParseEndPointAsSteamId();
|
||||
this.AddressOrAccountId = addressOrAccountId;
|
||||
this.Reason = reason;
|
||||
this.ExpirationTime = expirationTime;
|
||||
this.UniqueIdentifier = LastIdentifier; LastIdentifier++;
|
||||
|
||||
this.IsRangeBan = EndPoint.IndexOf(".x") > -1;
|
||||
}
|
||||
|
||||
public BannedPlayer(string name, ulong steamID, string reason, DateTime? expirationTime)
|
||||
{
|
||||
this.Name = name;
|
||||
this.SteamID = steamID;
|
||||
this.Reason = reason;
|
||||
this.ExpirationTime = expirationTime;
|
||||
this.UniqueIdentifier = LastIdentifier; LastIdentifier++;
|
||||
|
||||
this.IsRangeBan = false;
|
||||
|
||||
this.EndPoint = "";
|
||||
}
|
||||
|
||||
public bool CompareTo(string endpointCompare)
|
||||
{
|
||||
if (string.IsNullOrEmpty(EndPoint) || string.IsNullOrEmpty(endpointCompare)) { return false; }
|
||||
if (!IsRangeBan)
|
||||
{
|
||||
return endpointCompare == EndPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
int rangeBanIndex = EndPoint.IndexOf(".x");
|
||||
if (endpointCompare.Length < rangeBanIndex) return false;
|
||||
return endpointCompare.Substring(0, rangeBanIndex) == EndPoint.Substring(0, rangeBanIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool CompareTo(IPAddress ipCompare)
|
||||
{
|
||||
if (string.IsNullOrEmpty(EndPoint) || ipCompare == null) { return false; }
|
||||
if (ipCompare.IsIPv4MappedToIPv6 && CompareTo(ipCompare.MapToIPv4NoThrow().ToString()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return CompareTo(ipCompare.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,10 +44,10 @@ namespace Barotrauma.Networking
|
||||
foreach (string line in lines)
|
||||
{
|
||||
string[] separatedLine = line.Split(',');
|
||||
if (separatedLine.Length < 2) continue;
|
||||
if (separatedLine.Length < 2) { continue; }
|
||||
|
||||
string name = separatedLine[0];
|
||||
string identifier = separatedLine[1];
|
||||
string endpointStr = separatedLine[1];
|
||||
|
||||
DateTime? expirationTime = null;
|
||||
if (separatedLine.Length > 2 && !string.IsNullOrEmpty(separatedLine[2]))
|
||||
@@ -99,84 +59,57 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
string reason = separatedLine.Length > 3 ? string.Join(",", separatedLine.Skip(3)) : "";
|
||||
|
||||
if (expirationTime.HasValue && DateTime.Now > expirationTime.Value) continue;
|
||||
if (expirationTime.HasValue && DateTime.Now > expirationTime.Value) { continue; }
|
||||
|
||||
if (identifier.Contains(".") || identifier.Contains(":"))
|
||||
if (AccountId.Parse(endpointStr).TryUnwrap(out var accountId))
|
||||
{
|
||||
//identifier is an ip
|
||||
bannedPlayers.Add(new BannedPlayer(name, identifier, reason, expirationTime));
|
||||
bannedPlayers.Add(new BannedPlayer(name, accountId, reason, expirationTime));
|
||||
}
|
||||
else
|
||||
else if (Address.Parse(endpointStr).TryUnwrap(out var address))
|
||||
{
|
||||
//identifier should be a steam id
|
||||
if (ulong.TryParse(identifier, out ulong steamID))
|
||||
{
|
||||
bannedPlayers.Add(new BannedPlayer(name, steamID, reason, expirationTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Error in banlist: \"" + identifier + "\" is not a valid IP or a Steam ID");
|
||||
}
|
||||
bannedPlayers.Add(new BannedPlayer(name, address, reason, expirationTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsBanned(IPAddress IP, ulong steamID, ulong ownerSteamID, out string reason)
|
||||
public void RemoveExpired()
|
||||
{
|
||||
reason = string.Empty;
|
||||
if (IPAddress.IsLoopback(IP)) { return false; }
|
||||
var bannedPlayer = bannedPlayers.Find(bp =>
|
||||
bp.CompareTo(IP) ||
|
||||
(steamID > 0 && (bp.SteamID == steamID || SteamManager.SteamIDStringToUInt64(bp.EndPoint) == steamID)) ||
|
||||
(ownerSteamID > 0 && (bp.SteamID == ownerSteamID || SteamManager.SteamIDStringToUInt64(bp.EndPoint) == ownerSteamID)));
|
||||
reason = bannedPlayer?.Reason;
|
||||
return bannedPlayer != null;
|
||||
}
|
||||
|
||||
public bool IsBanned(IPAddress IP, out string reason)
|
||||
{
|
||||
reason = string.Empty;
|
||||
if (IPAddress.IsLoopback(IP)) { return false; }
|
||||
bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value);
|
||||
var bannedPlayer = bannedPlayers.Find(bp => bp.CompareTo(IP));
|
||||
reason = bannedPlayer?.Reason;
|
||||
}
|
||||
|
||||
public bool IsBanned(Endpoint endpoint, out string reason)
|
||||
=> IsBanned(endpoint.Address, out reason);
|
||||
|
||||
public bool IsBanned(Address address, out string reason)
|
||||
{
|
||||
RemoveExpired();
|
||||
if (address.IsLocalHost)
|
||||
{
|
||||
reason = string.Empty;
|
||||
return false;
|
||||
}
|
||||
var bannedPlayer = bannedPlayers.Find(bp => bp.AddressOrAccountId.TryGet(out Address adr) && address.Equals(adr));
|
||||
reason = bannedPlayer?.Reason ?? string.Empty;
|
||||
return bannedPlayer != null;
|
||||
}
|
||||
|
||||
public bool IsBanned(ulong steamID, out string reason)
|
||||
public bool IsBanned(AccountId accountId, out string reason)
|
||||
{
|
||||
reason = string.Empty;
|
||||
bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value);
|
||||
var bannedPlayer = bannedPlayers.Find(bp =>
|
||||
steamID > 0 &&
|
||||
(bp.SteamID == steamID || SteamManager.SteamIDStringToUInt64(bp.EndPoint) == steamID));
|
||||
reason = bannedPlayer?.Reason;
|
||||
RemoveExpired();
|
||||
var bannedPlayer = bannedPlayers.Find(bp => bp.AddressOrAccountId.TryGet(out AccountId id) && accountId.Equals(id));
|
||||
reason = bannedPlayer?.Reason ?? string.Empty;
|
||||
return bannedPlayer != null;
|
||||
}
|
||||
|
||||
public void BanPlayer(string name, IPAddress ip, string reason, TimeSpan? duration)
|
||||
public void BanPlayer(string name, Endpoint endpoint, string reason, TimeSpan? duration)
|
||||
=> BanPlayer(name, endpoint.Address, reason, duration);
|
||||
|
||||
public void BanPlayer(string name, Either<Address, AccountId> addressOrAccountId, string reason, TimeSpan? duration)
|
||||
{
|
||||
string ipStr = ip.IsIPv4MappedToIPv6 ? ip.MapToIPv4NoThrow().ToString() : ip.ToString();
|
||||
BanPlayer(name, ipStr, 0, reason, duration);
|
||||
}
|
||||
|
||||
public void BanPlayer(string name, string endPoint, string reason, TimeSpan? duration)
|
||||
{
|
||||
BanPlayer(name, endPoint, 0, reason, duration);
|
||||
}
|
||||
|
||||
public void BanPlayer(string name, ulong steamID, string reason, TimeSpan? duration)
|
||||
{
|
||||
if (steamID == 0) { return; }
|
||||
BanPlayer(name, "", steamID, reason, duration);
|
||||
}
|
||||
|
||||
private void BanPlayer(string name, string endPoint, ulong steamID, string reason, TimeSpan? duration)
|
||||
{
|
||||
var existingBan = bannedPlayers.Find(bp => bp.EndPoint == endPoint && bp.SteamID == steamID);
|
||||
var existingBan = bannedPlayers.Find(bp => bp.AddressOrAccountId == addressOrAccountId);
|
||||
if (existingBan != null)
|
||||
{
|
||||
if (!duration.HasValue) return;
|
||||
if (!duration.HasValue) { return; }
|
||||
|
||||
DebugConsole.Log("Set \"" + name + "\"'s ban duration to " + duration.Value);
|
||||
existingBan.ExpirationTime = DateTime.Now + duration.Value;
|
||||
@@ -187,8 +120,8 @@ namespace Barotrauma.Networking
|
||||
System.Diagnostics.Debug.Assert(!name.Contains(','));
|
||||
|
||||
string logMsg = "Banned " + name;
|
||||
if (!string.IsNullOrEmpty(reason)) logMsg += ", reason: " + reason;
|
||||
if (duration.HasValue) logMsg += ", duration: " + duration.Value.ToString();
|
||||
if (!string.IsNullOrEmpty(reason)) { logMsg += ", reason: " + reason; }
|
||||
if (duration.HasValue) { logMsg += ", duration: " + duration.Value.ToString(); }
|
||||
|
||||
DebugConsole.Log(logMsg);
|
||||
|
||||
@@ -198,46 +131,20 @@ namespace Barotrauma.Networking
|
||||
expirationTime = DateTime.Now + duration.Value;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(endPoint))
|
||||
{
|
||||
bannedPlayers.Add(new BannedPlayer(name, endPoint, reason, expirationTime));
|
||||
}
|
||||
else if (steamID > 0)
|
||||
{
|
||||
bannedPlayers.Add(new BannedPlayer(name, steamID, reason, expirationTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to ban a client (no valid IP or Steam ID given)");
|
||||
return;
|
||||
}
|
||||
bannedPlayers.Add(new BannedPlayer(name, addressOrAccountId, reason, expirationTime));
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
public void UnbanPlayer(string name)
|
||||
public void UnbanPlayer(Endpoint endpoint)
|
||||
=> UnbanPlayer(endpoint.Address);
|
||||
|
||||
public void UnbanPlayer(Either<Address, AccountId> addressOrAccountId)
|
||||
{
|
||||
name = name.ToLower();
|
||||
var player = bannedPlayers.Find(bp => bp.Name.ToLower() == name);
|
||||
var player = bannedPlayers.Find(bp => bp.AddressOrAccountId == addressOrAccountId);
|
||||
if (player == null)
|
||||
{
|
||||
DebugConsole.Log("Could not unban player \"" + name + "\". Matching player not found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveBan(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void UnbanEndPoint(string endPoint)
|
||||
{
|
||||
ulong steamId = SteamManager.SteamIDStringToUInt64(endPoint);
|
||||
var player = bannedPlayers.Find(bp =>
|
||||
bp.EndPoint == endPoint ||
|
||||
(steamId != 0 && steamId == SteamManager.SteamIDStringToUInt64(bp.EndPoint)));
|
||||
if (player == null)
|
||||
{
|
||||
DebugConsole.Log("Could not unban endpoint \"" + endPoint + "\". Matching player not found.");
|
||||
DebugConsole.Log("Could not unban endpoint \"" + addressOrAccountId + "\". Matching player not found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -255,22 +162,6 @@ namespace Barotrauma.Networking
|
||||
Save();
|
||||
}
|
||||
|
||||
private void RangeBan(BannedPlayer banned)
|
||||
{
|
||||
banned.EndPoint = ToRange(banned.EndPoint);
|
||||
|
||||
BannedPlayer bp;
|
||||
while ((bp = bannedPlayers.Find(x => banned.CompareTo(x.EndPoint))) != null)
|
||||
{
|
||||
//remove all specific bans that are now covered by the rangeban
|
||||
bannedPlayers.Remove(bp);
|
||||
}
|
||||
|
||||
bannedPlayers.Add(banned);
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
GameServer.Log("Saving banlist", ServerLog.MessageType.ServerMessage);
|
||||
@@ -283,9 +174,9 @@ namespace Barotrauma.Networking
|
||||
foreach (BannedPlayer banned in bannedPlayers)
|
||||
{
|
||||
string line = banned.Name;
|
||||
line += "," + ((banned.SteamID > 0) ? SteamManager.SteamIDUInt64ToString(banned.SteamID) : banned.EndPoint);
|
||||
line += "," + (banned.AddressOrAccountId.ToString());
|
||||
line += "," + (banned.ExpirationTime.HasValue ? banned.ExpirationTime.Value.ToString() : "");
|
||||
if (!string.IsNullOrWhiteSpace(banned.Reason)) line += "," + banned.Reason;
|
||||
if (!string.IsNullOrWhiteSpace(banned.Reason)) { line += "," + banned.Reason; }
|
||||
|
||||
lines.Add(line);
|
||||
}
|
||||
@@ -324,7 +215,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
outMsg.Write(bannedPlayer.Name);
|
||||
outMsg.Write(bannedPlayer.UniqueIdentifier);
|
||||
outMsg.Write(bannedPlayer.IsRangeBan);
|
||||
outMsg.Write(bannedPlayer.ExpirationTime != null);
|
||||
outMsg.WritePadBits();
|
||||
if (bannedPlayer.ExpirationTime != null)
|
||||
@@ -337,12 +227,19 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (c.Connection == GameMain.Server.OwnerConnection)
|
||||
{
|
||||
outMsg.Write(bannedPlayer.EndPoint);
|
||||
outMsg.Write(bannedPlayer.SteamID);
|
||||
if (bannedPlayer.AddressOrAccountId.TryGet(out Address endpoint))
|
||||
{
|
||||
outMsg.Write(true); outMsg.WritePadBits();
|
||||
outMsg.Write(endpoint.StringRepresentation);
|
||||
}
|
||||
else
|
||||
{
|
||||
outMsg.Write(false); outMsg.WritePadBits();
|
||||
outMsg.Write(((SteamId)bannedPlayer.AddressOrAccountId).StringRepresentation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Error while writing banlist. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||
@@ -355,38 +252,25 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!c.HasPermission(ClientPermissions.Ban))
|
||||
{
|
||||
UInt16 removeCount = incMsg.ReadUInt16();
|
||||
incMsg.BitPosition += removeCount * 4 * 8;
|
||||
UInt16 rangeBanCount = incMsg.ReadUInt16();
|
||||
incMsg.BitPosition += rangeBanCount * 4 * 8;
|
||||
UInt32 removeCount = incMsg.ReadVariableUInt32();
|
||||
incMsg.BitPosition += (int)removeCount * 4 * 8;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt16 removeCount = incMsg.ReadUInt16();
|
||||
UInt32 removeCount = incMsg.ReadVariableUInt32();
|
||||
for (int i = 0; i < removeCount; i++)
|
||||
{
|
||||
UInt16 id = incMsg.ReadUInt16();
|
||||
UInt32 id = incMsg.ReadUInt32();
|
||||
BannedPlayer bannedPlayer = bannedPlayers.Find(p => p.UniqueIdentifier == id);
|
||||
if (bannedPlayer != null)
|
||||
{
|
||||
GameServer.Log(GameServer.ClientLogName(c) + " unbanned " + bannedPlayer.Name + " (" + bannedPlayer.EndPoint + ")", ServerLog.MessageType.ConsoleUsage);
|
||||
GameServer.Log(GameServer.ClientLogName(c) + " unbanned " + bannedPlayer.Name + " (" + bannedPlayer.AddressOrAccountId + ")", ServerLog.MessageType.ConsoleUsage);
|
||||
RemoveBan(bannedPlayer);
|
||||
}
|
||||
}
|
||||
Int16 rangeBanCount = incMsg.ReadInt16();
|
||||
for (int i = 0; i < rangeBanCount; i++)
|
||||
{
|
||||
UInt16 id = incMsg.ReadUInt16();
|
||||
BannedPlayer bannedPlayer = bannedPlayers.Find(p => p.UniqueIdentifier == id);
|
||||
if (bannedPlayer != null)
|
||||
{
|
||||
GameServer.Log(GameServer.ClientLogName(c) + " rangebanned " + bannedPlayer.Name + " (" + bannedPlayer.EndPoint + ")", ServerLog.MessageType.ConsoleUsage);
|
||||
RangeBan(bannedPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
return removeCount > 0 || rangeBanCount > 0;
|
||||
return removeCount > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace Barotrauma.Networking
|
||||
msg.Write(SenderClient != null);
|
||||
if (SenderClient != null)
|
||||
{
|
||||
msg.Write((SenderClient.SteamID != 0) ? SenderClient.SteamID : SenderClient.ID);
|
||||
msg.Write(SenderClient.AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : SenderClient.SessionId.ToString());
|
||||
}
|
||||
msg.Write(Sender != null && c.InGame);
|
||||
if (Sender != null && c.InGame)
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public bool ReadyToStart;
|
||||
|
||||
public List<JobVariant> JobPreferences;
|
||||
public List<JobVariant> JobPreferences { get; set; }
|
||||
public JobVariant AssignedJob;
|
||||
|
||||
public float DeleteDisconnectedTimer;
|
||||
@@ -111,7 +111,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
JobPreferences = new List<JobVariant>();
|
||||
|
||||
VoipQueue = new VoipQueue(ID, true, true);
|
||||
VoipQueue = new VoipQueue(SessionId, true, true);
|
||||
GameMain.Server.VoipServer.RegisterQueue(VoipQueue);
|
||||
|
||||
//initialize to infinity, gets set to a proper value when initializing midround syncing
|
||||
@@ -162,7 +162,7 @@ namespace Barotrauma.Networking
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool EndpointMatches(string endPoint)
|
||||
public bool EndpointMatches(Endpoint endPoint)
|
||||
{
|
||||
return Connection.EndpointMatches(endPoint);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#define ALLOW_BOT_TRAITORS
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.IO;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Steam;
|
||||
@@ -85,7 +84,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
#endif
|
||||
|
||||
public override List<Client> ConnectedClients
|
||||
public override IReadOnlyList<Client> ConnectedClients
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -110,10 +109,19 @@ namespace Barotrauma.Networking
|
||||
public int QueryPort => serverSettings?.QueryPort ?? 0;
|
||||
|
||||
public NetworkConnection OwnerConnection { get; private set; }
|
||||
private readonly int? ownerKey;
|
||||
private readonly UInt64? ownerSteamId;
|
||||
private readonly Option<int> ownerKey;
|
||||
private readonly Option<SteamId> ownerSteamId;
|
||||
|
||||
public GameServer(string name, int port, int queryPort = 0, bool isPublic = false, string password = "", bool attemptUPnP = false, int maxPlayers = 10, int? ownKey = null, UInt64? steamId = null)
|
||||
public GameServer(
|
||||
string name,
|
||||
int port,
|
||||
int queryPort,
|
||||
bool isPublic,
|
||||
string password,
|
||||
bool attemptUPnP,
|
||||
int maxPlayers,
|
||||
Option<int> ownerKey,
|
||||
Option<SteamId> ownerSteamId)
|
||||
{
|
||||
name = name.Replace(":", "");
|
||||
name = name.Replace(";", "");
|
||||
@@ -132,9 +140,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
Voting = new Voting();
|
||||
|
||||
ownerKey = ownKey;
|
||||
this.ownerKey = ownerKey;
|
||||
|
||||
ownerSteamId = steamId;
|
||||
this.ownerSteamId = ownerSteamId;
|
||||
|
||||
entityEventManager = new ServerEntityEventManager(this);
|
||||
|
||||
@@ -147,15 +155,15 @@ namespace Barotrauma.Networking
|
||||
try
|
||||
{
|
||||
Log("Starting the server...", ServerLog.MessageType.ServerMessage);
|
||||
if (!ownerSteamId.HasValue || ownerSteamId.Value == 0)
|
||||
if (ownerSteamId.TryUnwrap(out var steamId))
|
||||
{
|
||||
Log("Using Lidgren networking. Manual port forwarding may be required. If players cannot connect to the server, you may want to use the in-game hosting menu (which uses SteamP2P networking and does not require port forwarding).", ServerLog.MessageType.ServerMessage);
|
||||
serverPeer = new LidgrenServerPeer(ownerKey, serverSettings);
|
||||
Log("Using SteamP2P networking.", ServerLog.MessageType.ServerMessage);
|
||||
serverPeer = new SteamP2PServerPeer(steamId, ownerKey.Fallback(0), serverSettings);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Using SteamP2P networking.", ServerLog.MessageType.ServerMessage);
|
||||
serverPeer = new SteamP2PServerPeer(ownerSteamId.Value, ownerKey.Value, serverSettings);
|
||||
Log("Using Lidgren networking. Manual port forwarding may be required. If players cannot connect to the server, you may want to use the in-game hosting menu (which uses SteamP2P networking and does not require port forwarding).", ServerLog.MessageType.ServerMessage);
|
||||
serverPeer = new LidgrenServerPeer(ownerKey, serverSettings);
|
||||
}
|
||||
|
||||
serverPeer.OnInitializationComplete = OnInitializationComplete;
|
||||
@@ -253,17 +261,15 @@ namespace Barotrauma.Networking
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
private void OnInitializationComplete(NetworkConnection connection)
|
||||
private void OnInitializationComplete(NetworkConnection connection, string clientName)
|
||||
{
|
||||
string clName = connection.Name;
|
||||
Client newClient = new Client(clName, GetNewClientID());
|
||||
Client newClient = new Client(clientName, GetNewClientSessionId());
|
||||
newClient.InitClientSync();
|
||||
newClient.Connection = connection;
|
||||
newClient.Connection.Status = NetworkConnectionStatus.Connected;
|
||||
newClient.SteamID = connection.SteamID;
|
||||
newClient.OwnerSteamID = connection.OwnerSteamID;
|
||||
newClient.AccountInfo = connection.AccountInfo;
|
||||
newClient.Language = connection.Language;
|
||||
ConnectedClients.Add(newClient);
|
||||
connectedClients.Add(newClient);
|
||||
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(newClient));
|
||||
if (previousPlayer != null)
|
||||
@@ -299,10 +305,10 @@ namespace Barotrauma.Networking
|
||||
previousPlayer.Name = newClient.Name;
|
||||
}
|
||||
|
||||
var savedPermissions = serverSettings.ClientPermissions.Find(cp =>
|
||||
cp.SteamID > 0 ?
|
||||
cp.SteamID == newClient.SteamID :
|
||||
newClient.EndpointMatches(cp.EndPoint));
|
||||
var savedPermissions = serverSettings.ClientPermissions.Find(scp =>
|
||||
scp.AddressOrAccountId.TryGet(out AccountId accountId)
|
||||
? newClient.AccountId.ValueEquals(accountId)
|
||||
: newClient.Connection.Endpoint.Address == scp.AddressOrAccountId);
|
||||
|
||||
if (savedPermissions != null)
|
||||
{
|
||||
@@ -346,7 +352,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (OwnerConnection != null && ChildServerRelay.HasShutDown)
|
||||
{
|
||||
Disconnect();
|
||||
Quit();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -377,7 +383,7 @@ namespace Barotrauma.Networking
|
||||
character.KillDisconnectedTimer += deltaTime;
|
||||
character.SetStun(1.0f);
|
||||
|
||||
Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && c.EndpointMatches(character.OwnerClientEndPoint));
|
||||
Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && c.EndpointMatches(character.OwnerClientEndpoint));
|
||||
|
||||
if ((OwnerConnection == null || owner?.Connection != OwnerConnection) && character.KillDisconnectedTimer > serverSettings.KillDisconnectedTime)
|
||||
{
|
||||
@@ -679,7 +685,7 @@ namespace Barotrauma.Networking
|
||||
pingInf.Write((byte)ConnectedClients.Count);
|
||||
ConnectedClients.ForEach(c2 =>
|
||||
{
|
||||
pingInf.Write(c2.ID);
|
||||
pingInf.Write(c2.SessionId);
|
||||
pingInf.Write(c2.Ping);
|
||||
});
|
||||
serverPeer.Send(pingInf, c.Connection, DeliveryMethod.Unreliable);
|
||||
@@ -788,11 +794,11 @@ namespace Barotrauma.Networking
|
||||
if (serverSettings.VoiceChatEnabled && !connectedClient.Muted)
|
||||
{
|
||||
byte id = inc.ReadByte();
|
||||
if (connectedClient.ID != id)
|
||||
if (connectedClient.SessionId != id)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError(
|
||||
"Client \"" + connectedClient.Name + "\" sent a VOIP update that didn't match its ID (" + id.ToString() + "!=" + connectedClient.ID.ToString() + ")");
|
||||
"Client \"" + connectedClient.Name + "\" sent a VOIP update that didn't match its ID (" + id.ToString() + "!=" + connectedClient.SessionId.ToString() + ")");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -1010,14 +1016,14 @@ namespace Barotrauma.Networking
|
||||
entityEventManager.CreateEvent(serverSerializable, extraData);
|
||||
}
|
||||
|
||||
private byte GetNewClientID()
|
||||
private byte GetNewClientSessionId()
|
||||
{
|
||||
byte userID = 1;
|
||||
while (connectedClients.Any(c => c.ID == userID))
|
||||
byte userId = 1;
|
||||
while (connectedClients.Any(c => c.SessionId == userId))
|
||||
{
|
||||
userID++;
|
||||
userId++;
|
||||
}
|
||||
return userID;
|
||||
return userId;
|
||||
}
|
||||
|
||||
private void ClientReadLobby(IReadMessage inc)
|
||||
@@ -1165,6 +1171,12 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.Log("Finished midround syncing " + c.Name + " - switching from ID " + prevID + " to " + c.LastRecvEntityEventID);
|
||||
//notify the client of the state of the respawn manager (so they show the respawn prompt if needed)
|
||||
if (respawnManager != null) { CreateEntityEvent(respawnManager); }
|
||||
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign)
|
||||
{
|
||||
//notify the client of the current bank balance and purchased repairs
|
||||
campaign.Bank.ForceUpdate();
|
||||
campaign.IncrementLastUpdateIdForFlag(MultiPlayerCampaign.NetFlags.Misc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1189,7 +1201,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
//give midround-joining clients a bit more time to get in sync if they keep receiving messages
|
||||
int receivedEventCount = lastRecvEntityEventID - c.LastRecvEntityEventID;
|
||||
if (receivedEventCount < 0) receivedEventCount += ushort.MaxValue;
|
||||
if (receivedEventCount < 0) { receivedEventCount += ushort.MaxValue; }
|
||||
c.MidRoundSyncTimeOut += receivedEventCount * 0.01f;
|
||||
DebugConsole.Log("Midround sync timeout " + c.MidRoundSyncTimeOut.ToString("0.##") + "/" + Timing.TotalTime.ToString("0.##"));
|
||||
}
|
||||
@@ -1241,7 +1253,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
//don't read further messages if the client has been disconnected (kicked due to spam for example)
|
||||
if (!connectedClients.Contains(c)) break;
|
||||
if (!connectedClients.Contains(c)) { break; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1341,7 +1353,6 @@ namespace Barotrauma.Networking
|
||||
case ClientPermissions.Ban:
|
||||
string bannedName = inc.ReadString().ToLowerInvariant();
|
||||
string banReason = inc.ReadString();
|
||||
bool range = inc.ReadBoolean();
|
||||
double durationSeconds = inc.ReadDouble();
|
||||
|
||||
TimeSpan? banDuration = null;
|
||||
@@ -1351,7 +1362,7 @@ namespace Barotrauma.Networking
|
||||
if (bannedClient != null)
|
||||
{
|
||||
Log("Client \"" + ClientLogName(sender) + "\" banned \"" + ClientLogName(bannedClient) + "\".", ServerLog.MessageType.ServerMessage);
|
||||
BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, range, banDuration);
|
||||
BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, banDuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1359,7 +1370,7 @@ namespace Barotrauma.Networking
|
||||
if (bannedPreviousClient != null)
|
||||
{
|
||||
Log("Client \"" + ClientLogName(sender) + "\" banned \"" + bannedPreviousClient.Name + "\".", ServerLog.MessageType.ServerMessage);
|
||||
BanPreviousPlayer(bannedPreviousClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, range, banDuration);
|
||||
BanPreviousPlayer(bannedPreviousClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, banDuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1368,9 +1379,16 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
break;
|
||||
case ClientPermissions.Unban:
|
||||
string unbannedName = inc.ReadString();
|
||||
string unbannedIP = inc.ReadString();
|
||||
UnbanPlayer(unbannedName, unbannedIP);
|
||||
bool isPlayerName = inc.ReadBoolean(); inc.ReadPadBits();
|
||||
string str = inc.ReadString();
|
||||
if (isPlayerName)
|
||||
{
|
||||
UnbanPlayer(playerName: str);
|
||||
}
|
||||
else if (Endpoint.Parse(str).TryUnwrap(out var endpoint))
|
||||
{
|
||||
UnbanPlayer(endpoint);
|
||||
}
|
||||
break;
|
||||
case ClientPermissions.ManageRound:
|
||||
bool end = inc.ReadBoolean();
|
||||
@@ -1506,7 +1524,7 @@ namespace Barotrauma.Networking
|
||||
break;
|
||||
case ClientPermissions.ManagePermissions:
|
||||
byte targetClientID = inc.ReadByte();
|
||||
Client targetClient = connectedClients.Find(c => c.ID == targetClientID);
|
||||
Client targetClient = connectedClients.Find(c => c.SessionId == targetClientID);
|
||||
if (targetClient == null || targetClient == sender || targetClient.Connection == OwnerConnection) { return; }
|
||||
|
||||
targetClient.ReadPermissions(inc);
|
||||
@@ -1592,7 +1610,7 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.NewMessage("Sending initial lobby update", Color.Gray);
|
||||
}
|
||||
|
||||
outmsg.Write(c.ID);
|
||||
outmsg.Write(c.SessionId);
|
||||
|
||||
var subList = GameMain.NetLobbyScreen.GetSubList();
|
||||
outmsg.Write((UInt16)subList.Count);
|
||||
@@ -1811,15 +1829,15 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
var tempClientData = new TempClient
|
||||
{
|
||||
ID = client.ID,
|
||||
SteamID = client.SteamID,
|
||||
NameID = client.NameID,
|
||||
SessionId = client.SessionId,
|
||||
AccountInfo = client.AccountInfo,
|
||||
NameId = client.NameId,
|
||||
Name = client.Name,
|
||||
PreferredJob = client.Character?.Info?.Job != null && gameStarted
|
||||
? client.Character.Info.Job.Prefab.Identifier
|
||||
: client.PreferredJob,
|
||||
PreferredTeam = client.PreferredTeam,
|
||||
CharacterID = client.Character == null || !gameStarted ? (ushort)0 : client.Character.ID,
|
||||
CharacterId = client.Character == null || !gameStarted ? (ushort)0 : client.Character.ID,
|
||||
Karma = c.HasPermission(ClientPermissions.ServerLog) ? client.Karma : 100.0f,
|
||||
Muted = client.Muted,
|
||||
InGame = client.InGame,
|
||||
@@ -2382,7 +2400,7 @@ namespace Barotrauma.Networking
|
||||
mpCampaign.ClearSavedExperiencePoints(teamClients[i]);
|
||||
}
|
||||
|
||||
spawnedCharacter.OwnerClientEndPoint = teamClients[i].Connection.EndPointString;
|
||||
spawnedCharacter.OwnerClientEndpoint = teamClients[i].Connection.Endpoint;
|
||||
spawnedCharacter.OwnerClientName = teamClients[i].Name;
|
||||
}
|
||||
|
||||
@@ -2693,9 +2711,15 @@ namespace Barotrauma.Networking
|
||||
Identifier newJob = inc.ReadIdentifier();
|
||||
CharacterTeamType newTeam = (CharacterTeamType)inc.ReadByte();
|
||||
|
||||
if (c == null || string.IsNullOrEmpty(newName) || !NetIdUtils.IdMoreRecent(nameId, c.NameID)) { return false; }
|
||||
|
||||
c.NameID = nameId;
|
||||
if (c == null || string.IsNullOrEmpty(newName) || !NetIdUtils.IdMoreRecent(nameId, c.NameId)) { return false; }
|
||||
if (!newJob.IsEmpty)
|
||||
{
|
||||
if (!JobPrefab.Prefabs.TryGet(newJob, out JobPrefab newJobPrefab) || newJobPrefab.HiddenJob)
|
||||
{
|
||||
newJob = Identifier.Empty;
|
||||
}
|
||||
}
|
||||
c.NameId = nameId;
|
||||
if (newName == c.Name && newJob == c.PreferredJob && newTeam == c.PreferredTeam) { return false; }
|
||||
c.PreferredJob = newJob;
|
||||
c.PreferredTeam = newTeam;
|
||||
@@ -2716,7 +2740,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
string oldName = c.Name;
|
||||
c.Name = newName;
|
||||
c.Connection.Name = newName;
|
||||
SendChatMessage($"ServerMessage.NameChangeSuccessful~[oldname]={oldName}~[newname]={newName}", ChatMessageType.Server);
|
||||
return true;
|
||||
}
|
||||
@@ -2797,7 +2820,7 @@ namespace Barotrauma.Networking
|
||||
DisconnectClient(client, logMsg, msg, reason, PlayerConnectionChangeType.Kicked);
|
||||
}
|
||||
|
||||
public override void BanPlayer(string playerName, string reason, bool range = false, TimeSpan? duration = null)
|
||||
public override void BanPlayer(string playerName, string reason, TimeSpan? duration = null)
|
||||
{
|
||||
Client client = connectedClients.Find(c =>
|
||||
c.Name.Equals(playerName, StringComparison.OrdinalIgnoreCase) ||
|
||||
@@ -2809,10 +2832,10 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
BanClient(client, reason, range, duration);
|
||||
BanClient(client, reason, duration);
|
||||
}
|
||||
|
||||
public void BanClient(Client client, string reason, bool range = false, TimeSpan? duration = null)
|
||||
public void BanClient(Client client, string reason, TimeSpan? duration = null)
|
||||
{
|
||||
if (client == null || client.Connection == OwnerConnection) { return; }
|
||||
|
||||
@@ -2827,45 +2850,32 @@ namespace Barotrauma.Networking
|
||||
string targetMsg = DisconnectReason.Banned.ToString();
|
||||
DisconnectClient(client, $"ServerMessage.BannedFromServer~[client]={client.Name}", targetMsg, reason, PlayerConnectionChangeType.Banned);
|
||||
|
||||
if (client.Connection is LidgrenConnection lidgrenConn && (client.SteamID == 0 || range))
|
||||
serverSettings.BanList.BanPlayer(client.Name, client.Connection.Endpoint, reason, duration);
|
||||
if (client.AccountInfo.AccountId.TryUnwrap(out var accountId))
|
||||
{
|
||||
string ip = "";
|
||||
ip = lidgrenConn.IPEndPoint.Address.IsIPv4MappedToIPv6 ?
|
||||
lidgrenConn.IPEndPoint.Address.MapToIPv4NoThrow().ToString() :
|
||||
lidgrenConn.IPEndPoint.Address.ToString();
|
||||
if (range) { ip = BanList.ToRange(ip); }
|
||||
serverSettings.BanList.BanPlayer(client.Name, ip, reason, duration);
|
||||
serverSettings.BanList.BanPlayer(client.Name, accountId, reason, duration);
|
||||
}
|
||||
if (client.SteamID > 0)
|
||||
foreach (var relatedId in client.AccountInfo.OtherMatchingIds)
|
||||
{
|
||||
serverSettings.BanList.BanPlayer(client.Name, client.SteamID, reason, duration);
|
||||
}
|
||||
if (client.OwnerSteamID > 0)
|
||||
{
|
||||
serverSettings.BanList.BanPlayer(client.Name, client.OwnerSteamID, reason, duration);
|
||||
serverSettings.BanList.BanPlayer(client.Name, relatedId, reason, duration);
|
||||
}
|
||||
}
|
||||
|
||||
public void BanPreviousPlayer(PreviousPlayer previousPlayer, string reason, bool range = false, TimeSpan? duration = null)
|
||||
public void BanPreviousPlayer(PreviousPlayer previousPlayer, string reason, TimeSpan? duration = null)
|
||||
{
|
||||
if (previousPlayer == null) { return; }
|
||||
|
||||
//reset karma to a neutral value, so if/when the ban is revoked the client wont get immediately punished by low karma again
|
||||
previousPlayer.Karma = Math.Max(previousPlayer.Karma, 50.0f);
|
||||
|
||||
if (!string.IsNullOrEmpty(previousPlayer.EndPoint) && (previousPlayer.SteamID == 0 || range))
|
||||
serverSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.Endpoint, reason, duration);
|
||||
if (previousPlayer.AccountInfo.AccountId.TryUnwrap(out var accountId))
|
||||
{
|
||||
string ip = previousPlayer.EndPoint;
|
||||
if (range) { ip = BanList.ToRange(ip); }
|
||||
serverSettings.BanList.BanPlayer(previousPlayer.Name, ip, reason, duration);
|
||||
serverSettings.BanList.BanPlayer(previousPlayer.Name, accountId, reason, duration);
|
||||
}
|
||||
if (previousPlayer.SteamID > 0)
|
||||
foreach (var relatedId in previousPlayer.AccountInfo.OtherMatchingIds)
|
||||
{
|
||||
serverSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.SteamID, reason, duration);
|
||||
}
|
||||
if (previousPlayer.OwnerSteamID > 0)
|
||||
{
|
||||
serverSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.OwnerSteamID, reason, duration);
|
||||
serverSettings.BanList.BanPlayer(previousPlayer.Name, relatedId, reason, duration);
|
||||
}
|
||||
|
||||
string msg = $"ServerMessage.BannedFromServer~[client]={previousPlayer.Name}";
|
||||
@@ -2876,16 +2886,17 @@ namespace Barotrauma.Networking
|
||||
SendChatMessage(msg, ChatMessageType.Server, changeType: PlayerConnectionChangeType.Banned);
|
||||
}
|
||||
|
||||
public override void UnbanPlayer(string playerName, string playerEndPoint)
|
||||
public override void UnbanPlayer(string playerName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(playerEndPoint))
|
||||
{
|
||||
serverSettings.BanList.UnbanEndPoint(playerEndPoint);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(playerName))
|
||||
{
|
||||
serverSettings.BanList.UnbanPlayer(playerName);
|
||||
}
|
||||
BannedPlayer bannedPlayer
|
||||
= serverSettings.BanList.BannedPlayers.FirstOrDefault(bp => bp.Name == playerName);
|
||||
if (bannedPlayer is null) { return; }
|
||||
serverSettings.BanList.UnbanPlayer(bannedPlayer.AddressOrAccountId);
|
||||
}
|
||||
|
||||
public override void UnbanPlayer(Endpoint endpoint)
|
||||
{
|
||||
serverSettings.BanList.UnbanPlayer(endpoint);
|
||||
}
|
||||
|
||||
public void DisconnectClient(NetworkConnection senderConnection, string msg = "", string targetmsg = "")
|
||||
@@ -2906,7 +2917,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (client == null) return;
|
||||
|
||||
if (gameStarted && client.Character != null)
|
||||
if (client.Character != null)
|
||||
{
|
||||
client.Character.ClientDisconnected = true;
|
||||
client.Character.ClearInputs();
|
||||
@@ -2925,7 +2936,7 @@ namespace Barotrauma.Networking
|
||||
targetmsg += $"/\n/ServerMessage.Reason/: /{reason}";
|
||||
}
|
||||
|
||||
if (client.SteamID != 0) { SteamManager.StopAuthSession(client.SteamID); }
|
||||
if (client.AccountId is Some<AccountId> { Value: SteamId steamId }) { SteamManager.StopAuthSession(steamId); }
|
||||
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(client));
|
||||
if (previousPlayer == null)
|
||||
@@ -3363,26 +3374,26 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void UpdateClientPermissions(Client client)
|
||||
{
|
||||
if (client.SteamID > 0)
|
||||
if (client.AccountId.TryUnwrap(out var accountId))
|
||||
{
|
||||
serverSettings.ClientPermissions.RemoveAll(cp => cp.SteamID == client.SteamID);
|
||||
serverSettings.ClientPermissions.RemoveAll(scp => scp.AddressOrAccountId == accountId);
|
||||
if (client.Permissions != ClientPermissions.None)
|
||||
{
|
||||
serverSettings.ClientPermissions.Add(new ServerSettings.SavedClientPermission(
|
||||
client.Name,
|
||||
client.SteamID,
|
||||
accountId,
|
||||
client.Permissions,
|
||||
client.PermittedConsoleCommands));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serverSettings.ClientPermissions.RemoveAll(cp => client.EndpointMatches(cp.EndPoint));
|
||||
serverSettings.ClientPermissions.RemoveAll(scp => client.Connection.Endpoint.Address == scp.AddressOrAccountId);
|
||||
if (client.Permissions != ClientPermissions.None)
|
||||
{
|
||||
serverSettings.ClientPermissions.Add(new ServerSettings.SavedClientPermission(
|
||||
client.Name,
|
||||
client.Connection.EndPointString,
|
||||
client.Connection.Endpoint.Address,
|
||||
client.Permissions,
|
||||
client.PermittedConsoleCommands));
|
||||
}
|
||||
@@ -3504,7 +3515,7 @@ namespace Barotrauma.Networking
|
||||
if (client.Character != null)
|
||||
{
|
||||
client.Character.IsRemotePlayer = false;
|
||||
client.Character.OwnerClientEndPoint = null;
|
||||
client.Character.OwnerClientEndpoint = null;
|
||||
client.Character.OwnerClientName = null;
|
||||
}
|
||||
|
||||
@@ -3531,7 +3542,7 @@ namespace Barotrauma.Networking
|
||||
newCharacter.Info.Character = newCharacter;
|
||||
}
|
||||
|
||||
newCharacter.OwnerClientEndPoint = client.Connection.EndPointString;
|
||||
newCharacter.OwnerClientEndpoint = client.Connection.Endpoint;
|
||||
newCharacter.OwnerClientName = client.Name;
|
||||
newCharacter.IsRemotePlayer = true;
|
||||
newCharacter.Enabled = true;
|
||||
@@ -3920,17 +3931,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public Tuple<ulong, string> FindPreviousClientData(Client client)
|
||||
{
|
||||
var player = previousPlayers.Find(p => p.MatchesClient(client));
|
||||
if (player != null)
|
||||
{
|
||||
return Tuple.Create(player.SteamID, player.EndPoint);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Disconnect()
|
||||
public override void Quit()
|
||||
{
|
||||
if (started)
|
||||
{
|
||||
@@ -3959,12 +3960,11 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
partial class PreviousPlayer
|
||||
class PreviousPlayer
|
||||
{
|
||||
public string Name;
|
||||
public string EndPoint;
|
||||
public UInt64 SteamID;
|
||||
public UInt64 OwnerSteamID;
|
||||
public Endpoint Endpoint;
|
||||
public AccountInfo AccountInfo;
|
||||
public float Karma;
|
||||
public int KarmaKickCount;
|
||||
public readonly List<Client> KickVoters = new List<Client>();
|
||||
@@ -3972,15 +3972,14 @@ namespace Barotrauma.Networking
|
||||
public PreviousPlayer(Client c)
|
||||
{
|
||||
Name = c.Name;
|
||||
EndPoint = c.Connection?.EndPointString ?? "";
|
||||
SteamID = c.SteamID;
|
||||
OwnerSteamID = c.OwnerSteamID;
|
||||
Endpoint = c.Connection.Endpoint;
|
||||
AccountInfo = c.AccountInfo;
|
||||
}
|
||||
|
||||
public bool MatchesClient(Client c)
|
||||
{
|
||||
if (c.SteamID > 0 && SteamID > 0) { return c.SteamID == SteamID; }
|
||||
return c.EndpointMatches(EndPoint);
|
||||
if (c.AccountInfo.AccountId.IsSome() && AccountInfo.AccountId.IsSome()) { return c.AccountInfo.AccountId == AccountInfo.AccountId; }
|
||||
return c.EndpointMatches(Endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Barotrauma.Steam;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -13,7 +14,7 @@ namespace Barotrauma.Networking
|
||||
msg.Write(SenderClient != null);
|
||||
if (SenderClient != null)
|
||||
{
|
||||
msg.Write((SenderClient.SteamID != 0) ? SenderClient.SteamID : SenderClient.ID);
|
||||
msg.Write(SenderClient.AccountId.TryUnwrap(out var accountId) ? accountId.StringRepresentation : SenderClient.SessionId.ToString());
|
||||
}
|
||||
msg.Write(Sender != null && c.InGame);
|
||||
if (Sender != null && c.InGame)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
using Barotrauma.Steam;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
@@ -13,7 +14,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
private readonly List<NetIncomingMessage> incomingLidgrenMessages;
|
||||
|
||||
public LidgrenServerPeer(int? ownKey, ServerSettings settings)
|
||||
public LidgrenServerPeer(Option<int> ownKey, ServerSettings settings)
|
||||
{
|
||||
serverSettings = settings;
|
||||
|
||||
@@ -184,7 +185,7 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
if (serverSettings.BanList.IsBanned(inc.SenderConnection.RemoteEndPoint.Address, 0, 0, out string banReason))
|
||||
if (serverSettings.BanList.IsBanned(new LidgrenEndpoint(inc.SenderConnection.RemoteEndPoint), out string banReason))
|
||||
{
|
||||
//IP banned: deny immediately
|
||||
inc.SenderConnection.Deny(DisconnectReason.Banned.ToString() + "/ " + banReason);
|
||||
@@ -195,7 +196,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (pendingClient == null)
|
||||
{
|
||||
pendingClient = new PendingClient(new LidgrenConnection("PENDING", inc.SenderConnection, 0));
|
||||
pendingClient = new PendingClient(new LidgrenConnection(inc.SenderConnection));
|
||||
pendingClients.Add(pendingClient);
|
||||
}
|
||||
|
||||
@@ -206,7 +207,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (netServer == null) { return; }
|
||||
|
||||
PendingClient pendingClient = pendingClients.Find(c => (c.Connection is LidgrenConnection l) && l.NetConnection == inc.SenderConnection);
|
||||
PendingClient pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == inc.SenderConnection);
|
||||
|
||||
PacketHeader packetHeader = (PacketHeader)inc.ReadByte();
|
||||
|
||||
@@ -231,7 +232,9 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
if (pendingClient != null) { pendingClients.Remove(pendingClient); }
|
||||
if (serverSettings.BanList.IsBanned(conn.IPEndPoint.Address, conn.SteamID, conn.OwnerSteamID, out string banReason))
|
||||
if (serverSettings.BanList.IsBanned(conn.Endpoint, out string banReason)
|
||||
|| (conn.AccountInfo.AccountId.TryUnwrap(out var accountId) && serverSettings.BanList.IsBanned(accountId, out banReason))
|
||||
|| conn.AccountInfo.OtherMatchingIds.Any(id => serverSettings.BanList.IsBanned(id, out banReason)))
|
||||
{
|
||||
Disconnect(conn, DisconnectReason.Banned.ToString() + "/ " + banReason);
|
||||
return;
|
||||
@@ -264,7 +267,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnectMsg = $"ServerMessage.HasDisconnected~[client]={conn.Name}";
|
||||
disconnectMsg = $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == conn).Name}";
|
||||
Disconnect(conn, disconnectMsg);
|
||||
}
|
||||
}
|
||||
@@ -285,18 +288,18 @@ namespace Barotrauma.Networking
|
||||
Steamworks.SteamServer.OnValidateAuthTicketResponse += OnAuthChange;
|
||||
}
|
||||
|
||||
private void OnAuthChange(Steamworks.SteamId steamID, Steamworks.SteamId ownerID, Steamworks.AuthResponse status)
|
||||
private void OnAuthChange(Steamworks.SteamId steamId, Steamworks.SteamId ownerId, Steamworks.AuthResponse status)
|
||||
{
|
||||
if (netServer == null) { return; }
|
||||
|
||||
PendingClient pendingClient = pendingClients.Find(c => c.SteamID == steamID);
|
||||
DebugConsole.Log(steamID + " validation: " + status+", "+(pendingClient!=null));
|
||||
PendingClient pendingClient = pendingClients.Find(c => c.AccountInfo.AccountId is Some<AccountId> { Value: SteamId id } && id.Value == steamId);
|
||||
DebugConsole.Log(steamId + " validation: " + status+", "+(pendingClient!=null));
|
||||
|
||||
if (pendingClient == null)
|
||||
{
|
||||
if (status != Steamworks.AuthResponse.OK)
|
||||
{
|
||||
LidgrenConnection connection = connectedClients.Find(c => c.SteamID == steamID) as LidgrenConnection;
|
||||
LidgrenConnection connection = connectedClients.Find(c => c.AccountInfo.AccountId is Some<AccountId> { Value: SteamId id } && id.Value == steamId) as LidgrenConnection;
|
||||
if (connection != null)
|
||||
{
|
||||
Disconnect(connection, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam authentication status changed: " + status.ToString());
|
||||
@@ -307,7 +310,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
LidgrenConnection pendingConnection = pendingClient.Connection as LidgrenConnection;
|
||||
string banReason;
|
||||
if (serverSettings.BanList.IsBanned(pendingConnection.NetConnection.RemoteEndPoint.Address, steamID, ownerID, out banReason))
|
||||
if (serverSettings.BanList.IsBanned(pendingConnection.Endpoint, out banReason)
|
||||
|| serverSettings.BanList.IsBanned(new SteamId(steamId), out banReason)
|
||||
|| serverSettings.BanList.IsBanned(new SteamId(ownerId), out banReason))
|
||||
{
|
||||
RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason);
|
||||
return;
|
||||
@@ -315,7 +320,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (status == Steamworks.AuthResponse.OK)
|
||||
{
|
||||
pendingClient.OwnerSteamID = ownerID;
|
||||
pendingClient.Connection.SetAccountInfo(new AccountInfo(new SteamId(steamId), new SteamId(ownerId)));
|
||||
pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
|
||||
pendingClient.UpdateTime = Timing.TotalTime;
|
||||
}
|
||||
@@ -333,7 +338,7 @@ namespace Barotrauma.Networking
|
||||
if (!(conn is LidgrenConnection lidgrenConn)) return;
|
||||
if (!connectedClients.Contains(lidgrenConn))
|
||||
{
|
||||
DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + lidgrenConn.IPString);
|
||||
DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + lidgrenConn.Endpoint.StringRepresentation);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -368,7 +373,7 @@ namespace Barotrauma.Networking
|
||||
NetSendResult result = netServer.SendMessage(lidgrenMsg, lidgrenConn.NetConnection, lidgrenDeliveryMethod);
|
||||
if (result != NetSendResult.Sent && result != NetSendResult.Queued)
|
||||
{
|
||||
DebugConsole.NewMessage("Failed to send message to "+conn.Name+": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow);
|
||||
DebugConsole.NewMessage("Failed to send message to "+conn.Endpoint.StringRepresentation+": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +387,7 @@ namespace Barotrauma.Networking
|
||||
lidgrenConn.Status = NetworkConnectionStatus.Disconnected;
|
||||
connectedClients.Remove(lidgrenConn);
|
||||
OnDisconnect?.Invoke(conn, msg);
|
||||
Steam.SteamManager.StopAuthSession(conn.SteamID);
|
||||
if (conn.AccountInfo.AccountId is Some<AccountId> { Value: SteamId steamId }) { Steam.SteamManager.StopAuthSession(steamId); }
|
||||
}
|
||||
lidgrenConn.NetConnection.Disconnect(msg ?? "Disconnected");
|
||||
}
|
||||
@@ -409,25 +414,25 @@ namespace Barotrauma.Networking
|
||||
NetSendResult result = netServer.SendMessage(lidgrenMsg, lidgrenConn.NetConnection, lidgrenDeliveryMethod);
|
||||
if (result != NetSendResult.Sent && result != NetSendResult.Queued)
|
||||
{
|
||||
DebugConsole.NewMessage("Failed to send message to " + conn.Name + ": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow);
|
||||
DebugConsole.NewMessage("Failed to send message to " + conn.Endpoint.StringRepresentation + ": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CheckOwnership(PendingClient pendingClient)
|
||||
{
|
||||
LidgrenConnection l = pendingClient.Connection as LidgrenConnection;
|
||||
if (OwnerConnection == null &&
|
||||
IPAddress.IsLoopback(l.NetConnection.RemoteEndPoint.Address.MapToIPv4NoThrow()) &&
|
||||
ownerKey != null && pendingClient.OwnerKey != 0 && pendingClient.OwnerKey == ownerKey)
|
||||
if (OwnerConnection == null
|
||||
&& pendingClient.Connection is LidgrenConnection l
|
||||
&& IPAddress.IsLoopback(l.NetConnection.RemoteEndPoint.Address)
|
||||
&& ownerKey.IsSome() && pendingClient.OwnerKey == ownerKey)
|
||||
{
|
||||
ownerKey = null;
|
||||
ownerKey = Option<int>.None();
|
||||
OwnerConnection = pendingClient.Connection;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ProcessAuthTicket(string name, int ownKey, ulong steamId, PendingClient pendingClient, byte[] ticket)
|
||||
protected override void ProcessAuthTicket(string name, Option<int> ownKey, Option<SteamId> steamId, PendingClient pendingClient, byte[] ticket)
|
||||
{
|
||||
if (pendingClient.SteamID == null)
|
||||
if (pendingClient.AccountInfo.AccountId.IsNone())
|
||||
{
|
||||
bool requireSteamAuth = GameSettings.CurrentConfig.RequireSteamAuthentication;
|
||||
#if DEBUG
|
||||
@@ -436,32 +441,42 @@ namespace Barotrauma.Networking
|
||||
|
||||
//steam auth cannot be done (SteamManager not initialized or no ticket given),
|
||||
//but it's not required either -> let the client join without auth
|
||||
if ((!Steam.SteamManager.IsInitialized || (ticket?.Length ?? 0) == 0) &&
|
||||
!requireSteamAuth)
|
||||
if ((!SteamManager.IsInitialized || (ticket?.Length ?? 0) == 0)
|
||||
&& !requireSteamAuth)
|
||||
{
|
||||
pendingClient.Connection.Name = name;
|
||||
pendingClient.Name = name;
|
||||
pendingClient.OwnerKey = ownKey;
|
||||
pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
|
||||
}
|
||||
else
|
||||
{
|
||||
Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId);
|
||||
if (authSessionStartState != Steamworks.BeginAuthResult.OK)
|
||||
if (!steamId.TryUnwrap(out var id))
|
||||
{
|
||||
if (requireSteamAuth)
|
||||
{
|
||||
RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString());
|
||||
RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: Steam ID not provided");
|
||||
return;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, id);
|
||||
if (authSessionStartState != Steamworks.BeginAuthResult.OK)
|
||||
{
|
||||
steamId = 0;
|
||||
pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
|
||||
if (requireSteamAuth)
|
||||
{
|
||||
RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString());
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
steamId = Option<SteamId>.None();
|
||||
pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
|
||||
}
|
||||
}
|
||||
}
|
||||
pendingClient.SteamID = steamId;
|
||||
pendingClient.Connection.Name = name;
|
||||
|
||||
pendingClient.Connection.SetAccountInfo(new AccountInfo(steamId.Select(uid => (AccountId)uid)));
|
||||
pendingClient.Name = name;
|
||||
pendingClient.OwnerKey = ownKey;
|
||||
pendingClient.AuthSessionStarted = true;
|
||||
@@ -469,7 +484,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pendingClient.SteamID != steamId)
|
||||
if (pendingClient.AccountInfo.AccountId != steamId.Select(uid => (AccountId)uid))
|
||||
{
|
||||
RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "SteamID mismatch");
|
||||
return;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -10,7 +9,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
public delegate void MessageCallback(NetworkConnection connection, IReadMessage message);
|
||||
public delegate void DisconnectCallback(NetworkConnection connection, string reason);
|
||||
public delegate void InitializationCompleteCallback(NetworkConnection connection);
|
||||
public delegate void InitializationCompleteCallback(NetworkConnection connection, string clientName);
|
||||
public delegate void ShutdownCallback();
|
||||
public delegate void OwnerDeterminedCallback(NetworkConnection connection);
|
||||
|
||||
@@ -20,7 +19,7 @@ namespace Barotrauma.Networking
|
||||
public ShutdownCallback OnShutdown;
|
||||
public OwnerDeterminedCallback OnOwnerDetermined;
|
||||
|
||||
protected int? ownerKey;
|
||||
protected Option<int> ownerKey;
|
||||
|
||||
public NetworkConnection OwnerConnection { get; protected set; }
|
||||
|
||||
@@ -33,43 +32,23 @@ namespace Barotrauma.Networking
|
||||
protected class PendingClient
|
||||
{
|
||||
public string Name;
|
||||
public int OwnerKey;
|
||||
public Option<int> OwnerKey;
|
||||
public NetworkConnection Connection;
|
||||
public ConnectionInitialization InitializationStep;
|
||||
public double UpdateTime;
|
||||
public double TimeOut;
|
||||
public int Retries;
|
||||
private UInt64? steamId;
|
||||
public UInt64? SteamID
|
||||
{
|
||||
get { return steamId; }
|
||||
set
|
||||
{
|
||||
steamId = value;
|
||||
Connection.SetSteamIDIfUnknown(value ?? 0);
|
||||
}
|
||||
}
|
||||
private UInt64? ownerSteamId;
|
||||
public UInt64? OwnerSteamID
|
||||
{
|
||||
get { return ownerSteamId; }
|
||||
set
|
||||
{
|
||||
ownerSteamId = value;
|
||||
Connection.SetOwnerSteamIDIfUnknown(value ?? 0);
|
||||
}
|
||||
}
|
||||
public Int32? PasswordSalt;
|
||||
public bool AuthSessionStarted;
|
||||
|
||||
public AccountInfo AccountInfo => Connection.AccountInfo;
|
||||
|
||||
public PendingClient(NetworkConnection conn)
|
||||
{
|
||||
OwnerKey = 0;
|
||||
OwnerKey = Option<int>.None();
|
||||
Connection = conn;
|
||||
InitializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
||||
Retries = 0;
|
||||
SteamID = null;
|
||||
OwnerSteamID = null;
|
||||
PasswordSalt = null;
|
||||
UpdateTime = Timing.TotalTime + Timing.Step * 3.0;
|
||||
TimeOut = NetworkConnection.TimeoutThreshold;
|
||||
@@ -101,7 +80,10 @@ namespace Barotrauma.Networking
|
||||
case ConnectionInitialization.SteamTicketAndVersion:
|
||||
string name = Client.SanitizeName(inc.ReadString());
|
||||
int ownerKey = inc.ReadInt32();
|
||||
UInt64 steamId = inc.ReadUInt64();
|
||||
UInt64 steamIdVal = inc.ReadUInt64();
|
||||
Option<SteamId> steamId = steamIdVal != 0
|
||||
? Option<SteamId>.Some(new SteamId(steamIdVal))
|
||||
: Option<SteamId>.None();
|
||||
UInt16 ticketLength = inc.ReadUInt16();
|
||||
byte[] ticketBytes = inc.ReadBytes(ticketLength);
|
||||
|
||||
@@ -136,7 +118,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (!pendingClient.AuthSessionStarted)
|
||||
{
|
||||
ProcessAuthTicket(name, ownerKey, steamId, pendingClient, ticketBytes);
|
||||
ProcessAuthTicket(name, ownerKey != 0 ? Option<int>.Some(ownerKey) : Option<int>.None(), steamId, pendingClient, ticketBytes);
|
||||
}
|
||||
break;
|
||||
case ConnectionInitialization.Password:
|
||||
@@ -172,34 +154,37 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void ProcessAuthTicket(string name, int ownKey, ulong steamId, PendingClient pendingClient, byte[] ticket);
|
||||
protected abstract void ProcessAuthTicket(string name, Option<int> ownKey, Option<SteamId> steamId, PendingClient pendingClient, byte[] ticket);
|
||||
|
||||
protected void BanPendingClient(PendingClient pendingClient, string banReason, TimeSpan? duration)
|
||||
{
|
||||
if (pendingClient.Connection is LidgrenConnection l)
|
||||
void banAccountId(AccountId accountId)
|
||||
{
|
||||
serverSettings.BanList.BanPlayer(pendingClient.Name, l.NetConnection.RemoteEndPoint.Address, banReason, duration);
|
||||
}
|
||||
else if (pendingClient.Connection is SteamP2PConnection s)
|
||||
{
|
||||
serverSettings.BanList.BanPlayer(pendingClient.Name, s.SteamID, banReason, duration);
|
||||
serverSettings.BanList.BanPlayer(pendingClient.Name, s.OwnerSteamID, banReason, duration);
|
||||
serverSettings.BanList.BanPlayer(pendingClient.Name, accountId, banReason, duration);
|
||||
}
|
||||
|
||||
if (pendingClient.AccountInfo.AccountId.TryUnwrap(out var id)) { banAccountId(id); }
|
||||
pendingClient.AccountInfo.OtherMatchingIds.ForEach(banAccountId);
|
||||
serverSettings.BanList.BanPlayer(pendingClient.Name, pendingClient.Connection.Endpoint, banReason, duration);
|
||||
}
|
||||
|
||||
|
||||
protected bool IsPendingClientBanned(PendingClient pendingClient, out string banReason)
|
||||
{
|
||||
if (pendingClient.Connection is LidgrenConnection l)
|
||||
bool isAccountIdBanned(AccountId accountId, out string banReason)
|
||||
{
|
||||
return serverSettings.BanList.IsBanned(l.NetConnection.RemoteEndPoint.Address, out banReason);
|
||||
banReason = default;
|
||||
return serverSettings.BanList.IsBanned(accountId, out banReason);
|
||||
}
|
||||
else if (pendingClient.Connection is SteamP2PConnection s)
|
||||
|
||||
banReason = default;
|
||||
bool isBanned = pendingClient.AccountInfo.AccountId.TryUnwrap(out var id)
|
||||
&& isAccountIdBanned(id, out banReason);
|
||||
foreach (var otherId in pendingClient.AccountInfo.OtherMatchingIds)
|
||||
{
|
||||
return serverSettings.BanList.IsBanned(s.SteamID, out banReason) ||
|
||||
serverSettings.BanList.IsBanned(s.OwnerSteamID, out banReason);
|
||||
if (isBanned) { break; }
|
||||
isBanned |= isAccountIdBanned(otherId, out banReason);
|
||||
}
|
||||
banReason = null;
|
||||
return false;
|
||||
return isBanned;
|
||||
}
|
||||
|
||||
protected abstract void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg);
|
||||
@@ -225,7 +210,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
CheckOwnership(pendingClient);
|
||||
|
||||
OnInitializationComplete?.Invoke(newConnection);
|
||||
OnInitializationComplete?.Invoke(newConnection, pendingClient.Name);
|
||||
}
|
||||
|
||||
pendingClient.TimeOut -= Timing.Step;
|
||||
@@ -244,8 +229,6 @@ namespace Barotrauma.Networking
|
||||
switch (pendingClient.InitializationStep)
|
||||
{
|
||||
case ConnectionInitialization.ContentPackageOrder:
|
||||
outMsg.Write(GameMain.Server.ServerName);
|
||||
|
||||
var mpContentPackages = ContentPackageManager.EnabledPackages.All.Where(cp => cp.HasMultiplayerSyncedContent).ToList();
|
||||
outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count);
|
||||
for (int i = 0; i < mpContentPackages.Count; i++)
|
||||
@@ -286,11 +269,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
pendingClients.Remove(pendingClient);
|
||||
|
||||
if (pendingClient.AuthSessionStarted)
|
||||
if (pendingClient.AuthSessionStarted && pendingClient.AccountInfo.AccountId is Some<AccountId> { Value: SteamId steamId })
|
||||
{
|
||||
Steam.SteamManager.StopAuthSession(pendingClient.SteamID.Value);
|
||||
pendingClient.SteamID = null;
|
||||
pendingClient.OwnerSteamID = null;
|
||||
Steam.SteamManager.StopAuthSession(steamId);
|
||||
pendingClient.Connection.SetAccountInfo(AccountInfo.None);
|
||||
pendingClient.AuthSessionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -10,29 +8,25 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
private bool started;
|
||||
|
||||
public UInt64 OwnerSteamID
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
private readonly SteamId ownerSteamId;
|
||||
|
||||
private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Value);
|
||||
private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Fallback(0));
|
||||
|
||||
private UInt64 ReadSteamId(IReadMessage inc)
|
||||
=> inc.ReadUInt64() ^ ownerKey64;
|
||||
private void WriteSteamId(IWriteMessage msg, UInt64 val)
|
||||
=> msg.Write(val ^ ownerKey64);
|
||||
private SteamId ReadSteamId(IReadMessage inc)
|
||||
=> new SteamId(inc.ReadUInt64() ^ ownerKey64);
|
||||
private void WriteSteamId(IWriteMessage msg, SteamId val)
|
||||
=> msg.Write(val.Value ^ ownerKey64);
|
||||
|
||||
public SteamP2PServerPeer(UInt64 steamId, int ownerKey, ServerSettings settings)
|
||||
public SteamP2PServerPeer(SteamId steamId, int ownerKey, ServerSettings settings)
|
||||
{
|
||||
serverSettings = settings;
|
||||
|
||||
connectedClients = new List<NetworkConnection>();
|
||||
pendingClients = new List<PendingClient>();
|
||||
|
||||
this.ownerKey = ownerKey;
|
||||
this.ownerKey = Option<int>.Some(ownerKey);
|
||||
|
||||
OwnerSteamID = steamId;
|
||||
ownerSteamId = steamId;
|
||||
|
||||
started = false;
|
||||
}
|
||||
@@ -40,7 +34,7 @@ namespace Barotrauma.Networking
|
||||
public override void Start()
|
||||
{
|
||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||
WriteSteamId(outMsg, OwnerSteamID);
|
||||
WriteSteamId(outMsg, ownerSteamId);
|
||||
outMsg.Write((byte)DeliveryMethod.Reliable);
|
||||
outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage));
|
||||
|
||||
@@ -129,9 +123,9 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!started) { return; }
|
||||
|
||||
UInt64 senderSteamId = ReadSteamId(inc);
|
||||
UInt64 ownerSteamId = ReadSteamId(inc);
|
||||
|
||||
SteamId senderSteamId = ReadSteamId(inc);
|
||||
SteamId ownerSteamId = ReadSteamId(inc);
|
||||
|
||||
PacketHeader packetHeader = (PacketHeader)inc.ReadByte();
|
||||
|
||||
if (packetHeader.IsServerMessage())
|
||||
@@ -140,11 +134,14 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
if (senderSteamId != OwnerSteamID) //sender is remote, handle disconnects and heartbeats
|
||||
if (senderSteamId != this.ownerSteamId) //sender is remote, handle disconnects and heartbeats
|
||||
{
|
||||
PendingClient pendingClient = pendingClients.Find(c => c.SteamID == senderSteamId);
|
||||
SteamP2PConnection connectedClient = connectedClients.Find(c => c.SteamID == senderSteamId) as SteamP2PConnection;
|
||||
|
||||
bool connectionMatches(NetworkConnection conn)
|
||||
=> conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var steamId } }
|
||||
&& steamId == senderSteamId;
|
||||
PendingClient pendingClient = pendingClients.Find(c => connectionMatches(c.Connection));
|
||||
SteamP2PConnection connectedClient = connectedClients.Find(connectionMatches) as SteamP2PConnection;
|
||||
|
||||
pendingClient?.Heartbeat();
|
||||
connectedClient?.Heartbeat();
|
||||
|
||||
@@ -171,7 +168,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else if (connectedClient != null)
|
||||
{
|
||||
string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={connectedClient.Name}";
|
||||
string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == connectedClient).Name}";
|
||||
Disconnect(connectedClient, disconnectMsg, false);
|
||||
}
|
||||
return;
|
||||
@@ -183,13 +180,9 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else if (packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
|
||||
if (pendingClient != null)
|
||||
{
|
||||
if (ownerSteamId != 0)
|
||||
{
|
||||
pendingClient.Connection.SetOwnerSteamIDIfUnknown(ownerSteamId);
|
||||
}
|
||||
pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, ownerSteamId));
|
||||
ReadConnectionInitializationStep(pendingClient, new ReadOnlyMessage(inc.Buffer, false, inc.BytePosition, inc.LengthBytes - inc.BytePosition, null));
|
||||
}
|
||||
else
|
||||
@@ -197,7 +190,7 @@ namespace Barotrauma.Networking
|
||||
ConnectionInitialization initializationStep = (ConnectionInitialization)inc.ReadByte();
|
||||
if (initializationStep == ConnectionInitialization.ConnectionStarted)
|
||||
{
|
||||
pendingClients.Add(new PendingClient(new SteamP2PConnection("PENDING", senderSteamId)) { SteamID = senderSteamId });
|
||||
pendingClients.Add(new PendingClient(new SteamP2PConnection(senderSteamId)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,13 +221,13 @@ namespace Barotrauma.Networking
|
||||
if (OwnerConnection == null)
|
||||
{
|
||||
string ownerName = inc.ReadString();
|
||||
OwnerConnection = new SteamP2PConnection(ownerName, OwnerSteamID)
|
||||
OwnerConnection = new SteamP2PConnection(this.ownerSteamId)
|
||||
{
|
||||
Language = GameSettings.CurrentConfig.Language
|
||||
};
|
||||
OwnerConnection.SetOwnerSteamIDIfUnknown(OwnerSteamID);
|
||||
OwnerConnection.SetAccountInfo(new AccountInfo(this.ownerSteamId, this.ownerSteamId));
|
||||
|
||||
OnInitializationComplete?.Invoke(OwnerConnection);
|
||||
OnInitializationComplete?.Invoke(OwnerConnection, ownerName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -261,17 +254,19 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!started) { return; }
|
||||
|
||||
if (!(conn is SteamP2PConnection steamp2pConn)) return;
|
||||
if (!(conn is SteamP2PConnection steamp2pConn)) { return; }
|
||||
if (!connectedClients.Contains(steamp2pConn) && conn != OwnerConnection)
|
||||
{
|
||||
DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + steamp2pConn.SteamID.ToString());
|
||||
DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + steamp2pConn.AccountInfo.AccountId.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; }
|
||||
|
||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||
byte[] msgData = new byte[16];
|
||||
msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length);
|
||||
WriteSteamId(msgToSend, conn.SteamID);
|
||||
WriteSteamId(msgToSend, connSteamId);
|
||||
msgToSend.Write((byte)deliveryMethod);
|
||||
msgToSend.Write((byte)((isCompressed ? PacketHeader.IsCompressed : PacketHeader.None) | PacketHeader.IsServerMessage));
|
||||
msgToSend.Write((UInt16)length);
|
||||
@@ -282,7 +277,7 @@ namespace Barotrauma.Networking
|
||||
ChildServerRelay.Write(bufToSend);
|
||||
}
|
||||
|
||||
private void SendDisconnectMessage(UInt64 steamId, string msg)
|
||||
private void SendDisconnectMessage(SteamId steamId, string msg)
|
||||
{
|
||||
if (!started) { return; }
|
||||
if (string.IsNullOrWhiteSpace(msg)) { return; }
|
||||
@@ -303,13 +298,16 @@ namespace Barotrauma.Networking
|
||||
if (!started) { return; }
|
||||
|
||||
if (!(conn is SteamP2PConnection steamp2pConn)) { return; }
|
||||
if (sendDisconnectMessage) { SendDisconnectMessage(steamp2pConn.SteamID, msg); }
|
||||
|
||||
if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; }
|
||||
|
||||
if (sendDisconnectMessage) { SendDisconnectMessage(connSteamId, msg); }
|
||||
if (connectedClients.Contains(steamp2pConn))
|
||||
{
|
||||
steamp2pConn.Status = NetworkConnectionStatus.Disconnected;
|
||||
connectedClients.Remove(steamp2pConn);
|
||||
OnDisconnect?.Invoke(conn, msg);
|
||||
Steam.SteamManager.StopAuthSession(conn.SteamID);
|
||||
Steam.SteamManager.StopAuthSession(connSteamId);
|
||||
}
|
||||
else if (steamp2pConn == OwnerConnection)
|
||||
{
|
||||
@@ -324,8 +322,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
protected override void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg)
|
||||
{
|
||||
var connSteamId = conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var id } }
|
||||
? id : null;
|
||||
if (connSteamId is null) { return; }
|
||||
|
||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||
WriteSteamId(msgToSend, conn.SteamID);
|
||||
WriteSteamId(msgToSend, connSteamId);
|
||||
msgToSend.Write((byte)deliveryMethod);
|
||||
msgToSend.Write(msg.Buffer, 0, msg.LengthBytes);
|
||||
byte[] bufToSend = (byte[])msgToSend.Buffer.Clone();
|
||||
@@ -333,11 +335,10 @@ namespace Barotrauma.Networking
|
||||
ChildServerRelay.Write(bufToSend);
|
||||
}
|
||||
|
||||
protected override void ProcessAuthTicket(string name, int ownKey, ulong steamId, PendingClient pendingClient, byte[] ticket)
|
||||
protected override void ProcessAuthTicket(string name, Option<int> ownKey, Option<SteamId> steamId, PendingClient pendingClient, byte[] ticket)
|
||||
{
|
||||
pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
|
||||
|
||||
pendingClient.Connection.Name = name;
|
||||
pendingClient.Name = name;
|
||||
pendingClient.AuthSessionStarted = true;
|
||||
}
|
||||
|
||||
@@ -444,26 +444,28 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
clients[i].Character = character;
|
||||
character.OwnerClientEndPoint = clients[i].Connection.EndPointString;
|
||||
character.OwnerClientEndpoint = clients[i].Connection.Endpoint;
|
||||
character.OwnerClientName = clients[i].Name;
|
||||
GameServer.Log(string.Format("Respawning {0} ({1}) as {2}", GameServer.ClientLogName(clients[i]), clients[i].Connection?.EndPointString, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning);
|
||||
GameServer.Log(
|
||||
$"Respawning {GameServer.ClientLogName(clients[i])} ({clients[i].Connection.Endpoint}) as {characterInfos[i].Job.Name}", ServerLog.MessageType.Spawning);
|
||||
}
|
||||
|
||||
if (RespawnShuttle != null)
|
||||
{
|
||||
Vector2 pos = cargoSp == null ? character.Position : cargoSp.Position;
|
||||
List<Item> newRespawnItems = new List<Item>();
|
||||
Vector2 pos = cargoSp?.Position ?? character.Position;
|
||||
if (divingSuitPrefab != null)
|
||||
{
|
||||
var divingSuit = new Item(divingSuitPrefab, pos, respawnSub);
|
||||
Spawner.CreateNetworkEvent(new EntitySpawner.SpawnEntity(divingSuit));
|
||||
respawnItems.Add(divingSuit);
|
||||
newRespawnItems.Add(divingSuit);
|
||||
|
||||
if (oxyPrefab != null && divingSuit.GetComponent<ItemContainer>() != null)
|
||||
{
|
||||
var oxyTank = new Item(oxyPrefab, pos, respawnSub);
|
||||
Spawner.CreateNetworkEvent(new EntitySpawner.SpawnEntity(oxyTank));
|
||||
divingSuit.Combine(oxyTank, user: null);
|
||||
respawnItems.Add(oxyTank);
|
||||
newRespawnItems.Add(oxyTank);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,13 +475,13 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
var scooter = new Item(scooterPrefab, pos, respawnSub);
|
||||
Spawner.CreateNetworkEvent(new EntitySpawner.SpawnEntity(scooter));
|
||||
respawnItems.Add(scooter);
|
||||
newRespawnItems.Add(scooter);
|
||||
if (batteryPrefab != null)
|
||||
{
|
||||
var battery = new Item(batteryPrefab, pos, respawnSub);
|
||||
Spawner.CreateNetworkEvent(new EntitySpawner.SpawnEntity(battery));
|
||||
scooter.Combine(battery, user: null);
|
||||
respawnItems.Add(battery);
|
||||
newRespawnItems.Add(battery);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -489,8 +491,9 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
//try to put the items in containers in the shuttle
|
||||
foreach (var respawnItem in respawnItems)
|
||||
foreach (var respawnItem in newRespawnItems)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(!respawnItem.Removed);
|
||||
foreach (Item shuttleItem in RespawnShuttle.GetItems(alsoFromConnectedSubs: false))
|
||||
{
|
||||
if (shuttleItem.NonInteractable || shuttleItem.NonPlayerTeamInteractable) { continue; }
|
||||
@@ -500,6 +503,7 @@ namespace Barotrauma.Networking
|
||||
break;
|
||||
}
|
||||
}
|
||||
respawnItems.Add(respawnItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ namespace Barotrauma.Networking
|
||||
WriteNetProperties(outMsg, c);
|
||||
WriteMonsterEnabled(outMsg);
|
||||
BanList.ServerAdminWrite(outMsg, c);
|
||||
Whitelist.ServerAdminWrite(outMsg, c);
|
||||
}
|
||||
|
||||
public void ServerWrite(IWriteMessage outMsg, Client c)
|
||||
@@ -171,7 +170,6 @@ namespace Barotrauma.Networking
|
||||
propertiesChanged |= changedMonsterSettings;
|
||||
if (changedMonsterSettings) { ReadMonsterEnabled(incMsg); }
|
||||
propertiesChanged |= BanList.ServerAdminRead(incMsg, c);
|
||||
propertiesChanged |= Whitelist.ServerAdminRead(incMsg, c);
|
||||
|
||||
if (propertiesChanged)
|
||||
{
|
||||
@@ -444,31 +442,27 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
ClientPermissions.Clear();
|
||||
|
||||
if (!File.Exists(ClientPermissionsFile))
|
||||
{
|
||||
if (File.Exists("Data/clientpermissions.txt"))
|
||||
{
|
||||
LoadClientPermissionsOld("Data/clientpermissions.txt");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!File.Exists(ClientPermissionsFile)) { return; }
|
||||
|
||||
XDocument doc = XMLExtensions.TryLoadXml(ClientPermissionsFile);
|
||||
if (doc == null) { return; }
|
||||
foreach (XElement clientElement in doc.Root.Elements())
|
||||
{
|
||||
string clientName = clientElement.GetAttributeString("name", "");
|
||||
string clientEndPoint = clientElement.GetAttributeString("endpoint", null) ?? clientElement.GetAttributeString("ip", "");
|
||||
string steamIdStr = clientElement.GetAttributeString("steamid", "");
|
||||
string addressStr = clientElement.GetAttributeString("address", null)
|
||||
?? clientElement.GetAttributeString("endpoint", null)
|
||||
?? clientElement.GetAttributeString("ip", "");
|
||||
string accountIdStr = clientElement.GetAttributeString("accountid", null)
|
||||
?? clientElement.GetAttributeString("steamid", "");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(clientName))
|
||||
{
|
||||
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - all clients must have a name and an IP address.");
|
||||
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - all clients must have a name.");
|
||||
continue;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(clientEndPoint) && string.IsNullOrWhiteSpace(steamIdStr))
|
||||
if (string.IsNullOrWhiteSpace(addressStr) && string.IsNullOrWhiteSpace(accountIdStr))
|
||||
{
|
||||
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - all clients must have an IP address or a Steam ID.");
|
||||
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - all clients must have an endpoint or a Steam ID.");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -525,69 +519,33 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(steamIdStr))
|
||||
if (!string.IsNullOrEmpty(accountIdStr))
|
||||
{
|
||||
if (ulong.TryParse(steamIdStr, out ulong steamID))
|
||||
if (AccountId.Parse(accountIdStr).TryUnwrap(out var accountId))
|
||||
{
|
||||
ClientPermissions.Add(new SavedClientPermission(clientName, steamID, permissions, permittedCommands));
|
||||
ClientPermissions.Add(new SavedClientPermission(clientName, accountId, permissions, permittedCommands));
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - \"" + steamIdStr + "\" is not a valid Steam ID.");
|
||||
continue;
|
||||
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - \"" + accountIdStr + "\" is not a valid account ID.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientPermissions.Add(new SavedClientPermission(clientName, clientEndPoint, permissions, permittedCommands));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method for loading old .txt client permission files to provide backwards compatibility
|
||||
/// </summary>
|
||||
private void LoadClientPermissionsOld(string file)
|
||||
{
|
||||
if (!File.Exists(file)) return;
|
||||
|
||||
string[] lines;
|
||||
try
|
||||
{
|
||||
lines = File.ReadAllLines(file);
|
||||
}
|
||||
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;
|
||||
if (Enum.TryParse(separatedLine.Last(), out permissions))
|
||||
{
|
||||
ClientPermissions.Add(new SavedClientPermission(name, ip, permissions, new HashSet<DebugConsole.Command>()));
|
||||
if (Address.Parse(addressStr).TryUnwrap(out var address))
|
||||
{
|
||||
ClientPermissions.Add(new SavedClientPermission(clientName, address, permissions, permittedCommands));
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - \"" + addressStr + "\" is not a valid endpoint.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveClientPermissions()
|
||||
{
|
||||
//delete old client permission file
|
||||
if (File.Exists("Data/clientpermissions.txt"))
|
||||
{
|
||||
File.Delete("Data/clientpermissions.txt");
|
||||
}
|
||||
|
||||
GameServer.Log("Saving client permissions", ServerLog.MessageType.ServerMessage);
|
||||
|
||||
XDocument doc = new XDocument(new XElement("ClientPermissions"));
|
||||
@@ -595,6 +553,7 @@ namespace Barotrauma.Networking
|
||||
foreach (SavedClientPermission clientPermission in ClientPermissions)
|
||||
{
|
||||
var matchingPreset = PermissionPreset.List.Find(p => p.MatchesPermissions(clientPermission.Permissions, clientPermission.PermittedCommands));
|
||||
#warning TODO: this is broken because of localization
|
||||
if (matchingPreset != null && matchingPreset.Name == "None")
|
||||
{
|
||||
continue;
|
||||
@@ -603,23 +562,14 @@ namespace Barotrauma.Networking
|
||||
XElement clientElement = new XElement("Client",
|
||||
new XAttribute("name", clientPermission.Name));
|
||||
|
||||
if (clientPermission.SteamID > 0)
|
||||
{
|
||||
clientElement.Add(new XAttribute("steamid", clientPermission.SteamID));
|
||||
}
|
||||
else
|
||||
{
|
||||
clientElement.Add(new XAttribute("endpoint", clientPermission.EndPoint));
|
||||
}
|
||||
clientElement.Add(clientPermission.AddressOrAccountId.TryGet(out AccountId accountId)
|
||||
? new XAttribute("accountid", accountId.StringRepresentation)
|
||||
: new XAttribute("address", ((Address)clientPermission.AddressOrAccountId).StringRepresentation));
|
||||
|
||||
if (matchingPreset == null)
|
||||
{
|
||||
clientElement.Add(new XAttribute("permissions", clientPermission.Permissions.ToString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
clientElement.Add(new XAttribute("preset", matchingPreset.Name));
|
||||
}
|
||||
clientElement.Add(matchingPreset == null
|
||||
? new XAttribute("permissions", clientPermission.Permissions.ToString())
|
||||
: new XAttribute("preset", matchingPreset.Name));
|
||||
|
||||
if (clientPermission.Permissions.HasFlag(Networking.ClientPermissions.ConsoleCommands))
|
||||
{
|
||||
foreach (DebugConsole.Command command in clientPermission.PermittedCommands)
|
||||
|
||||
@@ -257,11 +257,10 @@ namespace Barotrauma
|
||||
if ((DateTime.Now - sender.JoinTime).TotalSeconds > GameMain.Server.ServerSettings.DisallowKickVoteTime)
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage($"ServerMessage.kickvotedisallowed", sender);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Client kicked = GameMain.Server.ConnectedClients.Find(c => c.ID == kickedClientID);
|
||||
Client kicked = GameMain.Server.ConnectedClients.Find(c => c.SessionId == kickedClientID);
|
||||
if (kicked != null && kicked.Connection != GameMain.Server.OwnerConnection && !kicked.HasKickVoteFrom(sender))
|
||||
{
|
||||
kicked.AddKickVote(sender);
|
||||
@@ -293,9 +292,9 @@ namespace Barotrauma
|
||||
if (!ShouldRejectVote(sender, voteType))
|
||||
{
|
||||
pendingVotes.Enqueue(new TransferVote(sender,
|
||||
GameMain.Server.ConnectedClients.Find(c => c.ID == fromClientId),
|
||||
GameMain.Server.ConnectedClients.Find(c => c.SessionId == fromClientId),
|
||||
amount,
|
||||
GameMain.Server.ConnectedClients.Find(c => c.ID == toClientId)));
|
||||
GameMain.Server.ConnectedClients.Find(c => c.SessionId == toClientId)));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -372,14 +371,14 @@ namespace Barotrauma
|
||||
msg.Write((byte)yesClients.Count());
|
||||
foreach (Client c in yesClients)
|
||||
{
|
||||
msg.Write(c.ID);
|
||||
msg.Write(c.SessionId);
|
||||
}
|
||||
|
||||
var noClients = eligibleClients.Where(c => c.GetVote<int>(ActiveVote.VoteType) == 1);
|
||||
msg.Write((byte)noClients.Count());
|
||||
foreach (Client c in noClients)
|
||||
{
|
||||
msg.Write(c.ID);
|
||||
msg.Write(c.SessionId);
|
||||
}
|
||||
|
||||
msg.Write((byte)eligibleClients.Count());
|
||||
@@ -387,7 +386,7 @@ namespace Barotrauma
|
||||
switch (ActiveVote.State)
|
||||
{
|
||||
case VoteState.Started:
|
||||
msg.Write(ActiveVote.VoteStarter.ID);
|
||||
msg.Write(ActiveVote.VoteStarter.SessionId);
|
||||
msg.Write((byte)GameMain.Server.ServerSettings.VoteTimeout);
|
||||
|
||||
switch (ActiveVote.VoteType)
|
||||
@@ -401,8 +400,8 @@ namespace Barotrauma
|
||||
break;
|
||||
case VoteType.TransferMoney:
|
||||
var transferVote = (ActiveVote as TransferVote);
|
||||
msg.Write(transferVote.From?.ID ?? 0);
|
||||
msg.Write(transferVote.To?.ID ?? 0);
|
||||
msg.Write(transferVote.From?.SessionId ?? 0);
|
||||
msg.Write(transferVote.To?.SessionId ?? 0);
|
||||
msg.Write(transferVote.TransferAmount);
|
||||
break;
|
||||
}
|
||||
@@ -430,11 +429,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
var readyClients = GameMain.Server.ConnectedClients.FindAll(c => c.GetVote<bool>(VoteType.StartRound));
|
||||
msg.Write((byte)readyClients.Count);
|
||||
var readyClients = GameMain.Server.ConnectedClients.Where(c => c.GetVote<bool>(VoteType.StartRound));
|
||||
msg.Write((byte)readyClients.Count());
|
||||
foreach (Client c in readyClients)
|
||||
{
|
||||
msg.Write(c.ID);
|
||||
msg.Write(c.SessionId);
|
||||
}
|
||||
|
||||
msg.WritePadBits();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
{
|
||||
@@ -58,7 +59,6 @@ namespace Barotrauma.Steam
|
||||
Steamworks.SteamServer.SetKey("contentpackage", string.Join(",", contentPackages.Select(cp => cp.Name)));
|
||||
Steamworks.SteamServer.SetKey("contentpackagehash", string.Join(",", contentPackages.Select(cp => cp.Hash.StringRepresentation)));
|
||||
Steamworks.SteamServer.SetKey("contentpackageid", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopId)));
|
||||
Steamworks.SteamServer.SetKey("usingwhitelist", (server.ServerSettings.Whitelist != null && server.ServerSettings.Whitelist.Enabled).ToString());
|
||||
Steamworks.SteamServer.SetKey("modeselectionmode", server.ServerSettings.ModeSelectionMode.ToString());
|
||||
Steamworks.SteamServer.SetKey("subselectionmode", server.ServerSettings.SubSelectionMode.ToString());
|
||||
Steamworks.SteamServer.SetKey("voicechatenabled", server.ServerSettings.VoiceChatEnabled.ToString());
|
||||
@@ -76,12 +76,12 @@ namespace Barotrauma.Steam
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Steamworks.BeginAuthResult StartAuthSession(byte[] authTicketData, ulong clientSteamID)
|
||||
public static Steamworks.BeginAuthResult StartAuthSession(byte[] authTicketData, SteamId clientSteamID)
|
||||
{
|
||||
if (!IsInitialized || !Steamworks.SteamServer.IsValid) return Steamworks.BeginAuthResult.ServerNotConnectedToSteam;
|
||||
|
||||
DebugConsole.Log("SteamManager authenticating Steam client " + clientSteamID);
|
||||
Steamworks.BeginAuthResult startResult = Steamworks.SteamServer.BeginAuthSession(authTicketData, clientSteamID);
|
||||
Steamworks.BeginAuthResult startResult = Steamworks.SteamServer.BeginAuthSession(authTicketData, clientSteamID.Value);
|
||||
if (startResult != Steamworks.BeginAuthResult.OK)
|
||||
{
|
||||
DebugConsole.Log("Authentication failed: failed to start auth session (" + startResult.ToString() + ")");
|
||||
@@ -90,12 +90,12 @@ namespace Barotrauma.Steam
|
||||
return startResult;
|
||||
}
|
||||
|
||||
public static void StopAuthSession(ulong clientSteamID)
|
||||
public static void StopAuthSession(SteamId clientSteamId)
|
||||
{
|
||||
if (!IsInitialized || !Steamworks.SteamServer.IsValid) return;
|
||||
|
||||
DebugConsole.Log("SteamManager ending auth session with Steam client " + clientSteamID);
|
||||
Steamworks.SteamServer.EndSession(clientSteamID);
|
||||
DebugConsole.Log("SteamManager ending auth session with Steam client " + clientSteamId);
|
||||
Steamworks.SteamServer.EndSession(clientSteamId.Value);
|
||||
}
|
||||
|
||||
public static bool CloseServer()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user