v0.19.14.0
This commit is contained in:
@@ -25,7 +25,7 @@ namespace Barotrauma
|
||||
private PlayerBalanceElement? playerBalanceElement;
|
||||
|
||||
private List<CharacterInfo> PendingHires => campaign.Map?.CurrentLocation?.HireManager?.PendingHires;
|
||||
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign(ClientPermissions.ManageHires);
|
||||
private bool HasPermission => CampaignMode.AllowedToManageCampaign(ClientPermissions.ManageHires);
|
||||
|
||||
private Point resolutionWhenCreated;
|
||||
|
||||
|
||||
@@ -139,10 +139,10 @@ namespace Barotrauma
|
||||
return tab switch
|
||||
{
|
||||
StoreTab.Buy => true,
|
||||
StoreTab.Sell => campaignUI.Campaign.AllowedToManageCampaign(Networking.ClientPermissions.SellInventoryItems),
|
||||
StoreTab.SellSub => campaignUI.Campaign.AllowedToManageCampaign(Networking.ClientPermissions.SellSubItems),
|
||||
StoreTab.Sell => CampaignMode.AllowedToManageCampaign(Networking.ClientPermissions.SellInventoryItems),
|
||||
StoreTab.SellSub => CampaignMode.AllowedToManageCampaign(Networking.ClientPermissions.SellSubItems),
|
||||
_ => false,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
private void UpdatePermissions()
|
||||
|
||||
@@ -1867,10 +1867,13 @@ namespace Barotrauma
|
||||
GUITextBlock jobBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), nameLayout.RectTransform), job.Name, font: GUIStyle.SmallFont) { TextColor = job.Prefab.UIColor };
|
||||
}
|
||||
|
||||
LocalizedString traitString = TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), info.PersonalityTrait.DisplayName);
|
||||
Vector2 traitSize = GUIStyle.SmallFont.MeasureString(traitString);
|
||||
GUITextBlock traitBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), traitString, font: GUIStyle.SmallFont);
|
||||
traitBlock.RectTransform.NonScaledSize = traitSize.Pad(traitBlock.Padding).ToPoint();
|
||||
if (info.PersonalityTrait != null)
|
||||
{
|
||||
LocalizedString traitString = TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), info.PersonalityTrait.DisplayName);
|
||||
Vector2 traitSize = GUIStyle.SmallFont.MeasureString(traitString);
|
||||
GUITextBlock traitBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), traitString, font: GUIStyle.SmallFont);
|
||||
traitBlock.RectTransform.NonScaledSize = traitSize.Pad(traitBlock.Padding).ToPoint();
|
||||
}
|
||||
|
||||
IEnumerable<TalentPrefab> talentsOutsideTree = info.GetUnlockedTalentsOutsideTree().Select(e => TalentPrefab.TalentPrefabs.Find(c => c.Identifier == e));
|
||||
if (talentsOutsideTree.Count() > 0)
|
||||
|
||||
@@ -847,7 +847,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (UpgradePrefab prefab in prefabs)
|
||||
{
|
||||
if (prefab.MaxLevel is 0) { continue; }
|
||||
if (prefab.GetMaxLevelForCurrentSub() == 0) { continue; }
|
||||
CreateUpgradeEntry(prefab, category, parent.Content, submarine, entitiesOnSub);
|
||||
}
|
||||
}
|
||||
@@ -1080,7 +1080,7 @@ namespace Barotrauma
|
||||
|
||||
public static GUIFrame CreateUpgradeFrame(UpgradePrefab prefab, UpgradeCategory category, CampaignMode campaign, RectTransform rectTransform, bool addBuyButton = true)
|
||||
{
|
||||
int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
||||
int price = prefab.Price.GetBuyPrice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
||||
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton, upgradePrefab: prefab, currentLevel: campaign.UpgradeManager.GetUpgradeLevel(prefab, category));
|
||||
}
|
||||
|
||||
@@ -1177,11 +1177,12 @@ namespace Barotrauma
|
||||
|
||||
private static void UpdateUpgradePercentageText(GUITextBlock text, UpgradePrefab upgradePrefab, int currentLevel)
|
||||
{
|
||||
float nextIncrease = upgradePrefab.IncreaseOnTooltip * (Math.Min(currentLevel + 1, upgradePrefab.MaxLevel));
|
||||
int maxLevel = upgradePrefab.GetMaxLevelForCurrentSub();
|
||||
float nextIncrease = upgradePrefab.IncreaseOnTooltip * Math.Min(currentLevel + 1, maxLevel);
|
||||
if (nextIncrease != 0f)
|
||||
{
|
||||
text.Text = $"{Math.Round(nextIncrease, 1)} %";
|
||||
if (currentLevel == upgradePrefab.MaxLevel)
|
||||
if (currentLevel == maxLevel)
|
||||
{
|
||||
text.TextColor = Color.Gray;
|
||||
}
|
||||
@@ -1221,7 +1222,7 @@ namespace Barotrauma
|
||||
{
|
||||
LocalizedString promptBody = TextManager.GetWithVariables("Upgrades.PurchasePromptBody",
|
||||
("[upgradename]", prefab.Name),
|
||||
("[amount]", prefab.Price.GetBuyprice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation).ToString()));
|
||||
("[amount]", prefab.Price.GetBuyPrice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation).ToString()));
|
||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
|
||||
{
|
||||
if (GameMain.NetworkMember != null)
|
||||
@@ -1617,14 +1618,15 @@ namespace Barotrauma
|
||||
{
|
||||
int currentLevel = campaign.UpgradeManager.GetUpgradeLevel(prefab, category);
|
||||
|
||||
LocalizedString progressText = TextManager.GetWithVariables("upgrades.progressformat", ("[level]", currentLevel.ToString()), ("[maxlevel]", prefab.MaxLevel.ToString()));
|
||||
int maxLevel = prefab.GetMaxLevelForCurrentSub();
|
||||
LocalizedString progressText = TextManager.GetWithVariables("upgrades.progressformat", ("[level]", currentLevel.ToString()), ("[maxlevel]", maxLevel.ToString()));
|
||||
if (prefabFrame.FindChild("progressbar", true) is { } progressParent)
|
||||
{
|
||||
GUIProgressBar bar = progressParent.GetChild<GUIProgressBar>();
|
||||
if (bar != null)
|
||||
{
|
||||
bar.BarSize = currentLevel / (float) prefab.MaxLevel;
|
||||
bar.Color = currentLevel >= prefab.MaxLevel ? GUIStyle.Green : GUIStyle.Orange;
|
||||
bar.BarSize = currentLevel / (float)maxLevel;
|
||||
bar.Color = currentLevel >= maxLevel ? GUIStyle.Green : GUIStyle.Orange;
|
||||
}
|
||||
|
||||
GUITextBlock block = progressParent.GetChild<GUITextBlock>();
|
||||
@@ -1637,12 +1639,12 @@ namespace Barotrauma
|
||||
|
||||
GUITextBlock priceLabel = textBlocks[0];
|
||||
priceLabel.Visible = true;
|
||||
int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
||||
int price = prefab.Price.GetBuyPrice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
||||
|
||||
if (priceLabel != null && !WaitForServerUpdate)
|
||||
{
|
||||
priceLabel.Text = TextManager.FormatCurrency(price);
|
||||
if (currentLevel >= prefab.MaxLevel)
|
||||
if (currentLevel >= maxLevel)
|
||||
{
|
||||
priceLabel.Text = TextManager.Get("Upgrade.MaxedUpgrade");
|
||||
}
|
||||
@@ -1651,7 +1653,7 @@ namespace Barotrauma
|
||||
GUIButton button = buttonParent.GetChild<GUIButton>();
|
||||
if (button != null)
|
||||
{
|
||||
button.Enabled = currentLevel < prefab.MaxLevel;
|
||||
button.Enabled = currentLevel < maxLevel;
|
||||
if (WaitForServerUpdate || campaign.GetBalance() < price)
|
||||
{
|
||||
button.Enabled = false;
|
||||
@@ -1697,13 +1699,14 @@ namespace Barotrauma
|
||||
|
||||
foreach (GUIComponent component in indicators.Children)
|
||||
{
|
||||
if (!(component is GUIImage image)) { continue; }
|
||||
if (component is not GUIImage image) { continue; }
|
||||
|
||||
foreach (UpgradePrefab prefab in prefabs)
|
||||
{
|
||||
if (component.UserData != prefab) { continue; }
|
||||
|
||||
if (prefab.MaxLevel is 0)
|
||||
int maxLevel = prefab.GetMaxLevelForCurrentSub();
|
||||
if (maxLevel == 0)
|
||||
{
|
||||
component.Visible = false;
|
||||
continue;
|
||||
@@ -1715,7 +1718,6 @@ namespace Barotrauma
|
||||
GUIComponentStyle onStyle = styles["upgradeindicatoron".ToIdentifier()];
|
||||
GUIComponentStyle dimStyle = styles["upgradeindicatordim".ToIdentifier()];
|
||||
GUIComponentStyle offStyle = styles["upgradeindicatoroff".ToIdentifier()];
|
||||
int maxLevel = prefab.MaxLevel;
|
||||
|
||||
if (maxLevel == 0)
|
||||
{
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// There is a server-side implementation of the method in <see cref="MultiPlayerCampaign"/>
|
||||
/// </summary>
|
||||
public bool AllowedToManageCampaign(ClientPermissions permissions)
|
||||
public static bool AllowedToManageCampaign(ClientPermissions permissions)
|
||||
{
|
||||
//allow managing the round if the client has permissions, is the owner, the only client in the server,
|
||||
//or if no-one has management permissions
|
||||
@@ -99,7 +99,8 @@ namespace Barotrauma
|
||||
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign) ||
|
||||
GameMain.Client.ConnectedClients.Count == 1 ||
|
||||
GameMain.Client.IsServerOwner ||
|
||||
GameMain.Client.ConnectedClients.None(c => c.InGame && (c.IsOwner || c.HasPermission(permissions)));
|
||||
//allow managing if no-one with permissions is alive
|
||||
GameMain.Client.ConnectedClients.None(c => c.InGame && c.Character is { IsIncapacitated: false, IsDead: false } && (c.IsOwner || c.HasPermission(permissions)));
|
||||
}
|
||||
|
||||
public static bool AllowedToManageWallets()
|
||||
|
||||
@@ -265,6 +265,8 @@ namespace Barotrauma.Items.Components
|
||||
foreach (DeconstructItem deconstructItem in it.Prefab.DeconstructItems)
|
||||
{
|
||||
if (!deconstructItem.IsValidDeconstructor(item)) { continue; }
|
||||
float percentageHealth = it.Condition / it.MaxCondition;
|
||||
if (percentageHealth < deconstructItem.MinCondition || percentageHealth > deconstructItem.MaxCondition) { continue; }
|
||||
RegisterItem(deconstructItem.ItemIdentifier, deconstructItem.Amount);
|
||||
}
|
||||
|
||||
|
||||
@@ -1028,7 +1028,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (var c in MineralClusters)
|
||||
{
|
||||
var unobtainedMinerals = c.resources.Where(i => i != null && i.GetRootInventoryOwner() == i);
|
||||
var unobtainedMinerals = c.resources.Where(i => i != null && i.GetComponent<Holdable>() is { Attached: true });
|
||||
if (unobtainedMinerals.None()) { continue; }
|
||||
if (!CheckResourceMarkerVisibility(c.center, transducerCenter)) { continue; }
|
||||
var i = unobtainedMinerals.FirstOrDefault();
|
||||
|
||||
@@ -162,23 +162,27 @@ namespace Barotrauma
|
||||
|
||||
RemoveFogOfWar(StartLocation);
|
||||
|
||||
GenerateLocationConnectionVisuals();
|
||||
GenerateAllLocationConnectionVisuals();
|
||||
}
|
||||
|
||||
partial void GenerateLocationConnectionVisuals()
|
||||
partial void GenerateAllLocationConnectionVisuals()
|
||||
{
|
||||
foreach (LocationConnection connection in Connections)
|
||||
{
|
||||
Vector2 connectionStart = connection.Locations[0].MapPosition;
|
||||
Vector2 connectionEnd = connection.Locations[1].MapPosition;
|
||||
float connectionLength = Vector2.Distance(connectionStart, connectionEnd);
|
||||
int iterations = Math.Min((int)Math.Sqrt(connectionLength * generationParams.ConnectionIndicatorIterationMultiplier), 5);
|
||||
connection.CrackSegments.Clear();
|
||||
connection.CrackSegments.AddRange(MathUtils.GenerateJaggedLine(
|
||||
connectionStart, connectionEnd,
|
||||
iterations, connectionLength * generationParams.ConnectionIndicatorDisplacementMultiplier));
|
||||
GenerateLocationConnectionVisuals(connection);
|
||||
}
|
||||
}
|
||||
partial void GenerateLocationConnectionVisuals(LocationConnection connection)
|
||||
{
|
||||
Vector2 connectionStart = connection.Locations[0].MapPosition;
|
||||
Vector2 connectionEnd = connection.Locations[1].MapPosition;
|
||||
float connectionLength = Vector2.Distance(connectionStart, connectionEnd);
|
||||
int iterations = Math.Min((int)Math.Sqrt(connectionLength * generationParams.ConnectionIndicatorIterationMultiplier), 5);
|
||||
connection.CrackSegments.Clear();
|
||||
connection.CrackSegments.AddRange(MathUtils.GenerateJaggedLine(
|
||||
connectionStart, connectionEnd,
|
||||
iterations, connectionLength * generationParams.ConnectionIndicatorDisplacementMultiplier));
|
||||
}
|
||||
|
||||
private void LocationChanged(Location prevLocation, Location newLocation)
|
||||
{
|
||||
@@ -414,7 +418,7 @@ namespace Barotrauma
|
||||
new GUIMessageBox(string.Empty, TextManager.Get("LockedPathTooltip"));
|
||||
}
|
||||
//clients aren't allowed to select the location without a permission
|
||||
else if ((GameMain.GameSession?.GameMode as CampaignMode)?.AllowedToManageCampaign(Networking.ClientPermissions.ManageMap) ?? false)
|
||||
else if (CampaignMode.AllowedToManageCampaign(Networking.ClientPermissions.ManageMap))
|
||||
{
|
||||
connectionHighlightState = 0.0f;
|
||||
SelectedConnection = connection;
|
||||
|
||||
@@ -702,10 +702,30 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
Enabled = !GameMain.NetworkMember.GameStarted
|
||||
};
|
||||
var cargoFrame = new GUIListBox(new RectTransform(new Vector2(0.6f, 0.7f), settingsTabs[(int)SettingsTab.Rounds].RectTransform, Anchor.BottomRight, Pivot.BottomLeft))
|
||||
|
||||
var cargoFrame = new GUIFrame(new RectTransform(new Vector2(0.6f, 0.7f), settingsTabs[(int)SettingsTab.Rounds].RectTransform, Anchor.BottomRight, Pivot.BottomLeft))
|
||||
{
|
||||
Visible = false
|
||||
};
|
||||
var cargoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), cargoFrame.RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var filterText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), cargoContent.RectTransform), TextManager.Get("serverlog.filter"), font: GUIStyle.SubHeadingFont);
|
||||
var entityFilterBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), filterText.RectTransform, Anchor.CenterRight), font: GUIStyle.Font, createClearButton: true);
|
||||
filterText.RectTransform.MinSize = new Point(0, entityFilterBox.RectTransform.MinSize.Y);
|
||||
var cargoList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), cargoContent.RectTransform));
|
||||
entityFilterBox.OnTextChanged += (textBox, text) =>
|
||||
{
|
||||
foreach (var child in cargoList.Content.Children)
|
||||
{
|
||||
if (child.UserData is not ItemPrefab itemPrefab) { continue; }
|
||||
child.Visible = string.IsNullOrEmpty(text) || itemPrefab.Name.Contains(text, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
cargoButton.UserData = cargoFrame;
|
||||
cargoButton.OnClicked = (button, obj) =>
|
||||
{
|
||||
@@ -721,7 +741,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
GUITextBlock.AutoScaleAndNormalize(buttonHolder.Children.Select(c => ((GUIButton)c).TextBlock));
|
||||
|
||||
foreach (ItemPrefab ip in ItemPrefab.Prefabs)
|
||||
foreach (ItemPrefab ip in ItemPrefab.Prefabs.OrderBy(ip => ip.Name))
|
||||
{
|
||||
if (ip.AllowAsExtraCargo.HasValue)
|
||||
{
|
||||
@@ -732,10 +752,10 @@ namespace Barotrauma.Networking
|
||||
if (!ip.CanBeBought) { continue; }
|
||||
}
|
||||
|
||||
var itemFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), cargoFrame.Content.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal: true)
|
||||
var itemFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), cargoList.Content.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
UserData = cargoFrame,
|
||||
UserData = ip,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
@@ -778,7 +798,7 @@ namespace Barotrauma.Networking
|
||||
numberInput.IntValue = ExtraCargo.ContainsKey(ip) ? ExtraCargo[ip] : 0;
|
||||
CoroutineManager.Invoke(() =>
|
||||
{
|
||||
foreach (var child in cargoFrame.Content.GetAllChildren())
|
||||
foreach (var child in cargoList.Content.GetAllChildren())
|
||||
{
|
||||
if (child.GetChild<GUINumberInput>() is GUINumberInput otherNumberInput)
|
||||
{
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace Barotrauma
|
||||
foreach (GUITickBox tickBox in missionTickBoxes)
|
||||
{
|
||||
bool disable = hasMaxMissions && !tickBox.Selected;
|
||||
tickBox.Enabled = Campaign.AllowedToManageCampaign(ClientPermissions.ManageMap) && !disable;
|
||||
tickBox.Enabled = CampaignMode.AllowedToManageCampaign(ClientPermissions.ManageMap) && !disable;
|
||||
tickBox.Box.DisabledColor = disable ? tickBox.Box.Color * 0.5f : tickBox.Box.Color * 0.8f;
|
||||
foreach (GUIComponent child in tickBox.Parent.Parent.Children)
|
||||
{
|
||||
@@ -315,7 +315,7 @@ namespace Barotrauma
|
||||
if (GUI.MouseOn == tickBox) { return false; }
|
||||
if (tickBox != null)
|
||||
{
|
||||
if (Campaign.AllowedToManageCampaign(ClientPermissions.ManageMap) && tickBox.Enabled)
|
||||
if (CampaignMode.AllowedToManageCampaign(ClientPermissions.ManageMap) && tickBox.Enabled)
|
||||
{
|
||||
tickBox.Selected = !tickBox.Selected;
|
||||
}
|
||||
@@ -356,10 +356,10 @@ namespace Barotrauma
|
||||
};
|
||||
tickBox.RectTransform.MinSize = new Point(tickBox.Rect.Height, 0);
|
||||
tickBox.RectTransform.IsFixedSize = true;
|
||||
tickBox.Enabled = Campaign.AllowedToManageCampaign(ClientPermissions.ManageMap);
|
||||
tickBox.Enabled = CampaignMode.AllowedToManageCampaign(ClientPermissions.ManageMap);
|
||||
tickBox.OnSelected += (GUITickBox tb) =>
|
||||
{
|
||||
if (!Campaign.AllowedToManageCampaign(Networking.ClientPermissions.ManageMap)) { return false; }
|
||||
if (!CampaignMode.AllowedToManageCampaign(Networking.ClientPermissions.ManageMap)) { return false; }
|
||||
|
||||
if (tb.Selected)
|
||||
{
|
||||
@@ -379,7 +379,7 @@ namespace Barotrauma
|
||||
UpdateMaxMissions(connection.OtherLocation(currentDisplayLocation));
|
||||
|
||||
if ((Campaign is MultiPlayerCampaign multiPlayerCampaign) && !multiPlayerCampaign.SuppressStateSending &&
|
||||
Campaign.AllowedToManageCampaign(Networking.ClientPermissions.ManageMap))
|
||||
CampaignMode.AllowedToManageCampaign(Networking.ClientPermissions.ManageMap))
|
||||
{
|
||||
GameMain.Client?.SendCampaignState();
|
||||
}
|
||||
@@ -500,7 +500,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
},
|
||||
Enabled = true,
|
||||
Visible = Campaign.AllowedToManageCampaign(ClientPermissions.ManageMap)
|
||||
Visible = CampaignMode.AllowedToManageCampaign(ClientPermissions.ManageMap)
|
||||
};
|
||||
|
||||
buttonArea.RectTransform.MinSize = new Point(0, StartButton.RectTransform.MinSize.Y);
|
||||
|
||||
@@ -351,7 +351,7 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
if (string.IsNullOrEmpty(contentPackageNameElement.Text))
|
||||
{
|
||||
contentPackageNameElement.Flash();
|
||||
contentPackageNameElement.Flash(useRectangleFlash: true);
|
||||
return false;
|
||||
}
|
||||
if (ContentPackageManager.AllPackages.Any(cp => cp.Name.ToLower() == contentPackageNameElement.Text.ToLower()))
|
||||
@@ -405,7 +405,7 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
if (ContentPackage == null)
|
||||
{
|
||||
contentPackageDropDown.Flash();
|
||||
contentPackageDropDown.Flash(useRectangleFlash: true);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ namespace Barotrauma.CharacterEditor
|
||||
if (!File.Exists(evaluatedTexturePath))
|
||||
{
|
||||
GUI.AddMessage(GetCharacterEditorTranslation("TextureDoesNotExist"), GUIStyle.Red);
|
||||
texturePathElement.Flash(GUIStyle.Red);
|
||||
texturePathElement.Flash(useRectangleFlash: true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -425,7 +425,7 @@ namespace Barotrauma.CharacterEditor
|
||||
if (!path.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
GUI.AddMessage(TextManager.Get("WrongFileType"), GUIStyle.Red);
|
||||
texturePathElement.Flash(GUIStyle.Red);
|
||||
texturePathElement.Flash(useRectangleFlash: true);
|
||||
return false;
|
||||
}
|
||||
if (IsCopy)
|
||||
@@ -486,7 +486,8 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
var removeLimbButton = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), limbEditLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton")
|
||||
var limbButtonSize = Vector2.One * 0.8f;
|
||||
var removeLimbButton = new GUIButton(new RectTransform(limbButtonSize, limbEditLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton")
|
||||
{
|
||||
OnClicked = (b, d) =>
|
||||
{
|
||||
@@ -497,7 +498,7 @@ namespace Barotrauma.CharacterEditor
|
||||
return true;
|
||||
}
|
||||
};
|
||||
var addLimbButton = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), limbEditLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton")
|
||||
var addLimbButton = new GUIButton(new RectTransform(limbButtonSize, limbEditLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton")
|
||||
{
|
||||
OnClicked = (b, d) =>
|
||||
{
|
||||
|
||||
@@ -1817,7 +1817,11 @@ namespace Barotrauma
|
||||
subList = dropDown.ListBox.Content;
|
||||
}
|
||||
|
||||
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.15f), subList.RectTransform) { MinSize = new Point(0, 25) },
|
||||
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), subList.RectTransform)
|
||||
{
|
||||
//enough space for 2 lines (price and class) + some padding
|
||||
MinSize = new Point(0, (int)(GUIStyle.SmallFont.LineHeight * 2.3f))
|
||||
},
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
ToolTip = sub.Description,
|
||||
|
||||
@@ -7,6 +7,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -953,8 +955,19 @@ namespace Barotrauma
|
||||
okButton.Enabled = false;
|
||||
okButton.OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (!Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint)) { return false; }
|
||||
JoinServer(endpoint, "");
|
||||
if (Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint))
|
||||
{
|
||||
JoinServer(endpoint, "");
|
||||
}
|
||||
else if (LidgrenEndpoint.ParseFromWithHostNameCheck(endpointBox.Text, tryParseHostName: true).TryUnwrap(out var lidgrenEndpoint))
|
||||
{
|
||||
JoinServer(lidgrenEndpoint, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("error"), TextManager.GetWithVariable("invalidipaddress", "[serverip]:[port]", endpointBox.Text));
|
||||
endpointBox.Flash();
|
||||
}
|
||||
msgBox.Close();
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -1920,9 +1920,15 @@ namespace Barotrauma
|
||||
{
|
||||
filePath = $"{ContentPath.ModDirStr}/{filePath[packageDir.Length..]}";
|
||||
}
|
||||
if (!modProject.Files.Any(f => f.Type == subFileType &&
|
||||
f.Path == filePath))
|
||||
if (!modProject.Files.Any(f => f.Type == subFileType && f.Path == filePath))
|
||||
{
|
||||
//check if there's a file with the same name but different filename case
|
||||
var matchingFile = modProject.Files.FirstOrDefault(f => f.Type == subFileType && filePath.CleanUpPath().Equals(f.Path.CleanUpPath(), StringComparison.OrdinalIgnoreCase));
|
||||
if (matchingFile != null)
|
||||
{
|
||||
File.Delete(matchingFile.Path.Replace(ContentPath.ModDirStr, packageDir));
|
||||
modProject.RemoveFile(matchingFile);
|
||||
}
|
||||
var newFile = ModProject.File.FromPath(filePath, subFileType);
|
||||
modProject.AddFile(newFile);
|
||||
}
|
||||
@@ -2479,7 +2485,7 @@ namespace Barotrauma
|
||||
|
||||
new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), tierGroup.RectTransform), NumberType.Int)
|
||||
{
|
||||
IntValue = SubmarineInfo.GetDefaultTier(MainSub.Info.Price),
|
||||
IntValue = MainSub.Info.Tier,
|
||||
MinValueInt = 1,
|
||||
MaxValueInt = 3,
|
||||
OnValueChanged = (numberInput) =>
|
||||
@@ -2821,6 +2827,7 @@ namespace Barotrauma
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
var requiredPackages = MapEntity.mapEntityList.Select(e => e.Prefab.ContentPackage)
|
||||
.Where(cp => cp != null)
|
||||
.Distinct().OfType<ContentPackage>().Select(p => p.Name).ToHashSet();
|
||||
var tickboxes = requiredContentPackList.Content.Children.OfType<GUITickBox>().ToArray();
|
||||
tickboxes.ForEach(tb => tb.Selected = requiredPackages.Contains(tb.UserData as string ?? ""));
|
||||
@@ -2919,7 +2926,7 @@ namespace Barotrauma
|
||||
|
||||
subTypeDropdown.SelectItem(MainSub.Info.Type);
|
||||
|
||||
if (quickSave) { SaveSub(null); }
|
||||
if (quickSave) { SaveSub(packageToSaveInList.SelectedData as ContentPackage); }
|
||||
}
|
||||
|
||||
private void CreateSaveAssemblyScreen()
|
||||
|
||||
@@ -785,13 +785,7 @@ namespace Barotrauma
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
GameSettings.SetCurrentConfig(unsavedConfig);
|
||||
if (WorkshopMenu is MutableWorkshopMenu mutableWorkshopMenu &&
|
||||
mutableWorkshopMenu.CurrentTab == MutableWorkshopMenu.Tab.InstalledMods)
|
||||
{
|
||||
mutableWorkshopMenu.Apply();
|
||||
}
|
||||
GameSettings.SaveCurrentConfig();
|
||||
ApplyInstalledModChanges();
|
||||
mainFrame.Flash(color: GUIStyle.Green);
|
||||
return false;
|
||||
},
|
||||
@@ -804,6 +798,17 @@ namespace Barotrauma
|
||||
};
|
||||
}
|
||||
|
||||
public void ApplyInstalledModChanges()
|
||||
{
|
||||
GameSettings.SetCurrentConfig(unsavedConfig);
|
||||
if (WorkshopMenu is MutableWorkshopMenu mutableWorkshopMenu &&
|
||||
mutableWorkshopMenu.CurrentTab == MutableWorkshopMenu.Tab.InstalledMods)
|
||||
{
|
||||
mutableWorkshopMenu.Apply();
|
||||
}
|
||||
GameSettings.SaveCurrentConfig();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (GameMain.Client is null || GameSettings.CurrentConfig.Audio.VoiceSetting == VoiceMode.Disabled)
|
||||
|
||||
@@ -96,6 +96,8 @@ namespace Barotrauma
|
||||
{
|
||||
angle = targetLimb.body.Rotation + ((targetLimb.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
particleRotation = -targetLimb.body.Rotation;
|
||||
float offset = targetLimb.Params.GetSpriteOrientation() - MathHelper.PiOver2;
|
||||
particleRotation += offset;
|
||||
if (targetLimb.body.Dir < 0.0f)
|
||||
{
|
||||
particleRotation += MathHelper.Pi;
|
||||
|
||||
@@ -598,13 +598,14 @@ namespace Barotrauma.Steam
|
||||
|
||||
bool reinstallAction(GUIButton button, object o)
|
||||
{
|
||||
SettingsMenu.Instance?.ApplyInstalledModChanges();
|
||||
int prevIndex = ContentPackageManager.EnabledPackages.Regular.IndexOf(contentPackage);
|
||||
TaskPool.AddIfNotFound($"Reinstall{workshopItem.Id}",
|
||||
SteamManager.Workshop.Reinstall(workshopItem), t =>
|
||||
{
|
||||
ContentPackageManager.WorkshopPackages.Refresh();
|
||||
ContentPackageManager.EnabledPackages.RefreshUpdatedMods();
|
||||
if (SettingsMenu.Instance?.WorkshopMenu is MutableWorkshopMenu mutableWorkshopMenu)
|
||||
if (SettingsMenu.Instance?.WorkshopMenu is MutableWorkshopMenu mutableWorkshopMenu && !mutableWorkshopMenu.ViewingItemDetails)
|
||||
{
|
||||
mutableWorkshopMenu.PopulateInstalledModLists(forceRefreshEnabled: true);
|
||||
}
|
||||
|
||||
@@ -543,7 +543,8 @@ namespace Barotrauma.Steam
|
||||
|
||||
var localModProject = new ModProject(localPackage)
|
||||
{
|
||||
UgcId = Option<ContentPackageId>.Some(new SteamWorkshopId(resultId))
|
||||
UgcId = Option<ContentPackageId>.Some(new SteamWorkshopId(resultId)),
|
||||
ModVersion = modVersion
|
||||
};
|
||||
localModProject.DiscardHashAndInstallTime();
|
||||
localModProject.Save(localPackage.Path);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.19.11.0</Version>
|
||||
<Version>0.19.14.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.11.0</Version>
|
||||
<Version>0.19.14.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.11.0</Version>
|
||||
<Version>0.19.14.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.11.0</Version>
|
||||
<Version>0.19.14.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.11.0</Version>
|
||||
<Version>0.19.14.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// There is a client-side implementation of the method in <see cref="CampaignMode"/>
|
||||
/// </summary>
|
||||
public bool AllowedToManageCampaign(Client client, ClientPermissions permissions)
|
||||
public static bool AllowedToManageCampaign(Client client, ClientPermissions permissions)
|
||||
{
|
||||
//allow managing the campaign if the client has permissions, is the owner, or the only client in the server,
|
||||
//or if no-one has management permissions
|
||||
@@ -25,7 +25,8 @@ namespace Barotrauma
|
||||
client.HasPermission(ClientPermissions.ManageCampaign) ||
|
||||
GameMain.Server.ConnectedClients.Count == 1 ||
|
||||
IsOwner(client) ||
|
||||
GameMain.Server.ConnectedClients.None(c => c.InGame && (IsOwner(c) || c.HasPermission(permissions)));
|
||||
//allow managing if no-one with permissions is alive
|
||||
GameMain.Server.ConnectedClients.None(c => c.InGame && c.Character is { IsIncapacitated: false, IsDead: false } && (IsOwner(c) || c.HasPermission(permissions)));
|
||||
}
|
||||
|
||||
public bool AllowedToManageWallets(Client client)
|
||||
|
||||
@@ -1019,7 +1019,7 @@ namespace Barotrauma
|
||||
UpgradeManager.PurchaseUpgrade(prefab, category, client: sender);
|
||||
|
||||
// unstable logging
|
||||
int price = prefab.Price.GetBuyprice(UpgradeManager.GetUpgradeLevel(prefab, category), Map?.CurrentLocation);
|
||||
int price = prefab.Price.GetBuyPrice(UpgradeManager.GetUpgradeLevel(prefab, category), Map?.CurrentLocation);
|
||||
int level = UpgradeManager.GetUpgradeLevel(prefab, category);
|
||||
GameServer.Log($"SERVER: Purchased level {level} {category.Identifier}.{prefab.Identifier} for {price}", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
var allowOutpostAutoDocking = (AllowOutpostAutoDocking)msg.ReadByte();
|
||||
if (outpostAutoDockingPromptShown &&
|
||||
(GameMain.GameSession?.Campaign?.AllowedToManageCampaign(c, ClientPermissions.ManageMap) ?? false))
|
||||
CampaignMode.AllowedToManageCampaign(c, ClientPermissions.ManageMap))
|
||||
{
|
||||
this.allowOutpostAutoDocking = allowOutpostAutoDocking;
|
||||
}
|
||||
|
||||
@@ -486,9 +486,18 @@ namespace Barotrauma.Networking
|
||||
// -> something wen't wrong during startup, re-enable start button and reset AutoRestartTimer
|
||||
if (startGameCoroutine != null && !CoroutineManager.IsCoroutineRunning(startGameCoroutine))
|
||||
{
|
||||
if (ServerSettings.AutoRestart) ServerSettings.AutoRestartTimer = Math.Max(ServerSettings.AutoRestartInterval, 5.0f);
|
||||
//GameMain.NetLobbyScreen.StartButtonEnabled = true;
|
||||
if (ServerSettings.AutoRestart) { ServerSettings.AutoRestartTimer = Math.Max(ServerSettings.AutoRestartInterval, 5.0f); }
|
||||
|
||||
if (startGameCoroutine.Exception != null && OwnerConnection != null)
|
||||
{
|
||||
SendConsoleMessage(
|
||||
startGameCoroutine.Exception.Message + '\n' +
|
||||
(startGameCoroutine.Exception.StackTrace?.CleanupStackTrace() ?? "null"),
|
||||
connectedClients.Find(c => c.Connection == OwnerConnection),
|
||||
Color.Red);
|
||||
}
|
||||
|
||||
EndGame();
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
|
||||
startGameCoroutine = null;
|
||||
@@ -1377,9 +1386,9 @@ namespace Barotrauma.Networking
|
||||
bool end = inc.ReadBoolean();
|
||||
if (end)
|
||||
{
|
||||
if (mpCampaign == null ||
|
||||
mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageRound) ||
|
||||
mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign))
|
||||
if (mpCampaign == null ||
|
||||
CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageRound) ||
|
||||
CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign))
|
||||
{
|
||||
bool save = inc.ReadBoolean();
|
||||
if (GameStarted)
|
||||
@@ -1409,7 +1418,7 @@ namespace Barotrauma.Networking
|
||||
SendDirectChatMessage("Cannot continue the campaign from the previous save (round already running).", sender, ChatMessageType.Error);
|
||||
break;
|
||||
}
|
||||
else if (mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageMap))
|
||||
else if (CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageMap))
|
||||
{
|
||||
MultiPlayerCampaign.LoadCampaign(GameMain.GameSession.SavePath);
|
||||
}
|
||||
@@ -1420,7 +1429,7 @@ namespace Barotrauma.Networking
|
||||
Log("Client \"" + ClientLogName(sender) + "\" started the round.", ServerLog.MessageType.ServerMessage);
|
||||
StartGame();
|
||||
}
|
||||
else if (mpCampaign != null && (mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || mpCampaign.AllowedToManageCampaign(sender, ClientPermissions.ManageMap)))
|
||||
else if (mpCampaign != null && (CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageMap)))
|
||||
{
|
||||
var availableTransition = mpCampaign.GetAvailableTransition(out _, out _);
|
||||
//don't force location if we've teleported
|
||||
@@ -1991,7 +2000,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
//and assume the message was received, so we don't have to keep resending
|
||||
//these large initial messages until the client acknowledges receiving them
|
||||
c.LastRecvLobbyUpdate++;
|
||||
c.LastRecvLobbyUpdate = GameMain.NetLobbyScreen.LastUpdateID;
|
||||
|
||||
}
|
||||
else
|
||||
@@ -2010,7 +2019,7 @@ namespace Barotrauma.Networking
|
||||
c.ChatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, c.LastRecvChatMsgID));
|
||||
for (int i = 0; i < c.ChatMsgQueue.Count && i < ChatMessage.MaxMessagesPerPacket; i++)
|
||||
{
|
||||
if (outmsg.LengthBytes + c.ChatMsgQueue[i].EstimateLengthBytesServer(c) > MsgConstants.MTU - 5)
|
||||
if (outmsg.LengthBytes + c.ChatMsgQueue[i].EstimateLengthBytesServer(c) > MsgConstants.MTU - 5 && i > 0)
|
||||
{
|
||||
//not enough room in this packet
|
||||
return;
|
||||
@@ -2589,26 +2598,24 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void EndGame(CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None, bool wasSaved = false)
|
||||
{
|
||||
if (!GameStarted)
|
||||
if (GameStarted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
Log("Ending the round...\n" + Environment.StackTrace.CleanupStackTrace(), ServerLog.MessageType.ServerMessage);
|
||||
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
Log("Ending the round...\n" + Environment.StackTrace.CleanupStackTrace(), ServerLog.MessageType.ServerMessage);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Ending the round...", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Ending the round...", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
}
|
||||
|
||||
string endMessage = TextManager.FormatServerMessage("RoundSummaryRoundHasEnded");
|
||||
var traitorResults = TraitorManager?.GetEndResults() ?? new List<TraitorMissionResult>();
|
||||
|
||||
List<Mission> missions = GameMain.GameSession.Missions.ToList();
|
||||
if (GameMain.GameSession.IsRunning)
|
||||
if (GameMain.GameSession is { IsRunning: true })
|
||||
{
|
||||
GameMain.GameSession.EndRound(endMessage, traitorResults);
|
||||
}
|
||||
@@ -2634,7 +2641,10 @@ namespace Barotrauma.Networking
|
||||
c.PositionUpdateLastSent.Clear();
|
||||
}
|
||||
|
||||
KarmaManager.OnRoundEnded();
|
||||
if (GameStarted)
|
||||
{
|
||||
KarmaManager.OnRoundEnded();
|
||||
}
|
||||
|
||||
RespawnManager = null;
|
||||
GameStarted = false;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.19.11.0</Version>
|
||||
<Version>0.19.14.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -186,8 +186,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (character.SelectedItem != Item)
|
||||
{
|
||||
if (Item.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true) ||
|
||||
Item.TryInteract(character, ignoreRequiredItems: true, forceUseKey: true))
|
||||
if (Item.TryInteract(character, ignoreRequiredItems: true, forceUseKey: true) ||
|
||||
Item.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true))
|
||||
{
|
||||
character.SelectedItem = Item;
|
||||
}
|
||||
|
||||
@@ -1337,7 +1337,7 @@ namespace Barotrauma
|
||||
bool limbsValid = true;
|
||||
foreach (Limb limb in limbs)
|
||||
{
|
||||
if (limb.body == null || !limb.body.Enabled) { continue; }
|
||||
if (limb?.body == null || !limb.body.Enabled) { continue; }
|
||||
if (!CheckValidity(limb.body))
|
||||
{
|
||||
limbsValid = false;
|
||||
@@ -1959,7 +1959,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (Limb l in Limbs)
|
||||
{
|
||||
l.Remove();
|
||||
l?.Remove();
|
||||
}
|
||||
limbs = null;
|
||||
}
|
||||
@@ -1968,7 +1968,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (PhysicsBody b in collider)
|
||||
{
|
||||
b.Remove();
|
||||
b?.Remove();
|
||||
}
|
||||
collider = null;
|
||||
}
|
||||
@@ -1977,7 +1977,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var joint in LimbJoints)
|
||||
{
|
||||
var j = joint.Joint;
|
||||
var j = joint?.Joint;
|
||||
if (GameMain.World.JointList.Contains(j))
|
||||
{
|
||||
GameMain.World.Remove(j);
|
||||
|
||||
@@ -2721,6 +2721,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
bool selectInputSameAsDeselect = false;
|
||||
#if CLIENT
|
||||
selectInputSameAsDeselect = GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select] == GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Deselect];
|
||||
#endif
|
||||
|
||||
if (SelectedCharacter != null && (IsKeyHit(InputType.Grab) || IsKeyHit(InputType.Health))) //Let people use ladders and buttons and stuff when dragging chars
|
||||
{
|
||||
DeselectCharacter();
|
||||
@@ -2760,14 +2765,16 @@ namespace Barotrauma
|
||||
{
|
||||
FocusedCharacter.onCustomInteract(FocusedCharacter, this);
|
||||
}
|
||||
else if (IsKeyHit(InputType.Deselect) && SelectedItem != null)
|
||||
else if (IsKeyHit(InputType.Deselect) && SelectedItem != null &&
|
||||
(focusedItem == null || focusedItem == SelectedItem || !selectInputSameAsDeselect))
|
||||
{
|
||||
SelectedItem = null;
|
||||
#if CLIENT
|
||||
CharacterHealth.OpenHealthWindow = null;
|
||||
#endif
|
||||
}
|
||||
else if (IsKeyHit(InputType.Deselect) && SelectedSecondaryItem != null)
|
||||
else if (IsKeyHit(InputType.Deselect) && SelectedSecondaryItem != null && SelectedSecondaryItem.GetComponent<Ladder>() == null &&
|
||||
(focusedItem == null || focusedItem == SelectedSecondaryItem || !selectInputSameAsDeselect))
|
||||
{
|
||||
SelectedSecondaryItem = null;
|
||||
#if CLIENT
|
||||
@@ -2782,6 +2789,10 @@ namespace Barotrauma
|
||||
{
|
||||
#if CLIENT
|
||||
if (CharacterInventory.DraggingItemToWorld) { return; }
|
||||
if (selectInputSameAsDeselect)
|
||||
{
|
||||
keys[(int)InputType.Deselect].Reset();
|
||||
}
|
||||
#endif
|
||||
bool canInteract = focusedItem.TryInteract(this);
|
||||
#if CLIENT
|
||||
|
||||
@@ -543,7 +543,7 @@ namespace Barotrauma
|
||||
|
||||
private void GetName(Rand.RandSync randSync, out string name)
|
||||
{
|
||||
var nameElement = CharacterConfigElement.GetChildElement("names") ?? CharacterConfigElement.GetChildElement("name");
|
||||
ContentXElement nameElement = CharacterConfigElement.GetChildElement("names") ?? CharacterConfigElement.GetChildElement("name");
|
||||
ContentPath namesXmlFile = nameElement?.GetAttributeContentPath("path") ?? ContentPath.Empty;
|
||||
XElement namesXml = null;
|
||||
if (!namesXmlFile.IsNullOrEmpty()) //names.xml is defined
|
||||
@@ -554,8 +554,8 @@ namespace Barotrauma
|
||||
else //the legacy firstnames.txt/lastnames.txt shit is defined
|
||||
{
|
||||
namesXml = new XElement("names", new XAttribute("format", "[firstname] [lastname]"));
|
||||
var firstNamesPath = ReplaceVars(nameElement.GetAttributeContentPath("firstname")?.Value ?? "");
|
||||
var lastNamesPath = ReplaceVars(nameElement.GetAttributeContentPath("lastname")?.Value ?? "");
|
||||
string firstNamesPath = nameElement == null ? string.Empty : ReplaceVars(nameElement.GetAttributeContentPath("firstname")?.Value ?? "");
|
||||
string lastNamesPath = nameElement == null ? string.Empty : ReplaceVars(nameElement.GetAttributeContentPath("lastname")?.Value ?? "");
|
||||
if (File.Exists(firstNamesPath) && File.Exists(lastNamesPath))
|
||||
{
|
||||
var firstNames = File.ReadAllLines(firstNamesPath);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
{
|
||||
var affliction = character.CharacterHealth.GetAffliction(afflictionIdentifier);
|
||||
if (affliction == null) { return false; }
|
||||
return minimumPercentage <= affliction.Strength / affliction.Prefab.MaxStrength;
|
||||
return affliction.Strength >= affliction.Prefab.ActivationThreshold && minimumPercentage <= affliction.Strength / affliction.Prefab.MaxStrength;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -13,21 +13,23 @@ namespace Barotrauma.Abilities
|
||||
|
||||
protected override void ApplyEffect()
|
||||
{
|
||||
if (!SelectedItemHasTag(Character)) { return; }
|
||||
if (!SelectedItemHasTag(Character, tag)) { return; }
|
||||
|
||||
Character closestCharacter = null;
|
||||
float closestDistance = squaredMaxDistance;
|
||||
|
||||
foreach (Character crewCharacter in Character.GetFriendlyCrew(Character))
|
||||
{
|
||||
if (crewCharacter != Character && Vector2.DistanceSquared(Character.SimPosition, Character.GetRelativeSimPosition(crewCharacter)) is float tempDistance && tempDistance < closestDistance)
|
||||
if (crewCharacter != Character &&
|
||||
Vector2.DistanceSquared(Character.WorldPosition, crewCharacter.WorldPosition) is float tempDistance && tempDistance < closestDistance &&
|
||||
SelectedItemHasTag(crewCharacter, tag))
|
||||
{
|
||||
closestCharacter = crewCharacter;
|
||||
closestDistance = tempDistance;
|
||||
}
|
||||
}
|
||||
|
||||
if (closestCharacter == null || !SelectedItemHasTag(closestCharacter)) { return; }
|
||||
if (closestCharacter == null) { return; }
|
||||
|
||||
if (closestDistance < squaredMaxDistance)
|
||||
{
|
||||
@@ -35,7 +37,7 @@ namespace Barotrauma.Abilities
|
||||
ApplyEffectSpecific(closestCharacter);
|
||||
}
|
||||
|
||||
bool SelectedItemHasTag(Character character) =>
|
||||
static bool SelectedItemHasTag(Character character, string tag) =>
|
||||
(character.SelectedItem != null && character.SelectedItem.HasTag(tag)) ||
|
||||
(character.SelectedSecondaryItem != null && character.SelectedSecondaryItem.HasTag(tag));
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Barotrauma
|
||||
{
|
||||
Option<ContentPackageId> ugcId = ContentPackageId.Parse(otherModName.Value);
|
||||
ContentPackage? otherMod =
|
||||
allPackages.FirstOrDefault(p => ugcId == p.UgcId)
|
||||
allPackages.FirstOrDefault(p => ugcId.IsSome() && ugcId == p.UgcId)
|
||||
?? allPackages.FirstOrDefault(p => p.Name == otherModName)
|
||||
?? allPackages.FirstOrDefault(p => p.NameMatches(otherModName))
|
||||
?? throw new MissingContentPackageException(ContentPackage, otherModName.Value);
|
||||
|
||||
@@ -1334,7 +1334,7 @@ namespace Barotrauma
|
||||
if (!prefab.UpgradeCategories.Contains(category)) { continue; }
|
||||
if (!string.IsNullOrWhiteSpace(prefabIdentifier) && prefab.Identifier != prefabIdentifier) { continue; }
|
||||
|
||||
int targetLevel = prefab.MaxLevel - upgradeManager.GetRealUpgradeLevel(prefab, category);
|
||||
int targetLevel = prefab.GetMaxLevelForCurrentSub() - upgradeManager.GetRealUpgradeLevel(prefab, category);
|
||||
for (int i = 0; i < targetLevel; i++)
|
||||
{
|
||||
upgradeManager.PurchaseUpgrade(prefab, category, force: true);
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace Barotrauma
|
||||
humanPrefab.GiveItems(newCharacter, newCharacter.Submarine);
|
||||
if (LootingIsStealing)
|
||||
{
|
||||
foreach (Item item in newCharacter.Inventory.AllItems)
|
||||
foreach (Item item in newCharacter.Inventory.FindAllItems(recursive: true))
|
||||
{
|
||||
item.SpawnedInCurrentOutpost = true;
|
||||
item.AllowStealing = false;
|
||||
|
||||
@@ -273,13 +273,13 @@ namespace Barotrauma
|
||||
IsCampaignSet = element.GetAttributeBool("campaign", LevelType == LevelData.LevelType.Outpost || (parentSet?.IsCampaignSet ?? false));
|
||||
ResetTime = element.GetAttributeFloat("resettime", 0);
|
||||
|
||||
DefaultCommonness = 1.0f;
|
||||
DefaultCommonness = element.GetAttributeFloat("commonness", 1.0f);
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "commonness":
|
||||
DefaultCommonness = subElement.GetAttributeFloat("commonness", 0.0f);
|
||||
DefaultCommonness = subElement.GetAttributeFloat("commonness", DefaultCommonness);
|
||||
foreach (XElement overrideElement in subElement.Elements())
|
||||
{
|
||||
if (overrideElement.NameAsIdentifier() == "override")
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (!(e.ChangedData.BalanceChanged is Some<int> { Value: var changed })) { return; }
|
||||
|
||||
if (changed != 0) { return; }
|
||||
if (changed == 0) { return; }
|
||||
|
||||
bool isGain = changed > 0;
|
||||
Color clr = isGain ? GUIStyle.Yellow : GUIStyle.Red;
|
||||
|
||||
@@ -177,12 +177,13 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
int price = prefab.Price.GetBuyprice(GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation);
|
||||
int price = prefab.Price.GetBuyPrice(GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation);
|
||||
int currentLevel = GetUpgradeLevel(prefab, category);
|
||||
|
||||
if (currentLevel + 1 > prefab.MaxLevel)
|
||||
int maxLevel = prefab.GetMaxLevelForCurrentSub();
|
||||
if (currentLevel + 1 > maxLevel)
|
||||
{
|
||||
DebugConsole.ThrowError($"Tried to purchase \"{prefab.Name}\" over the max level! ({currentLevel + 1} > {prefab.MaxLevel}). The transaction has been cancelled.");
|
||||
DebugConsole.ThrowError($"Tried to purchase \"{prefab.Name}\" over the max level! ({currentLevel + 1} > {maxLevel}). The transaction has been cancelled.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -472,7 +473,7 @@ namespace Barotrauma
|
||||
{
|
||||
int newLevel = BuyUpgrade(prefab, category, Submarine.MainSub, level);
|
||||
DebugConsole.Log($" - {category.Identifier}.{prefab.Identifier} lvl. {level}, new: ({newLevel})");
|
||||
SetUpgradeLevel(prefab, category, Math.Clamp(GetRealUpgradeLevel(prefab, category) + level, 0, prefab.MaxLevel));
|
||||
SetUpgradeLevel(prefab, category, GetRealUpgradeLevel(prefab, category) + level);
|
||||
}
|
||||
|
||||
PendingUpgrades.Clear();
|
||||
@@ -652,16 +653,13 @@ namespace Barotrauma
|
||||
|
||||
/// <summary>
|
||||
/// Gets the progress that is shown on the store interface.
|
||||
/// Includes values stored in the metadata and <see cref="PendingUpgrades"/>
|
||||
/// Includes values stored in the metadata and <see cref="PendingUpgrades"/>, and takes submarine tier and class restrictions into account
|
||||
/// </summary>
|
||||
/// <param name="prefab"></param>
|
||||
/// <param name="category"></param>
|
||||
/// <returns></returns>
|
||||
public int GetUpgradeLevel(UpgradePrefab prefab, UpgradeCategory category)
|
||||
{
|
||||
if (!Metadata.HasKey(FormatIdentifier(prefab, category))) { return GetPendingLevel(); }
|
||||
|
||||
return GetRealUpgradeLevel(prefab, category) + GetPendingLevel();
|
||||
return Math.Min(GetRealUpgradeLevel(prefab, category) + GetPendingLevel(), prefab.GetMaxLevelForCurrentSub());
|
||||
|
||||
int GetPendingLevel()
|
||||
{
|
||||
@@ -671,11 +669,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the level of the upgrade that is stored in the metadata.
|
||||
/// Gets the level of the upgrade that is stored in the metadata. May be higher than the apparent level on the current sub if the player has switched to a lower-tier sub
|
||||
/// </summary>
|
||||
/// <param name="prefab"></param>
|
||||
/// <param name="category"></param>
|
||||
/// <returns></returns>
|
||||
public int GetRealUpgradeLevel(UpgradePrefab prefab, UpgradeCategory category)
|
||||
{
|
||||
return !Metadata.HasKey(FormatIdentifier(prefab, category)) ? 0 : Metadata.GetInt(FormatIdentifier(prefab, category), 0);
|
||||
@@ -684,9 +679,6 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Stores the target upgrade level in the campaign metadata.
|
||||
/// </summary>
|
||||
/// <param name="prefab"></param>
|
||||
/// <param name="category"></param>
|
||||
/// <param name="level"></param>
|
||||
private void SetUpgradeLevel(UpgradePrefab prefab, UpgradeCategory category, int level)
|
||||
{
|
||||
Metadata.SetValue(FormatIdentifier(prefab, category), level);
|
||||
|
||||
@@ -1164,11 +1164,14 @@ namespace Barotrauma.Items.Components
|
||||
public override void ReceiveSignal(Signal signal, Connection connection)
|
||||
{
|
||||
#if CLIENT
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient &&
|
||||
!(GameMain.GameSession?.Campaign?.AllowedToManageCampaign(ClientPermissions.ManageMap) ?? false))
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (GameMain.GameSession?.Campaign != null && !CampaignMode.AllowedToManageCampaign(ClientPermissions.ManageMap))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dockingCooldown > 0.0f) { return; }
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
const float MaxAttachDistance = 150.0f;
|
||||
private const float MaxAttachDistance = ItemPrefab.DefaultInteractDistance * 0.95f;
|
||||
|
||||
//the position(s) in the item that the Character grabs
|
||||
protected Vector2[] handlePos;
|
||||
@@ -731,10 +731,24 @@ namespace Barotrauma.Items.Components
|
||||
mouseDiff = mouseDiff.ClampLength(MaxAttachDistance);
|
||||
|
||||
Vector2 userPos = useWorldCoordinates ? user.WorldPosition : user.Position;
|
||||
|
||||
Vector2 attachPos = userPos + mouseDiff;
|
||||
|
||||
if (user.Submarine == null && Level.Loaded != null)
|
||||
if (user.Submarine != null)
|
||||
{
|
||||
if (Submarine.PickBody(
|
||||
ConvertUnits.ToSimUnits(user.Position),
|
||||
ConvertUnits.ToSimUnits(user.Position + mouseDiff), collisionCategory: Physics.CollisionWall) != null)
|
||||
{
|
||||
attachPos = userPos + mouseDiff * Submarine.LastPickedFraction;
|
||||
|
||||
//round down if we're placing on the right side and vice versa: ensures we don't round the position inside a wall
|
||||
return
|
||||
new Vector2(
|
||||
mouseDiff.X > 0 ? (float)Math.Floor(attachPos.X / Submarine.GridSize.X) * Submarine.GridSize.X : (float)Math.Ceiling(attachPos.X / Submarine.GridSize.X) * Submarine.GridSize.X,
|
||||
mouseDiff.Y > 0 ? (float)Math.Floor(attachPos.Y / Submarine.GridSize.Y) * Submarine.GridSize.X : (float)Math.Ceiling(attachPos.Y / Submarine.GridSize.Y) * Submarine.GridSize.Y);
|
||||
}
|
||||
}
|
||||
else if (Level.Loaded != null)
|
||||
{
|
||||
bool edgeFound = false;
|
||||
foreach (var cell in Level.Loaded.GetCells(attachPos))
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace Barotrauma.Items.Components
|
||||
reloadTimer = reload;
|
||||
reloadTimer /= 1f + character.GetStatValue(StatTypes.MeleeAttackSpeed);
|
||||
reloadTimer /= 1f + item.GetQualityModifier(Quality.StatType.StrikingSpeedMultiplier);
|
||||
character.AnimController.LockFlippingUntil = (float)Timing.TotalTime + reloadTimer;
|
||||
character.AnimController.LockFlippingUntil = (float)Timing.TotalTime + reloadTimer * 0.9f;
|
||||
|
||||
item.body.FarseerBody.CollisionCategories = Physics.CollisionProjectile;
|
||||
item.body.FarseerBody.CollidesWith = Physics.CollisionCharacter | Physics.CollisionWall | Physics.CollisionItemBlocking;
|
||||
|
||||
@@ -514,7 +514,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
if (Rand.Range(0.0f, 1.0f) < FireProbability * deltaTime)
|
||||
if (Rand.Range(0.0f, 1.0f) < FireProbability * deltaTime && item.CurrentHull != null)
|
||||
{
|
||||
Vector2 displayPos = ConvertUnits.ToDisplayUnits(rayStart + (rayEnd - rayStart) * lastPickedFraction * 0.9f);
|
||||
if (item.CurrentHull.Submarine != null) { displayPos += item.CurrentHull.Submarine.Position; }
|
||||
|
||||
@@ -284,9 +284,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Entity.Spawner.AddItemToSpawnQueue(itemPrefab, outputContainer.Inventory, condition, onSpawned: (Item spawnedItem) =>
|
||||
{
|
||||
spawnedItem.SpawnedInCurrentOutpost = item.SpawnedInCurrentOutpost;
|
||||
spawnedItem.StolenDuringRound = targetItem.StolenDuringRound;
|
||||
spawnedItem.AllowStealing = targetItem.AllowStealing;
|
||||
spawnedItem.OriginalOutpost = targetItem.OriginalOutpost;
|
||||
spawnedItem.SpawnedInCurrentOutpost = targetItem.SpawnedInCurrentOutpost;
|
||||
for (int i = 0; i < outputContainer.Capacity; i++)
|
||||
{
|
||||
var containedItem = outputContainer.Inventory.GetItemAt(i);
|
||||
|
||||
@@ -83,8 +83,16 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (lastUser == value) { return; }
|
||||
lastUser = value;
|
||||
degreeOfSuccess = lastUser == null ? 0.0f : Math.Min(DegreeOfSuccess(lastUser), 1.0f);
|
||||
LastUserWasPlayer = lastUser.IsPlayer;
|
||||
if (lastUser == null)
|
||||
{
|
||||
degreeOfSuccess = 0.0f;
|
||||
LastUserWasPlayer = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
degreeOfSuccess = Math.Min(DegreeOfSuccess(lastUser), 1.0f);
|
||||
LastUserWasPlayer = lastUser.IsPlayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -390,6 +390,8 @@ namespace Barotrauma
|
||||
{
|
||||
public static readonly PrefabCollection<ItemPrefab> Prefabs = new PrefabCollection<ItemPrefab>();
|
||||
|
||||
public const float DefaultInteractDistance = 120.0f;
|
||||
|
||||
//default size
|
||||
public Vector2 Size { get; private set; }
|
||||
|
||||
@@ -590,7 +592,7 @@ namespace Barotrauma
|
||||
public override ImmutableHashSet<string> Aliases => aliases;
|
||||
|
||||
//how close the Character has to be to the item to pick it up
|
||||
[Serialize(120.0f, IsPropertySaveable.No)]
|
||||
[Serialize(DefaultInteractDistance, IsPropertySaveable.No)]
|
||||
public float InteractDistance { get; private set; }
|
||||
|
||||
// this can be used to allow items which are behind other items tp
|
||||
|
||||
@@ -3015,6 +3015,7 @@ namespace Barotrauma
|
||||
var selectedLocation = allValidLocations.FirstOrDefault(l =>
|
||||
Vector2.Distance(l.Edge.Point1, l.Edge.Point2) is float edgeLength &&
|
||||
!l.Edge.OutsideLevel &&
|
||||
((l.Edge.Cell1?.IsDestructible ?? false) || (l.Edge.Cell2?.IsDestructible ?? false)) &&
|
||||
requiredAmount <= (int)Math.Floor(edgeLength / ((1.0f - maxResourceOverlap) * prefab.Size.X)));
|
||||
|
||||
|
||||
@@ -3905,7 +3906,7 @@ namespace Barotrauma
|
||||
|
||||
private bool HasEndOutpost()
|
||||
{
|
||||
if (preSelectedStartOutpost != null) { return true; }
|
||||
if (preSelectedEndOutpost != null) { return true; }
|
||||
//don't create an end outpost for locations
|
||||
if (LevelData.Type == LevelData.LevelType.Outpost) { return false; }
|
||||
if (EndLocation != null && !EndLocation.Type.HasOutpost) { return false; }
|
||||
|
||||
@@ -906,11 +906,17 @@ namespace Barotrauma
|
||||
|
||||
public LocationType GetLocationType()
|
||||
{
|
||||
if (IsCriticallyRadiated() && LocationType.Prefabs[Type.ReplaceInRadiation] is { } newLocationType)
|
||||
if (IsCriticallyRadiated() && !Type.ReplaceInRadiation.IsEmpty)
|
||||
{
|
||||
return newLocationType;
|
||||
if (LocationType.Prefabs.TryGet(Type.ReplaceInRadiation, out LocationType newLocationType))
|
||||
{
|
||||
return newLocationType;
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Error when trying to get a new location type for an irradiated location - location type \"{newLocationType}\" not found.");
|
||||
}
|
||||
}
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Barotrauma
|
||||
private set;
|
||||
}
|
||||
|
||||
public string ReplaceInRadiation { get; }
|
||||
public Identifier ReplaceInRadiation { get; }
|
||||
|
||||
public Sprite Sprite { get; private set; }
|
||||
public Sprite RadiationSprite { get; }
|
||||
@@ -108,7 +108,7 @@ namespace Barotrauma
|
||||
|
||||
HideEntitySubcategories = element.GetAttributeStringArray("hideentitysubcategories", Array.Empty<string>()).ToList();
|
||||
|
||||
ReplaceInRadiation = element.GetAttributeString(nameof(ReplaceInRadiation).ToLower(), "");
|
||||
ReplaceInRadiation = element.GetAttributeIdentifier(nameof(ReplaceInRadiation), Identifier.Empty);
|
||||
|
||||
string teamStr = element.GetAttributeString("outpostteam", "FriendlyNPC");
|
||||
Enum.TryParse(teamStr, out OutpostTeam);
|
||||
|
||||
@@ -560,6 +560,42 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
//make sure the location at the right side of the gate between biomes isn't a dead-end
|
||||
//those may sometimes generate if all the connections of the right-side location lead to the previous biome
|
||||
//(i.e. a situation where the adjacent locations happen to be at the left side of the border of the biomes, see see Regalis11/Barotrauma#10047)
|
||||
for (int i = 0; i < Connections.Count; i++)
|
||||
{
|
||||
var connection = Connections[i];
|
||||
if (!connection.Locked) { continue; }
|
||||
var rightMostLocation =
|
||||
connection.Locations[0].MapPosition.X > connection.Locations[1].MapPosition.X ?
|
||||
connection.Locations[0] :
|
||||
connection.Locations[1];
|
||||
|
||||
//if there's only one connection (= the connection between biomes), create a new connection to the closest location to the right
|
||||
if (rightMostLocation.Connections.Count == 1)
|
||||
{
|
||||
Location closestLocation = null;
|
||||
float closestDist = float.PositiveInfinity;
|
||||
foreach (Location otherLocation in Locations)
|
||||
{
|
||||
if (otherLocation == rightMostLocation || otherLocation.MapPosition.X < rightMostLocation.MapPosition.X) { continue; }
|
||||
float dist = Vector2.DistanceSquared(rightMostLocation.MapPosition, otherLocation.MapPosition);
|
||||
if (dist < closestDist || closestLocation == null)
|
||||
{
|
||||
closestLocation = otherLocation;
|
||||
closestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
var newConnection = new LocationConnection(rightMostLocation, closestLocation);
|
||||
rightMostLocation.Connections.Add(newConnection);
|
||||
closestLocation.Connections.Add(newConnection);
|
||||
Connections.Add(newConnection);
|
||||
GenerateLocationConnectionVisuals(newConnection);
|
||||
}
|
||||
}
|
||||
|
||||
//remove orphans
|
||||
Locations.RemoveAll(l => !Connections.Any(c => c.Locations.Contains(l)));
|
||||
|
||||
@@ -606,7 +642,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
partial void GenerateLocationConnectionVisuals();
|
||||
partial void GenerateAllLocationConnectionVisuals();
|
||||
|
||||
partial void GenerateLocationConnectionVisuals(LocationConnection connection);
|
||||
|
||||
private int GetZoneIndex(float xPos)
|
||||
{
|
||||
|
||||
@@ -8,23 +8,7 @@ using Lidgren.Network;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
interface IWritableBitField
|
||||
{
|
||||
public void WriteBoolean(bool b);
|
||||
public void WriteInteger(int value, int min, int max);
|
||||
public void WriteFloat(float value, float min, float max, int numberOfBits);
|
||||
|
||||
public void WriteToMessage(IWriteMessage msg);
|
||||
}
|
||||
|
||||
interface IReadableBitField
|
||||
{
|
||||
public bool ReadBoolean();
|
||||
public int ReadInteger(int min, int max);
|
||||
public float ReadFloat(float min, float max, int numberOfBits);
|
||||
}
|
||||
|
||||
sealed class WriteOnlyBitField : IWritableBitField, IDisposable
|
||||
sealed class WriteOnlyBitField : IDisposable
|
||||
{
|
||||
private const int AmountOfBoolsInByte = 7; // Reserve last bit for end marker
|
||||
private readonly List<byte> Buffer = new List<byte>();
|
||||
@@ -100,7 +84,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ReadOnlyBitField : IReadableBitField
|
||||
sealed class ReadOnlyBitField
|
||||
{
|
||||
private const int AmountOfBoolsInByte = 7; // Reserve last bit for end marker
|
||||
private readonly ImmutableArray<byte> buffer;
|
||||
@@ -110,17 +94,14 @@ namespace Barotrauma
|
||||
{
|
||||
List<byte> bytes = new List<byte>();
|
||||
byte currentByte;
|
||||
int reads = 0;
|
||||
do
|
||||
{
|
||||
if (inc.BitPosition >= inc.LengthBits)
|
||||
{
|
||||
throw new Exception("Failed to find the end of the bit field: end of the message reached.");
|
||||
}
|
||||
currentByte = inc.ReadByte();
|
||||
bytes.Add(currentByte);
|
||||
|
||||
reads++;
|
||||
if (reads > 100)
|
||||
{
|
||||
throw new Exception($"Failed to find the end of the bit field after 100 reads. Terminating to prevent the game from freezing.");
|
||||
}
|
||||
}
|
||||
while (!IsBitSet(currentByte, AmountOfBoolsInByte));
|
||||
|
||||
|
||||
@@ -113,6 +113,11 @@ namespace Barotrauma.Networking
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (AggregateException aggregateException)
|
||||
{
|
||||
if (aggregateException.InnerException is OperationCanceledException) { return -1; }
|
||||
throw;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return -1;
|
||||
|
||||
@@ -61,9 +61,9 @@ namespace Barotrauma
|
||||
{
|
||||
public interface IReadWriteBehavior
|
||||
{
|
||||
public delegate object? ReadDelegate(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField);
|
||||
public delegate object? ReadDelegate(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField);
|
||||
|
||||
public delegate void WriteDelegate(object? obj, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField);
|
||||
public delegate void WriteDelegate(object? obj, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField);
|
||||
|
||||
public ReadDelegate ReadAction { get; }
|
||||
public WriteDelegate WriteAction { get; }
|
||||
@@ -71,9 +71,9 @@ namespace Barotrauma
|
||||
|
||||
public readonly struct ReadWriteBehavior<T> : IReadWriteBehavior
|
||||
{
|
||||
public delegate T ReadDelegate(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField);
|
||||
public delegate T ReadDelegate(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField);
|
||||
|
||||
public delegate void WriteDelegate(T obj, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField);
|
||||
public delegate void WriteDelegate(T obj, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField);
|
||||
|
||||
public IReadWriteBehavior.ReadDelegate ReadAction { get; }
|
||||
public IReadWriteBehavior.WriteDelegate WriteAction { get; }
|
||||
@@ -256,18 +256,18 @@ namespace Barotrauma
|
||||
ReadImmutableArray<object>,
|
||||
WriteImmutableArray<object>);
|
||||
|
||||
private static ImmutableArray<T> ReadImmutableArray<T>(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : notnull
|
||||
private static ImmutableArray<T> ReadImmutableArray<T>(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : notnull
|
||||
{
|
||||
return ReadArray<T>(inc, attribute, bitField).ToImmutableArray();
|
||||
}
|
||||
|
||||
private static void WriteImmutableArray<T>(ImmutableArray<T> array, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : notnull
|
||||
private static void WriteImmutableArray<T>(ImmutableArray<T> array, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) where T : notnull
|
||||
{
|
||||
ToolBox.ThrowIfNull(array);
|
||||
WriteIReadOnlyCollection<T>(array, attribute, msg, bitField);
|
||||
}
|
||||
|
||||
private static T[] ReadArray<T>(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : notnull
|
||||
private static T[] ReadArray<T>(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : notnull
|
||||
{
|
||||
int length = bitField.ReadInteger(0, attribute.ArrayMaxSize);
|
||||
|
||||
@@ -286,13 +286,13 @@ namespace Barotrauma
|
||||
return array;
|
||||
}
|
||||
|
||||
private static void WriteArray<T>(T[] array, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : notnull
|
||||
private static void WriteArray<T>(T[] array, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) where T : notnull
|
||||
{
|
||||
ToolBox.ThrowIfNull(array);
|
||||
WriteIReadOnlyCollection(array, attribute, msg, bitField);
|
||||
}
|
||||
|
||||
private static void WriteIReadOnlyCollection<T>(IReadOnlyCollection<T> array, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : notnull
|
||||
private static void WriteIReadOnlyCollection<T>(IReadOnlyCollection<T> array, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) where T : notnull
|
||||
{
|
||||
bitField.WriteInteger(array.Count, 0, attribute.ArrayMaxSize);
|
||||
|
||||
@@ -307,18 +307,18 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private static T ReadINetSerializableStruct<T>(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : INetSerializableStruct
|
||||
private static T ReadINetSerializableStruct<T>(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : INetSerializableStruct
|
||||
{
|
||||
return INetSerializableStruct.ReadInternal<T>(inc, bitField);
|
||||
}
|
||||
|
||||
private static void WriteINetSerializableStruct<T>(T serializableStruct, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : INetSerializableStruct
|
||||
private static void WriteINetSerializableStruct<T>(T serializableStruct, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) where T : INetSerializableStruct
|
||||
{
|
||||
ToolBox.ThrowIfNull(serializableStruct);
|
||||
serializableStruct.WriteInternal(msg, bitField);
|
||||
}
|
||||
|
||||
private static T ReadEnum<T>(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : Enum
|
||||
private static T ReadEnum<T>(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : Enum
|
||||
{
|
||||
var type = typeof(T);
|
||||
|
||||
@@ -338,7 +338,7 @@ namespace Barotrauma
|
||||
throw new InvalidOperationException($"An enum {type} with value {enumIndex} could not be found in {nameof(ReadEnum)}");
|
||||
}
|
||||
|
||||
private static void WriteEnum<T>(T value, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : Enum
|
||||
private static void WriteEnum<T>(T value, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) where T : Enum
|
||||
{
|
||||
ToolBox.ThrowIfNull(value);
|
||||
|
||||
@@ -346,7 +346,7 @@ namespace Barotrauma
|
||||
bitField.WriteInteger((int)Convert.ChangeType(value, value.GetTypeCode()), range.Start, range.End);
|
||||
}
|
||||
|
||||
private static T? ReadNullable<T>(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : struct =>
|
||||
private static T? ReadNullable<T>(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : struct =>
|
||||
ReadOption<T>(inc, attribute, bitField) switch
|
||||
{
|
||||
Some<T> { Value: var value } => value,
|
||||
@@ -354,10 +354,10 @@ namespace Barotrauma
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
private static void WriteNullable<T>(T? value, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : struct =>
|
||||
private static void WriteNullable<T>(T? value, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) where T : struct =>
|
||||
WriteOption<T>(value.HasValue ? Option<T>.Some(value.Value) : Option<T>.None(), attribute, msg, bitField);
|
||||
|
||||
private static Option<T> ReadOption<T>(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) where T : notnull
|
||||
private static Option<T> ReadOption<T>(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) where T : notnull
|
||||
{
|
||||
bool hasValue = bitField.ReadBoolean();
|
||||
if (!hasValue)
|
||||
@@ -373,7 +373,7 @@ namespace Barotrauma
|
||||
throw new InvalidOperationException($"Could not find suitable behavior for type {typeof(T)} in {nameof(ReadOption)}");
|
||||
}
|
||||
|
||||
private static void WriteOption<T>(Option<T> option, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) where T : notnull
|
||||
private static void WriteOption<T>(Option<T> option, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) where T : notnull
|
||||
{
|
||||
ToolBox.ThrowIfNull(option);
|
||||
|
||||
@@ -391,22 +391,22 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ReadBoolean(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => bitField.ReadBoolean();
|
||||
private static void WriteBoolean(bool b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { bitField.WriteBoolean(b); }
|
||||
private static bool ReadBoolean(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => bitField.ReadBoolean();
|
||||
private static void WriteBoolean(bool b, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) { bitField.WriteBoolean(b); }
|
||||
|
||||
private static byte ReadByte(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => inc.ReadByte();
|
||||
private static void WriteByte(byte b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteByte(b); }
|
||||
private static byte ReadByte(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadByte();
|
||||
private static void WriteByte(byte b, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) { msg.WriteByte(b); }
|
||||
|
||||
private static ushort ReadUInt16(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => inc.ReadUInt16();
|
||||
private static void WriteUInt16(ushort b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteUInt16(b); }
|
||||
private static ushort ReadUInt16(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadUInt16();
|
||||
private static void WriteUInt16(ushort b, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) { msg.WriteUInt16(b); }
|
||||
|
||||
private static short ReadInt16(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => inc.ReadInt16();
|
||||
private static void WriteInt16(short b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteInt16(b); }
|
||||
private static short ReadInt16(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadInt16();
|
||||
private static void WriteInt16(short b, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) { msg.WriteInt16(b); }
|
||||
|
||||
private static uint ReadUInt32(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => inc.ReadUInt32();
|
||||
private static void WriteUInt32(uint b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteUInt32(b); }
|
||||
private static uint ReadUInt32(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadUInt32();
|
||||
private static void WriteUInt32(uint b, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) { msg.WriteUInt32(b); }
|
||||
|
||||
private static int ReadInt32(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField)
|
||||
private static int ReadInt32(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
|
||||
{
|
||||
if (IsRanged(attribute.MinValueInt, attribute.MaxValueInt))
|
||||
{
|
||||
@@ -416,7 +416,7 @@ namespace Barotrauma
|
||||
return inc.ReadInt32();
|
||||
}
|
||||
|
||||
private static void WriteInt32(int i, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField)
|
||||
private static void WriteInt32(int i, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField)
|
||||
{
|
||||
ToolBox.ThrowIfNull(i);
|
||||
|
||||
@@ -429,13 +429,13 @@ namespace Barotrauma
|
||||
msg.WriteInt32(i);
|
||||
}
|
||||
|
||||
private static ulong ReadUInt64(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => inc.ReadUInt64();
|
||||
private static void WriteUInt64(ulong b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteUInt64(b); }
|
||||
private static ulong ReadUInt64(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadUInt64();
|
||||
private static void WriteUInt64(ulong b, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) { msg.WriteUInt64(b); }
|
||||
|
||||
private static long ReadInt64(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => inc.ReadInt64();
|
||||
private static void WriteInt64(long b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteInt64(b); }
|
||||
private static long ReadInt64(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadInt64();
|
||||
private static void WriteInt64(long b, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) { msg.WriteInt64(b); }
|
||||
|
||||
private static float ReadSingle(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField)
|
||||
private static float ReadSingle(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
|
||||
{
|
||||
if (IsRanged(attribute.MinValueFloat, attribute.MaxValueFloat))
|
||||
{
|
||||
@@ -445,7 +445,7 @@ namespace Barotrauma
|
||||
return inc.ReadSingle();
|
||||
}
|
||||
|
||||
private static void WriteSingle(float f, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField)
|
||||
private static void WriteSingle(float f, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField)
|
||||
{
|
||||
ToolBox.ThrowIfNull(f);
|
||||
|
||||
@@ -458,16 +458,16 @@ namespace Barotrauma
|
||||
msg.WriteSingle(f);
|
||||
}
|
||||
|
||||
private static double ReadDouble(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => inc.ReadDouble();
|
||||
private static void WriteDouble(double b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteDouble(b); }
|
||||
private static double ReadDouble(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadDouble();
|
||||
private static void WriteDouble(double b, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) { msg.WriteDouble(b); }
|
||||
|
||||
private static string ReadString(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => inc.ReadString();
|
||||
private static void WriteString(string b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteString(b); }
|
||||
private static string ReadString(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadString();
|
||||
private static void WriteString(string b, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) { msg.WriteString(b); }
|
||||
|
||||
private static Identifier ReadIdentifier(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => inc.ReadIdentifier();
|
||||
private static void WriteIdentifier(Identifier b, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField) { msg.WriteIdentifier(b); }
|
||||
private static Identifier ReadIdentifier(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => inc.ReadIdentifier();
|
||||
private static void WriteIdentifier(Identifier b, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField) { msg.WriteIdentifier(b); }
|
||||
|
||||
private static AccountId ReadAccountId(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField)
|
||||
private static AccountId ReadAccountId(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
|
||||
{
|
||||
string str = inc.ReadString();
|
||||
return AccountId.Parse(str).TryUnwrap(out var accountId)
|
||||
@@ -475,14 +475,14 @@ namespace Barotrauma
|
||||
: throw new InvalidCastException($"Could not parse \"{str}\" as an {nameof(AccountId)}");
|
||||
}
|
||||
|
||||
private static void WriteAccountId(AccountId accountId, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField)
|
||||
private static void WriteAccountId(AccountId accountId, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField)
|
||||
{
|
||||
msg.WriteString(accountId.StringRepresentation);
|
||||
}
|
||||
|
||||
private static Color ReadColor(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField) => attribute.IncludeColorAlpha ? inc.ReadColorR8G8B8A8() : inc.ReadColorR8G8B8();
|
||||
private static Color ReadColor(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField) => attribute.IncludeColorAlpha ? inc.ReadColorR8G8B8A8() : inc.ReadColorR8G8B8();
|
||||
|
||||
private static void WriteColor(Color color, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField)
|
||||
private static void WriteColor(Color color, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField)
|
||||
{
|
||||
ToolBox.ThrowIfNull(color);
|
||||
|
||||
@@ -495,7 +495,7 @@ namespace Barotrauma
|
||||
msg.WriteColorR8G8B8(color);
|
||||
}
|
||||
|
||||
private static Vector2 ReadVector2(IReadMessage inc, NetworkSerialize attribute, IReadableBitField bitField)
|
||||
private static Vector2 ReadVector2(IReadMessage inc, NetworkSerialize attribute, ReadOnlyBitField bitField)
|
||||
{
|
||||
float x = ReadSingle(inc, attribute, bitField);
|
||||
float y = ReadSingle(inc, attribute, bitField);
|
||||
@@ -503,7 +503,7 @@ namespace Barotrauma
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
|
||||
private static void WriteVector2(Vector2 vector2, NetworkSerialize attribute, IWriteMessage msg, IWritableBitField bitField)
|
||||
private static void WriteVector2(Vector2 vector2, NetworkSerialize attribute, IWriteMessage msg, WriteOnlyBitField bitField)
|
||||
{
|
||||
ToolBox.ThrowIfNull(vector2);
|
||||
|
||||
@@ -690,11 +690,11 @@ namespace Barotrauma
|
||||
/// <returns>A new struct of type T with fields and properties deserialized</returns>
|
||||
public static T Read<T>(IReadMessage inc) where T : INetSerializableStruct
|
||||
{
|
||||
IReadableBitField bitField = new ReadOnlyBitField(inc);
|
||||
ReadOnlyBitField bitField = new ReadOnlyBitField(inc);
|
||||
return ReadInternal<T>(inc, bitField);
|
||||
}
|
||||
|
||||
public static T ReadInternal<T>(IReadMessage inc, IReadableBitField bitField) where T : INetSerializableStruct
|
||||
public static T ReadInternal<T>(IReadMessage inc, ReadOnlyBitField bitField) where T : INetSerializableStruct
|
||||
{
|
||||
object? newObject = Activator.CreateInstance(typeof(T));
|
||||
if (newObject is null) { return default!; }
|
||||
@@ -744,14 +744,14 @@ namespace Barotrauma
|
||||
/// <param name="msg">Outgoing network message</param>
|
||||
public void Write(IWriteMessage msg)
|
||||
{
|
||||
IWritableBitField bitField = new WriteOnlyBitField();
|
||||
WriteOnlyBitField bitField = new WriteOnlyBitField();
|
||||
IWriteMessage structWriteMsg = new WriteOnlyMessage();
|
||||
WriteInternal(structWriteMsg, bitField);
|
||||
bitField.WriteToMessage(msg);
|
||||
msg.WriteBytes(structWriteMsg.Buffer, 0, structWriteMsg.LengthBytes);
|
||||
}
|
||||
|
||||
public void WriteInternal(IWriteMessage msg, IWritableBitField bitField)
|
||||
public void WriteInternal(IWriteMessage msg, WriteOnlyBitField bitField)
|
||||
{
|
||||
var properties = NetSerializableProperties.GetPropertiesAndFields(GetType());
|
||||
|
||||
|
||||
@@ -40,6 +40,25 @@ namespace Barotrauma.Networking
|
||||
return Option<LidgrenAddress>.None();
|
||||
}
|
||||
|
||||
public static Option<LidgrenAddress> ParseHostName(string endpointStr)
|
||||
{
|
||||
try
|
||||
{
|
||||
var resolvedAddresses = Dns.GetHostAddresses(endpointStr);
|
||||
return resolvedAddresses.Any()
|
||||
? Option<LidgrenAddress>.Some(new LidgrenAddress(resolvedAddresses.First()))
|
||||
: Option<LidgrenAddress>.None();
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
return Option<LidgrenAddress>.None();
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
return Option<LidgrenAddress>.None();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
=> obj switch
|
||||
{
|
||||
|
||||
@@ -23,6 +23,11 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
public new static Option<LidgrenEndpoint> Parse(string endpointStr)
|
||||
{
|
||||
return ParseFromWithHostNameCheck(endpointStr, tryParseHostName: false);
|
||||
}
|
||||
|
||||
public static Option<LidgrenEndpoint> ParseFromWithHostNameCheck(string endpointStr, bool tryParseHostName)
|
||||
{
|
||||
string hostName = endpointStr;
|
||||
int port = NetConfig.DefaultPort;
|
||||
@@ -33,7 +38,8 @@ namespace Barotrauma.Networking
|
||||
port = int.TryParse(split[1], out var tmpPort) ? tmpPort : port;
|
||||
}
|
||||
|
||||
if (LidgrenAddress.Parse(hostName).TryUnwrap(out var adr))
|
||||
if (LidgrenAddress.Parse(hostName).TryUnwrap(out var adr) ||
|
||||
(tryParseHostName && LidgrenAddress.ParseHostName(hostName).TryUnwrap(out adr)))
|
||||
{
|
||||
return Option<LidgrenEndpoint>.Some(new LidgrenEndpoint(adr.NetAddress, port));
|
||||
}
|
||||
|
||||
@@ -37,7 +37,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
internal static class MsgWriter
|
||||
{
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, bool val)
|
||||
internal static void UpdateBitLength(ref int bitLength, int bitPos)
|
||||
{
|
||||
bitLength = Math.Max(bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void WriteBoolean(ref byte[] buf, ref int bitPos, ref int bitLength, bool val)
|
||||
{
|
||||
#if DEBUG
|
||||
int resetPos = bitPos;
|
||||
@@ -52,7 +57,7 @@ namespace Barotrauma.Networking
|
||||
buf[bytePos] &= bitMask;
|
||||
if (val) buf[bytePos] |= bitFlag;
|
||||
bitPos++;
|
||||
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
#if DEBUG
|
||||
bool testVal = MsgReader.ReadBoolean(buf, ref resetPos);
|
||||
if (testVal != val || resetPos != bitPos)
|
||||
@@ -62,63 +67,71 @@ namespace Barotrauma.Networking
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static void WritePadBits(ref byte[] buf, ref int bitPos)
|
||||
internal static void WritePadBits(ref byte[] buf, ref int bitPos, ref int bitLength)
|
||||
{
|
||||
int bitOffset = bitPos % 8;
|
||||
bitPos += ((8 - bitOffset) % 8);
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
EnsureBufferSize(ref buf, bitPos);
|
||||
}
|
||||
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, byte val)
|
||||
internal static void WriteByte(ref byte[] buf, ref int bitPos, ref int bitLength, byte val)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + 8);
|
||||
NetBitWriter.WriteByte(val, 8, buf, bitPos);
|
||||
bitPos += 8;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, UInt16 val)
|
||||
internal static void WriteUInt16(ref byte[] buf, ref int bitPos, ref int bitLength, UInt16 val)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + 16);
|
||||
NetBitWriter.WriteUInt16(val, 16, buf, bitPos);
|
||||
bitPos += 16;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, Int16 val)
|
||||
internal static void WriteInt16(ref byte[] buf, ref int bitPos, ref int bitLength, Int16 val)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + 16);
|
||||
NetBitWriter.WriteUInt16((UInt16)val, 16, buf, bitPos);
|
||||
bitPos += 16;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, UInt32 val)
|
||||
internal static void WriteUInt32(ref byte[] buf, ref int bitPos, ref int bitLength, UInt32 val)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + 32);
|
||||
NetBitWriter.WriteUInt32(val, 32, buf, bitPos);
|
||||
bitPos += 32;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, Int32 val)
|
||||
internal static void WriteInt32(ref byte[] buf, ref int bitPos, ref int bitLength, Int32 val)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + 32);
|
||||
NetBitWriter.WriteUInt32((UInt32)val, 32, buf, bitPos);
|
||||
bitPos += 32;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, UInt64 val)
|
||||
internal static void WriteUInt64(ref byte[] buf, ref int bitPos, ref int bitLength, UInt64 val)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + 64);
|
||||
NetBitWriter.WriteUInt64(val, 64, buf, bitPos);
|
||||
bitPos += 64;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, Int64 val)
|
||||
internal static void WriteInt64(ref byte[] buf, ref int bitPos, ref int bitLength, Int64 val)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + 64);
|
||||
NetBitWriter.WriteUInt64((UInt64)val, 64, buf, bitPos);
|
||||
bitPos += 64;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, Single val)
|
||||
internal static void WriteSingle(ref byte[] buf, ref int bitPos, ref int bitLength, Single val)
|
||||
{
|
||||
// Use union to avoid BitConverter.GetBytes() which allocates memory on the heap
|
||||
SingleUIntUnion su;
|
||||
@@ -129,61 +142,62 @@ namespace Barotrauma.Networking
|
||||
|
||||
NetBitWriter.WriteUInt32(su.UIntValue, 32, buf, bitPos);
|
||||
bitPos += 32;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, Double val)
|
||||
internal static void WriteDouble(ref byte[] buf, ref int bitPos, ref int bitLength, Double val)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + 64);
|
||||
|
||||
byte[] bytes = BitConverter.GetBytes(val);
|
||||
WriteBytes(ref buf, ref bitPos, bytes, 0, 8);
|
||||
WriteBytes(ref buf, ref bitPos, ref bitLength, bytes, 0, 8);
|
||||
}
|
||||
|
||||
internal static void WriteColorR8G8B8(ref byte[] buf, ref int bitPos, Color val)
|
||||
internal static void WriteColorR8G8B8(ref byte[] buf, ref int bitPos, ref int bitLength, Color val)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + 24);
|
||||
|
||||
Write(ref buf, ref bitPos, val.R);
|
||||
Write(ref buf, ref bitPos, val.G);
|
||||
Write(ref buf, ref bitPos, val.B);
|
||||
WriteByte(ref buf, ref bitPos, ref bitLength, val.R);
|
||||
WriteByte(ref buf, ref bitPos, ref bitLength, val.G);
|
||||
WriteByte(ref buf, ref bitPos, ref bitLength, val.B);
|
||||
}
|
||||
|
||||
internal static void WriteColorR8G8B8A8(ref byte[] buf, ref int bitPos, Color val)
|
||||
internal static void WriteColorR8G8B8A8(ref byte[] buf, ref int bitPos, ref int bitLength, Color val)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + 32);
|
||||
|
||||
Write(ref buf, ref bitPos, val.R);
|
||||
Write(ref buf, ref bitPos, val.G);
|
||||
Write(ref buf, ref bitPos, val.B);
|
||||
Write(ref buf, ref bitPos, val.A);
|
||||
WriteByte(ref buf, ref bitPos, ref bitLength, val.R);
|
||||
WriteByte(ref buf, ref bitPos, ref bitLength, val.G);
|
||||
WriteByte(ref buf, ref bitPos, ref bitLength, val.B);
|
||||
WriteByte(ref buf, ref bitPos, ref bitLength, val.A);
|
||||
}
|
||||
|
||||
internal static void Write(ref byte[] buf, ref int bitPos, string val)
|
||||
internal static void WriteString(ref byte[] buf, ref int bitPos, ref int bitLength, string val)
|
||||
{
|
||||
if (string.IsNullOrEmpty(val))
|
||||
{
|
||||
WriteVariableUInt32(ref buf, ref bitPos, 0u);
|
||||
WriteVariableUInt32(ref buf, ref bitPos, ref bitLength, 0u);
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(val);
|
||||
WriteVariableUInt32(ref buf, ref bitPos, (uint)bytes.Length);
|
||||
WriteBytes(ref buf, ref bitPos, bytes, 0, bytes.Length);
|
||||
WriteVariableUInt32(ref buf, ref bitPos, ref bitLength, (uint)bytes.Length);
|
||||
WriteBytes(ref buf, ref bitPos, ref bitLength, bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
internal static void WriteVariableUInt32(ref byte[] buf, ref int bitPos, uint value)
|
||||
internal static void WriteVariableUInt32(ref byte[] buf, ref int bitPos, ref int bitLength, uint value)
|
||||
{
|
||||
uint remainingValue = value;
|
||||
while (remainingValue >= 0x80)
|
||||
{
|
||||
Write(ref buf, ref bitPos, (byte)(remainingValue | 0x80));
|
||||
WriteByte(ref buf, ref bitPos, ref bitLength, (byte)(remainingValue | 0x80));
|
||||
remainingValue >>= 7;
|
||||
}
|
||||
|
||||
Write(ref buf, ref bitPos, (byte)remainingValue);
|
||||
WriteByte(ref buf, ref bitPos, ref bitLength, (byte)remainingValue);
|
||||
}
|
||||
|
||||
internal static void WriteRangedInteger(ref byte[] buf, ref int bitPos, int val, int min, int max)
|
||||
internal static void WriteRangedInteger(ref byte[] buf, ref int bitPos, ref int bitLength, int val, int min, int max)
|
||||
{
|
||||
uint range = (uint)(max - min);
|
||||
int numberOfBits = NetUtility.BitsToHoldUInt(range);
|
||||
@@ -193,9 +207,10 @@ namespace Barotrauma.Networking
|
||||
uint rvalue = (uint)(val - min);
|
||||
NetBitWriter.WriteUInt32(rvalue, numberOfBits, buf, bitPos);
|
||||
bitPos += numberOfBits;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void WriteRangedSingle(ref byte[] buf, ref int bitPos, Single val, Single min, Single max, int numberOfBits)
|
||||
internal static void WriteRangedSingle(ref byte[] buf, ref int bitPos, ref int bitLength, Single val, Single min, Single max, int numberOfBits)
|
||||
{
|
||||
float range = max - min;
|
||||
float unit = ((val - min) / range);
|
||||
@@ -205,13 +220,15 @@ namespace Barotrauma.Networking
|
||||
|
||||
NetBitWriter.WriteUInt32((UInt32)(maxVal * unit), numberOfBits, buf, bitPos);
|
||||
bitPos += numberOfBits;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void WriteBytes(ref byte[] buf, ref int bitPos, byte[] val, int pos, int length)
|
||||
internal static void WriteBytes(ref byte[] buf, ref int bitPos, ref int bitLength, byte[] val, int pos, int length)
|
||||
{
|
||||
EnsureBufferSize(ref buf, bitPos + length * 8);
|
||||
NetBitWriter.WriteBytes(val, pos, length, buf, bitPos);
|
||||
bitPos += length * 8;
|
||||
UpdateBitLength(ref bitLength, bitPos);
|
||||
}
|
||||
|
||||
internal static void EnsureBufferSize(ref byte[] buf, int numberOfBits)
|
||||
@@ -447,77 +464,77 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void WriteBoolean(bool val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteBoolean(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WritePadBits()
|
||||
{
|
||||
MsgWriter.WritePadBits(ref buf, ref seekPos);
|
||||
MsgWriter.WritePadBits(ref buf, ref seekPos, ref lengthBits);
|
||||
}
|
||||
|
||||
public void WriteByte(byte val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteByte(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteUInt16(UInt16 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteUInt16(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteInt16(Int16 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteInt16(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteUInt32(UInt32 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteUInt32(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteInt32(Int32 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteInt32(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteUInt64(UInt64 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteUInt64(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteInt64(Int64 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteInt64(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteSingle(Single val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteSingle(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteDouble(Double val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteDouble(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteColorR8G8B8(Color val)
|
||||
{
|
||||
MsgWriter.WriteColorR8G8B8(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteColorR8G8B8(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteColorR8G8B8A8(Color val)
|
||||
{
|
||||
MsgWriter.WriteColorR8G8B8A8(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteColorR8G8B8A8(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteVariableUInt32(UInt32 val)
|
||||
{
|
||||
MsgWriter.WriteVariableUInt32(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteVariableUInt32(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteString(String val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteString(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteIdentifier(Identifier val)
|
||||
@@ -527,17 +544,17 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void WriteRangedInteger(int val, int min, int max)
|
||||
{
|
||||
MsgWriter.WriteRangedInteger(ref buf, ref seekPos, val, min, max);
|
||||
MsgWriter.WriteRangedInteger(ref buf, ref seekPos, ref lengthBits, val, min, max);
|
||||
}
|
||||
|
||||
public void WriteRangedSingle(Single val, Single min, Single max, int bitCount)
|
||||
{
|
||||
MsgWriter.WriteRangedSingle(ref buf, ref seekPos, val, min, max, bitCount);
|
||||
MsgWriter.WriteRangedSingle(ref buf, ref seekPos, ref lengthBits, val, min, max, bitCount);
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] val, int startPos, int length)
|
||||
{
|
||||
MsgWriter.WriteBytes(ref buf, ref seekPos, val, startPos, length);
|
||||
MsgWriter.WriteBytes(ref buf, ref seekPos, ref lengthBits, val, startPos, length);
|
||||
}
|
||||
|
||||
public byte[] PrepareForSending(bool compressPastThreshold, out bool isCompressed, out int length)
|
||||
@@ -814,77 +831,77 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void WriteBoolean(bool val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteBoolean(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WritePadBits()
|
||||
{
|
||||
MsgWriter.WritePadBits(ref buf, ref seekPos);
|
||||
MsgWriter.WritePadBits(ref buf, ref seekPos, ref lengthBits);
|
||||
}
|
||||
|
||||
public void WriteByte(byte val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteByte(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteUInt16(UInt16 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteUInt16(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteInt16(Int16 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteInt16(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteUInt32(UInt32 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteUInt32(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteInt32(Int32 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteInt32(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteUInt64(UInt64 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteUInt64(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteInt64(Int64 val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteInt64(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteSingle(Single val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteSingle(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteDouble(Double val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteDouble(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteColorR8G8B8(Color val)
|
||||
{
|
||||
MsgWriter.WriteColorR8G8B8(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteColorR8G8B8(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteColorR8G8B8A8(Color val)
|
||||
{
|
||||
MsgWriter.WriteColorR8G8B8A8(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteColorR8G8B8A8(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteVariableUInt32(UInt32 val)
|
||||
{
|
||||
MsgWriter.WriteVariableUInt32(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteVariableUInt32(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteString(String val)
|
||||
{
|
||||
MsgWriter.Write(ref buf, ref seekPos, val);
|
||||
MsgWriter.WriteString(ref buf, ref seekPos, ref lengthBits, val);
|
||||
}
|
||||
|
||||
public void WriteIdentifier(Identifier val)
|
||||
@@ -894,17 +911,17 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void WriteRangedInteger(int val, int min, int max)
|
||||
{
|
||||
MsgWriter.WriteRangedInteger(ref buf, ref seekPos, val, min, max);
|
||||
MsgWriter.WriteRangedInteger(ref buf, ref seekPos, ref lengthBits, val, min, max);
|
||||
}
|
||||
|
||||
public void WriteRangedSingle(Single val, Single min, Single max, int bitCount)
|
||||
{
|
||||
MsgWriter.WriteRangedSingle(ref buf, ref seekPos, val, min, max, bitCount);
|
||||
MsgWriter.WriteRangedSingle(ref buf, ref seekPos, ref lengthBits, val, min, max, bitCount);
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] val, int startPos, int length)
|
||||
{
|
||||
MsgWriter.WriteBytes(ref buf, ref seekPos, val, startPos, length);
|
||||
MsgWriter.WriteBytes(ref buf, ref seekPos, ref lengthBits, val, startPos, length);
|
||||
}
|
||||
|
||||
public bool ReadBoolean()
|
||||
|
||||
@@ -286,8 +286,13 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
public DateTime InstallTime => cachedDateTime ??= DateTime.UtcNow + TimeSpan.FromSeconds(InstallTimeDiffInSeconds);
|
||||
public RegularPackage? RegularPackage => ContentPackageManager.RegularPackages.FirstOrDefault(p => p.Hash.Equals(Hash));
|
||||
public CorePackage? CorePackage => ContentPackageManager.CorePackages.FirstOrDefault(p => p.Hash.Equals(Hash));
|
||||
public RegularPackage? RegularPackage =>
|
||||
ContentPackageManager.RegularPackages.FirstOrDefault(p => p.Name.Equals(Name) && p.Hash.Equals(Hash)) ??
|
||||
ContentPackageManager.RegularPackages.FirstOrDefault(p => p.Hash.Equals(Hash));
|
||||
|
||||
public CorePackage? CorePackage =>
|
||||
ContentPackageManager.CorePackages.FirstOrDefault(p => p.Name.Equals(Name) && p.Hash.Equals(Hash)) ??
|
||||
ContentPackageManager.CorePackages.FirstOrDefault(p => p.Hash.Equals(Hash));
|
||||
public ContentPackage? ContentPackage => (ContentPackage?)RegularPackage ?? CorePackage;
|
||||
|
||||
public ServerContentPackage() { }
|
||||
|
||||
@@ -1717,19 +1717,7 @@ namespace Barotrauma
|
||||
}
|
||||
float spread = Rand.Range(-chosenItemSpawnInfo.AimSpreadRad, chosenItemSpawnInfo.AimSpreadRad);
|
||||
float rotation = chosenItemSpawnInfo.RotationRad;
|
||||
Vector2 worldPos;
|
||||
if (sourceBody != null)
|
||||
{
|
||||
worldPos = sourceBody.Position;
|
||||
if (user?.Submarine != null)
|
||||
{
|
||||
worldPos += user.Submarine.Position;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
worldPos = entity.WorldPosition;
|
||||
}
|
||||
Vector2 spawnPos = sourceBody != null ? sourceBody.SimPosition : entity.SimPosition;
|
||||
switch (chosenItemSpawnInfo.RotationType)
|
||||
{
|
||||
case ItemSpawnInfo.SpawnRotationType.Fixed:
|
||||
@@ -1743,7 +1731,7 @@ namespace Barotrauma
|
||||
}
|
||||
break;
|
||||
case ItemSpawnInfo.SpawnRotationType.Target:
|
||||
rotation = MathUtils.VectorToAngle(entity.WorldPosition - worldPos);
|
||||
rotation = MathUtils.VectorToAngle(entity.SimPosition - spawnPos);
|
||||
break;
|
||||
case ItemSpawnInfo.SpawnRotationType.Limb:
|
||||
if (sourceBody != null)
|
||||
@@ -1787,10 +1775,7 @@ namespace Barotrauma
|
||||
rotation += spread;
|
||||
if (projectile != null)
|
||||
{
|
||||
projectile.Shoot(user,
|
||||
ConvertUnits.ToSimUnits(worldPos),
|
||||
ConvertUnits.ToSimUnits(worldPos),
|
||||
rotation,
|
||||
projectile.Shoot(user, spawnPos, spawnPos, rotation,
|
||||
ignoredBodies: user?.AnimController.Limbs.Where(l => !l.IsSevered).Select(l => l.body.FarseerBody).ToList(), createNetworkEvent: true);
|
||||
}
|
||||
else if (newItem.body != null)
|
||||
|
||||
@@ -43,9 +43,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public int GetBuyprice(int level, Location? location = null)
|
||||
public int GetBuyPrice(int level, Location? location = null)
|
||||
{
|
||||
int maxLevel = Prefab.MaxLevel;
|
||||
int maxLevel = Prefab.GetMaxLevelForCurrentSub();
|
||||
|
||||
if (level > maxLevel) { maxLevel = level; }
|
||||
|
||||
@@ -292,16 +292,10 @@ namespace Barotrauma
|
||||
onRemoveOverrideFile: null
|
||||
);
|
||||
|
||||
private readonly int maxLevel;
|
||||
|
||||
public int MaxLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
Submarine? sub = GameMain.GameSession?.Submarine ?? Submarine.MainSub;
|
||||
return sub is { Info: var info } ? GetMaxLevel(info) : maxLevel;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Maximum upgrade level without taking submarine tier or class restrictions into account
|
||||
/// </summary>
|
||||
public readonly int MaxLevel;
|
||||
|
||||
public LocalizedString Name { get; }
|
||||
|
||||
@@ -343,7 +337,7 @@ namespace Barotrauma
|
||||
{
|
||||
Name = element.GetAttributeString("name", string.Empty)!;
|
||||
Description = element.GetAttributeString("description", string.Empty)!;
|
||||
maxLevel = element.GetAttributeInt("maxlevel", 1);
|
||||
MaxLevel = element.GetAttributeInt("maxlevel", 1);
|
||||
SuppressWarnings = element.GetAttributeBool("supresswarnings", false);
|
||||
HideInMenus = element.GetAttributeBool("hideinmenus", false);
|
||||
SourceElement = element;
|
||||
@@ -428,9 +422,21 @@ namespace Barotrauma
|
||||
.ToImmutableHashSet() ?? ImmutableHashSet<Identifier>.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum upgrade level for the current sub, taking tier and class restrictions into account
|
||||
/// </summary>
|
||||
public int GetMaxLevelForCurrentSub()
|
||||
{
|
||||
Submarine? sub = GameMain.GameSession?.Submarine ?? Submarine.MainSub;
|
||||
return sub is { Info: var info } ? GetMaxLevel(info) : MaxLevel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum upgrade level for the specified sub, taking tier and class restrictions into account
|
||||
/// </summary>
|
||||
public int GetMaxLevel(SubmarineInfo info)
|
||||
{
|
||||
int level = maxLevel;
|
||||
int level = MaxLevel;
|
||||
|
||||
foreach (UpgradeMaxLevelMod mod in MaxLevelsMods)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,54 @@
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.19.14.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
- Fixed submarine upgrades getting clamped to the maximum of that upgrade between rounds, disregarding class/tier bonuses.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.19.13.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
- Fixed "failed to find the end of the bit field after 100 reads" error when trying to join a server that has a large number of mods enabled.
|
||||
- Fixed "Tandem Fire" talent causing a crash due to the changes in the previous version.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.19.12.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
- Fixed submarine upgrades getting lost if you switch to a lower-tier sub that can't have as many levels of upgrades as the current sub, and then back again.
|
||||
- Fixed some monster events not being as common/uncommon as intended. In more technical terms (which may be of interest to modders): the commonness defined as an attribute of an EventSet did nothing, making the event default to a commonness of 1. The commonnesses defined for specific level types worked correctly.
|
||||
- Fixed clients getting stuck in a non-functional lobby if they happen to disconnect or get kicked back to the lobby at a specific point when loading a new round.
|
||||
- Fixed large turret hardpoint origin being off, causing turrets installed on a large hardpoint to be misaligned.
|
||||
- Attempt to fix crashing when disconnecting from the server you're hosting.
|
||||
- Fixed Ctrl+Shift+S shortcut (quicksave) not working in the sub editor.
|
||||
- Fixed toolbelts and storage containers in old subs going inside toolbelts.
|
||||
- Fixed submarine tier resetting to default when reopening the sub editor's save dialog.
|
||||
- Fixed sub editor not taking filename case into account when saving an existing sub: if you'd try to save the file with a different filename case, it'd ask about overwriting the existing sub, but save it as a new file even if you opt to overwrite.
|
||||
- Fixes to Herja room names (use Engineering, Gunnery compartment, etc. labels), add camera to the front, with a periscope for the captain.
|
||||
- Fixed non-purchaseable talent items not being available as extra cargo.
|
||||
- Sorted extra cargo alphabetically + added a filter box.
|
||||
- Fixed taking items that spawned inside another item (e.g. tanks in a diving mask) from NPCs spawned by an event not counting as stealing.
|
||||
- Fixed characters falling off ladders when using aimable tools.
|
||||
- Fixed money gain/lose popups no longer showing in the campaign.
|
||||
- Fixed inability to manage the campaign if there's no-one with permissions alive. Previously we allowed anyone to manage the campaign if there's no-one with permissions present in the server, but that's not enough, because the players with permissions can't end the round if they're dead. Now if there's no-one with permissions alive, anyone is allowed to manage the campaign.
|
||||
- If Select and Deselect have been bound to the same key, the deselect input is ignored when interacting with another item than the selected one. Prevents e.g. falling off ladders when trying to open a hatch when both Select and Deselect have been bound to E.
|
||||
- Made it possible to enter a hostname (e.g. someserver.com) in the direct join prompt.
|
||||
- Adjusted the size of the submarine list elements in the server lobby to reduce the amount of empty space on large resolutions.
|
||||
- Fixed event texts for the "scan ruin" mission being in an incorrect language.
|
||||
- Attachable items cannot be attached inside walls.
|
||||
- Fixed distance at which you can attach items being slightly longer than the interact distance, making it possible to attach items out of reach.
|
||||
- Fixed inability to turn when you're dual wielding melee weapons and attacking continuously.
|
||||
- Fixed inability to cancel deconstruction if there's non-deconstructible items in the queue.
|
||||
- Fixed local copy of a mod you're publishing not using the version number you've entered in the publish menu.
|
||||
- Fixed crashing when trying to open the tab menu's character tab with a character who has no personality trait (may happen e.g. if you use a mod that adds custom personality traits and try to play that save without the mod).
|
||||
- Fixed sourcerect issue in alien generator + decorative sprite not disappearing when the fuel rod is taken out.
|
||||
- Fixed corrupted mods causing a nullref exception when autodetecting required mods in the sub editor.
|
||||
- Fixed minerals not disappearing from mineral scanner if they get detached by something else than a character picking them up (e.g. by the destructible ice wall they're on breaking).
|
||||
- Fixed event-specific metal crate deconstructing to steel.
|
||||
- Fixed inability to join servers that have enabled multiple mods with identical content.
|
||||
- Fixed tandem fire not working if there's a character between you and the other character on a periscope.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.19.11.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -29,7 +29,17 @@ namespace TestProject
|
||||
[Fact]
|
||||
public void TestBitField()
|
||||
{
|
||||
// 0-length bitfield test
|
||||
SerializeDeserializeBitField(Array.Empty<bool>());
|
||||
|
||||
// Normal bitfield test
|
||||
Prop.ForAll<bool[]>(SerializeDeserializeBitField).VerboseCheckThrowOnFailure();
|
||||
|
||||
// Large bitfield test
|
||||
Prop.ForAll(
|
||||
Arb.Generate<bool[]>().Resize(1000).Where(arr => arr.Length >= 800)
|
||||
.ToArbitrary(),
|
||||
SerializeDeserializeBitField).VerboseCheckThrowOnFailure();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -278,7 +288,7 @@ namespace TestProject
|
||||
private static void SerializeDeserializeBitField(bool[] arg)
|
||||
{
|
||||
ReadWriteMessage msg = new ReadWriteMessage();
|
||||
IWritableBitField bitFieldWrite = new WriteOnlyBitField();
|
||||
WriteOnlyBitField bitFieldWrite = new WriteOnlyBitField();
|
||||
|
||||
foreach (bool b in arg)
|
||||
{
|
||||
@@ -288,7 +298,7 @@ namespace TestProject
|
||||
bitFieldWrite.WriteToMessage(msg);
|
||||
msg.BitPosition = 0;
|
||||
|
||||
IReadableBitField bitFieldRead = new ReadOnlyBitField(msg);
|
||||
ReadOnlyBitField bitFieldRead = new ReadOnlyBitField(msg);
|
||||
|
||||
foreach (bool b in arg)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user